From 62a0f807f3f36947311324606058d4e43a24c968 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Sun, 29 May 2022 21:07:45 +0100 Subject: [PATCH] Extract more --- amigae33a/E_v3.3a/Modules.lha | Bin 659318 -> 0 bytes amigae33a/E_v3.3a/Modules/Modules/afc/BeBox.m | Bin 0 -> 5030 bytes .../E_v3.3a/Modules/Modules/afc/Bitmapper.m | Bin 0 -> 5398 bytes .../E_v3.3a/Modules/Modules/afc/DirList.m | Bin 0 -> 2808 bytes .../E_v3.3a/Modules/Modules/afc/Displayer.m | Bin 0 -> 8982 bytes .../E_v3.3a/Modules/Modules/afc/IFFParser.m | Bin 0 -> 3486 bytes .../E_v3.3a/Modules/Modules/afc/Localer.m | Bin 0 -> 1012 bytes .../Modules/Modules/afc/Mousepointer.m | Bin 0 -> 3498 bytes .../E_v3.3a/Modules/Modules/afc/NodeMaster.m | Bin 0 -> 5028 bytes .../E_v3.3a/Modules/Modules/afc/Parser.m | Bin 0 -> 1260 bytes .../E_v3.3a/Modules/Modules/afc/ReqTooller.m | Bin 0 -> 10890 bytes .../E_v3.3a/Modules/Modules/afc/StringNode.m | Bin 0 -> 3656 bytes .../E_v3.3a/Modules/Modules/afc/ToolType.m | Bin 0 -> 1270 bytes .../Modules/Modules/afc/Worldbuilder.m | Bin 0 -> 27524 bytes .../Modules/Modules/afc/explain_exception.m | Bin 0 -> 3740 bytes .../E_v3.3a/Modules/Modules/afc/hardsprite.m | Bin 0 -> 1134 bytes amigae33a/E_v3.3a/Modules/Modules/afc/mgui.m | Bin 0 -> 6394 bytes .../E_v3.3a/Modules/Modules/afc/rexxer.m | Bin 0 -> 2514 bytes .../Modules/Modules/afc/super_picture.m | Bin 0 -> 6374 bytes .../E_v3.3a/Modules/Modules/afc/tasker.m | Bin 0 -> 3204 bytes .../Modules/Modules/afc/validPortName.m | Bin 0 -> 264 bytes .../E_v3.3a/Modules/Modules/amigaguide.m | Bin 0 -> 375 bytes .../E_v3.3a/Modules/Modules/amigalib/Tasks.m | Bin 0 -> 600 bytes .../Modules/Modules/amigalib/argarray.m | Bin 0 -> 820 bytes .../E_v3.3a/Modules/Modules/amigalib/boopsi.m | Bin 0 -> 572 bytes .../E_v3.3a/Modules/Modules/amigalib/cx.m | Bin 0 -> 1970 bytes .../Modules/Modules/amigalib/interrupts.m | Bin 0 -> 282 bytes .../E_v3.3a/Modules/Modules/amigalib/io.m | Bin 0 -> 522 bytes .../E_v3.3a/Modules/Modules/amigalib/lists.m | Bin 0 -> 112 bytes .../E_v3.3a/Modules/Modules/amigalib/ports.m | Bin 0 -> 608 bytes .../E_v3.3a/Modules/Modules/amigalib/random.m | Bin 0 -> 366 bytes .../E_v3.3a/Modules/Modules/amigalib/time.m | Bin 0 -> 444 bytes amigae33a/E_v3.3a/Modules/Modules/asl.m | Bin 0 -> 108 bytes amigae33a/E_v3.3a/Modules/Modules/bgui.m | Bin 0 -> 141 bytes amigae33a/E_v3.3a/Modules/Modules/bullet.m | Bin 0 -> 82 bytes .../E_v3.3a/Modules/Modules/class/hash.m | Bin 0 -> 1122 bytes amigae33a/E_v3.3a/Modules/Modules/class/sc.m | Bin 0 -> 7028 bytes .../E_v3.3a/Modules/Modules/class/sctext.m | Bin 0 -> 2510 bytes .../E_v3.3a/Modules/Modules/class/stack.m | Bin 0 -> 528 bytes .../E_v3.3a/Modules/Modules/colorwheel.m | Bin 0 -> 60 bytes .../E_v3.3a/Modules/Modules/commodities.m | Bin 0 -> 340 bytes amigae33a/E_v3.3a/Modules/Modules/console.m | Bin 0 -> 60 bytes .../E_v3.3a/Modules/Modules/cybergraphics.m | Bin 0 -> 400 bytes amigae33a/E_v3.3a/Modules/Modules/datatypes.m | Bin 0 -> 276 bytes .../Modules/datatypes/animationclass.m | Bin 0 -> 1306 bytes .../Modules/Modules/datatypes/datatypes.m | Bin 0 -> 1674 bytes .../Modules/datatypes/datatypesclass.m | Bin 0 -> 3952 bytes .../Modules/Modules/datatypes/pictureclass.m | Bin 0 -> 1074 bytes .../Modules/Modules/datatypes/soundclass.m | Bin 0 -> 544 bytes .../Modules/Modules/datatypes/textclass.m | Bin 0 -> 504 bytes .../E_v3.3a/Modules/Modules/devices/audio.m | Bin 0 -> 704 bytes .../Modules/Modules/devices/bootblock.m | Bin 0 -> 158 bytes .../E_v3.3a/Modules/Modules/devices/cd.m | Bin 0 -> 2992 bytes .../Modules/Modules/devices/clipboard.m | Bin 0 -> 660 bytes .../E_v3.3a/Modules/Modules/devices/console.m | Bin 0 -> 1060 bytes .../E_v3.3a/Modules/Modules/devices/conunit.m | Bin 0 -> 852 bytes .../Modules/Modules/devices/gameport.m | Bin 0 -> 448 bytes .../Modules/Modules/devices/hardblocks.m | Bin 0 -> 2266 bytes .../E_v3.3a/Modules/Modules/devices/input.m | Bin 0 -> 204 bytes .../Modules/Modules/devices/inputevent.m | Bin 0 -> 2880 bytes .../Modules/Modules/devices/keyboard.m | Bin 0 -> 160 bytes .../E_v3.3a/Modules/Modules/devices/keymap.m | Bin 0 -> 742 bytes .../Modules/Modules/devices/narrator.m | Bin 0 -> 1436 bytes .../Modules/Modules/devices/parallel.m | Bin 0 -> 1024 bytes .../E_v3.3a/Modules/Modules/devices/printer.m | Bin 0 -> 2156 bytes .../E_v3.3a/Modules/Modules/devices/prtbase.m | Bin 0 -> 1824 bytes .../E_v3.3a/Modules/Modules/devices/prtgfx.m | Bin 0 -> 1010 bytes .../Modules/Modules/devices/scsidisk.m | Bin 0 -> 612 bytes .../E_v3.3a/Modules/Modules/devices/serial.m | Bin 0 -> 1332 bytes .../E_v3.3a/Modules/Modules/devices/timer.m | Bin 0 -> 414 bytes .../Modules/Modules/devices/trackdisk.m | Bin 0 -> 2046 bytes amigae33a/E_v3.3a/Modules/Modules/diskfont.m | Bin 0 -> 106 bytes .../Modules/Modules/diskfont/diskfont.m | Bin 0 -> 888 bytes .../Modules/Modules/diskfont/diskfonttag.m | Bin 0 -> 1664 bytes .../E_v3.3a/Modules/Modules/diskfont/glyph.m | Bin 0 -> 458 bytes .../Modules/Modules/diskfont/oterrors.m | Bin 0 -> 336 bytes amigae33a/E_v3.3a/Modules/Modules/dos.m | Bin 0 -> 1785 bytes .../E_v3.3a/Modules/Modules/dos/datetime.m | Bin 0 -> 348 bytes amigae33a/E_v3.3a/Modules/Modules/dos/dos.m | Bin 0 -> 3856 bytes .../E_v3.3a/Modules/Modules/dos/dos_lib.m | Bin 0 -> 64 bytes .../E_v3.3a/Modules/Modules/dos/dosasl.m | Bin 0 -> 1160 bytes .../E_v3.3a/Modules/Modules/dos/dosextens.m | Bin 0 -> 5860 bytes .../E_v3.3a/Modules/Modules/dos/doshunks.m | Bin 0 -> 932 bytes .../E_v3.3a/Modules/Modules/dos/dostags.m | Bin 0 -> 748 bytes amigae33a/E_v3.3a/Modules/Modules/dos/exall.m | Bin 0 -> 462 bytes .../E_v3.3a/Modules/Modules/dos/filehandler.m | Bin 0 -> 1124 bytes .../E_v3.3a/Modules/Modules/dos/notify.m | Bin 0 -> 716 bytes .../E_v3.3a/Modules/Modules/dos/rdargs.m | Bin 0 -> 404 bytes .../E_v3.3a/Modules/Modules/dos/record.m | Bin 0 -> 214 bytes amigae33a/E_v3.3a/Modules/Modules/dos/stdio.m | Bin 0 -> 404 bytes amigae33a/E_v3.3a/Modules/Modules/dos/var.m | Bin 0 -> 416 bytes amigae33a/E_v3.3a/Modules/Modules/dtclass.m | Bin 0 -> 36 bytes amigae33a/E_v3.3a/Modules/Modules/exec.m | Bin 0 -> 1365 bytes .../E_v3.3a/Modules/Modules/exec/alerts.m | Bin 0 -> 3166 bytes .../E_v3.3a/Modules/Modules/exec/devices.m | Bin 0 -> 202 bytes .../E_v3.3a/Modules/Modules/exec/errors.m | Bin 0 -> 210 bytes .../E_v3.3a/Modules/Modules/exec/execbase.m | Bin 0 -> 2154 bytes .../E_v3.3a/Modules/Modules/exec/interrupts.m | Bin 0 -> 338 bytes amigae33a/E_v3.3a/Modules/Modules/exec/io.m | Bin 0 -> 592 bytes .../E_v3.3a/Modules/Modules/exec/libraries.m | Bin 0 -> 474 bytes .../E_v3.3a/Modules/Modules/exec/lists.m | Bin 0 -> 332 bytes .../E_v3.3a/Modules/Modules/exec/memory.m | Bin 0 -> 772 bytes .../E_v3.3a/Modules/Modules/exec/nodes.m | Bin 0 -> 592 bytes .../E_v3.3a/Modules/Modules/exec/ports.m | Bin 0 -> 310 bytes .../E_v3.3a/Modules/Modules/exec/resident.m | Bin 0 -> 358 bytes .../E_v3.3a/Modules/Modules/exec/semaphores.m | Bin 0 -> 436 bytes .../E_v3.3a/Modules/Modules/exec/strings.m | Bin 0 -> 110 bytes .../E_v3.3a/Modules/Modules/exec/tasks.m | Bin 0 -> 1426 bytes .../E_v3.3a/Modules/Modules/exec/types.m | Bin 0 -> 98 bytes amigae33a/E_v3.3a/Modules/Modules/expansion.m | Bin 0 -> 363 bytes .../E_v3.3a/Modules/Modules/gadgets/button.m | Bin 0 -> 242 bytes .../Modules/Modules/gadgets/calendar.m | Bin 0 -> 502 bytes .../Modules/Modules/gadgets/colorwheel.m | Bin 0 -> 490 bytes .../Modules/Modules/gadgets/gradientslider.m | Bin 0 -> 154 bytes .../E_v3.3a/Modules/Modules/gadgets/tabs.m | Bin 0 -> 316 bytes .../Modules/Modules/gadgets/tapedeck.m | Bin 0 -> 288 bytes amigae33a/E_v3.3a/Modules/Modules/gadtools.m | Bin 0 -> 330 bytes amigae33a/E_v3.3a/Modules/Modules/graphics.m | Bin 0 -> 2138 bytes .../E_v3.3a/Modules/Modules/graphics/clip.m | Bin 0 -> 1194 bytes .../E_v3.3a/Modules/Modules/graphics/coerce.m | Bin 0 -> 122 bytes .../Modules/Modules/graphics/collide.m | Bin 0 -> 114 bytes .../E_v3.3a/Modules/Modules/graphics/copper.m | Bin 0 -> 1140 bytes .../Modules/Modules/graphics/display.m | Bin 0 -> 338 bytes .../Modules/Modules/graphics/displayinfo.m | Bin 0 -> 2164 bytes .../E_v3.3a/Modules/Modules/graphics/gels.m | Bin 0 -> 1898 bytes .../E_v3.3a/Modules/Modules/graphics/gfx.m | Bin 0 -> 742 bytes .../Modules/Modules/graphics/gfxbase.m | Bin 0 -> 3186 bytes .../Modules/Modules/graphics/gfxmacros.m | Bin 0 -> 1458 bytes .../Modules/Modules/graphics/gfxnodes.m | Bin 0 -> 322 bytes .../Modules/Modules/graphics/graphint.m | Bin 0 -> 140 bytes .../E_v3.3a/Modules/Modules/graphics/layers.m | Bin 0 -> 722 bytes .../E_v3.3a/Modules/Modules/graphics/modeid.m | Bin 0 -> 6766 bytes .../Modules/Modules/graphics/monitor.m | Bin 0 -> 2586 bytes .../Modules/Modules/graphics/rastport.m | Bin 0 -> 1536 bytes .../Modules/Modules/graphics/regions.m | Bin 0 -> 252 bytes .../E_v3.3a/Modules/Modules/graphics/rpattr.m | Bin 0 -> 200 bytes .../E_v3.3a/Modules/Modules/graphics/scale.m | Bin 0 -> 408 bytes .../E_v3.3a/Modules/Modules/graphics/sprite.m | Bin 0 -> 486 bytes .../E_v3.3a/Modules/Modules/graphics/text.m | Bin 0 -> 1874 bytes .../Modules/Modules/graphics/videocontrol.m | Bin 0 -> 1888 bytes .../E_v3.3a/Modules/Modules/graphics/view.m | Bin 0 -> 3710 bytes amigae33a/E_v3.3a/Modules/Modules/gtx.m | Bin 0 -> 493 bytes .../Modules/Modules/hardware/adkbits.m | Bin 0 -> 714 bytes .../E_v3.3a/Modules/Modules/hardware/blit.m | Bin 0 -> 1006 bytes .../E_v3.3a/Modules/Modules/hardware/cia.m | Bin 0 -> 2980 bytes .../E_v3.3a/Modules/Modules/hardware/custom.m | Bin 0 -> 3996 bytes .../Modules/Modules/hardware/dmabits.m | Bin 0 -> 572 bytes .../Modules/Modules/hardware/intbits.m | Bin 0 -> 594 bytes amigae33a/E_v3.3a/Modules/Modules/icon.m | Bin 0 -> 227 bytes amigae33a/E_v3.3a/Modules/Modules/iff.m | Bin 0 -> 328 bytes amigae33a/E_v3.3a/Modules/Modules/iffparse.m | Bin 0 -> 583 bytes .../E_v3.3a/Modules/Modules/images/led.m | Bin 0 -> 142 bytes amigae33a/E_v3.3a/Modules/Modules/input.m | Bin 0 -> 37 bytes amigae33a/E_v3.3a/Modules/Modules/intuition.m | Bin 0 -> 1875 bytes .../Modules/Modules/intuition/cghooks.m | Bin 0 -> 404 bytes .../Modules/Modules/intuition/classes.m | Bin 0 -> 770 bytes .../Modules/Modules/intuition/classusr.m | Bin 0 -> 1552 bytes .../Modules/Modules/intuition/gadgetclass.m | Bin 0 -> 3454 bytes .../Modules/Modules/intuition/icclass.m | Bin 0 -> 188 bytes .../Modules/Modules/intuition/imageclass.m | Bin 0 -> 2616 bytes .../Modules/Modules/intuition/intuition.m | Bin 0 -> 11864 bytes .../Modules/Modules/intuition/intuitionbase.m | Bin 0 -> 588 bytes .../Modules/Modules/intuition/iobsolete.m | Bin 0 -> 3320 bytes .../Modules/Modules/intuition/pointerclass.m | Bin 0 -> 544 bytes .../Modules/Modules/intuition/preferences.m | Bin 0 -> 2984 bytes .../Modules/Modules/intuition/screens.m | Bin 0 -> 3786 bytes .../Modules/Modules/intuition/sghooks.m | Bin 0 -> 1418 bytes amigae33a/E_v3.3a/Modules/Modules/keymap.m | Bin 0 -> 81 bytes amigae33a/E_v3.3a/Modules/Modules/layers.m | Bin 0 -> 554 bytes .../Modules/Modules/libraries/amigaguide.m | Bin 0 -> 2530 bytes .../E_v3.3a/Modules/Modules/libraries/asl.m | Bin 0 -> 6128 bytes .../E_v3.3a/Modules/Modules/libraries/bgui.m | Bin 0 -> 11052 bytes .../Modules/Modules/libraries/bgui_macros.m | Bin 0 -> 15610 bytes .../Modules/Modules/libraries/commodities.m | Bin 0 -> 1568 bytes .../Modules/Modules/libraries/configregs.m | Bin 0 -> 2244 bytes .../Modules/Modules/libraries/configvars.m | Bin 0 -> 550 bytes .../Modules/Modules/libraries/cybergraphics.m | Bin 0 -> 1208 bytes .../Modules/Modules/libraries/diskfont.m | Bin 0 -> 888 bytes .../Modules/Modules/libraries/expansion.m | Bin 0 -> 128 bytes .../Modules/Modules/libraries/expansionbase.m | Bin 0 -> 746 bytes .../Modules/Modules/libraries/gadtools.m | Bin 0 -> 3690 bytes .../E_v3.3a/Modules/Modules/libraries/iff.m | Bin 0 -> 1104 bytes .../Modules/Modules/libraries/iffparse.m | Bin 0 -> 1550 bytes .../Modules/Modules/libraries/locale.m | Bin 0 -> 2422 bytes .../Modules/Modules/libraries/lowlevel.m | Bin 0 -> 3574 bytes .../Modules/Modules/libraries/mathieeesp.m | Bin 0 -> 332 bytes .../Modules/Modules/libraries/mathlibrary.m | Bin 0 -> 144 bytes .../Modules/Modules/libraries/mathresource.m | Bin 0 -> 450 bytes .../E_v3.3a/Modules/Modules/libraries/midi.m | Bin 0 -> 4036 bytes .../Modules/Modules/libraries/muibuilder.m | Bin 0 -> 1032 bytes .../Modules/Modules/libraries/nofrag.m | Bin 0 -> 448 bytes .../Modules/Modules/libraries/nonvolatile.m | Bin 0 -> 392 bytes .../Modules/Modules/libraries/ppbase.m | Bin 0 -> 520 bytes .../Modules/Modules/libraries/realtime.m | Bin 0 -> 1922 bytes .../Modules/Modules/libraries/reqbase.m | Bin 0 -> 3450 bytes .../Modules/Modules/libraries/reqtools.m | Bin 0 -> 4944 bytes .../Modules/Modules/libraries/translator.m | Bin 0 -> 90 bytes .../Modules/Modules/libraries/triton.m | Bin 0 -> 5506 bytes .../Modules/Modules/libraries/triton_macros.m | Bin 0 -> 12544 bytes .../E_v3.3a/Modules/Modules/libraries/vmem.m | Bin 0 -> 108 bytes .../Modules/Modules/libraries/wizard.m | Bin 0 -> 8360 bytes amigae33a/E_v3.3a/Modules/Modules/locale.m | Bin 0 -> 301 bytes amigae33a/E_v3.3a/Modules/Modules/lowlevel.m | Bin 0 -> 223 bytes amigae33a/E_v3.3a/Modules/Modules/mathffp.m | Bin 0 -> 100 bytes .../E_v3.3a/Modules/Modules/mathieeedoubbas.m | Bin 0 -> 175 bytes .../Modules/Modules/mathieeedoubtrans.m | Bin 0 -> 238 bytes .../E_v3.3a/Modules/Modules/mathieeesingbas.m | Bin 0 -> 159 bytes .../Modules/Modules/mathieeesingtrans.m | Bin 0 -> 221 bytes amigae33a/E_v3.3a/Modules/Modules/mathtrans.m | Bin 0 -> 145 bytes amigae33a/E_v3.3a/Modules/Modules/midi.m | Bin 0 -> 421 bytes amigae33a/E_v3.3a/Modules/Modules/nofrag.m | Bin 0 -> 116 bytes .../E_v3.3a/Modules/Modules/nonvolatile.m | Bin 0 -> 104 bytes .../Modules/Modules/oomodules/commodity.m | Bin 0 -> 2684 bytes .../Modules/Modules/oomodules/coordinate.m | Bin 0 -> 6220 bytes .../Modules/oomodules/coordinate/line.m | Bin 0 -> 1814 bytes .../Modules/oomodules/coordinate/polyline.m | Bin 0 -> 1036 bytes .../Modules/Modules/oomodules/library.m | Bin 0 -> 716 bytes .../Modules/Modules/oomodules/library/asl.m | Bin 0 -> 1824 bytes .../Modules/oomodules/library/commodities.m | Bin 0 -> 846 bytes .../Modules/oomodules/library/device.m | Bin 0 -> 1826 bytes .../oomodules/library/device/keyboard.m | Bin 0 -> 1044 bytes .../oomodules/library/device/printer.m | Bin 0 -> 2014 bytes .../oomodules/library/device/trackdisk.m | Bin 0 -> 1866 bytes .../Modules/oomodules/library/exec/port.m | Bin 0 -> 1630 bytes .../oomodules/library/exec/port/arexxport.m | Bin 0 -> 1060 bytes .../oomodules/library/exec/port/portlist.m | Bin 0 -> 1194 bytes .../Modules/oomodules/library/gadtools.m | Bin 0 -> 838 bytes .../Modules/oomodules/library/locale.m | Bin 0 -> 2010 bytes .../oomodules/library/locale/cataloglist.m | Bin 0 -> 2222 bytes .../Modules/oomodules/library/reqtools.m | Bin 0 -> 1840 bytes .../Modules/oomodules/list/associativearray.m | Bin 0 -> 2962 bytes .../associativearray/associativestringarray.m | Bin 0 -> 662 bytes .../Modules/oomodules/list/doublylinked.m | Bin 0 -> 3618 bytes .../Modules/Modules/oomodules/list/elist.m | Bin 0 -> 2684 bytes .../Modules/Modules/oomodules/list/execlist.m | Bin 0 -> 1272 bytes .../Modules/oomodules/list/queuestack.m | Bin 0 -> 8638 bytes .../oomodules/list/stringlist/stringlist.m | Bin 0 -> 2194 bytes .../Modules/Modules/oomodules/object.m | Bin 0 -> 1338 bytes .../E_v3.3a/Modules/Modules/oomodules/sort.m | Bin 0 -> 1114 bytes .../Modules/Modules/oomodules/sort/address.m | Bin 0 -> 2902 bytes .../Modules/Modules/oomodules/sort/numbers.m | Bin 0 -> 1098 bytes .../Modules/oomodules/sort/numbers/float.m | Bin 0 -> 1828 bytes .../Modules/oomodules/sort/numbers/fraction.m | Bin 0 -> 3862 bytes .../Modules/oomodules/sort/numbers/integer.m | Bin 0 -> 1394 bytes .../oomodules/sort/numbers/twonumbers.m | Bin 0 -> 728 bytes .../Modules/Modules/oomodules/sort/string.m | Bin 0 -> 3284 bytes .../Modules/oomodules/sort/string/rawstring.m | Bin 0 -> 808 bytes .../E_v3.3a/Modules/Modules/other/battclock.m | Bin 0 -> 244 bytes .../E_v3.3a/Modules/Modules/other/battmem.m | Bin 0 -> 360 bytes .../E_v3.3a/Modules/Modules/other/bitfield.m | Bin 0 -> 344 bytes .../E_v3.3a/Modules/Modules/other/bits.m | Bin 0 -> 256 bytes amigae33a/E_v3.3a/Modules/Modules/other/cia.m | Bin 0 -> 320 bytes .../E_v3.3a/Modules/Modules/other/clearlist.m | Bin 0 -> 178 bytes .../Modules/Modules/other/cloneworkbench.m | Bin 0 -> 678 bytes .../E_v3.3a/Modules/Modules/other/disk.m | Bin 0 -> 422 bytes .../E_v3.3a/Modules/Modules/other/dislib.m | Bin 0 -> 544 bytes .../E_v3.3a/Modules/Modules/other/dispose.m | Bin 0 -> 114 bytes .../Modules/other/disposeelinkedlist.m | Bin 0 -> 172 bytes .../Modules/Modules/other/disposelink.m | Bin 0 -> 122 bytes amigae33a/E_v3.3a/Modules/Modules/other/dll.m | Bin 0 -> 1132 bytes .../E_v3.3a/Modules/Modules/other/ecode.m | Bin 0 -> 1614 bytes .../Modules/Modules/other/fastinsert.m | Bin 0 -> 302 bytes .../E_v3.3a/Modules/Modules/other/initlist.m | Bin 0 -> 116 bytes .../E_v3.3a/Modules/Modules/other/isdigit.m | Bin 0 -> 122 bytes .../Modules/Modules/other/isidentifier.m | Bin 0 -> 260 bytes .../E_v3.3a/Modules/Modules/other/lowerchar.m | Bin 0 -> 148 bytes .../E_v3.3a/Modules/Modules/other/misc.m | Bin 0 -> 216 bytes amigae33a/E_v3.3a/Modules/Modules/other/mod.m | Bin 0 -> 142 bytes .../E_v3.3a/Modules/Modules/other/potgo.m | Bin 0 -> 260 bytes .../Modules/other/qualifieditemaddress.m | Bin 0 -> 582 bytes .../E_v3.3a/Modules/Modules/other/readstr.m | Bin 0 -> 312 bytes .../Modules/Modules/other/sendexplorer.m | Bin 0 -> 602 bytes .../E_v3.3a/Modules/Modules/other/sendrexx.m | Bin 0 -> 878 bytes .../Modules/Modules/other/setprogname.m | Bin 0 -> 228 bytes .../Modules/Modules/other/skipnonwhite.m | Bin 0 -> 202 bytes .../Modules/Modules/other/skiptochar.m | Bin 0 -> 138 bytes .../Modules/Modules/other/skiptoedelim.m | Bin 0 -> 230 bytes .../E_v3.3a/Modules/Modules/other/skipwhite.m | Bin 0 -> 170 bytes .../E_v3.3a/Modules/Modules/other/split.m | Bin 0 -> 672 bytes .../E_v3.3a/Modules/Modules/other/stack.m | Bin 0 -> 486 bytes .../E_v3.3a/Modules/Modules/other/strcopy.m | Bin 0 -> 156 bytes .../E_v3.3a/Modules/Modules/other/upperchar.m | Bin 0 -> 148 bytes .../Modules/Modules/plugins/animcontrol.m | Bin 0 -> 2536 bytes .../E_v3.3a/Modules/Modules/plugins/button.m | Bin 0 -> 2214 bytes .../Modules/Modules/plugins/calendar.m | Bin 0 -> 1778 bytes .../Modules/Modules/plugins/colorwheel.m | Bin 0 -> 2744 bytes .../Modules/Modules/plugins/gradient.m | Bin 0 -> 2242 bytes .../E_v3.3a/Modules/Modules/plugins/iconify.m | Bin 0 -> 2006 bytes .../Modules/Modules/plugins/imagebutton.m | Bin 0 -> 2346 bytes .../E_v3.3a/Modules/Modules/plugins/led.m | Bin 0 -> 1358 bytes .../Modules/Modules/plugins/password.m | Bin 0 -> 2542 bytes .../E_v3.3a/Modules/Modules/plugins/tabs.m | Bin 0 -> 2006 bytes .../Modules/Modules/plugins/tapedeck.m | Bin 0 -> 2384 bytes .../Modules/Modules/plugins/text_plug.m | Bin 0 -> 2672 bytes .../E_v3.3a/Modules/Modules/plugins/ticker.m | Bin 0 -> 558 bytes .../E_v3.3a/Modules/Modules/plugins/toolify.m | Bin 0 -> 1686 bytes amigae33a/E_v3.3a/Modules/Modules/pointer.m | Bin 0 -> 74 bytes .../E_v3.3a/Modules/Modules/powerpacker.m | Bin 0 -> 260 bytes .../E_v3.3a/Modules/Modules/prefs/font.m | Bin 0 -> 300 bytes .../E_v3.3a/Modules/Modules/prefs/icontrol.m | Bin 0 -> 446 bytes .../E_v3.3a/Modules/Modules/prefs/input.m | Bin 0 -> 230 bytes .../E_v3.3a/Modules/Modules/prefs/locale.m | Bin 0 -> 1058 bytes .../E_v3.3a/Modules/Modules/prefs/overscan.m | Bin 0 -> 292 bytes .../E_v3.3a/Modules/Modules/prefs/palette.m | Bin 0 -> 170 bytes .../E_v3.3a/Modules/Modules/prefs/pointer.m | Bin 0 -> 300 bytes .../E_v3.3a/Modules/Modules/prefs/prefhdr.m | Bin 0 -> 140 bytes .../Modules/Modules/prefs/printergfx.m | Bin 0 -> 890 bytes .../E_v3.3a/Modules/Modules/prefs/printerps.m | Bin 0 -> 1618 bytes .../Modules/Modules/prefs/printertxt.m | Bin 0 -> 886 bytes .../Modules/Modules/prefs/screenmode.m | Bin 0 -> 226 bytes .../E_v3.3a/Modules/Modules/prefs/serial.m | Bin 0 -> 426 bytes .../E_v3.3a/Modules/Modules/prefs/sound.m | Bin 0 -> 282 bytes .../E_v3.3a/Modules/Modules/prefs/wbpattern.m | Bin 0 -> 344 bytes amigae33a/E_v3.3a/Modules/Modules/ramdrive.m | Bin 0 -> 45 bytes amigae33a/E_v3.3a/Modules/Modules/realtime.m | Bin 0 -> 176 bytes amigae33a/E_v3.3a/Modules/Modules/req.m | Bin 0 -> 396 bytes amigae33a/E_v3.3a/Modules/Modules/reqtools.m | Bin 0 -> 454 bytes .../Modules/Modules/resources/battclock.m | Bin 0 -> 78 bytes .../Modules/Modules/resources/battmem.m | Bin 0 -> 74 bytes .../Modules/resources/battmembitsamiga.m | Bin 0 -> 226 bytes .../Modules/resources/battmembitsshared.m | Bin 0 -> 376 bytes .../E_v3.3a/Modules/Modules/resources/card.m | Bin 0 -> 1790 bytes .../E_v3.3a/Modules/Modules/resources/cia.m | Bin 0 -> 102 bytes .../E_v3.3a/Modules/Modules/resources/disk.m | Bin 0 -> 886 bytes .../Modules/Modules/resources/filesysres.m | Bin 0 -> 422 bytes .../Modules/Modules/resources/mathresource.m | Bin 0 -> 458 bytes .../E_v3.3a/Modules/Modules/resources/misc.m | Bin 0 -> 214 bytes .../E_v3.3a/Modules/Modules/resources/potgo.m | Bin 0 -> 102 bytes .../E_v3.3a/Modules/Modules/rexx/errors.m | Bin 0 -> 846 bytes .../E_v3.3a/Modules/Modules/rexx/rexxio.m | Bin 0 -> 674 bytes .../E_v3.3a/Modules/Modules/rexx/rxslib.m | Bin 0 -> 1354 bytes .../E_v3.3a/Modules/Modules/rexx/storage.m | Bin 0 -> 2348 bytes .../E_v3.3a/Modules/Modules/rexxsyslib.m | Bin 0 -> 230 bytes amigae33a/E_v3.3a/Modules/Modules/timer.m | Bin 0 -> 72 bytes .../E_v3.3a/Modules/Modules/tools/Boopsi.m | Bin 0 -> 166 bytes .../E_v3.3a/Modules/Modules/tools/EasyGUI.m | Bin 0 -> 29484 bytes .../Modules/Modules/tools/EasyGUI_debug.m | Bin 0 -> 30450 bytes .../Modules/Modules/tools/EasyGUI_lite.m | Bin 0 -> 21630 bytes .../Modules/Modules/tools/EasyGUI_notag.m | Bin 0 -> 712 bytes .../E_v3.3a/Modules/Modules/tools/Vector.m | Bin 0 -> 1610 bytes .../E_v3.3a/Modules/Modules/tools/arexx.m | Bin 0 -> 1174 bytes .../E_v3.3a/Modules/Modules/tools/async.m | Bin 0 -> 1066 bytes .../Modules/Modules/tools/clonescreen.m | Bin 0 -> 1388 bytes .../Modules/Modules/tools/constructors.m | Bin 0 -> 328 bytes .../Modules/Modules/tools/cookrawkey.m | Bin 0 -> 1020 bytes .../E_v3.3a/Modules/Modules/tools/copylist.m | Bin 0 -> 172 bytes .../E_v3.3a/Modules/Modules/tools/ctype.m | Bin 0 -> 716 bytes .../Modules/Modules/tools/exceptions.m | Bin 0 -> 576 bytes .../E_v3.3a/Modules/Modules/tools/file.m | Bin 0 -> 942 bytes .../Modules/Modules/tools/filledvdefs.m | Bin 0 -> 442 bytes .../Modules/Modules/tools/filledvector.m | Bin 0 -> 6044 bytes .../E_v3.3a/Modules/Modules/tools/ghost.m | Bin 0 -> 710 bytes .../E_v3.3a/Modules/Modules/tools/ilbm.m | Bin 0 -> 1894 bytes .../E_v3.3a/Modules/Modules/tools/ilbmdefs.m | Bin 0 -> 562 bytes .../E_v3.3a/Modules/Modules/tools/inithook.m | Bin 0 -> 178 bytes .../Modules/Modules/tools/installhook.m | Bin 0 -> 142 bytes .../E_v3.3a/Modules/Modules/tools/iterators.m | Bin 0 -> 112 bytes .../E_v3.3a/Modules/Modules/tools/lisp.m | Bin 0 -> 1736 bytes .../E_v3.3a/Modules/Modules/tools/longreal.m | Bin 0 -> 6846 bytes .../Modules/Modules/tools/longrealtiny.m | Bin 0 -> 2552 bytes .../E_v3.3a/Modules/Modules/tools/macros.m | Bin 0 -> 306 bytes .../Modules/Modules/tools/muicustomclass.m | Bin 0 -> 428 bytes amigae33a/E_v3.3a/Modules/Modules/tools/pt.m | Bin 0 -> 5252 bytes .../E_v3.3a/Modules/Modules/tools/scrbuffer.m | Bin 0 -> 812 bytes .../E_v3.3a/Modules/Modules/tools/simplelex.m | Bin 0 -> 1782 bytes .../E_v3.3a/Modules/Modules/tools/stack.m | Bin 0 -> 528 bytes .../E_v3.3a/Modules/Modules/tools/textlen.m | Bin 0 -> 342 bytes .../E_v3.3a/Modules/Modules/tools/trapguru.m | Bin 0 -> 220 bytes .../E_v3.3a/Modules/Modules/translator.m | Bin 0 -> 54 bytes amigae33a/E_v3.3a/Modules/Modules/triton.m | Bin 0 -> 348 bytes amigae33a/E_v3.3a/Modules/Modules/utility.m | Bin 0 -> 557 bytes .../E_v3.3a/Modules/Modules/utility/date.m | Bin 0 -> 152 bytes .../E_v3.3a/Modules/Modules/utility/hooks.m | Bin 0 -> 118 bytes .../E_v3.3a/Modules/Modules/utility/name.m | Bin 0 -> 250 bytes .../E_v3.3a/Modules/Modules/utility/pack.m | Bin 0 -> 424 bytes .../E_v3.3a/Modules/Modules/utility/tagitem.m | Bin 0 -> 280 bytes .../E_v3.3a/Modules/Modules/utility/utility.m | Bin 0 -> 156 bytes amigae33a/E_v3.3a/Modules/Modules/vector.m | Bin 0 -> 175 bytes amigae33a/E_v3.3a/Modules/Modules/vmem.m | Bin 0 -> 114 bytes amigae33a/E_v3.3a/Modules/Modules/wb.m | Bin 0 -> 142 bytes amigae33a/E_v3.3a/Modules/Modules/wizard.m | Bin 0 -> 495 bytes .../Modules/Modules/workbench/startup.m | Bin 0 -> 264 bytes .../Modules/Modules/workbench/workbench.m | Bin 0 -> 1462 bytes amigae33a/E_v3.3a/Src.lha | Bin 2618056 -> 0 bytes .../E_v3.3a/Src/Src/Afc/BeBox_Example1.e | 125 + .../E_v3.3a/Src/Src/Afc/Change_Example.e | 56 + .../E_v3.3a/Src/Src/Afc/Displayer_Example1.e | 69 + .../E_v3.3a/Src/Src/Afc/Displayer_Example2.e | 147 ++ amigae33a/E_v3.3a/Src/Src/Afc/Docs/AFC.guide | 381 ++++ .../E_v3.3a/Src/Src/Afc/Docs/Bitmapper.guide | 393 ++++ .../E_v3.3a/Src/Src/Afc/Docs/DirList.guide | 235 ++ .../E_v3.3a/Src/Src/Afc/Docs/Displayer.guide | 610 +++++ .../E_v3.3a/Src/Src/Afc/Docs/Hardsprite.guide | 169 ++ .../E_v3.3a/Src/Src/Afc/Docs/IffParser.guide | 471 ++++ .../E_v3.3a/Src/Src/Afc/Docs/Localer.guide | 188 ++ .../Src/Src/Afc/Docs/Mousepointer.guide | 289 +++ .../E_v3.3a/Src/Src/Afc/Docs/NodeMaster.guide | 855 +++++++ .../E_v3.3a/Src/Src/Afc/Docs/ReqTooller.guide | 380 ++++ .../E_v3.3a/Src/Src/Afc/Docs/StringNode.guide | 520 +++++ .../E_v3.3a/Src/Src/Afc/Docs/Tasker.guide | 452 ++++ .../E_v3.3a/Src/Src/Afc/Docs/ToolType.guide | 161 ++ .../Src/Src/Afc/Docs/Worldbuilder.guide | 1457 ++++++++++++ .../E_v3.3a/Src/Src/Afc/Docs/bebox.guide | 305 +++ .../Src/Src/Afc/Docs/explain_exception.guide | 78 + amigae33a/E_v3.3a/Src/Src/Afc/Docs/mgui.guide | 576 +++++ .../E_v3.3a/Src/Src/Afc/Docs/parser.guide | 161 ++ .../E_v3.3a/Src/Src/Afc/Docs/rexxer.guide | 354 +++ .../Src/Src/Afc/Docs/super_picture.guide | 523 +++++ .../Src/Src/Afc/Docs/validPortName.guide | 102 + .../E_v3.3a/Src/Src/Afc/EasyGUI_Example.e | 101 + .../E_v3.3a/Src/Src/Afc/First_Del_Example.e | 60 + .../E_v3.3a/Src/Src/Afc/Hardsprite_Example.e | 72 + .../E_v3.3a/Src/Src/Afc/IFFParser_Example.e | 85 + .../E_v3.3a/Src/Src/Afc/IFFParser_Example2.e | 58 + .../E_v3.3a/Src/Src/Afc/Localer_Example1.e | 35 + amigae33a/E_v3.3a/Src/Src/Afc/MGUI_Example1.e | 92 + .../Src/Src/Afc/Mousepointer_Example.e | 59 + .../E_v3.3a/Src/Src/Afc/Parser_Example1.e | 29 + .../Src/Src/Afc/PatternMatch_Example.e | 47 + .../E_v3.3a/Src/Src/Afc/Push_Pop_Example.e | 61 + .../E_v3.3a/Src/Src/Afc/RamScan_Example.e | 52 + .../E_v3.3a/Src/Src/Afc/ReqTooller_Example1.e | 113 + .../E_v3.3a/Src/Src/Afc/Rexxer_Receiver.e | 44 + amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Sender.e | 35 + .../E_v3.3a/Src/Src/Afc/Search_Example.e | 55 + .../E_v3.3a/Src/Src/Afc/SetAttrs_Example.e | 51 + amigae33a/E_v3.3a/Src/Src/Afc/Sort_Example.e | 97 + .../E_v3.3a/Src/Src/Afc/SuperPic_Example1.e | 81 + .../E_v3.3a/Src/Src/Afc/Tasker_Example1.e | 30 + .../E_v3.3a/Src/Src/Afc/Tasker_Example2.e | 94 + .../E_v3.3a/Src/Src/Afc/ToolType_Example1.e | 37 + .../Src/Src/Afc/Worldbuilder_Example1.e | 224 ++ .../Src/Src/Afc/Worldbuilder_Example2.e | 174 ++ amigae33a/E_v3.3a/Src/Src/Args/GetArgs.e | 5 + amigae33a/E_v3.3a/Src/Src/Args/ReadArgs.e | 17 + amigae33a/E_v3.3a/Src/Src/Args/WbArg.e | 15 + .../E_v3.3a/Src/Src/Class/BinTree/bintree | Bin 0 -> 1672 bytes .../E_v3.3a/Src/Src/Class/BinTree/bintree.e | 60 + amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.doc | 175 ++ amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.e | 117 + .../E_v3.3a/Src/Src/Class/Hash/hashtest.e | 58 + amigae33a/E_v3.3a/Src/Src/Class/README | 6 + .../E_v3.3a/Src/Src/Class/ScrollWin/sc.doc | 109 + .../Src/Src/Class/ScrollWin/textview.e | 15 + amigae33a/E_v3.3a/Src/Src/Class/Stack/stack.e | 35 + .../E_v3.3a/Src/Src/Class/Stack/stackuse.e | 13 + amigae33a/E_v3.3a/Src/Src/Dos/Shell.e | 15 + amigae33a/E_v3.3a/Src/Src/Dos/date.e | 28 + amigae33a/E_v3.3a/Src/Src/Dos/readtext.e | 27 + .../E_v3.3a/Src/Src/Explorer/Explorer.doc | 224 ++ .../E_v3.3a/Src/Src/Explorer/empty-handler.e | 103 + .../E_v3.3a/Src/Src/Explorer/empty.mountlist | 5 + .../E_v3.3a/Src/Src/Explorer/explorer.config | Bin 0 -> 68154 bytes .../E_v3.3a/Src/Src/Gfx/24bitColourDemo.e | 46 + .../Gfx/Chunky3d/TEXTUREMAP_ROAD.br.chunky | Bin 0 -> 16384 bytes amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/c2p4.m | Bin 0 -> 1374 bytes amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls.e | 143 ++ .../E_v3.3a/Src/Src/Gfx/Chunky3d/ls_sculpt.e | 205 ++ amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/rr.e | 226 ++ .../Src/Src/Gfx/Chunky3d/screenmodereq_db.m | Bin 0 -> 752 bytes amigae33a/E_v3.3a/Src/Src/Gfx/ColourScreen.e | 14 + amigae33a/E_v3.3a/Src/Src/Gfx/IfsFern.e | 56 + amigae33a/E_v3.3a/Src/Src/Gfx/IntMandel.e | 56 + amigae33a/E_v3.3a/Src/Src/Gfx/Kohonen.e | 97 + amigae33a/E_v3.3a/Src/Src/Gfx/Mandel.e | 24 + amigae33a/E_v3.3a/Src/Src/Gfx/Mandel256.e | 78 + amigae33a/E_v3.3a/Src/Src/Gfx/MandelCalc881.m | Bin 0 -> 184 bytes amigae33a/E_v3.3a/Src/Src/Gfx/PPV.e | 32 + amigae33a/E_v3.3a/Src/Src/Gfx/RewriteGfx.e | 169 ++ .../E_v3.3a/Src/Src/Gfx/TextureMapping/README | 46 + .../Src/Gfx/TextureMapping/c2p_cpu3blit1.m | Bin 0 -> 1548 bytes .../TextureMapping/car64x64x8.iff.cmchunky | Bin 0 -> 4864 bytes .../E_v3.3a/Src/Src/Gfx/TextureMapping/geom.e | 37 + .../E_v3.3a/Src/Src/Gfx/TextureMapping/geom.m | Bin 0 -> 1188 bytes .../Src/Gfx/TextureMapping/screenmodereq_db.e | 34 + .../Src/Gfx/TextureMapping/screenmodereq_db.m | Bin 0 -> 760 bytes .../Src/Gfx/TextureMapping/texturemapper.e | 81 + .../Src/Gfx/TextureMapping/texturemapper.m | Bin 0 -> 1620 bytes .../Src/Src/Gfx/TextureMapping/tmaptest.e | 121 + amigae33a/E_v3.3a/Src/Src/Gfx/Trace.e | 65 + amigae33a/E_v3.3a/Src/Src/Gfx/nice.e | 196 ++ amigae33a/E_v3.3a/Src/Src/Gfx/paint.e | 23 + amigae33a/E_v3.3a/Src/Src/Gfx/paint.m | Bin 0 -> 496 bytes amigae33a/E_v3.3a/Src/Src/Gfx/sim_flock.e | 112 + amigae33a/E_v3.3a/Src/Src/Guide/address.e | 13 + amigae33a/E_v3.3a/Src/Src/Guide/args.e | 28 + amigae33a/E_v3.3a/Src/Src/Guide/args.info | Bin 0 -> 802 bytes amigae33a/E_v3.3a/Src/Src/Guide/args20.e | 20 + amigae33a/E_v3.3a/Src/Src/Guide/bintree.e | 48 + amigae33a/E_v3.3a/Src/Src/Guide/csv-buff.e | 68 + amigae33a/E_v3.3a/Src/Src/Guide/csv-estr.e | 50 + amigae33a/E_v3.3a/Src/Src/Guide/csv-norm.e | 42 + amigae33a/E_v3.3a/Src/Src/Guide/csv.e | 72 + amigae33a/E_v3.3a/Src/Src/Guide/datafile | 6 + amigae33a/E_v3.3a/Src/Src/Guide/dragon.e | 113 + amigae33a/E_v3.3a/Src/Src/Guide/except.e | 22 + amigae33a/E_v3.3a/Src/Src/Guide/except2.e | 22 + amigae33a/E_v3.3a/Src/Src/Guide/float.e | 59 + amigae33a/E_v3.3a/Src/Src/Guide/gadgets.e | 19 + amigae33a/E_v3.3a/Src/Src/Guide/graphics.e | 25 + amigae33a/E_v3.3a/Src/Src/Guide/idcmp.e | 24 + amigae33a/E_v3.3a/Src/Src/Guide/screens.e | 28 + amigae33a/E_v3.3a/Src/Src/Guide/screens2.e | 33 + amigae33a/E_v3.3a/Src/Src/Guide/set-use.e | 24 + amigae33a/E_v3.3a/Src/Src/Guide/set.e | 80 + amigae33a/E_v3.3a/Src/Src/Guide/simple.e | 3 + amigae33a/E_v3.3a/Src/Src/Guide/static.e | 12 + amigae33a/E_v3.3a/Src/Src/Guide/static2.e | 17 + amigae33a/E_v3.3a/Src/Src/Guide/static3.e | 12 + amigae33a/E_v3.3a/Src/Src/Guide/timing.e | 60 + amigae33a/E_v3.3a/Src/Src/Guide/tree-use.e | 19 + amigae33a/E_v3.3a/Src/Src/Guide/tree.e | 82 + amigae33a/E_v3.3a/Src/Src/Guide/while.e | 10 + amigae33a/E_v3.3a/Src/Src/HelloWorld.e | 5 + amigae33a/E_v3.3a/Src/Src/HelloWorld.e.info | Bin 0 -> 1802 bytes amigae33a/E_v3.3a/Src/Src/Intui/AppMenuItem.e | 23 + amigae33a/E_v3.3a/Src/Src/Intui/Public.e | 35 + .../E_v3.3a/Src/Src/Intui/ScrollerWindow.e | 308 +++ amigae33a/E_v3.3a/Src/Src/Intui/Talk2Boopsi.e | 29 + amigae33a/E_v3.3a/Src/Src/Intui/gradient.e | 32 + amigae33a/E_v3.3a/Src/Src/Lang/EYacc/bcalc.y | 70 + .../E_v3.3a/Src/Src/Lang/EYacc/calcmain.e | 10 + amigae33a/E_v3.3a/Src/Src/Lang/Elex.e | 193 ++ amigae33a/E_v3.3a/Src/Src/Lang/Forth.e | 125 + amigae33a/E_v3.3a/Src/Src/Lang/Lambda.e | 74 + amigae33a/E_v3.3a/Src/Src/Lang/NGRC.e | 742 ++++++ .../E_v3.3a/Src/Src/Lang/Yax/QuickSort.yax | 83 + amigae33a/E_v3.3a/Src/Src/Lang/Yax/Yax.e | 742 ++++++ amigae33a/E_v3.3a/Src/Src/Lang/Yax/fac.yax | 2 + amigae33a/E_v3.3a/Src/Src/Lang/Yax/pi.yax | 42 + .../E_v3.3a/Src/Src/Lang/Yax/sincosdemo.yax | 66 + amigae33a/E_v3.3a/Src/Src/Lang/Yax/xpaint.yax | 75 + amigae33a/E_v3.3a/Src/Src/Lang/Yax/yax.doc | 224 ++ amigae33a/E_v3.3a/Src/Src/Library/Pgs/gio.m | Bin 0 -> 1334 bytes amigae33a/E_v3.3a/Src/Src/Library/Pgs/noisy.e | 54 + amigae33a/E_v3.3a/Src/Src/Library/Pgs/pgs.m | Bin 0 -> 1005 bytes amigae33a/E_v3.3a/Src/Src/Library/README | 5 + .../Src/Src/Library/Stack/stack_pragmas.h | 5 + .../E_v3.3a/Src/Src/Library/Stack/stacklib.e | 26 + .../E_v3.3a/Src/Src/Library/Stack/stackuse.c | 21 + .../Src/Modules/datatypes/animationclass.e | 81 + .../Src/Src/Modules/datatypes/datatypes.e | 107 + .../Src/Modules/datatypes/datatypesclass.e | 234 ++ .../Src/Src/Modules/datatypes/pictureclass.e | 67 + .../Src/Src/Modules/datatypes/soundclass.e | 34 + .../Src/Src/Modules/datatypes/textclass.e | 38 + .../E_v3.3a/Src/Src/Modules/devices/audio.e | 43 + .../Src/Src/Modules/devices/bootblock.e | 12 + .../E_v3.3a/Src/Src/Modules/devices/cd.e | 172 ++ .../Src/Src/Modules/devices/clipboard.e | 47 + .../E_v3.3a/Src/Src/Modules/devices/console.e | 62 + .../E_v3.3a/Src/Src/Modules/devices/conunit.e | 57 + .../Src/Src/Modules/devices/gameport.e | 27 + .../Src/Src/Modules/devices/hardblocks.e | 134 ++ .../E_v3.3a/Src/Src/Modules/devices/input.e | 12 + .../Src/Src/Modules/devices/inputevent.e | 135 ++ .../Src/Src/Modules/devices/keyboard.e | 9 + .../E_v3.3a/Src/Src/Modules/devices/keymap.e | 49 + .../Src/Src/Modules/devices/narrator.e | 95 + .../Src/Src/Modules/devices/parallel.e | 59 + .../E_v3.3a/Src/Src/Modules/devices/printer.e | 143 ++ .../E_v3.3a/Src/Src/Modules/devices/prtbase.e | 116 + .../E_v3.3a/Src/Src/Modules/devices/prtgfx.e | 62 + .../Src/Src/Modules/devices/scsidisk.e | 36 + .../E_v3.3a/Src/Src/Modules/devices/serial.e | 75 + .../E_v3.3a/Src/Src/Modules/devices/timer.e | 34 + .../Src/Src/Modules/devices/trackdisk.e | 116 + .../Src/Src/Modules/diskfont/diskfont.e | 71 + .../Src/Src/Modules/diskfont/diskfonttag.e | 89 + .../E_v3.3a/Src/Src/Modules/diskfont/glyph.e | 36 + .../Src/Src/Modules/diskfont/oterrors.e | 18 + .../E_v3.3a/Src/Src/Modules/dos/datetime.e | 25 + amigae33a/E_v3.3a/Src/Src/Modules/dos/dos.e | 187 ++ .../E_v3.3a/Src/Src/Modules/dos/dos_lib.e | 6 + .../E_v3.3a/Src/Src/Modules/dos/dosasl.e | 71 + .../E_v3.3a/Src/Src/Modules/dos/dosextens.e | 349 +++ .../E_v3.3a/Src/Src/Modules/dos/doshunks.e | 53 + .../E_v3.3a/Src/Src/Modules/dos/dostags.e | 41 + amigae33a/E_v3.3a/Src/Src/Modules/dos/exall.e | 34 + .../E_v3.3a/Src/Src/Modules/dos/filehandler.e | 70 + .../E_v3.3a/Src/Src/Modules/dos/notify.e | 45 + .../E_v3.3a/Src/Src/Modules/dos/rdargs.e | 27 + .../E_v3.3a/Src/Src/Modules/dos/record.e | 15 + amigae33a/E_v3.3a/Src/Src/Modules/dos/stdio.e | 20 + amigae33a/E_v3.3a/Src/Src/Modules/dos/var.e | 26 + .../E_v3.3a/Src/Src/Modules/exec/alerts.e | 163 ++ .../E_v3.3a/Src/Src/Modules/exec/devices.e | 20 + .../E_v3.3a/Src/Src/Modules/exec/errors.e | 13 + .../E_v3.3a/Src/Src/Modules/exec/execbase.e | 116 + .../E_v3.3a/Src/Src/Modules/exec/interrupts.e | 32 + amigae33a/E_v3.3a/Src/Src/Modules/exec/io.e | 43 + .../E_v3.3a/Src/Src/Modules/exec/libraries.e | 34 + .../E_v3.3a/Src/Src/Modules/exec/lists.e | 24 + .../E_v3.3a/Src/Src/Modules/exec/memory.e | 58 + .../E_v3.3a/Src/Src/Modules/exec/nodes.e | 39 + .../E_v3.3a/Src/Src/Modules/exec/ports.e | 26 + .../E_v3.3a/Src/Src/Modules/exec/resident.e | 24 + .../E_v3.3a/Src/Src/Modules/exec/semaphores.e | 37 + .../E_v3.3a/Src/Src/Modules/exec/strings.e | 11 + .../E_v3.3a/Src/Src/Modules/exec/tasks.e | 92 + .../E_v3.3a/Src/Src/Modules/exec/types.e | 7 + .../E_v3.3a/Src/Src/Modules/gadgets/button.e | 15 + .../Src/Src/Modules/gadgets/calendar.e | 25 + .../Src/Src/Modules/gadgets/colorwheel.e | 31 + .../Src/Src/Modules/gadgets/gradientslider.e | 10 + .../E_v3.3a/Src/Src/Modules/gadgets/tabs.e | 17 + .../Src/Src/Modules/gadgets/tapedeck.e | 17 + .../E_v3.3a/Src/Src/Modules/graphics/clip.e | 73 + .../E_v3.3a/Src/Src/Modules/graphics/coerce.e | 8 + .../Src/Src/Modules/graphics/collide.e | 8 + .../E_v3.3a/Src/Src/Modules/graphics/copper.e | 79 + .../Src/Src/Modules/graphics/display.e | 20 + .../Src/Src/Modules/graphics/displayinfo.e | 117 + .../E_v3.3a/Src/Src/Modules/graphics/gels.e | 118 + .../E_v3.3a/Src/Src/Modules/graphics/gfx.e | 55 + .../Src/Src/Modules/graphics/gfxbase.e | 170 ++ .../Src/Src/Modules/graphics/gfxmacros.e | 44 + .../Src/Src/Modules/graphics/gfxnodes.e | 23 + .../Src/Src/Modules/graphics/graphint.e | 12 + .../E_v3.3a/Src/Src/Modules/graphics/layers.e | 41 + .../E_v3.3a/Src/Src/Modules/graphics/modeid.e | 253 +++ .../Src/Src/Modules/graphics/monitor.e | 126 ++ .../Src/Src/Modules/graphics/rastport.e | 101 + .../Src/Src/Modules/graphics/regions.e | 16 + .../E_v3.3a/Src/Src/Modules/graphics/rpattr.e | 12 + .../E_v3.3a/Src/Src/Modules/graphics/scale.e | 27 + .../E_v3.3a/Src/Src/Modules/graphics/sprite.e | 28 + .../E_v3.3a/Src/Src/Modules/graphics/text.e | 119 + .../Src/Src/Modules/graphics/videocontrol.e | 71 + .../E_v3.3a/Src/Src/Modules/graphics/view.e | 202 ++ .../Src/Src/Modules/hardware/adkbits.e | 40 + .../E_v3.3a/Src/Src/Modules/hardware/blit.e | 70 + .../E_v3.3a/Src/Src/Modules/hardware/cia.e | 169 ++ .../E_v3.3a/Src/Src/Modules/hardware/custom.e | 269 +++ .../Src/Src/Modules/hardware/dmabits.e | 34 + .../Src/Src/Modules/hardware/intbits.e | 36 + .../E_v3.3a/Src/Src/Modules/images/led.e | 12 + .../Src/Src/Modules/intuition/cghooks.e | 29 + .../Src/Src/Modules/intuition/classes.e | 47 + .../Src/Src/Modules/intuition/classusr.e | 94 + .../Src/Src/Modules/intuition/gadgetclass.e | 192 ++ .../Src/Src/Modules/intuition/icclass.e | 12 + .../Src/Src/Modules/intuition/imageclass.e | 148 ++ .../Src/Src/Modules/intuition/intuition.e | 649 ++++++ .../Src/Src/Modules/intuition/intuitionbase.e | 38 + .../Src/Src/Modules/intuition/iobsolete.e | 188 ++ .../Src/Src/Modules/intuition/pointerclass.e | 23 + .../Src/Src/Modules/intuition/preferences.e | 165 ++ .../Src/Src/Modules/intuition/screens.e | 222 ++ .../Src/Src/Modules/intuition/sghooks.e | 84 + .../Src/Src/Modules/libraries/amigaguide.e | 156 ++ .../E_v3.3a/Src/Src/Modules/libraries/asl.e | 302 +++ .../Src/Src/Modules/libraries/commodities.e | 85 + .../Src/Src/Modules/libraries/configregs.e | 114 + .../Src/Src/Modules/libraries/configvars.e | 36 + .../Src/Src/Modules/libraries/diskfont.e | 71 + .../Src/Src/Modules/libraries/expansion.e | 10 + .../Src/Src/Modules/libraries/expansionbase.e | 48 + .../Src/Src/Modules/libraries/gadtools.e | 201 ++ .../Src/Src/Modules/libraries/iffparse.e | 100 + .../Src/Src/Modules/libraries/locale.e | 147 ++ .../Src/Src/Modules/libraries/lowlevel.e | 161 ++ .../Src/Src/Modules/libraries/mathieeesp.e | 21 + .../Src/Src/Modules/libraries/mathlibrary.e | 12 + .../Src/Src/Modules/libraries/mathresource.e | 24 + .../Src/Src/Modules/libraries/nonvolatile.e | 30 + .../Src/Src/Modules/libraries/realtime.e | 114 + .../Src/Src/Modules/libraries/translator.e | 7 + .../E_v3.3a/Src/Src/Modules/prefs/font.e | 23 + .../E_v3.3a/Src/Src/Modules/prefs/icontrol.e | 27 + .../E_v3.3a/Src/Src/Modules/prefs/input.e | 16 + .../E_v3.3a/Src/Src/Modules/prefs/locale.e | 53 + .../E_v3.3a/Src/Src/Modules/prefs/overscan.e | 21 + .../E_v3.3a/Src/Src/Modules/prefs/palette.e | 15 + .../E_v3.3a/Src/Src/Modules/prefs/pointer.e | 25 + .../E_v3.3a/Src/Src/Modules/prefs/prefhdr.e | 12 + .../Src/Src/Modules/prefs/printergfx.e | 50 + .../E_v3.3a/Src/Src/Modules/prefs/printerps.e | 92 + .../Src/Src/Modules/prefs/printertxt.e | 56 + .../Src/Src/Modules/prefs/screenmode.e | 17 + .../E_v3.3a/Src/Src/Modules/prefs/serial.e | 27 + .../E_v3.3a/Src/Src/Modules/prefs/sound.e | 19 + .../E_v3.3a/Src/Src/Modules/prefs/wbpattern.e | 24 + .../Src/Src/Modules/resources/battclock.e | 6 + .../Src/Src/Modules/resources/battmem.e | 6 + .../Src/Modules/resources/battmembitsamiga.e | 10 + .../Src/Modules/resources/battmembitsshared.e | 14 + .../E_v3.3a/Src/Src/Modules/resources/card.e | 96 + .../E_v3.3a/Src/Src/Modules/resources/cia.e | 7 + .../E_v3.3a/Src/Src/Modules/resources/disk.e | 57 + .../Src/Src/Modules/resources/filesysres.e | 32 + .../Src/Src/Modules/resources/mathresource.e | 24 + .../E_v3.3a/Src/Src/Modules/resources/misc.e | 13 + .../E_v3.3a/Src/Src/Modules/resources/potgo.e | 8 + .../E_v3.3a/Src/Src/Modules/rexx/errors.e | 55 + .../E_v3.3a/Src/Src/Modules/rexx/rexxio.e | 52 + .../E_v3.3a/Src/Src/Modules/rexx/rxslib.e | 85 + .../E_v3.3a/Src/Src/Modules/rexx/storage.e | 160 ++ .../E_v3.3a/Src/Src/Modules/utility/date.e | 13 + .../E_v3.3a/Src/Src/Modules/utility/hooks.e | 12 + .../E_v3.3a/Src/Src/Modules/utility/name.e | 18 + .../E_v3.3a/Src/Src/Modules/utility/pack.e | 23 + .../E_v3.3a/Src/Src/Modules/utility/tagitem.e | 18 + .../E_v3.3a/Src/Src/Modules/utility/utility.e | 15 + .../Src/Src/Modules/workbench/startup.e | 21 + .../Src/Src/Modules/workbench/workbench.e | 102 + .../E_v3.3a/Src/Src/OOmodules/Coordinate/er.e | 72 + .../Src/Src/OOmodules/Coordinate/line.e | 100 + .../Src/Src/OOmodules/Coordinate/polyline.e | 34 + .../Src/OOmodules/Coordinate/polylinewin.e | 94 + amigae33a/E_v3.3a/Src/Src/OOmodules/README | 15 + .../E_v3.3a/Src/Src/OOmodules/application.e | 66 + .../E_v3.3a/Src/Src/OOmodules/commodity.e | 466 ++++ .../E_v3.3a/Src/Src/OOmodules/coordinate.e | 734 ++++++ amigae33a/E_v3.3a/Src/Src/OOmodules/library.e | 183 ++ .../Src/Src/OOmodules/library/Examples | 39 + .../Src/Src/OOmodules/library/anylibrary.e | 142 ++ .../E_v3.3a/Src/Src/OOmodules/library/asl.e | 309 +++ .../Src/OOmodules/library/asl/simpletest.e | 17 + .../Src/Src/OOmodules/library/commodities.e | 164 ++ .../Src/Src/OOmodules/library/device.e | 351 +++ .../Src/OOmodules/library/device/keyboard.e | 48 + .../Src/OOmodules/library/device/printer.e | 238 ++ .../OOmodules/library/device/printer/test.e | 11 + .../OOmodules/library/device/printer/test2.e | 44 + .../Src/OOmodules/library/device/trackdisk.e | 117 + .../OOmodules/library/device/trackdisk/test.e | 23 + .../E_v3.3a/Src/Src/OOmodules/library/exec.e | 14 + .../Src/Src/OOmodules/library/exec/Examples | 8 + .../Src/Src/OOmodules/library/exec/port.e | 433 ++++ .../Src/OOmodules/library/exec/port/Examples | 24 + .../library/exec/port/arexxPort/test.e | 31 + .../OOmodules/library/exec/port/arexxport.e | 168 ++ .../library/exec/port/portList/test.e | 309 +++ .../OOmodules/library/exec/port/portlist.e | 196 ++ .../Src/Src/OOmodules/library/gadtools.e | 94 + .../Src/Src/OOmodules/library/locale.e | 392 ++++ .../Src/Src/OOmodules/library/locale/Examples | 19 + .../OOmodules/library/locale/catalogList.e | 375 +++ .../library/locale/catalogList/Examples | 26 + .../library/locale/catalogList/test.e | 72 + .../OOmodules/library/locale/cataloglist.m | Bin 0 -> 2222 bytes .../Src/Src/OOmodules/library/locale/test.e | 37 + .../library/locale/testObjectString.e | 86 + .../Src/Src/OOmodules/library/reqtools.e | 274 +++ .../Src/Src/OOmodules/library/reqtools/test.e | 28 + .../Src/Src/OOmodules/library/reqtools_test.e | 33 + .../E_v3.3a/Src/Src/OOmodules/list/Examples | 12 + .../Src/Src/OOmodules/list/associativeArray.e | 566 +++++ .../OOmodules/list/associativeArray/Examples | 21 + .../Src/OOmodules/list/associativeArray/ar.e | 147 ++ .../Src/OOmodules/list/associativeArray/ar2.e | 163 ++ .../associativeArray/associativeStringArray.e | 10 + .../associativeArray/associativestringarray.m | Bin 0 -> 662 bytes .../list/associativeArray/listTest.e | 149 ++ .../Src/Src/OOmodules/list/doublylinked.e | 666 ++++++ .../Src/OOmodules/list/doublylinked/Examples | 16 + .../OOmodules/list/doublylinked/stringlist.e | 214 ++ .../list/doublylinked/stringlist/Examples | 18 + .../list/doublylinked/stringlist/test.e | 61 + .../list/doublylinked/stringlist/testExec.e | 46 + .../Src/OOmodules/list/doublylinked/test.e | 87 + .../E_v3.3a/Src/Src/OOmodules/list/elist.e | 513 +++++ .../Src/Src/OOmodules/list/elist/examples | 48 + .../Src/Src/OOmodules/list/elist/test.e | 116 + .../E_v3.3a/Src/Src/OOmodules/list/execlist.e | 176 ++ .../Src/Src/OOmodules/list/execlist/Examples | 35 + .../Src/Src/OOmodules/list/execlist/test.e | 64 + .../Src/Src/OOmodules/list/queuestack.e | 381 ++++ amigae33a/E_v3.3a/Src/Src/OOmodules/object.e | 491 ++++ .../Src/Src/OOmodules/oodoc/authors/gg.guide | 71 + .../Src/OOmodules/oodoc/authors/jevr.guide | 202 ++ .../Src/Src/OOmodules/oodoc/guides/Examples | 104 + .../Src/Src/OOmodules/oodoc/guides/OOEproject | 351 +++ .../E_v3.3a/Src/Src/OOmodules/oodoc/misc/todo | 111 + .../Src/OOmodules/oodoc/scripts/ADoc2AG.sh | 42 + .../Src/OOmodules/oodoc/scripts/getADoc.sh | 34 + .../Src/Src/OOmodules/oodoc/scripts/readme | 23 + .../Src/OOmodules/oodoc/templates/Examples | 25 + .../OOmodules/oodoc/templates/new_object.e | 256 +++ amigae33a/E_v3.3a/Src/Src/OOmodules/sort.e | 358 +++ .../E_v3.3a/Src/Src/OOmodules/sort/Examples | 12 + .../E_v3.3a/Src/Src/OOmodules/sort/address.e | 157 ++ .../E_v3.3a/Src/Src/OOmodules/sort/numbers.e | 31 + .../Src/Src/OOmodules/sort/numbers/Examples | 7 + .../Src/Src/OOmodules/sort/numbers/float.e | 103 + .../Src/OOmodules/sort/numbers/floattest.e | 30 + .../Src/Src/OOmodules/sort/numbers/fractest.e | 72 + .../Src/Src/OOmodules/sort/numbers/fraction.e | 242 ++ .../Src/Src/OOmodules/sort/numbers/integer.e | 80 + .../Src/OOmodules/sort/numbers/twoNumbers.e | 26 + .../E_v3.3a/Src/Src/OOmodules/sort/string.e | 853 +++++++ .../Src/Src/OOmodules/sort/string/Examples | 15 + .../Src/Src/OOmodules/sort/string/rawstring.e | 12 + .../Src/Src/OOmodules/sort/string/test.e | 19 + .../E_v3.3a/Src/Src/OOmodules/sort/test.e | 47 + amigae33a/E_v3.3a/Src/Src/Pd/ARexxPort.e | 367 +++ .../Src/Src/Pd/E-Empty/empty-handler.e | 172 ++ .../Src/Src/Pd/E-Empty/empty.mountlist | 5 + amigae33a/E_v3.3a/Src/Src/Pd/FD2Module.e | 204 ++ amigae33a/E_v3.3a/Src/Src/Pd/IFF/README | 13 + amigae33a/E_v3.3a/Src/Src/Pd/IFF/ReadIFF.e | 139 ++ amigae33a/E_v3.3a/Src/Src/Pd/IFF/ScanIFF.e | 149 ++ amigae33a/E_v3.3a/Src/Src/Pd/IFF/readclip.e | 166 ++ amigae33a/E_v3.3a/Src/Src/Pd/MakeKickFile.e | 109 + amigae33a/E_v3.3a/Src/Src/Pd/PubScreenNames.e | 164 ++ amigae33a/E_v3.3a/Src/Src/Pd/Pyth2.e | 213 ++ amigae33a/E_v3.3a/Src/Src/Pd/Talk.e | 150 ++ amigae33a/E_v3.3a/Src/Src/Pd/agacc.e | 71 + amigae33a/E_v3.3a/Src/Src/Pd/brush2image.e | 131 ++ amigae33a/E_v3.3a/Src/Src/Pd/findf.e | 244 ++ amigae33a/E_v3.3a/Src/Src/Pd/floodwindow.e | 80 + amigae33a/E_v3.3a/Src/Src/Pd/gtlv.e | 233 ++ amigae33a/E_v3.3a/Src/Src/Pd/ham8demo.e | 76 + amigae33a/E_v3.3a/Src/Src/Pd/mweg.e | 256 +++ .../E_v3.3a/Src/Src/Pd/oomodules/device.e | 136 ++ .../E_v3.3a/Src/Src/Pd/oomodules/library.e | 21 + .../Src/Src/Pd/oomodules/objects.build | 23 + .../E_v3.3a/Src/Src/Pd/oomodules/printer.e | 159 ++ .../Src/Src/Pd/oomodules/printer_test.e | 40 + .../E_v3.3a/Src/Src/Pd/oomodules/reqtools.e | 69 + .../Src/Src/Pd/oomodules/reqtools_test.e | 26 + amigae33a/E_v3.3a/Src/Src/Pd/queens.e | 80 + amigae33a/E_v3.3a/Src/Src/Pd/readclip.e | 166 ++ amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/ReadMe | 247 ++ .../Src/Src/Pd/rexxHostC/big/big_host.e | 144 ++ .../Src/Src/Pd/rexxHostC/big/big_host.info | Bin 0 -> 626 bytes .../Src/Src/Pd/rexxHostC/big/big_host.rexx | 20 + .../Src/Src/Pd/rexxHostC/mini/mini_host.e | 14 + .../Src/Src/Pd/rexxHostC/mini/mini_host.info | Bin 0 -> 626 bytes .../Src/Src/Pd/rexxHostC/mini/mini_host.rexx | 5 + .../E_v3.3a/Src/Src/Pd/rexxHostC/rexxhostc.m | Bin 0 -> 4126 bytes amigae33a/E_v3.3a/Src/Src/Pd/scroll.e | 101 + amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.e | 107 + amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.readme | 18 + amigae33a/E_v3.3a/Src/Src/Pd/showiff.e | 71 + amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread.e | 44 + .../E_v3.3a/Src/Src/Pd/threads/Thread2.e | 93 + .../Src/Src/Pd/threads/modules/geta4.e | 17 + .../Src/Src/Pd/threads/modules/geta4.m | Bin 0 -> 122 bytes .../E_v3.3a/Src/Src/Pd/threads/thread.doc | 52 + amigae33a/E_v3.3a/Src/Src/README | 23 + amigae33a/E_v3.3a/Src/Src/Reqs/AslDemo.e | 25 + amigae33a/E_v3.3a/Src/Src/Reqs/Ereq.e | 12 + amigae33a/E_v3.3a/Src/Src/Reqs/GadToolsDemo.e | 100 + amigae33a/E_v3.3a/Src/Src/Reqs/ReqDemo.e | 20 + amigae33a/E_v3.3a/Src/Src/Reqs/ReqToolsDemo.e | 35 + amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filehook.e | 98 + amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filepat.e | 82 + amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filereq.e | 47 + amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/fontreq.e | 61 + .../E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.e | 309 +++ .../E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.m | Bin 0 -> 2948 bytes .../Src/Src/Rkrm/Clipboard/changehook_test.e | 101 + .../E_v3.3a/Src/Src/Rkrm/Clipboard/clipdemo.e | 218 ++ .../E_v3.3a/Src/Src/Rkrm/Commodities/HotKey.e | 163 ++ .../Src/Src/Rkrm/Commodities/PopShell.e | 153 ++ .../E_v3.3a/Src/Src/Rkrm/Commodities/broker.e | 113 + .../E_v3.3a/Src/Src/Rkrm/Commodities/divert.e | 163 ++ .../E_v3.3a/Src/Src/Rkrm/Console/AskKeymap.e | 65 + .../E_v3.3a/Src/Src/Rkrm/Console/Console.e | 230 ++ .../E_v3.3a/Src/Src/Rkrm/Console/console | Bin 0 -> 4052 bytes .../Rkrm/Exec_Library/DeviceIO/deviceuse.e | 85 + .../Src/Rkrm/Exec_Library/Interrupts/rbf.e | 140 ++ .../Exec_Library/Interrupts/timersoftint.e | 124 + .../Src/Rkrm/Exec_Library/Interrupts/vertb.e | 64 + .../Src/Rkrm/Exec_Library/Lists/buildlist.e | 95 + .../Src/Rkrm/Exec_Library/Memory/allocate.e | 40 + .../Src/Rkrm/Exec_Library/Memory/allocentry.e | 43 + .../Src/Src/Rkrm/Exec_Library/Ports/port1.e | 51 + .../Src/Src/Rkrm/Exec_Library/Ports/port2.e | 69 + .../Rkrm/Exec_Library/Semaphores/semaphore.e | 13 + .../Src/Rkrm/Exec_Library/Signals/signals.e | 71 + .../Src/Rkrm/Exec_Library/Tasks/simpletask.e | 56 + .../Src/Rkrm/Exec_Library/Tasks/tasklist.e | 102 + .../Src/Src/Rkrm/Exec_Library/Tasks/trap.e | 43 + .../Src/Src/Rkrm/Expansion/findboards.e | 80 + .../Src/Src/Rkrm/GadTools/gadtoolsgadgets.e | 273 +++ .../Src/Src/Rkrm/GadTools/gadtoolsmenu.e | 98 + .../Src/Src/Rkrm/GadTools/simplegtgadget.e | 103 + .../Src/Src/Rkrm/Gameport/Absolute_Joystick.e | 291 +++ .../Rkrm/Graphics_Libraries/Layers/clipping.e | 137 ++ .../Rkrm/Graphics_Libraries/Layers/layers.e | 371 +++ .../Graphics_Libraries/Primitives/RGBBoxes.e | 199 ++ .../Graphics_Libraries/Primitives/WBClone.e | 294 +++ .../Primitives/genlockdemo.e | 403 ++++ .../Primitives/usercopperexample.e | 135 ++ .../Sprites_Bobs/animtools.e | 356 +++ .../Sprites_Bobs/animtools.m | Bin 0 -> 4640 bytes .../Graphics_Libraries/Sprites_Bobs/bob.e | 124 + .../Graphics_Libraries/Sprites_Bobs/collide.e | 514 +++++ .../Graphics_Libraries/Sprites_Bobs/ssprite.e | 103 + .../Graphics_Libraries/Sprites_Bobs/vsprite.e | 155 ++ .../Graphics_Libraries/Text/MeasureText.e | 190 ++ .../Rkrm/Graphics_Libraries/Text/availfonts.e | 272 +++ .../Rkrm/Graphics_Libraries/Text/cliptext.e | 261 +++ .../E_v3.3a/Src/Src/Rkrm/IFFParse/clipftxt.e | 166 ++ .../E_v3.3a/Src/Src/Rkrm/IFFParse/sift.e | 157 ++ .../Src/Rkrm/Intuition/Boopsi/rkmbutclass.e | 345 +++ .../Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.e | 143 ++ .../Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.m | Bin 0 -> 1514 bytes .../Src/Rkrm/Intuition/Boopsi/talk2boopsi.e | 107 + .../Src/Rkrm/Intuition/Boopsi/userkmmodel.e | 182 ++ .../Src/Rkrm/Intuition/Gadgets/simplegad.e | 70 + .../Src/Src/Rkrm/Intuition/Gadgets/strhooks.e | 188 ++ .../Src/Rkrm/Intuition/Gadgets/updatestrgad.e | 119 + .../Intuition/IO_Methods/closewindowsafely.e | 58 + .../Intuition/IO_Methods/closewindowsafely.m | Bin 0 -> 258 bytes .../Src/Rkrm/Intuition/IO_Methods/eventloop.e | 130 ++ .../Rkrm/Intuition/Images_Text/compleximage.e | 83 + .../Rkrm/Intuition/Images_Text/intuitext.e | 64 + .../Rkrm/Intuition/Images_Text/shadowborder.e | 66 + .../Rkrm/Intuition/Images_Text/simpleimage.e | 62 + .../Intuition/Intuition_GUI/easyintuition.e | 110 + .../Intuition/Intuition_GUI/easyintuition37.e | 103 + .../Src/Src/Rkrm/Intuition/Menus/menulayout.e | 460 ++++ .../Src/Src/Rkrm/Intuition/Menus/simplemenu.e | 139 ++ .../Intuition/Mouse_Keyboard/custompointer.e | 66 + .../Rkrm/Intuition/Mouse_Keyboard/mousetest.e | 174 ++ .../Rkrm/Intuition/Mouse_Keyboard/rawkey.e | 149 ++ .../Intuition/Requesters_Alerts/blockinput.e | 111 + .../Requesters_Alerts/displayalert.e | 26 + .../Intuition/Requesters_Alerts/easyrequest.e | 41 + .../Src/Rkrm/Intuition/Screens/clonescreen.e | 120 + .../Src/Rkrm/Intuition/Screens/doublebuffer.e | 144 ++ .../Rkrm/Intuition/Screens/dualplayfield.e | 157 ++ .../Rkrm/Intuition/Screens/newlookscreen.e | 47 + .../Src/Rkrm/Intuition/Screens/publicscreen.e | 70 + .../Rkrm/Intuition/Screens/pubscreenbeep.e | 28 + .../Src/Rkrm/Intuition/Screens/screen34to37.e | 57 + .../Src/Rkrm/Intuition/Special/remembertest.e | 85 + .../Src/Src/Rkrm/Intuition/Windows/lines.e | 294 +++ .../Rkrm/Intuition/Windows/openwindowtags.e | 44 + .../Rkrm/Intuition/Windows/visiblewindow.e | 114 + .../Src/Rkrm/Intuition/Windows/winpubscreen.e | 57 + .../E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.e | 155 ++ .../E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.m | Bin 0 -> 2128 bytes .../E_v3.3a/Src/Src/Rkrm/Keymap/mapansi.e | 99 + .../E_v3.3a/Src/Src/Rkrm/Keymap/maprawkey.e | 97 + amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dpieee.e | 29 + amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dptrans.e | 31 + amigae33a/E_v3.3a/Src/Src/Rkrm/Math/spieee.e | 32 + amigae33a/E_v3.3a/Src/Src/Rkrm/Math/sptrans.e | 30 + .../Src/Src/Rkrm/Preferences/prefnotify.e | 57 + .../Src/Src/Rkrm/Preferences/showprefs.e | 137 ++ amigae33a/E_v3.3a/Src/Src/Rkrm/README | 41 + .../Src/Src/Rkrm/Resources/Allocate_Misc.e | 47 + .../Src/Src/Rkrm/Resources/CIA_interval.e | 271 +++ .../Src/Src/Rkrm/Resources/Get_Disk_Unit_ID.e | 26 + .../Src/Src/Rkrm/Resources/Get_Filesys.e | 38 + .../Src/Src/Rkrm/Resources/Query_Serial.e | 60 + .../Src/Src/Rkrm/Resources/Read_BattClock.e | 63 + .../Src/Src/Rkrm/Resources/Read_Potinp.e | 65 + amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/a2d.e | 55 + .../E_v3.3a/Src/Src/Rkrm/Utility/hooks1.e | 39 + amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/istr.e | 39 + amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/tag1.e | 74 + .../E_v3.3a/Src/Src/Rkrm/Utility/uptime.e | 54 + .../E_v3.3a/Src/Src/Rkrm/Workbench/appicon.e | 80 + .../Src/Src/Rkrm/Workbench/appmenuitem.e | 69 + .../Src/Src/Rkrm/Workbench/appwindow.e | 76 + .../Src/Src/Rkrm/Workbench/iconexample.e | 185 ++ .../E_v3.3a/Src/Src/Rkrm/Workbench/prargs.e | 55 + .../Src/Src/Tools/AmigaLib/AmigaLib.doc | 115 + .../E_v3.3a/Src/Src/Tools/AmigaLib/argarray.e | 46 + .../E_v3.3a/Src/Src/Tools/AmigaLib/boopsi.e | 41 + amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/cx.e | 116 + .../Src/Src/Tools/AmigaLib/interrupts.e | 28 + amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/io.e | 42 + .../E_v3.3a/Src/Src/Tools/AmigaLib/lists.e | 9 + .../E_v3.3a/Src/Src/Tools/AmigaLib/ports.e | 37 + .../E_v3.3a/Src/Src/Tools/AmigaLib/random.e | 23 + .../E_v3.3a/Src/Src/Tools/AmigaLib/tasks.e | 46 + .../Src/Src/Tools/AmigaLib/testargarray.e | 23 + .../E_v3.3a/Src/Src/Tools/AmigaLib/testcx.e | 94 + .../Src/Src/Tools/AmigaLib/testinterrupts.e | 20 + .../Src/Src/Tools/AmigaLib/testinterrupts2.e | 33 + .../E_v3.3a/Src/Src/Tools/AmigaLib/testtime.e | 8 + .../E_v3.3a/Src/Src/Tools/AmigaLib/time.e | 24 + .../E_v3.3a/Src/Src/Tools/Arexx/arexx.doc | 63 + amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.e | 73 + .../E_v3.3a/Src/Src/Tools/Arexx/arexxtest.e | 11 + .../Src/Src/Tools/Arexx/arexxtest.rexx | 14 + .../E_v3.3a/Src/Src/Tools/Async/async.guide | 346 +++ .../E_v3.3a/Src/Src/Tools/Async/histogram.e | 36 + .../E_v3.3a/Src/Src/Tools/Async/playsamp.e | 152 ++ amigae33a/E_v3.3a/Src/Src/Tools/Async/typef.e | 26 + .../E_v3.3a/Src/Src/Tools/Boopsi/Boopsi.e | 21 + .../Src/Src/Tools/CloneScreen/clonescreen.e | 76 + .../Src/Src/Tools/CloneScreen/testclone.e | 21 + .../Src/Tools/Constructors/constructors.doc | 18 + .../Src/Src/Tools/Constructors/constructors.e | 22 + .../Src/Tools/Constructors/constructorstest.e | 11 + .../Src/Src/Tools/CookRawKey/cookRawkey.doc | 36 + .../Src/Src/Tools/CookRawKey/cookRawkey.e | 69 + .../Src/Src/Tools/CookRawKey/cookRawkeyTest.e | 124 + amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctest.e | 5 + .../E_v3.3a/Src/Src/Tools/Ctype/ctype.doc | 16 + .../Src/Src/Tools/EasyGUI/Classes/GI1.License | 56 + .../Src/Src/Tools/EasyGUI/Classes/GI1.Readme | 12 + .../EasyGUI/Classes/Gadgets/button.gadget | Bin 0 -> 4868 bytes .../EasyGUI/Classes/Gadgets/calendar.gadget | Bin 0 -> 6100 bytes .../Tools/EasyGUI/Classes/Gadgets/tabs.gadget | Bin 0 -> 6008 bytes .../EasyGUI/Classes/Gadgets/tapedeck.gadget | Bin 0 -> 5404 bytes .../Tools/EasyGUI/Classes/Images/led.image | Bin 0 -> 2920 bytes .../Src/Src/Tools/EasyGUI/Docs/EasyGUI.doc | 1322 +++++++++++ .../Src/Tools/EasyGUI/Docs/animcontrol.doc | 61 + .../Src/Src/Tools/EasyGUI/Docs/button.doc | 68 + .../Src/Src/Tools/EasyGUI/Docs/calendar.doc | 51 + .../Src/Src/Tools/EasyGUI/Docs/colorwheel.doc | 62 + .../Src/Src/Tools/EasyGUI/Docs/gradient.doc | 51 + .../Src/Tools/EasyGUI/Docs/imagebutton.doc | 81 + .../Src/Src/Tools/EasyGUI/Docs/led.doc | 50 + .../Src/Src/Tools/EasyGUI/Docs/password.doc | 48 + .../Src/Src/Tools/EasyGUI/Docs/tabs.doc | 47 + .../Src/Src/Tools/EasyGUI/Docs/tapedeck.doc | 52 + .../Src/Src/Tools/EasyGUI/Docs/ticker.doc | 23 + .../Src/Src/Tools/EasyGUI/Examples/all.e | 379 ++++ .../Tools/EasyGUI/Examples/animcontrol_test.e | 32 + .../Src/Tools/EasyGUI/Examples/button_test.e | 42 + .../Tools/EasyGUI/Examples/calendar_test.e | 38 + .../Tools/EasyGUI/Examples/colorwheel_test.e | 62 + .../Tools/EasyGUI/Examples/gradient_test.e | 40 + .../Src/Tools/EasyGUI/Examples/iconify_test.e | 33 + .../Tools/EasyGUI/Examples/imagebutton_test.e | 128 ++ .../Src/Src/Tools/EasyGUI/Examples/led_test.e | 55 + .../Src/Tools/EasyGUI/Examples/led_test2.e | 149 ++ .../Src/Tools/EasyGUI/Examples/led_test3.e | 171 ++ .../Src/Tools/EasyGUI/Examples/led_test4.e | 127 ++ .../Tools/EasyGUI/Examples/password_test.e | 41 + .../Src/Tools/EasyGUI/Examples/tabs_test.e | 36 + .../Src/Tools/EasyGUI/Examples/tabs_test2.e | 28 + .../Tools/EasyGUI/Examples/tapedeck_test.e | 32 + .../Src/Src/Tools/EasyGUI/Examples/testaw.e | 59 + .../Src/Tools/EasyGUI/Examples/testchange.e | 32 + .../Src/Tools/EasyGUI/Examples/testchange2.e | 277 +++ .../Src/Src/Tools/EasyGUI/Examples/testkey.e | 83 + .../Src/Tools/EasyGUI/Examples/testmulti.e | 59 + .../Src/Tools/EasyGUI/Examples/testmulti2.e | 44 + .../Src/Src/Tools/EasyGUI/Examples/testqual.e | 14 + .../Src/Tools/EasyGUI/Examples/ticker_test.e | 19 + .../Src/Tools/EasyGUI/Examples/toolify_test.e | 23 + .../Src/Tools/EasyGUI/Plugins/animcontrol.e | 100 + .../Src/Src/Tools/EasyGUI/Plugins/button.e | 92 + .../Src/Src/Tools/EasyGUI/Plugins/calendar.e | 68 + .../Src/Tools/EasyGUI/Plugins/colorwheel.e | 114 + .../Src/Src/Tools/EasyGUI/Plugins/gradient.e | 86 + .../Src/Src/Tools/EasyGUI/Plugins/iconify.e | 94 + .../Src/Tools/EasyGUI/Plugins/imagebutton.e | 101 + .../Src/Src/Tools/EasyGUI/Plugins/led.e | 52 + .../Src/Src/Tools/EasyGUI/Plugins/password.e | 132 ++ .../Src/Src/Tools/EasyGUI/Plugins/tabs.e | 89 + .../Src/Src/Tools/EasyGUI/Plugins/tapedeck.e | 87 + .../Src/Src/Tools/EasyGUI/Plugins/ticker.e | 18 + .../Src/Src/Tools/EasyGUI/Plugins/toolify.e | 75 + .../E_v3.3a/Src/Src/Tools/EasyGUI/README | 83 + .../Src/Src/Tools/EasyGUI/Source/EasyGUI.e | 2008 +++++++++++++++++ .../Src/Tools/EasyGUI/Source/README_IMPORTANT | 26 + .../Src/Tools/EasyGUI/Tools/EasyGUI_notag.e | 29 + .../Src/Src/Tools/EasyGUI/Tools/copylist.e | 11 + .../Src/Tools/EasyGUI/Tools/easygui_notag.m | Bin 0 -> 712 bytes .../Src/Src/Tools/EasyGUI/Tools/ghost.doc | 25 + .../Src/Src/Tools/EasyGUI/Tools/ghost.e | 32 + .../Src/Src/Tools/EasyGUI/Tools/textlen.e | 16 + .../Src/Src/Tools/Exceptions/exceptions.e | 26 + .../Src/Src/Tools/Exceptions/exceptionstest.e | 18 + amigae33a/E_v3.3a/Src/Src/Tools/File/file.doc | 35 + amigae33a/E_v3.3a/Src/Src/Tools/File/file.e | 71 + .../E_v3.3a/Src/Src/Tools/File/filetest.e | 13 + .../Src/Tools/FilledVector/FilledVector.guide | 1084 +++++++++ .../Src/Tools/FilledVector/ObjectDesign.guide | 524 +++++ .../Src/Tools/FilledVector/examples/cube.e | 69 + .../Src/Tools/FilledVector/examples/cube39.e | 67 + .../Src/Tools/FilledVector/examples/torus.e | 373 +++ .../Src/Tools/FilledVector/examples/wb1200.e | 444 ++++ .../Src/Src/Tools/FilledVector/examples/zed.e | 267 +++ .../Src/Src/Tools/FilledVector/filledvdefs.e | 80 + .../Src/Src/Tools/FilledVector/readnff | Bin 0 -> 2700 bytes .../E_v3.3a/Src/Src/Tools/Hook/hooktest.e | 16 + .../E_v3.3a/Src/Src/Tools/Hook/installhook.e | 22 + .../E_v3.3a/Src/Src/Tools/ILBM/ilbm.guide | 335 +++ .../E_v3.3a/Src/Src/Tools/ILBM/picwindow.e | 92 + .../E_v3.3a/Src/Src/Tools/ILBM/showpic.e | 70 + .../E_v3.3a/Src/Src/Tools/InitHook/inithook.e | 26 + .../Src/Src/Tools/Iterators/iterators_test.e | 21 + .../E_v3.3a/Src/Src/Tools/Lex/simplelex.doc | 47 + .../E_v3.3a/Src/Src/Tools/Lex/simplelex.e | 65 + .../E_v3.3a/Src/Src/Tools/Lex/simplelextest.e | 73 + .../E_v3.3a/Src/Src/Tools/Lex/testinput.lists | 16 + amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisp.e | 133 ++ .../E_v3.3a/Src/Src/Tools/Lisp/lisptest.e | 33 + .../E_v3.3a/Src/Src/Tools/LongReal/longdemo.e | 85 + .../Src/Src/Tools/LongReal/longreal.doc | 99 + .../E_v3.3a/Src/Src/Tools/LongReal/longreal.e | 519 +++++ .../Src/Src/Tools/LongReal/longrealtest.e | 26 + .../Src/Src/Tools/LongReal/longrealtiny.e | 143 ++ .../E_v3.3a/Src/Src/Tools/Macros/macros.e | 24 + amigae33a/E_v3.3a/Src/Src/Tools/Pt/Player.e | 16 + amigae33a/E_v3.3a/Src/Src/Tools/README | 3 + .../Src/Src/Tools/ScrBuffer/ScrBuffer.guide | 226 ++ .../E_v3.3a/Src/Src/Tools/ScrBuffer/thebox.e | 75 + .../E_v3.3a/Src/Src/Tools/TrapGuru/gurutest.e | 20 + .../E_v3.3a/Src/Src/Tools/TrapGuru/trapguru.e | 45 + .../E_v3.3a/Src/Src/Tools/Useful/UsefulV2.doc | 150 ++ .../E_v3.3a/Src/Src/Tools/Useful/battclock.e | 19 + .../E_v3.3a/Src/Src/Tools/Useful/battmem.e | 29 + .../E_v3.3a/Src/Src/Tools/Useful/bitfield.e | 18 + amigae33a/E_v3.3a/Src/Src/Tools/Useful/cia.e | 27 + amigae33a/E_v3.3a/Src/Src/Tools/Useful/disk.e | 38 + .../E_v3.3a/Src/Src/Tools/Useful/ecode.e | 207 ++ amigae33a/E_v3.3a/Src/Src/Tools/Useful/misc.e | 16 + .../E_v3.3a/Src/Src/Tools/Useful/potgo.e | 22 + .../Src/Src/Tools/Useful/sendexplorer.e | 16 + .../E_v3.3a/Src/Src/Tools/Useful/sendrexx.e | 46 + .../Src/Src/Tools/Useful/setprogname.e | 16 + .../E_v3.3a/Src/Src/Tools/Useful/split.e | 62 + .../E_v3.3a/Src/Src/Tools/Vector/Vector.e | 173 ++ .../E_v3.3a/Src/Src/Tools/Vector/vectest1.e | 16 + .../E_v3.3a/Src/Src/Tools/Vector/vectest2.e | 46 + .../E_v3.3a/Src/Src/Tools/Vector/vectest3.e | 44 + .../E_v3.3a/Src/Src/Tools/Vector/vectest4.e | 92 + .../E_v3.3a/Src/Src/Tools/qItemAddress/README | 18 + .../Tools/qItemAddress/qualifiedItemAddress.e | 96 + .../E_v3.3a/Src/Src/Tools/qItemAddress/test.e | 168 ++ .../E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt.c | 367 +++ .../Src/Src/Utils/Ag2Txt/Ag2Txt_OS1.3.e | 313 +++ .../Src/Src/Utils/Ag2Txt/Ag2Txt_OS2.0.e | 306 +++ .../Src/Src/Utils/Ag2Txt/Ag2Txt_v2.readme | 40 + .../Src/Src/Utils/AgSplit/AGSplit.readme | 80 + .../Src/Utils/AgSplit/AGSplit_EBeginnersGuide | 36 + .../Src/Src/Utils/AgSplit/AGSplit_EGuide | 28 + .../Src/Src/Utils/Build/.build example 1 | 12 + .../Src/Src/Utils/Build/.build example 2 | 8 + .../Src/Src/Utils/Build/.build example 3 | 108 + .../E_v3.3a/Src/Src/Utils/Build/EBuild.guide | 290 +++ amigae33a/E_v3.3a/Src/Src/Utils/Build/build.e | 437 ++++ amigae33a/E_v3.3a/Src/Src/Utils/D.e | 297 +++ amigae33a/E_v3.3a/Src/Src/Utils/DirQuick.e | 26 + .../Src/Src/Utils/EDBG/README_IMPORTANT | 28 + amigae33a/E_v3.3a/Src/Src/Utils/EDBG/edbg.e | 1424 ++++++++++++ amigae33a/E_v3.3a/Src/Src/Utils/EDBG/eexe.e | 498 ++++ .../E_v3.3a/Src/Src/Utils/EDBG/pix/about.iff2 | Bin 0 -> 4500 bytes .../E_v3.3a/Src/Src/Utils/EDBG/pix/about.raw | Bin 0 -> 7872 bytes .../Src/Src/Utils/EDBG/pix/toolbar.iff | Bin 0 -> 2540 bytes .../Src/Src/Utils/EDBG/pix/toolbar.raw | Bin 0 -> 2424 bytes amigae33a/E_v3.3a/Src/Src/Utils/EDBG/schex.e | 55 + amigae33a/E_v3.3a/Src/Src/Utils/EDBG/screg.e | 59 + amigae33a/E_v3.3a/Src/Src/Utils/EDBG/sctext.e | 107 + .../E_v3.3a/Src/Src/Utils/FindString13.e | 360 +++ amigae33a/E_v3.3a/Src/Src/Utils/GDU.e | 234 ++ amigae33a/E_v3.3a/Src/Src/Utils/Mem.e | 29 + amigae33a/E_v3.3a/Src/Src/Utils/Nkript.e | 71 + amigae33a/E_v3.3a/Src/Src/Utils/ShowHunk.e | 862 +++++++ amigae33a/E_v3.3a/Src/Src/Utils/Watch.e | 48 + .../E_v3.3a/Src/Src/Various/2ndMousePort.e | 28 + amigae33a/E_v3.3a/Src/Src/Various/Pi.e | 79 + amigae33a/E_v3.3a/Src/Src/Various/Race.e | 301 +++ amigae33a/E_v3.3a/Src/Src/Various/SrcGen.e | 439 ++++ amigae33a/E_v3.3a/Src/Src/Various/Trees.e | 43 + amigae33a/E_v3.3a/Src/Src/Various/breukfind.e | 35 + .../Src/Src/Various/dokkenou/dokkenou.dvi | Bin 0 -> 3436 bytes .../Src/Src/Various/dokkenou/dokkenou.e | 213 ++ .../Src/Src/Various/dokkenou/dokkenou.tex | 68 + .../Src/Src/Various/dokkenou/dokkenou.txt | 57 + amigae33a/E_v3.3a/Src/Src/Various/freq.e | 379 ++++ amigae33a/E_v3.3a/Src/Src/Various/huff.e | 112 + amigae33a/E_v3.3a/Src/Src/Various/prime.e | 4 + amigae33a/E_v3.3a/Src/Src/Various/radix.e | 108 + 1168 files changed, 84489 insertions(+) delete mode 100644 amigae33a/E_v3.3a/Modules.lha create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/BeBox.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/Bitmapper.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/DirList.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/Displayer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/IFFParser.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/Localer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/Mousepointer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/NodeMaster.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/Parser.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/ReqTooller.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/StringNode.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/ToolType.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/Worldbuilder.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/explain_exception.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/hardsprite.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/mgui.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/rexxer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/super_picture.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/tasker.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/afc/validPortName.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigaguide.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/Tasks.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/argarray.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/boopsi.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/cx.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/interrupts.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/io.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/lists.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/ports.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/random.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/amigalib/time.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/asl.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/bgui.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/bullet.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/class/hash.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/class/sc.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/class/sctext.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/class/stack.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/colorwheel.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/commodities.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/console.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/cybergraphics.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/datatypes.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/datatypes/animationclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/datatypes/datatypes.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/datatypes/datatypesclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/datatypes/pictureclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/datatypes/soundclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/datatypes/textclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/audio.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/bootblock.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/cd.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/clipboard.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/console.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/conunit.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/gameport.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/hardblocks.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/input.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/inputevent.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/keyboard.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/keymap.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/narrator.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/parallel.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/printer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/prtbase.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/prtgfx.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/scsidisk.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/serial.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/timer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/devices/trackdisk.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/diskfont.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/diskfont/diskfont.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/diskfont/diskfonttag.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/diskfont/glyph.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/diskfont/oterrors.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/datetime.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/dos.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/dos_lib.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/dosasl.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/dosextens.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/doshunks.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/dostags.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/exall.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/filehandler.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/notify.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/rdargs.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/record.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/stdio.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dos/var.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/dtclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/alerts.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/devices.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/errors.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/execbase.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/interrupts.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/io.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/libraries.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/lists.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/memory.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/nodes.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/ports.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/resident.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/semaphores.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/strings.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/tasks.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/exec/types.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/expansion.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gadgets/button.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gadgets/calendar.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gadgets/colorwheel.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gadgets/gradientslider.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gadgets/tabs.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gadgets/tapedeck.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gadtools.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/clip.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/coerce.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/collide.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/copper.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/display.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/displayinfo.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/gels.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/gfx.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/gfxbase.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/gfxmacros.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/gfxnodes.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/graphint.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/layers.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/modeid.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/monitor.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/rastport.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/regions.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/rpattr.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/scale.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/sprite.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/text.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/videocontrol.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/graphics/view.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/gtx.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/hardware/adkbits.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/hardware/blit.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/hardware/cia.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/hardware/custom.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/hardware/dmabits.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/hardware/intbits.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/icon.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/iff.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/iffparse.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/images/led.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/input.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/cghooks.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/classes.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/classusr.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/gadgetclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/icclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/imageclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/intuition.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/intuitionbase.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/iobsolete.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/pointerclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/preferences.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/screens.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/intuition/sghooks.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/keymap.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/layers.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/amigaguide.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/asl.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/bgui.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/bgui_macros.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/commodities.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/configregs.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/configvars.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/cybergraphics.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/diskfont.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/expansion.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/expansionbase.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/gadtools.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/iff.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/iffparse.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/locale.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/lowlevel.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/mathieeesp.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/mathlibrary.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/mathresource.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/midi.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/muibuilder.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/nofrag.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/nonvolatile.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/ppbase.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/realtime.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/reqbase.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/reqtools.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/translator.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/triton.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/triton_macros.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/vmem.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/libraries/wizard.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/locale.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/lowlevel.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/mathffp.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/mathieeedoubbas.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/mathieeedoubtrans.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/mathieeesingbas.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/mathieeesingtrans.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/mathtrans.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/midi.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/nofrag.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/nonvolatile.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/commodity.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate/line.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate/polyline.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/asl.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/commodities.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device/keyboard.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device/printer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device/trackdisk.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port/arexxport.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port/portlist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/gadtools.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/locale.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/locale/cataloglist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/library/reqtools.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/list/associativearray.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/list/associativearray/associativestringarray.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/list/doublylinked.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/list/elist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/list/execlist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/list/queuestack.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/list/stringlist/stringlist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/object.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/address.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/float.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/fraction.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/integer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/twonumbers.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/string.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/string/rawstring.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/battclock.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/battmem.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/bitfield.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/bits.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/cia.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/clearlist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/cloneworkbench.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/disk.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/dislib.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/dispose.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/disposeelinkedlist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/disposelink.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/dll.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/ecode.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/fastinsert.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/initlist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/isdigit.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/isidentifier.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/lowerchar.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/misc.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/mod.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/potgo.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/qualifieditemaddress.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/readstr.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/sendexplorer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/sendrexx.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/setprogname.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/skipnonwhite.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/skiptochar.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/skiptoedelim.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/skipwhite.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/split.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/stack.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/strcopy.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/other/upperchar.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/animcontrol.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/button.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/calendar.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/colorwheel.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/gradient.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/iconify.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/imagebutton.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/led.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/password.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/tabs.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/tapedeck.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/text_plug.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/ticker.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/plugins/toolify.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/pointer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/powerpacker.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/font.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/icontrol.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/input.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/locale.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/overscan.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/palette.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/pointer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/prefhdr.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/printergfx.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/printerps.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/printertxt.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/screenmode.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/serial.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/sound.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/prefs/wbpattern.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/ramdrive.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/realtime.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/req.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/reqtools.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/battclock.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/battmem.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/battmembitsamiga.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/battmembitsshared.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/card.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/cia.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/disk.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/filesysres.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/mathresource.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/misc.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/resources/potgo.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/rexx/errors.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/rexx/rexxio.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/rexx/rxslib.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/rexx/storage.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/rexxsyslib.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/timer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/Boopsi.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_debug.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_lite.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_notag.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/Vector.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/arexx.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/async.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/clonescreen.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/constructors.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/cookrawkey.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/copylist.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/ctype.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/exceptions.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/file.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/filledvdefs.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/filledvector.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/ghost.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/ilbm.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/ilbmdefs.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/inithook.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/installhook.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/iterators.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/lisp.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/longreal.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/longrealtiny.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/macros.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/muicustomclass.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/pt.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/scrbuffer.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/simplelex.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/stack.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/textlen.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/tools/trapguru.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/translator.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/triton.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/utility.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/utility/date.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/utility/hooks.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/utility/name.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/utility/pack.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/utility/tagitem.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/utility/utility.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/vector.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/vmem.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/wb.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/wizard.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/workbench/startup.m create mode 100644 amigae33a/E_v3.3a/Modules/Modules/workbench/workbench.m delete mode 100644 amigae33a/E_v3.3a/Src.lha create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/BeBox_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Change_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/AFC.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/Bitmapper.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/DirList.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/Displayer.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/Hardsprite.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/IffParser.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/Localer.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/Mousepointer.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/NodeMaster.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/ReqTooller.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/StringNode.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/Tasker.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/ToolType.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/Worldbuilder.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/bebox.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/explain_exception.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/mgui.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/parser.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/rexxer.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/super_picture.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Docs/validPortName.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/EasyGUI_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/First_Del_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Hardsprite_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Localer_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/MGUI_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Mousepointer_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Parser_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/PatternMatch_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Push_Pop_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/RamScan_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/ReqTooller_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Receiver.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Sender.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Search_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/SetAttrs_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Sort_Example.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/SuperPic_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/ToolType_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Args/GetArgs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Args/ReadArgs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Args/WbArg.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/BinTree/bintree create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/BinTree/bintree.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/Hash/hashtest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/sc.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/textview.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/Stack/stack.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Class/Stack/stackuse.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Dos/Shell.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Dos/date.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Dos/readtext.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Explorer/Explorer.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Explorer/empty-handler.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Explorer/empty.mountlist create mode 100644 amigae33a/E_v3.3a/Src/Src/Explorer/explorer.config create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/24bitColourDemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/TEXTUREMAP_ROAD.br.chunky create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/c2p4.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls_sculpt.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/rr.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/screenmodereq_db.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/ColourScreen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/IfsFern.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/IntMandel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Kohonen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Mandel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Mandel256.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/MandelCalc881.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/PPV.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/RewriteGfx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/c2p_cpu3blit1.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/car64x64x8.iff.cmchunky create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/geom.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/geom.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/screenmodereq_db.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/screenmodereq_db.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/texturemapper.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/texturemapper.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/tmaptest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/Trace.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/nice.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/paint.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/paint.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Gfx/sim_flock.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/address.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/args.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/args.info create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/args20.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/bintree.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/csv-buff.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/csv-estr.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/csv-norm.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/csv.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/datafile create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/dragon.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/except.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/except2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/float.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/gadgets.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/graphics.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/idcmp.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/screens.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/screens2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/set-use.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/set.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/simple.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/static.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/static2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/static3.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/timing.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/tree-use.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/tree.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Guide/while.e create mode 100644 amigae33a/E_v3.3a/Src/Src/HelloWorld.e create mode 100644 amigae33a/E_v3.3a/Src/Src/HelloWorld.e.info create mode 100644 amigae33a/E_v3.3a/Src/Src/Intui/AppMenuItem.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Intui/Public.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Intui/ScrollerWindow.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Intui/Talk2Boopsi.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Intui/gradient.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/EYacc/bcalc.y create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/EYacc/calcmain.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Elex.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Forth.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Lambda.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/NGRC.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Yax/QuickSort.yax create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Yax/Yax.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Yax/fac.yax create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Yax/pi.yax create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Yax/sincosdemo.yax create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Yax/xpaint.yax create mode 100644 amigae33a/E_v3.3a/Src/Src/Lang/Yax/yax.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Library/Pgs/gio.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Library/Pgs/noisy.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Library/Pgs/pgs.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Library/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Library/Stack/stack_pragmas.h create mode 100644 amigae33a/E_v3.3a/Src/Src/Library/Stack/stacklib.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Library/Stack/stackuse.c create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/datatypes/animationclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypes.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypesclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/datatypes/pictureclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/datatypes/soundclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/datatypes/textclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/audio.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/bootblock.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/cd.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/clipboard.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/console.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/conunit.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/gameport.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/hardblocks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/input.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/inputevent.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/keyboard.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/keymap.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/narrator.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/parallel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/printer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/prtbase.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/prtgfx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/scsidisk.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/serial.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/timer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/devices/trackdisk.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfont.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfonttag.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/diskfont/glyph.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/diskfont/oterrors.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/datetime.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/dos.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/dos_lib.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/dosasl.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/dosextens.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/doshunks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/dostags.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/exall.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/filehandler.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/notify.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/rdargs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/record.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/stdio.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/dos/var.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/alerts.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/devices.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/errors.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/execbase.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/interrupts.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/io.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/libraries.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/lists.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/memory.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/nodes.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/ports.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/resident.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/semaphores.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/strings.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/tasks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/exec/types.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/gadgets/button.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/gadgets/calendar.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/gadgets/colorwheel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/gadgets/gradientslider.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tabs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tapedeck.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/clip.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/coerce.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/collide.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/copper.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/display.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/displayinfo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/gels.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxbase.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxmacros.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxnodes.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/graphint.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/layers.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/modeid.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/monitor.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/rastport.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/regions.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/rpattr.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/scale.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/sprite.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/text.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/videocontrol.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/graphics/view.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/hardware/adkbits.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/hardware/blit.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/hardware/cia.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/hardware/custom.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/hardware/dmabits.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/hardware/intbits.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/images/led.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/cghooks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/classes.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/classusr.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/gadgetclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/icclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/imageclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuition.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuitionbase.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/iobsolete.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/pointerclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/preferences.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/screens.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/intuition/sghooks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/amigaguide.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/asl.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/commodities.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/configregs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/configvars.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/diskfont.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansion.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansionbase.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/gadtools.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/iffparse.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/locale.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/lowlevel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathieeesp.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathlibrary.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathresource.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/nonvolatile.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/realtime.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/libraries/translator.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/font.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/icontrol.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/input.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/locale.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/overscan.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/palette.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/pointer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/prefhdr.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/printergfx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/printerps.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/printertxt.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/screenmode.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/serial.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/sound.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/prefs/wbpattern.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/battclock.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/battmem.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsamiga.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsshared.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/card.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/cia.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/disk.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/filesysres.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/mathresource.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/misc.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/resources/potgo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/rexx/errors.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/rexx/rexxio.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/rexx/rxslib.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/rexx/storage.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/utility/date.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/utility/hooks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/utility/name.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/utility/pack.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/utility/tagitem.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/utility/utility.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/workbench/startup.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Modules/workbench/workbench.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/er.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/line.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polyline.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polylinewin.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/README create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/application.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/commodity.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/coordinate.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/anylibrary.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/asl.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/asl/simpletest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/commodities.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/device.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/keyboard.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxPort/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxport.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portList/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portlist.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/gadtools.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/cataloglist.m create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/testObjectString.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/associativeStringArray.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/associativestringarray.m create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/listTest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/testExec.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/list/queuestack.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/object.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/gg.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/jevr.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/OOEproject create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/misc/todo create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/ADoc2AG.sh create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/getADoc.sh create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/readme create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/new_object.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/address.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/float.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/floattest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fractest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fraction.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/integer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/twoNumbers.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/Examples create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/rawstring.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/OOmodules/sort/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/ARexxPort.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty-handler.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty.mountlist create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/FD2Module.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/IFF/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/IFF/ReadIFF.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/IFF/ScanIFF.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/IFF/readclip.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/MakeKickFile.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/PubScreenNames.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/Pyth2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/Talk.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/agacc.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/brush2image.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/findf.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/floodwindow.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/gtlv.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/ham8demo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/mweg.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/oomodules/device.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/oomodules/library.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/oomodules/objects.build create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/queens.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/readclip.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/ReadMe create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.info create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.rexx create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.info create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.rexx create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/rexxhostc.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/scroll.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.readme create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/showiff.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/threads/modules/geta4.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/threads/modules/geta4.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Pd/threads/thread.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Reqs/AslDemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Reqs/Ereq.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Reqs/GadToolsDemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Reqs/ReqDemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Reqs/ReqToolsDemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filehook.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filepat.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filereq.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/fontreq.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/changehook_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/clipdemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/HotKey.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/PopShell.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/broker.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/divert.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Console/AskKeymap.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Console/Console.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Console/console create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/DeviceIO/deviceuse.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/rbf.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/timersoftint.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/vertb.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Lists/buildlist.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocate.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocentry.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Semaphores/semaphore.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Signals/signals.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/simpletask.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/tasklist.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/trap.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Expansion/findboards.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsgadgets.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsmenu.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/simplegtgadget.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Gameport/Absolute_Joystick.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/clipping.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/layers.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/RGBBoxes.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/WBClone.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/genlockdemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/usercopperexample.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/animtools.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/animtools.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/bob.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/collide.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/ssprite.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/vsprite.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/MeasureText.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/availfonts.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/cliptext.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/clipftxt.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/sift.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmbutclass.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/talk2boopsi.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/userkmmodel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/simplegad.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/strhooks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/updatestrgad.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/closewindowsafely.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/closewindowsafely.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/eventloop.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/compleximage.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/intuitext.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/shadowborder.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/simpleimage.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition37.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/menulayout.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/simplemenu.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/custompointer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/mousetest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/rawkey.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/blockinput.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/displayalert.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/easyrequest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/clonescreen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/doublebuffer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/dualplayfield.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/newlookscreen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/publicscreen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/pubscreenbeep.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/screen34to37.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Special/remembertest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/lines.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/openwindowtags.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/visiblewindow.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/winpubscreen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/mapansi.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/maprawkey.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dpieee.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dptrans.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Math/spieee.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Math/sptrans.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/prefnotify.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/showprefs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Allocate_Misc.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/CIA_interval.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Disk_Unit_ID.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Filesys.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Query_Serial.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_BattClock.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_Potinp.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/a2d.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/hooks1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/istr.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/tag1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/uptime.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appicon.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appmenuitem.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appwindow.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/iconexample.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/prargs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/AmigaLib.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/argarray.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/boopsi.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/cx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/interrupts.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/io.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/lists.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/ports.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/random.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/tasks.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testargarray.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testcx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testtime.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/time.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.rexx create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Async/async.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Async/histogram.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Async/playsamp.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Async/typef.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Boopsi/Boopsi.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/clonescreen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/testclone.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructorstest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkeyTest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctype.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.License create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.Readme create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/button.gadget create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/calendar.gadget create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/tabs.gadget create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/tapedeck.gadget create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Images/led.image create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/EasyGUI.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/animcontrol.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/button.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/calendar.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/colorwheel.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/gradient.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/imagebutton.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/led.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/password.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tabs.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tapedeck.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/ticker.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/all.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/animcontrol_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/button_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/calendar_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/colorwheel_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/gradient_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/iconify_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/imagebutton_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test3.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test4.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/password_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tapedeck_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testaw.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testkey.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testqual.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/ticker_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/toolify_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/animcontrol.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/button.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/calendar.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/colorwheel.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/gradient.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/iconify.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/imagebutton.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/led.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/password.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tabs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tapedeck.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/ticker.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/toolify.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/EasyGUI.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/README_IMPORTANT create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/EasyGUI_notag.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/copylist.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/easygui_notag.m create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/ghost.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/ghost.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/textlen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptions.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptionstest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/File/file.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/File/file.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/File/filetest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/FilledVector.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/ObjectDesign.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube39.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/torus.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/wb1200.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/zed.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/filledvdefs.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/readnff create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Hook/hooktest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Hook/installhook.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/ILBM/ilbm.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/ILBM/picwindow.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/ILBM/showpic.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/InitHook/inithook.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Iterators/iterators_test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelextest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Lex/testinput.lists create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisp.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisptest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longdemo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtiny.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Macros/macros.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Pt/Player.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/ScrBuffer.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/thebox.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/gurutest.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/trapguru.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/UsefulV2.doc create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/battclock.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/battmem.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/bitfield.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/cia.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/disk.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/ecode.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/misc.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/potgo.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendexplorer.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendrexx.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/setprogname.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Useful/split.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Vector/Vector.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest1.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest2.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest3.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest4.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/README create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/qualifiedItemAddress.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/test.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt.c create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS1.3.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS2.0.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_v2.readme create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit.readme create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EBeginnersGuide create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EGuide create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 1 create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 2 create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 3 create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Build/EBuild.guide create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Build/build.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/D.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/DirQuick.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/README_IMPORTANT create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/edbg.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/eexe.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/about.iff2 create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/about.raw create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/toolbar.iff create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/toolbar.raw create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/schex.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/screg.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/EDBG/sctext.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/FindString13.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/GDU.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Mem.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Nkript.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/ShowHunk.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Utils/Watch.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/2ndMousePort.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/Pi.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/Race.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/SrcGen.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/Trees.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/breukfind.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.dvi create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.tex create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.txt create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/freq.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/huff.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/prime.e create mode 100644 amigae33a/E_v3.3a/Src/Src/Various/radix.e diff --git a/amigae33a/E_v3.3a/Modules.lha b/amigae33a/E_v3.3a/Modules.lha deleted file mode 100644 index 84eff470c888617654c4db169a594d5bd7c36489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 659318 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 SA42TyP8 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/Bitmapper.m b/amigae33a/E_v3.3a/Modules/Modules/afc/Bitmapper.m new file mode 100644 index 0000000000000000000000000000000000000000..b8e1ae63f3a93b5834cfa59cf4b626a1116a671a GIT binary patch literal 5398 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 X7jcZ25l$4ThXNG{gZZSMAp66eYcx=FJk`O!a0x zMpNCc(%_1H+uYi_{d8)tHEAso>G}w%6q4S0&WbnlbBfRl`3Iy_$$Zh=a93rkzUjUS zrOfyB!M)a1qVB$xy_Vy3f8k+keSnga7VND21G~lFL!z8b5s>V)a`!@HZrR(OZkZH4 z;b`rh+&v0Id&kp0{N>kPeE*t;V2f1}#< zp<)z_MwMt}wM95vUrkyoZj>DXG#w|1=BQf##Fq;-u)2EO>h7sKk!t<*5v#Q`fUmQS z@3E?t{!_KO9qG7g4Lwq|`s;%0f$M@~T`00jBdCi_-_FDXk;mJSA5*0#i{>SXK-37% zrz+50U@7{G$`Waz`DE_tPYBrnX;;vpF>nun9@5R>M?0h&B&2K?cTJ;8XHqt2vElWJ zV5|+V-}w53w0Ce{6mN_>0bebB$mY9aj5%xYJx9~H zgKtIX_q zgk^qC5Kh@HXNc>y$~_hP2a3)r?#6EJWw;~NgSN89m1;C-z5gj&_raq)|93pJ;y1

4UAGR`;pacApg-`VQob-dl^I_hlUmZNI2kMySwsm~skRhE{j#ag}m%t~dUR;;~_ zQ~f0o^%~7TemI?_jM4lv13nJE3Z62W4FVrAntv(a=fQ7)4;#&95BNFo_rM2@=HDzI zFq$ov_k({6u7k5*_;39Lj$c%J?|>(b=6(V^0e%ZyGn)1YxC%ZAu9zD@)q!!!B6SDj zEsHwtW7IGvEQ)<>QS=tZHH-m^6zG&UForFP+{O3^;|fN?qVRVZ*D;>8D7207wnc<< z1xoZLb-OuPDAvm?QnyIK;y0K^?+aRBs(c~nhk}NgMm`ht0@LtKK{ckKUj&^MG{%&^ z5%dE=-xYLHP_k_bc!16%~D91oF}bRD;L+xrR9y)R}cV&Y&_5nllEGz;wcyto^!Bgf6`pY@H3QR zD{Dnw)bWbGS}(8HOT|^BLD=+DY^hSKuegnU;?-7MGYl{KJn9t9S)+M2Vhh!c228S3U= z@7alobfIt=ESDWa$A>H|Wuv)V-hhi9$U3C#`9gL!ZDi)m=f*D0re~l{Kuge0j}~Uq zh09~3GigYlfHW?@G4i=w+L+DeO~+c1^89q##1z&Vth=N%eK9-hNMcelJvWnaB&sXP zPy1G8{APYCJ(Vw9a_pkgE^D$cM%XDOyyiqU2Z$_<_@pzV^N=RtHwmeXrjVY`&IsU$ f2uW*e=FOl@cT*hQPoM zKY*b#>de4^_ytU;1EPNbiG?XjYR-GMp#mvadiT70-u-q`yWgzh0wS4wvE!Q|F-`r> z*$HR2H^W(Fn#u)O^}`eAcz$xLG@orv9syPW`yiZMEkWG_>>y06yDvcR`OG;EyMoJ? zU_`#WX#t#v&N#^}-UC=GP`4&MpepRbgF+vs^QOQYQPs1K;O!L{((8KjC#{$%mZEBn zQw6N}bz%N4BYy=DG4>r;M3tx)g=H2|p2DzoPLqQ+xda6iqS(eC$+uzhsEpOcl#SDi zqV5yXkC-p+OZ#_9b}!#X$Z*#^VS(*#Npfl+{cL$LmE-}SvUzuy_Tqvzb~M*vHe>HKrP zj$CDWc8!=N4v5RdA4ID%4L6A<@hwp&9uZY%%xHZ=g$<_}$Are(&2 zx1jdCr%V<7N=Tc~_I=NlRfLxg!*>V0vD=f~%Rm+SGjDX*9}c7$Qe=FUeO&<>%}TjZ xYqjr{w`+9B@E8f#s_oXd>rIE8#iJzrZmkv5xQtA-*-jq#|K4ecG!(H5%5TxY8D0PY literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/Mousepointer.m b/amigae33a/E_v3.3a/Modules/Modules/afc/Mousepointer.m new file mode 100644 index 0000000000000000000000000000000000000000..ffdab0b9937cc6d740881a3193dfe48ed613bf9d GIT binary patch literal 3498 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 QDV5hZmkZx41vBXV7k2zCMgRZ+ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/Parser.m b/amigae33a/E_v3.3a/Modules/Modules/afc/Parser.m new file mode 100644 index 0000000000000000000000000000000000000000..0cdc9a0227c6b7923cb09db932d0e52858540345 GIT binary patch literal 1260 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 eWF#yoBlF39+J4vr8~Cr!qp)+E9R$kcb8m zy*4x-cwMl+H!s+y?>bl-tR^ro8Cdi3Y9_i-<#Oe~q1cnNCul~9pa zLWN!lwf-U$j};@3#5h+3@@3=P=;9MIWoOE-ZhLhD*BVj8j$+K_j3IiCXF$x1%JbDD zkBcTh_fQzSudWm^k9OAQyVTUUZi_oqi$uddzNBWMuI(a;pdi&ps))$PSC6? zqnk$EXraFRHXF3PkfCKG2gLfQVf>E$E~)RUj=k9LK8im>Wdj!o5m(+GymX)+_HO@% z@$>8xIh{n-kCkjVd34tPlyqz9qp)xmR(;X=Dc*Z*6dcr zY!!KJ6%FL+DRSZyZ}Q=(mDn+AOJtP5x#!pg#*C-f&ChnR)@@enonrkCgHP$;>`Jh9 zU$l0rurAIttmM=V$yPQ`awR|s&JW}xh+Ot+t@BCfqX#=i1GrfWIC=LtcpdFEigp~4HT!%iGk55=VpVIDrTM>q4u-njNSh>8^8 zJr8T&adv*lD$TvGy^o-NZjQ!{*7P-;ygJeJS5~CaiEzCzSNDF!yGj?kIGGtM>fk)j z3u8J@rY7bx8a9_h(~}mFYtU4NZ<3zs{}0_frh}TDYR#{$Vt;^&9?mbTR2~tLH{5() zIXy#*@DJfr@PEK3!_7aJ;pgE$f}e%I10RF`20jA+7(N959DXv~Yz)8$;opLvfKS4Y z!!xfR{wMg6aPzO<;Ln7c&CBo#{5t$8_}lP<@OR+{;J=6Wg_|vYhR(nH;N@`BI1ewW zTXYoqPwRAS5q1$4gq?*A=p_FHy9@giro&1w;AFHNb?fBbgH?4p@*V6;*e5zkXzRZR z`vP_oR)j6X24S*Jec+(Suy0}DraQ0?V5dkTU%61Kq_df_md+P)`5Qze50i`fjRx*~ zc{2WGe=fg@?^rtCL0i~g55=Ak*nFXj`{+N62h%}rQ;CJQ*mn;@8wP*Px*n1jzn03C zQZB!iFRW-Rn7sV?a_nRAJB9lqc^!zdh)a|rNz1Q@2i%e*WmfRiCzP?md6IMavR0~4 z!BRU*QepYsc8?gjS97IurTrWscX=zDrL+|Yk-J#ZZdiSZCh@#gUT?!Gi2b)v5K7(FUU;4m}x zC6RnXE0uGFyayfO>n;<85mFMaD<6951J literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/ToolType.m b/amigae33a/E_v3.3a/Modules/Modules/afc/ToolType.m new file mode 100644 index 0000000000000000000000000000000000000000..5c1bea824c2bfc577b7ad183b438361794473d96 GIT binary patch literal 1270 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 BCqn=L literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/explain_exception.m b/amigae33a/E_v3.3a/Modules/Modules/afc/explain_exception.m new file mode 100644 index 0000000000000000000000000000000000000000..e598c31138aac852fd7f8519904d01e7e1e6c37d GIT binary patch literal 3740 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/rexxer.m b/amigae33a/E_v3.3a/Modules/Modules/afc/rexxer.m new file mode 100644 index 0000000000000000000000000000000000000000..22003efaf1626f2ac704aa47d722cbd7d086d2ad GIT binary patch literal 2514 zcma)8O=ufe5FSYzck6CkVMNHm#2X=sTq%+9sf17@%W7p~uZ$cUH>8#2Saw__M@Y5n z1Rs_jOb^Pqj0vGoC~Xg=m-diD4!IeMX?+kx2OU&Z^6NKm-_}wwp$jv! zZ{EE5`DXS>shP|KogwG3pPK5eUrHa5=SOQ^v?FQJPX9Sfv8dPwJpnx&$%y?#%dpUNcciL0-D$!ut^&R=>M&<=+u}fsgRhU=T?HI{b zgjZ%sv@gafz|ss;AVzGR-WEdIya5}dXHSP75A=E@PDZdqhLgeZ-6?y`jqZ`BWprm( z?5I3fRYbq?>hH?gdveM|7SiGt`H^3LdYe4%x=j8sy{@X5;!KoJE%O3ZIF zw|8z95|b-0$?J>L_dLkCv!uKPq?dEy&T{X^f7HL!Orj2??JnIWr+@k%VYQ#zlj7 zKuu5sr|ZGl;5wPseb^c1B~gnJcvJF5h=RlBa1VlV0%Z41WZ1++=;$d=GtZ!p5JRWOLe1c4PUP3HUPw4b+Vru;gi`{>*I0P2WGNIy{?Fx&5t}g5@k%%h4T?hr~KVJuT8=3ZeF^1uZjCp^%2;2}&}VPi!a zfrUt0D}2N|{Fu~NDU^$V*(YO2CD;)4Rh>f|nIrY%RDPrSu?h`cfV9d@xy#JYv8$U! zxK@ureH-}_m+U+`^_6c|PWCm@tLtma>q;Z=$gF;V=d!D>IXt$z$O8QaPi v*H^fDM&xn{7G4^V%2_Ba36s;Yudzq;8Vycl5Q`zm;m_OrG)k3^(+~Owuj47H literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/super_picture.m b/amigae33a/E_v3.3a/Modules/Modules/afc/super_picture.m new file mode 100644 index 0000000000000000000000000000000000000000..5036e89d1cbb251bda3afc3becc057c44789928e GIT binary patch literal 6374 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 O+%+CTd1q7B;PXHDnFYK6 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/tasker.m b/amigae33a/E_v3.3a/Modules/Modules/afc/tasker.m new file mode 100644 index 0000000000000000000000000000000000000000..9ecce81701530b6287b850962ab5346e0eabfc52 GIT binary patch literal 3204 zcmcIn-)kII6h1q$^+)?_v$X{}P-Y?Emkn#~S7 zn^L5d5hVCf1p6R;Dt!Vmz2m&E> z98&2uBC~&A?jHW!(g!8XIii>DE1#n-shtt+GIIBFiS&qLS z3y(FjA3XnASj$?|!9KFaVr-P&b)}ONG8sPQm-1UQZhsP56F0f=WJ!E&wh?6|D#ZDU zIsk(;qHLHy>I8gbePu1BxE39gJ=O^U(5u56;x$9yd%KnHI_LDftKc1pQUf-xd9n zX}FHoX%gQUzBIm+RT4G*Vc{`psHw;vC>#`TG8S)w^O1e2a2@KvfsS)oTJ+@q*m2Pd z!TUL&*0D}RY`Ha}Te4T5iT8kUouN0;{kSa0VtvV)e@@ ze8V?$PxV3W;0WPY_O2PqS=6A!$MRJ$kK;Tzzk};AgnBr!`qLl_tNZ0AbV+p5@Y|E! zF0m^jFEL#hKh8^ZA*Q9A2}zy_ciaHT_N@$c#ZWXQm1RGg8RbJo^dG&5IpHQOaD%nB zKW%wN@KpW!E7I|M!)DC+g$Rj~)QM)TxEbo3_vIXo#j~fhuCGz>5qpm8W%B(v?)GDP zw$|?(&R5KSsz03f=O1EzO;c8K-Vz+f(f>erl^r=V)ub$5@gc4mzkIgA`;#U7_L!El z5cp--(qIKxGHzRVlaqj6;0?b&Vj0i)s|OLVQ>>MZl!jnD!E#W%UkXSEWurUd#PHNOv=E5LP@Ui1$W$ zMcGTn>@6+VD)?IxlG3-Z$IR-=3Q-1p>3z9+;q1!Unk{)!_Cj@8vV>egShdTG)%rpe za(D~)_GsK`wl;RR9q;v4=c?1T9Io(8lP#0sRB%{D)2P~MGvH4|8ja@GW@CHnvc;X_ kv64pVb#!4zDdE2gV5)t{{0(Q@iTHREM9E)ZmLCb$zkQp(qyPW_ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/afc/validPortName.m b/amigae33a/E_v3.3a/Modules/Modules/afc/validPortName.m new file mode 100644 index 0000000000000000000000000000000000000000..f847494cf809dcddc6c3e5acb28ffa0562853e19 GIT binary patch literal 264 zcmW-b&1%9>5QR_u!62b4A0P-8BqsL-x`?78f;S?xt_r5rf)Ic34-pr4<;v%I@f{oF~iI`OrsOlkp*yMsk6g0mA^C1EXx41b@7u1e*lW+pBn`MT zj-GM@SOd^WaEi%oZHeywC-$2g`;zcqNBJh#rKMkrhdkw2DFqx@O=R%6iQ@6FJ6o(| bG#T-d>j5d!Ow-x#(Q;Jzn60NPfC%^p#Vt)~ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/amigaguide.m b/amigae33a/E_v3.3a/Modules/Modules/amigaguide.m new file mode 100644 index 0000000000000000000000000000000000000000..9e618f61845ca2d97aec5358ca28bda06c75817f GIT binary patch literal 375 zcmZXQ(GG$j6oyYX4exj*vSt@KH(3ura>iH)PN?bAm&`WMxMJV`?LP-Db#sOzh+Zq9 zURvTqcm$?ci_>&+AGrHVCF62xl=kDa0*NJfuohlOu>%#a+R||EQHZ7OK+w}2&ABtGMV+pk68+e X7JK*3-m>zj|IVh2hf!Mv9{~6Qrb2z8 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/amigalib/Tasks.m b/amigae33a/E_v3.3a/Modules/Modules/amigalib/Tasks.m new file mode 100644 index 0000000000000000000000000000000000000000..88de905454b1c22ba2d855f18bc3ac16c85e2205 GIT binary patch literal 600 zcmYLGO-mb56g`uqI);J9;zEkhXRuIk>TJY97LwFzf~1o|KkP!OWAX@tGjVXnwiFlB zf8ZZ!_TA+tWZ6~Ys=5X?rc79J;NOUf`*a;wTc?^#J2ky zXk6scy2{S&yAf6(9>aQ*=F%+7u9vH@Sox)L4r+f;6y`p#G-1#*8gelB0lOOMEWX2n zQ$;~c5zR;tVF%f_<|uEt{l8~oOGR!!E8EykyTEs`B_5%~`_(=#>WfuWM4f(R_yv}Z z*L6%}ZH<~t?Y)f*QLhbWc@J}Q6Mu$2S!zR`EporawlE#IUzOh06$*UU@7p}pX{CjU zMo?L)Twe-NT00#pcl$R#tWs-;;Gppl56PFu6UA4Ccrf^^-*WHvbqf*p!6{6S zuGuJ>BMjU<_e4#-9KsyW;O1QASf8dDDU7Em!0O0ACi0aRA2JK$JtwOsOtz#=wA#ng z`(J0q(0_V-M)bT;+R?FZ`#nE-v0=xF*FJpdf0A~`OFSUUFvFfz+?U}|=OmDE#S8te b7x)KG;Kxb45&}7xJ^7)@P_ZlKpERz2Acc-N literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/amigalib/argarray.m b/amigae33a/E_v3.3a/Modules/Modules/amigalib/argarray.m new file mode 100644 index 0000000000000000000000000000000000000000..b90dfcb0be85c5b36ef01f9ac083dc24b545a4c8 GIT binary patch literal 820 zcmb7Czi-n(6#m?pI#f{X z1Ajp$Ce(oei7gWo0|R5FvULHKp+g26^SyI|DwufIyLI`o z_BrO9)9ko`YiJ#2j;G1?xdGzu@2;g+$|7f}X30Id!`xT&l$B4cjumD%bse{8Rh!Ew zIv+u4U&7@5Nscq)*m>fNqzkE@40WlQ`=T(}ewvV7dZ{$+bV7~-9N`#XcCU3|yG^B!1eiGW{eyCz|(P`rd)DZAo?f@y8)*G{QARH{hNz< zbx@X}7)xwN7JR3E(AGltc|UmO4s{OWH4A=0U7;=#|3>{xr4MClE@#}{P+w6G#6@;_ n;rCGWdi|Y|?+sV`(Y_ZphXcPGHG0J6@|xw$Q$Cw_v?#v;1=i3w literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/amigalib/boopsi.m b/amigae33a/E_v3.3a/Modules/Modules/amigalib/boopsi.m new file mode 100644 index 0000000000000000000000000000000000000000..b34f38432b4b5dbd6208f184c8c0d702aa4a1515 GIT binary patch literal 572 zcma)&u};G<5QhJhAWURc8QCyZg&5l886triA({>aCJ-%2L{u8NO42<%1FzBt$jrnW zFfy_;P|hxG5e12pY@MyopYQIZ+dIZK7E#(?33hd|MSDNE0Q^@2B84rEz#N@5Qm|$U ze%J{f>1OBb1!Zs@Ocm|6VbkKG4d%johb7nmut7dUIdvS|z;rPL&UW&iZZP@CYHa!9QPuJk6 zD$SD0`Qs?(UHPXQ=zbumb@Lc(wus(@C6tLoxe{&ErDDUQuNEqCn?&c0LC_0kE}i A4gdfE literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/amigalib/cx.m b/amigae33a/E_v3.3a/Modules/Modules/amigalib/cx.m new file mode 100644 index 0000000000000000000000000000000000000000..687101684bd3e710c201aa6cb91fb09888228be3 GIT binary patch literal 1970 zcmbtVO>7%Q7=3Fe_O>#`R8|fZYDZCpn#8dK;smG)sA&we4l=)oAjeJCscG!2>`e$# z4+~PIsFz-Pt~mD4q8uV5E+_}Yfm07CLR^BVL{Sek2MbxSVR+xz>o`uNBH`%G&NutM zpM5j)W$N5sSB9a^ z_@BS!F9NoUIUujbku-KnRgoO7B9UI&YvsSvUuH1#L^oY4I|-<`c&Io%V)U@NHsFGz zO?Gf;Cu-5-*GoI_^B?C|!kQ#|Im~q1wIst!*8%Yneg-D<8uPSNT=KY4auTe<#1)QY z>f`|Jdp+F23C8M;*UwecolM`FJjt&8gHbDfs9t`VVUDs2TP3L|R~AoZkz2!1{u@N` z={vXHxDR`58ulFY0~h--^lt9a8ScZ_q;6)@dV|;`?vBjpjo1IO&W_~t=E!Azx1&nR z#YmBFi(D=0jX79D%$6|ue-ss5B-=aleK-5sN4FTgB^ihyWEJisL3>w?>s_!5__#hE9pc@hck-}x?UmaOM{V`Nc+^?=-gFq*3Bpl3Gu_YESpqCtk`Q ztLhe?tf>rL=CgV5d+|b_onp1k68@=61?F^eq`s~8nbOU!zQJLA5j;&_{L$6-UiclR z{yU-7(XnM#*I9qSoZ-&5wU_T{w!e?F_HFA^+xn?b?KbO3wQ;4Rc1xo5tIZQ8x&?hY z9ir_GjIdKf~F<=V9i- z_fNC_lRr998IFoLqpq7%Cz&JrnbkBi zoP%^u`#E+(H9c_-k=&NpFHW)-iyiCQwu(vI!VNXJ6M+9Uczb@4+BuICF&~55#H^2K z*+=B259=|pgaIU08czLUWyy2uWXjKCzmwl-&r6r)y~=W}SSwYX^nz0^tt@%P1*b7D z+(fzVIB!m^IyJ9B)4D)UOB`W4;i7$Y*?Zgh%&gw-MoyU!6<1=X-Q~KMt}IafN^RAt zd+&PnN^P;=tkTI^r%y!hO3a2=PhYEYcA}Rjkt4qwR<-lWq<+!7=shcU0>l3&5Ow;R3{nc23}Sv0BKmkZp|x(rKTeb05Higaavi`+i) zXWN|hH~MsN@d01I(w_uXEFh!xaL@uajBh4lb*{Z~Efv)$&?cL3u%}W`%+rw9h*w`R zXjuBit)kILsZn1pAY1i2Kv}qp$B-cD??~cK_(ivqmb(;`#-;J9%JVT5?GII~iSB5( zrD9oWvcJjRCJj#qG>{7v@bo{kDMfF1){#TvuEHt%vn&iz=9ClDgmcuyog4@U()?Np zAJV!HydZ_lwb`*A&W-RX#pGdFv~1UW1hQ@O-t^3d*N%vjI8hIY8`o^bh@Cm%*sjO6 hsiV^KBFER9u<-lWq<+!7=shcU*p#1q>is(Sd;lBnoA76fpS3 i`js-UFmU9hmiuHDmq1KnWMBj{SaNeR82;`6_gI8WUwIx6Jj}w$Ka}sNClGpupQE&gMLNm z)Y((eU;_CUo=VA*vE8zYVtRX?tklp8_r3dZbndy5-gSEic!b=l55Yzj6nO@2U((Lc z=TP#ZB})aKsnd{zKBv#>JxSWX@x9)WdA%z$C5=#ixL1F!HNNv1HD@0N4EF{_eCpl9 z(hPPJWjm6zz1VG`#LQY{TP%`IF0XEHw5qUHP;` zfh?xN(H&Cv#65TWpnh2Gg}sMTrf##wJjZ`kqPtrCDr#$$aqnJl3hrLrL&a&Wb|t65 zx0*OjSZgf`dJdj&sbUP{l3t3r2~3nv{m`HK$D{F-T^QL{&=DT1RjvGS?0aj32B9D+ z@6ynV{Dv9_fC%*8@EXtjXmolW`jfX_6r6cs@WBa#$#n8E0t&E({>2ef&0!F~pws>W Dm*~bK literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/amigalib/random.m b/amigae33a/E_v3.3a/Modules/Modules/amigalib/random.m new file mode 100644 index 0000000000000000000000000000000000000000..9d19f4ee3ef7f6334495009c1532d6ed64fb4d0d GIT binary patch literal 366 zcmZ?u^><-lWq^PN0Vsok6U<-+lBRy43=9go3>;n!`3wv^Al8M31O^5v2uq(q-$u4w z+tF_)12aRk|9b`wzgWLgkRFfcj9`7i4NMIT4FCV@G3c{QdJ_dFMAisfuVHprl1L7bc)?i>^;3`VYOHU0-%u8Va0uu&CAOr!H tywY3-2ClTk;u4r7P!vV>|9=LK29R0_5W%nyh`WF|3y9-@7#IQ!3;=aoQG@^h literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/amigalib/time.m b/amigae33a/E_v3.3a/Modules/Modules/amigalib/time.m new file mode 100644 index 0000000000000000000000000000000000000000..6bffc4b337c39f277f93784f9d7791b2ed99a127 GIT binary patch literal 444 zcmZXQJx{_w7{~u$c{21dy-39+Vq9s#^^_IaCCO} zTR6JurklHi^*LJF!6&)PFTdyRe=nm8V~7f}YHgsghAo=A`V}zwtiew@m@J8D=r5vg ze50;lx|#v^T9y1!;nmdJgC8v9W3<}i0E&~m>CeBz>FO5fk!{N3!53tCMO;t$un);^ z5WjZ&IB1WvJtsN!d~~4I@{=U3TCiL>f5(S@t;Z2}S)kf%!7WBtm9Q<$kU8d^xH?dR zcpb14&v~ST%<|@TsJPq;ybwtO@dJ<8XRc?*4hv6Bm(NUx-)O!UM4{>eWi+jTnGw4r sL#xY_3G51QGl%8AwDwQb+xwr!JrPx8jh4}wvB^@4tjwob543~o4=UDcMF0Q* literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/asl.m b/amigae33a/E_v3.3a/Modules/Modules/asl.m new file mode 100644 index 0000000000000000000000000000000000000000..cd17f1d842a1b609da8ac9a6962543dfae6957f8 GIT binary patch literal 108 zcmZ?u^><-lV@NE{NlGkEWpK>N$xn96%t;MOEi6qfE)j4mN=-%Lb3nyGLL6Ylj>S1p TF$NBhVg#Q9iOKn&fq?-4?7<~> literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/bgui.m b/amigae33a/E_v3.3a/Modules/Modules/bgui.m new file mode 100644 index 0000000000000000000000000000000000000000..6accdbbc7f5b37e6118c8228cc3cbea6e4b28881 GIT binary patch literal 141 zcmZ?u^><-lV@OIb%}h!xPGxXP5A}?9Pc3oINh~f7C@F#n_@$QnCuOB3mpC$TfK>#g z7M7+KmpF28a)J3CsW}BeHbk{gesXqrW?o8uIYe=2UJjawOTK$zN_uLEZ)!<-lV@N8^$w@6qN-R!g@GnTsbInW7%u5w;&dD!Mg|In-Q%gMa(()ZSIQ^4K V5;OCloS@X4RG=;>?>_?r0{~gq8h!u( literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/class/hash.m b/amigae33a/E_v3.3a/Modules/Modules/class/hash.m new file mode 100644 index 0000000000000000000000000000000000000000..0e7ed0002f5a00008fb01856fa8eb2a5fd04cc14 GIT binary patch literal 1122 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 E0Db9-$p8QV literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/class/sctext.m b/amigae33a/E_v3.3a/Modules/Modules/class/sctext.m new file mode 100644 index 0000000000000000000000000000000000000000..30ccc61585f103db39b28fd11e14dee483c75e6b GIT binary patch literal 2510 zcmb_ePiP}m82=_s+p&ZaHHRQUXG0Go**0a_LzNz~R3Texy6h@mT(_kiH+3h?kfb(3 z(TNl((nA)CEaK5?ORs`R1dl~>*h3G+4N})2ku9=HEY;`ld-G;Cl@<>gc=NvZd*AoH z@8A1gUVUx$73wGTiyDd;l5-!C_FL`^agxf4lk_M>a$iy(U73AEVWS{UE@a3tMoCw6 z1$0EwRYxdlGob1YDQwH3+|AsIuQ|Zi0?G}j^?=%7>7-4RTp}}f_p}b)Gfdj-)!Spw zCfhmf-X>c2(WFW4ZtZ3x>t-8iX&K~Qd4@?F&D!oZMQ+L6BpENbH7Py8(gF9zv}=d1 zyFa+hQLm*bTNTpp2pNUb1dIOT)U1)Wng;&aWv`Diy3i*^&up>MxN|( zlj7M1kjFhpOd?0KkH9l34$~Q#k1phG&~(ujdovIED7PcN?vZ*2P8mvSc6fp#J;SHoK}7K|fuTMaKBpX2u>__c{x@?Q3*=LuFHD612QW|S>vKIw($jiGQ|;SsFk(DOTZqQH(Y$DC{U#+9!h z=63$vpLsx4SuI^u=2oge3DLwihVwX@Cau9P5V?T;S_s;hpRmE96!+$@1*#AcyC|2JV z9oW!j9*&7Ii9|Kdic6{>I@pIDzCJJGb40tRt^T(>`SNGmEB*Knb|Q|6=C)|3GKA{z zJZsA8K?O-4V6pBHtUST~2{Q67I#ZOpld5dJr?MxwvSnWGXRAaqH#5jh3@a@_p5=Qg zb)tGHcEjC8T-DMpBT7! zZ2y(x(3qh^V+-dQva^gi8rE%Ii-$zdyJ$@;TFbsF7>rBF1bX*6vF$Tr-%?VSzag= zZM$MsD=bN2%C9ahFBVscu&ettTSw?YgCBz;iepTWUbZTpAoSsPnTBp#mHCCr(tDN! z@EIpP079e*{79pVG_abtO5pM&O&Ts)@06@^a5&3rG~%66bg&9}yh?*XdVYR+(e@A0 zC_w{7$65xbj{h>fzkb*oww4!tEJnj{w={oCoe8((R+J(hzO=l=(a_|G_^4HtsHa8u z(G`!^L&G%WX(-I2Dd8ureG0@R#jHYcamBXEFE7~h<#M{bFov6^(U6w`M4H&{!3{oF Lo0j5r`NijNdKhF( literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/class/stack.m b/amigae33a/E_v3.3a/Modules/Modules/class/stack.m new file mode 100644 index 0000000000000000000000000000000000000000..ab5a6de76c1e73ab4b40e6899701841fd1d03a47 GIT binary patch literal 528 zcmZuuu}T9$5PeD3^9U&pNfB(^G$O<#)?#rOl~eFyBe777XowP`3zx&#ZJEw5u~)E2 zE#e2*TMKf<5rXUNCMQB1n0s&D%+6c(w)g8>n8P%jgk%lL(D%qcRO6DT#sa*n#zhxQ zz(4WBMAs@`0n15!rZM!SH~ic8`mp^cWYDk3WOlVtb^%_7Z5ZQAGrJ@0nar1574OM5 zuue+Mon+cnRUE~Sh2_3>O!dz{nmIC!|FmI#AO X;we+x^#5+eq{nCrYh7QMN>KnmMMk2( literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/colorwheel.m b/amigae33a/E_v3.3a/Modules/Modules/colorwheel.m new file mode 100644 index 0000000000000000000000000000000000000000..e9388fe038e58aeffb8444b79c9f00ecf047b6b1 GIT binary patch literal 60 zcmZ?u^><-lV@S@=$uBC;NKMU2N-R!gaL&&wOD!t#2zCm|4{~?n;DibQ*&+ErQ4Y@k H3=9kaPPr1) literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/commodities.m b/amigae33a/E_v3.3a/Modules/Modules/commodities.m new file mode 100644 index 0000000000000000000000000000000000000000..dee90039f54c26ae90ca1a6751c00aa5f963b166 GIT binary patch literal 340 zcmYk2!A`_53`BE64yXQ7Ns3gVYFDrauHLT220~JtwCa96IB5~w=4mGOINflt>Q0U8 z851ePgqh5GIKL~0P?kLHG5Duj@1edu-6q;p#~c}qC*f&JN2Q&p6E8E`7I9$O)RJ88DC6 JvglhW^#i+@Z#e(} literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/console.m b/amigae33a/E_v3.3a/Modules/Modules/console.m new file mode 100644 index 0000000000000000000000000000000000000000..cb1a2c4ede5a750b7ef307ee6ab4f4904f63b8e0 GIT binary patch literal 60 zcmZ?u^><-lV@S@=E6&eJO-U`wOipDG5O7ZM%qu7@@kq=|$w@8Z;0#JE_fD;J&d)1L PEh^#QWaRqKz`y_iKEM)$ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/cybergraphics.m b/amigae33a/E_v3.3a/Modules/Modules/cybergraphics.m new file mode 100644 index 0000000000000000000000000000000000000000..a7083fd97f16296734cde2f19840780a2eff7a0f GIT binary patch literal 400 zcmZvY-EM<0422EtTGFdM$=-pIwL%)|L?`XqfZIk&7v`itJpD#s?NG&qCHp(a@ljs0 zjf7d*6vTVR`k+etqE*4j4fJ$(EzlCk)A4y&sZIP+W-3Z0EXlg0?>}(=rmTySV=LwK zeQKo}6S3B&?2O*?hsBDC?lAIKwk2wMS69+8Gd2+fp_ojcX7e?<{w~(Ba~#19q|(n2 zsT) z6A;u@+AtbwddAC|j2&e3I(h+&E4*S%t%x1*DRo(2u%W2uO&9G#ScN3DAo4*lo^AJk zV`K?w9E=! z7kRsSv`ot+u3}~YT*Fn@*5$s;vwWJyNm?S_!OT!#f-|#iL>hU#e9G!JDx1%TW`NmLBL`3wK6Ua7U=(PQ16IHW8Ed8)Z7H_gy^2%H~yC&eHgq9s-?w zX%QzkNT54&FpCeDw8Qzq4#ubxx*}YgU%)zs&7Z=K#3U4I=t@_5{b&HtJqGI$5KwM4iky2wqPde}q@D{o>% zO-7#U3!CHQ4)F%#|DrUb$LD#FN8NnI$Q?OeiOJ(1#(LwPOSfPfbx+Q9A$kvG&-c(i zSM-Bp`YthIJz!)Yo&Eq_(rsxYq9!;l5$Qfy51C`jAzeN0!wDliRAjBPTVqD=IX3gK z7v^h5xal}eCydY!rhtoJ3C~d?a?o4Ub4AE7Mz(ije8Bu%uhS#1UM$jGk^uY#?Q9vF literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/datatypes/datatypes.m b/amigae33a/E_v3.3a/Modules/Modules/datatypes/datatypes.m new file mode 100644 index 0000000000000000000000000000000000000000..53e0d4e4bd644578facc8dd212d70ec8d0732b13 GIT binary patch literal 1674 zcmZWqO^@P65N$q|AT%NpAKiNZ;0VvtW@dkXCHB1 z@8W0^m!{Upa#$ZD?PF4qrB!V(-HhrFk@;}^!nhup-SX|=bwJ>}1xsNL9rfsG-+Lp!fkZ#~W z4Ba(H#M-Qh1jdLa)26|5HW zPO5vk@|@5KALbmWz8AWl@K&z!V7>zSZ;KXk>C6x!G?15w{bgfPg)1)AVtRWDgC`_# zsML(H3&uvw3nwf6phNDzX_$Yt*{)j5JQ=RkoJ%l|@O}yK%vnhHcI7+z4xS--iG!4$ zoK$5>Rh+3tl|#C&$(#!}Tm;aM_$_rqA239Dx~I4!h3|wyp&0$%TEyyTR|wd2kqsq( zA0kHaZg{_%2SSqF$J>F;Jpq%f7qEOspvzI3S0-0T9R>@Zn~dS6SRaYeQ?B(e%`utR(DR$sWB04MM3Y==XKJ*7sRbf^%V!v$(b^$qUucZM+`eD_ z$Kfm~_Zs|v+L*n^uJY&TU7O94&Z|&r@dM$>dgob_{slTH6ufUDV_c91I0o}8WC{XAd13d7+1A}ZGJ1W*?q~kd4OK@z(5w$H>R+_fJ zOh19!$M6~aQCaI8$xdK0Lp0;5_Bv}{&)!?9bbVV~7v_2Ockv=>`ej{+$`7LY`n3?F z{47iISm0zsh-sXkq@!e{Srs4~<79T63NY*A!Dt-kS`?y=v+8j&iBATz(FE#v$gfY+ zk&$SxG05|5k}PsT3)OruhN~&LJNO|AJVg|vY;XqYk|?ryn&q@n%La>F3&vk{5+B1l z9>gl@c{=AiBWau^qx^(Y71GX0oQzKllRkFAJV~?UB?+2w7s#_1Uht4{@6y=sgK;7D zd6vwecS-D*RFE-NlXR5Lbzb@{i=V=FaWWt3s@0Qpp5?>oNFOpwXf3Ey!M{1Kihk>t zM%!3MTZ0bnJI|8wIL@vbFTGTcPiMnCNoTNG-1lgZ540r2%2RQt<1|lkcD1@_KQnaE zY%paft^M!(>L$PA42nnT^DBGaWQN0ZmdCSvVfvgMr|lV0S9&G?>y-M9Me;IUF%SbM zWk(~&lfifagwHO1riY4KS;Uig$mY9RwW`plmb#25gO$N-Y({c*BZZf7Jd3lzjc zAs6C3mm#wj^DLcXc3vz~tb@Oi#fx-uYWfASRWZ1FP+)CMRI_+=l;pY~HOM!|Ssc&K zBekQ+X4k%$Mo7m<*bmk>GoT3VVGkCDL|+U75@`ARf0TUm#G^Py}h$Hobo5WDnLWa8iYL$j<%1%5~#zP6Pw zZ16h1@(rg^)7Fu@e?b*1fCx~}lNOU#u> z!G`hz;KzGr;HSELT%3wn$Navz~veR_c2$JCQy=%b&|SGb;SM2LxW4{aw3{7AaeZA$hO zaLgp@)h{tx_-JXt>lr3%RyQ^4BW>fkVriR&XV|()*=k}Gbwd}dD$xSqy`j?V9y_!; z9n(EE_}rmS-SA-+UtZ%x-7Mdh%zIai3ba-Cj{J`hwu zAdb@S66dBlro}zWv-KU3`JG{6i2WW?@i_~u%X?)02Yr`lF~Nq+ernQxi1@8YB2`qa zjfKP$Sa)%+3OTI~^sN1=bHl8){BE(~8aXkYp|QZ5xW$`j`L2tgO}1asW-(RB6tVtD zJ>BrE?p;dFUZl4UVyKYcLU5reg@hgU`ZMwnb<F?FO~J?Nr-f1o0{xv>|6A;({AIHSvQz<*Kg_NqVMBp zY82ljt~YRC`6W@MzeonuncZHZD`uTo@jWsqBfDjofk7C_Ix4_@!UkcL&d5NO`i`yk zaLx)pAyxp4;wfe14J(lzT~3>}gj!H>@6qDAHf?E8#LJ2Em!S5|y#e1PQTv8IGHZ36py}(C%RAfplYXpF z9vtwq>S3!H|I;ETgD~q65hLo#d_cL0mOqERp*g-?Vyq6nAjOXA%6_Sh_-sGme|hp3^LR0w3>J$A2L1;K?`rJ; literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/datatypes/pictureclass.m b/amigae33a/E_v3.3a/Modules/Modules/datatypes/pictureclass.m new file mode 100644 index 0000000000000000000000000000000000000000..b6341d4260c380ca51bbd8171f029d418cf48415 GIT binary patch literal 1074 zcmYjPOK#gh45i#OP@Nz(0;A{+vMbQsU?fd#Blo~!Hig}QR-5IKjmcXLBDS)MJM#>}c!YZ{_0a)=r; z<*;qsompedV&ipA&n}E8a3m3Qa75>{YR}7hZptakAQ#-rYTC{@!iCqFn`$<1*%fx{ z%sjW=7TE1}SzE>-cWUZQo0Oy>U~awLY??Ym}G_WLVd`c1OF~~?q^!Z{1(hG%8!OBS7AC-Hs+1QV0U^H zV6w>iDo8wzR2U|{&2wyCr1GP+_D6{tWO|UVkq?5Pm>}HOUqSLzWx1Bd5ZMF%$wuDx zYdiTSXr?2TuH(K4f==XVT!*v&Y)~rm!usCzh;q5ew4;Ztog6upvv0wvsktRgG^BOz=bN$ z6Wm=d365D82Hq(2B6w`<+peXG3| z<8xU%5-9QPehJS1Xahe2`a{rX_$GNW&V0S$_z%4kZiDoJytmrCJ?wgvqc2_!?NBcr f`NcTXK_QhH#OWW@)ug>>%#&%^mhEM24lMBxfw1V* literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/datatypes/soundclass.m b/amigae33a/E_v3.3a/Modules/Modules/datatypes/soundclass.m new file mode 100644 index 0000000000000000000000000000000000000000..96ece7b6de438e25c2ff061c9292de59581a1a97 GIT binary patch literal 544 zcmY+BU2DQH6o!xDK(^wX>~i@Y6N}bYyCOE%4l}t5lLjyW0t&^=ab}&9q)v73E zRpn}JH7)3F)pD~kMu;x)ZQyeSy**sK3KF?<;Ra)$`jii&5rBjI$#4<}!3_0XB%fBv zhTQcdSKL|pZKxOWi19d#g{5DAv;!8QLwhAPiQR^!kSdtKpU|(fy8p_=XvxC{FVA< z(bh?Zo%iO=%PcDffkQjg#Omv}pj}mH_L|1`@N zjWeUOmo3uiysYYi*Hk-QOp+>LfVf1qkl$pj=-?`LVtd?sc3lx-qyBvudCr&*-VaLY zyJP91YD0bfPc4NH)BP!riMZ2L_#XjKD@e$m7Xu87eUF~ z-9|YK?I&>T$L`IbaDaJ_+l|h_^Z+cslBRa`{72M8dt}981Yuv=5pKiL?(lPT`EOM9 IBJC*h2NBp`ZvX%Q literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/audio.m b/amigae33a/E_v3.3a/Modules/Modules/devices/audio.m new file mode 100644 index 0000000000000000000000000000000000000000..35cd1b7b143041f39e9d1fc7841273311aa4e6a7 GIT binary patch literal 704 zcmZ8fO;5r=5M2x)0um0yGw~paF~pzX+Ah-AZb@53PEFHpu(43Xm*FJ8#NTB6E$X$- zbeAU5wA-0CZ{C~TmRYt=DnwqpPZf}Q9vs2?L26k>NSp@iC{76}V+8|1%lHQF5$Og= zl7=s0i&atu)_D}H0*Fhb2H8a-=F`=4UabND@>MM2G%E6|O`5D{qR9KesGLe=(7A^Uz1qkf_#@^#+NQ$Fh~56jnzFOtoq^Bq-iO<{ z6ZH(6D~*Qa4-9U&L%`7eL}3nNighF1xjm+ar?9GYFEHGFS9U5F?C!t=yT{qbj^Qzj zxh}oiSB|B|K?RjyZ$s+nzBZ(sGt-r)3;L+!PPnE`G!tZyTahXUXiLt56DuyB#W!;C j%=f~cZ8AIz(tz*z07XtM91pH`FaHJmk=Vqc=t=Mo0+W|T literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/bootblock.m b/amigae33a/E_v3.3a/Modules/Modules/devices/bootblock.m new file mode 100644 index 0000000000000000000000000000000000000000..60961e21faa07ca3a5d260916bf1516b33173088 GIT binary patch literal 158 zcmXwu!3sb?6h$wMl6;S)GR#6^7Gtl51tE*cfBGZth*$5ubI(<+t`Omy>xblpkT-|8 zZ@^lz@OGJa0>n&WoL6`5-XdX+r^DIp7}wVTDSyDt*aD%{x;Luq4Vy|ENZA#w8a&c8 Lb=iEzBNgxfE}|C{ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/cd.m b/amigae33a/E_v3.3a/Modules/Modules/devices/cd.m new file mode 100644 index 0000000000000000000000000000000000000000..c5f5980d1bea38fdaedd795b6c645f570e6fdc65 GIT binary patch literal 2992 zcmaJ?+j84f6g_qvV@zl>C6rPMwB>%Cp~DAMmW~opSu&EGHoSO@t$?X7!Iqh{PkrD6 z__TfsuUx}gXCKLKXQ*e=datw2zO22^w(iEB+Ew=RwEWUGU+PNj{HmH47fSs+T8wk0 zTB@ehsF)7NOT%cwt`*DS=pjv7^~rpkpO@Co<9xX=%uD#UVVGx&)ufm#<_dmW)75;o zI>i~!TjR;e5iH@7JfNIXhJ|_TDs~|4{r0Th8}~qhdXz2eA((^I|+KhNXQC zw)CCI4g85-Eml@_u7OCj$iX+I*ibNuP4HUh(|m+k;|$hSJO2q3CSDLiG~i_&Ur{4QJD3g6E5~Xd$kpL`JXxGA z^U-9*@#m)n{MxD*7VDL<>Favw>yGGs8yJ*o)zuYzd*AhRk_U2(m^q0YPwynk_V@pr`!b##~=**d^YbT>YRSF-*PR;oik(`g28%y0*+ z`$>?2WZvzou-zjkI@D3W3(QQg<0XTB&y^c3F#NEeB8<7ATn~#!5285fI-y`6fYS?| zlPq!Ed*CtBOTg01Nf?>6yj5kLYWK)X1bto5C@w*B_okbL12^uSSYIF0ztc~dHGRLr zoERU@xqUA4Jc%>J%lfJ8n_X6Mbka!z4-9UgkH|unVH&}rpSz61W?06%Wj0+6F?grp zdTEyWgR~dm5|O$=Iu>F7P(Aw^M8{4TfbJM|S@Rp)HJdz$UP2zCdC6rihy>A*42ryh z{{2lk>BLFKN;s8Gl$U04Pj20{p3GF(T5pyZ$_k=G>mT>f!H&$2W$u<(#bmbV)Mw# zMPD__-;2{A3*rbiwnh!_%}k&dBuK5o72c(ZyNxq8Y8$vAg3Eo?lwO;{Fh;t3kMBuN zh?ZHHw^1{ONLbui*M*hEv9IsrjdBXfQ|#;==`3s6l_(EF?P71Rmfyu#^y9sA`i zi&2|*Btok7J-nhAY17|l$m3fVd&WFg_P-5;B$?~iU|}<2X_=j4-@Itz53(3Z7(du| zMkPV`S`Q>%gl*B&Zr}$TFvG>mHk-{)^s&qwCJN8mk0s_+iFv5wuFewfCf4~mP$$c< zKR56GhQu(7mU{{JG1Y$x+K+;)(@)FY_A>5wfb?_6XtAnVVfiHk!yF7=F z`sQ}bYO;|lGwB^UT-od%v^C2KN<)c%d`*Sd1#j_Vou| zzy(D_Zgwofj=WuZ7m}IR+lUXXjCP!B*v!!UvIf!Smt}`9Fh~>54>iVbw#oZJDBWqu ioI_xAEDgRZf01s1=f;sAVC^u6J7o@?*hx5GO8p1gRAaLM literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/clipboard.m b/amigae33a/E_v3.3a/Modules/Modules/devices/clipboard.m new file mode 100644 index 0000000000000000000000000000000000000000..a00ab09008effe6f75fa0bd0ad99ad8aea989f43 GIT binary patch literal 660 zcmZuuO-sW-5S>U3HI^b$iioHO4<0;t@DHTPVuNi{wpH;I)?||g^HGyj=)dvzc=8|B znN3SuFfcIl-t2qxS~hfTIE3~0yJ-y78~|uP&|0kk{3M>w^86z$BLE#50M&9X)s}%% z!=H&Pl71Qx)I_97FJd(!(!xSD>PW2=Ra}NkB}Q5R)FRVJGaPi>?JTmmB1Wlo_tef2 ztB7&`RAefQ4jNpBiHJ(FqUlN&MPATEKG(vp7V2d^-y|}Nsu|JB@iq{Zz+O|^cX=3= za+~vhFXsd9)j7MAlem8_)JZzagLSrqenGmVO+m6nN;JSJmWK5W^xqy?J=+_*lj(-B zdW>_=?M>VPn=;2nyn}U2d)71OY&3o4&JLs5?8ULz#Ipv@xaXSO_MF;nKVnt?k9NvbLl3rcs{qD|{jkd=Tf%t}Ro) zWY3v1GiPSAwr&gAm-zkulMZsIhdq(WUwMr4BxL#SCU-uVtTWDuvio_s!=6HWoEN*! zhQj_bYZsPwTbq>#BS(msZh0s22$92>(~E`NK~xXiF}M$1>36X4Eh~YjdP1gYLlumx za&!kbA=eYCIw!MgyDC(-Hf280Ok0}7G4mt2%&o1~Cv&E%*4M@XaW8wSXPcO7~fjw z+D&rsk_=q~)AL(m)cm3~r(jO&oonhC{gk3VG|Gvd^?IC%FA|>P%pL32W5*#!r$&#j zh_mO6Iq7C&74^xxLX=h2B_~bzRqrF=*9l)G{3hYWfAOusnzf$BH#b$l*u&JBGx?Gx z>3cr%M2@O=sp?!OA@iP$-XAIMTj%!{7d&i7>&6O~slwGz;WHU^(svPk8F&SFFELBI za9^55cX|)CDQyE$a;KG`TBwTM)i1pC3f)@D8vDUsG=~$(=(R@8z0pgh;7F!5o+ADc T{HC+(`Ha8dHUsx_K@Q(PGYz`x literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/conunit.m b/amigae33a/E_v3.3a/Modules/Modules/devices/conunit.m new file mode 100644 index 0000000000000000000000000000000000000000..d2d2d6d0aa5147bd251b250611a938daa0fdf73b GIT binary patch literal 852 zcmZ8fZHv=D5T4EDYAA>JK}8P{IZ#wYyhB7p#PrhBLYtPfN7XMONw?{8c_Z1g8-JF+ z#D7$0b{l+ID4pk-XJ($6b~u@Oa0vVNs|)%%umCIt&Ta>gl*M%+B!EqsyaGVhrf+bN zJK2h2Rc;G!|161v5ewImQ{n;!g|K6JZj85LI>-#;(8H6cHAKc(P30( z`y_6_SZ`HF+q_(v%Mf#;jGHp!lAqE7eXyC+F=vJWc7zK_UgzY1p#z)UUYB$i^xBtr zB!l#Xdr_8_jchYLf;`-pYMn(X71I^ju~Zu_(v7(*{yOY|R9mr<8&co}*+Z$~sNtC? zI-eGMBvn&Ii6~N1_0Y%(?SWkxb_Mnr7vtY~AvFW+8LAk5egfSX&ZqumIA6HF=LR1A z;{fi=CWFwOPe3b}R-Au!gNZxCEL9ztDt|QFb31&R8;=Ho8+=6#b-JrNEwR%rL^SJS s?0yQp;e~rSUKkCw__A;ZbAV%%&@`>_r(WPL!>J$o!{vPRZAcB^H^@S&kpKVy literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/gameport.m b/amigae33a/E_v3.3a/Modules/Modules/devices/gameport.m new file mode 100644 index 0000000000000000000000000000000000000000..0dbf984456d540ed616f87d3d01e35cf41f84829 GIT binary patch literal 448 zcmZ9}Z%e~45C-tG>d-l5_<4NOKWCZknvi5leNzUOGIUI81@|reM)kS2>xLne%P$X? zgYr^EbVuveDtDC0YR8?6MO$fK|<^HQnUg6|5n{B!KZUp3f z@$*)GH0$wxvOk_BL3D=wKy#^L9kDTmWf!_!GtnLN26{rBO~rhh46)9x#SHrqKXc}Y zW_`!d6-%|UXx51rYxh{Jbi%nEGcFiKUc?;8MCv8$Q(^=QPE6*#9VT;T5yxyGqO)PP zquxW$V~t7tz&@$mx<#14#4!)taQe^j9z0W_%A8SYD(&$P+P3eLrYiIuN9cg{2U5pZ AD*ylh literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/hardblocks.m b/amigae33a/E_v3.3a/Modules/Modules/devices/hardblocks.m new file mode 100644 index 0000000000000000000000000000000000000000..318216a9ce4c9ac84bb891cfc50badfc14578d09 GIT binary patch literal 2266 zcmc&!zi-<{6h66*VFZRD7)IeCgNFmIUIKXnt?} z$8G-D5@P2cvH#(N5QRx)rREof$u7yZO@Bg5_S(a#x>_uhEKE7C0PYgDo8^}Tvk%UD zxvA>r&JLZsrTVdEE3zFTgG}p`z9}}PZvKfwaA5`k`PlkuiSs^r45>?nu4=9k_X79g zd0{TnVx=aUaE4Xttl6(q;YdvUn}qSsaBr$i&V18M(XFDcAB#`Juw8!BhIx< zwWX#}z4tu_Vr|jx8ym5~v9Y5*!rvixH$mHTW1JL*Xks>cYV}-8sjJJ+)l=+1*OhKv zD;__d^LDQ=qeq@629=2cy>mTb9zG!Scw_Uu1!`UIb*VW7rs1BiD(@?NPO^2OOL{Vx z3N|*VR8|{z#s&`Yq_7p-V_nwD7Ajrw$}#tI;^j6LIi@}b&lh-q{{ty z28Nu!65`^)t4qjl=~Zo@ifUm>ryfdv&-FaFvKaW;!C)3dlP6I?-r%(jtlwhYelO@p!Kil@&hQy0r%#;cmb)GICe!%o z$YC9K`x?Xco;bhBv(f3$?emWFY7k`YoP$U|Nv6Gi9J*NI6YSu;H=Z_3_;VU1l(uC( zm?1B@+~C)5u`dUcVbI(kL~%HIHW`M!ARJQ+RCw3%93|s$62{@_w86h{Y&US!9o3sr zIeOqRi=(p$H=yR&MLM01{a1x*jb%eET`QWW8^p%dVrm_Mn|H9+RcmSB{Jst%b$%s SISH_!*j01(?yTUXFIcUkOd{U^ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/inputevent.m b/amigae33a/E_v3.3a/Modules/Modules/devices/inputevent.m new file mode 100644 index 0000000000000000000000000000000000000000..5ac6f790485059bd029ca0bf025326bb19ce9eae GIT binary patch literal 2880 zcmZuyTXGvk6m1Jx2t{#3FjR_46<$Kj3NjkC?8fuT%*YP>OpT?9GaySs58M0@?*taa z2Rkz7_RBpcs#2BuoWAEi`-+G0i0w1|`PcmD$saAoTK};A!vkaWVzt{=H`QVbrpMZh zEvh>WfbTc>4%=hx>Ac)*NT!F={$_V+0oGwH)|oD6mGsiXsr&n`oYx=fYE94q^n21- zIh(C3C4*Zn*1J>u9_y{v)y?s2dAl$|2k`UEq9jOn$*TW{vFa25<5R2W7ByCs|G~Dt zt~T59dc}}omrgfI^E;_anyNO{qPpFdm-7n6k+qqY^Z8{t{f&`j=i_pTU#yEr+8a>S zOlCpnjylWu1~_*$|6yHDxAk&CJ_zsWdoJEZmHNu9)@!qYI!is`57*`5s**JPx7jOs zmb5&--j-MMdb3p-mRI$*x+b4T_@evx3}pAK)v{h}tF_6JVrLC))VZOJTv4r^^^IKR zS^1VdN7Xl*-C9inRqpdXSM^;*t)%$bX1cB_l!ZECe!~*pR?AIIC6mb#(lLl~344YK zVcnnDA%1-&_`8W0h_T@5ut<5ry_^x#Vh&>oY4fGve&A(UapH|mcs`0RA}G-`d}El1 zUnH@Ja-Jq}CiPg`a4x}KQZ!)V5ielm`MEgfz%-sshRRhU-t$1?P;z1pyZ{l?{egoQ z3dYnh_J!6@`8eg-DUbtvk)M)|CIKnSX?7Hbh3_R<5c_9}bG?g4!Tu-Aw|PD?sTs6L3k-SF>_R0l-=m|2Rj&nYqTM6)F8fT+&+&p^nNTeo2m zO%Ryy6Aw0E_ZpsDQq~-bPCwG@RE!ZKMd8{Fi@;$}8*5V-lmDq%6FCp4hKfAom`IUP z9jMOxjutv)r~SymH7vW1*J*v@z8{C77a>!c2=vC`f(Cc*aE_U@d+TzKW|Bh{?2JP& z!60GERqUU1-@VKiq8P~+O#Q%napU0Qd^pMT7;A*0eBNMFL&;9|8(b(xF8da-SluFU zWU2N?4c5xSR(Qz>rDP>NbxYvwtQM!MmQ8jt`y1b7{NhSY{QK3xl42tK1%?eM(hB7ra*eDH> zJem2>kzx5DFzM+pqj`+5?R);S5t$+=j~~qKH|92Z{$x-am$D%4R&zEg#|!;OBa2}% xNecQ$67SW7nQA#O>qE;Vy9?>K_n%{sR=wbXNcX literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/keyboard.m b/amigae33a/E_v3.3a/Modules/Modules/devices/keyboard.m new file mode 100644 index 0000000000000000000000000000000000000000..836fb44d96fcb0a2b42e3d1233d4c962495a07a9 GIT binary patch literal 160 zcmZ?u^><-lWq^VUFa{Tx!3ZR47({?1kGGRce2}YekZZ7Oh=-$}i;rs%16YO|B;)Af yf+`~b)WZeQ=fj!RkY+Z5v zEG@ScmyiaASeS&L*(53F#S{aTeYKv#tXD5Lj`&Y?-KndO_fh@fh zJP7Z(BlzTP%H}RICYJ76c4+xxG4nmev|MX^&Rn@x_`-zac?=zNU#PJ|<}DP`$RQCW zKG1Bwm^tDR5iwnwADKQfy4;J+tof5;V+#F$OhI3RLAn}j@W2lFgmKi8zRiR2DISsk zWZofvg=x>= zXYdicVb7Z|b8p-ROOZWu=FEBA8_RZ0xhRY0P4-b#A9<1dmK5f5k$8F}QXo6(MFOV4 zx2#A`I!~is8ZxvBbP)EV<1i&u(R)c4O!^tRpPY`mDkky(Z&bjeDlGf}qj8ek@TO@brt4w3GCW_(ACR|C9;6|*$FgR8T>p;~( zsXt1?SrP?Fta9kGGbl~^({#qY>a5yeBj`QKP<^nugzgNkEur0DS=k7dm3ELR*HFa? zrfJlj4YS>mbGv9~8VsZ7+0+GTlADBMj*wGR`@zW(8fH5Rw}ZhMX8(JWX*8Zj>8Vn1 z>itR3+fYcPgLh8k!cA;Ua@)4iY1aKp4J>b#Vb`5yJTk3nhF1~qL0_>PpOx`It!8s(a4I6} zVDe=4UC-2%Qh_V~ugZ~GQmv!X6#yJgY`JG zAkHm%2G%5(pm_@onP$y(&Z~X}d(LqGxvFIw4Q_h{KUsWphMeb?UB6zbmQ+XaL-bem zth)+beu4hZ(B5m#t76RL85tf@@y#>*gsLs8quOBqpVfa*{r1k8C z=jT}aICX9ujPR_^80CPP+_2vF2RN`FJvn>I+lJFN8XQKSkYo65tZOly@D}S1GBTUbRMe^s2<~_~u6YRF zWBkW<)3#D7=ktI5bNsuNxlU+I{`329SWx5^Lwx_C=;?`QxnBJ2HtiNQy#QWns0E>rJm z9uj3dIrF^(;T{nxZ6fEXDpYmv-A2JJQ-wq?s4nqL0xh+vjjSY}hr2v4liNJ89~)^t zd2$71YO8xpns~zViJq|AFt~{(t+f{F4vfz?b+sl=tkC*SA>I9{g*~P`yGxSuHKM7| zn;GrX4a_ATdf}K}=+kwbq)zbzMjOWl>}5|Gr@?pq;Yi2R^Iab^KY1EgwHNX%7Kf-V-gu5h|>(Cry_ tc?LKCds4N(YoZr)!7Z~)W<{KHHvGA~#vi9$trn}7kBcA6&x>n^{{ubj&h`KR literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/printer.m b/amigae33a/E_v3.3a/Modules/Modules/devices/printer.m new file mode 100644 index 0000000000000000000000000000000000000000..d7d8ec584e55f2ad859a64962b77685ba2f2cc7d GIT binary patch literal 2156 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 WN$(?b>D!aRn3ZG&j(BF#1IEAg6Ni=n literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/prtgfx.m b/amigae33a/E_v3.3a/Modules/Modules/devices/prtgfx.m new file mode 100644 index 0000000000000000000000000000000000000000..d67420cea047a92ca735436f4aa062a290406fde GIT binary patch literal 1010 zcmZ`&&2Q5%6o2gss;UTa;J|?c2M#-M0K|ayqeWU?t}b#o`_}uoNNbNrh<&n_mDF|WGDjAP#^??a ztUt9(+2AakysPus&yeqKm7||$qBXDY*I%&y=5C#{@3-r;5?gzF&iB&cw8C{p|c+ z{*$kKhduQ52A1QGTvdVN_#{;7X?8A@7I~Xj>87=}=L%0+CDvtHF)@T^xou5qXT#xd z-7S6y{rhE^nZmn&6r$V|JV}IH1Ny1fVgF0H+2g3Jt1r0gM2zyTmf4N3PlYf%E>`)y zRnpyU1YczeE!sj>*33-9vl?!|xzuer#OL8PU`6~I{+mX}RI=Hy$G#rxS#<_~XAc}+ zjs5*&)!xZ;esCJc3-1O#kCWv1jC+FxJW0OB4)uYi=VO>T^B&OI;pZj9fG5d#`URL{ W*?k(%u#52VN%QeRyjYHbu>Jvioz_AC literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/scsidisk.m b/amigae33a/E_v3.3a/Modules/Modules/devices/scsidisk.m new file mode 100644 index 0000000000000000000000000000000000000000..47f5b4c165016ff1a789233e5630e88e287da5bb GIT binary patch literal 612 zcmZvYUr&QD6vZzKE@WBEvP>V$;pghLE}@?usKcGe1LsT<2Rc3wqxu; z0;K21xu=JUIOT8#hwHap4D6zZ?;i;Edw{yEzsk)LpbtL4(liFY^&mjySF7#1`Lq+H z15-9TQyulN{N8NL7H2&e;LHefx)CB{B;8OSeUp#MtZRx0P+ioGX?9j(f)AJVYFn>d z2@i&taAirCN^ELbmkV%>c^=*srU2Z|BavmA#|&UhTdA3nq0R*3`Yn^WKs0Q5)S?Lz zkBe716H3zrm+Dzdq$7MDU1rF*%2{40fODkxj=nHVeLpyF98+Qu6^YD|Qiq2l&1Edo zf;e@!J0#4R!dgT;+B>psQBkX&>z^(-EAmu{gsire^@jQclfUm0{_)$S=+sYtVb3Sh bNgGWqrgLr&VHR^#e3&s_muzAaGha#89iDsT|Xf8^5f- zq5p`^JL`OaC8XVFXJ_7bW`l~fN1J57+kfqX`m*Q}bzW2d?vALMmA{*LSu@|lSv8wC z6XKICyP|FC(cwiiz4%%nNcQjQ@y+G5{EmH}&p&XE%V}{n2jDzC`Zz9bCbGl*qjCMM zsjf=^DDaxHzAoyz_=8IQ)sC}wD6Gq3vdrG0=vQ4eWefOzhvIoN`!TK>TMtCDg_VMB z>e9))DViG_L6mS+cFmu-UaQz+ebf|(IK#Tv6mPMHQ*IN{#$VdwRWDVEZ{ClBMDY%! z%fwxh=S+5(s3b8bP7-A2yka)szwJP$nQzXt?~nL|6M$}jy6f}_(~gbRr+ht+iNMH4 zE*Wm`wzaY#lA<=}t*AWng4A(C<#8NhABob3bhFJ6#HTFSiL9$ms?Jzz2r_c_a##5($5C`e8)w9)B4ue?PE}_m&>J1~$aDwD~*(wB|UZ$*hLI{xn@E3ne4Uo+}uYG{ZNmXLNjLQV_w<0(cYq8T!k|{ zqyvdf9M8B~e+t?u;$67rAw>qf1UByGDcg}b9!UnJeg1Lc6`?=qg=_9J++M0;=ZNDe ztTZu$`d!lW#%Z#j+HHsQEFAKi;6U1y`3FuII}y5$Z*ai>FsfquW>WsFF3JOe{{f+@ B3VQ$m literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/timer.m b/amigae33a/E_v3.3a/Modules/Modules/devices/timer.m new file mode 100644 index 0000000000000000000000000000000000000000..adb2537685be3c1423bcabf0749c4036308cc895 GIT binary patch literal 414 zcmYk2O-{ow5QV43R3TKTM_^Z0+#w_uSmZ|}4hS|CGM2DNRne5LISXqJ!;Q+kNkJWH z;_)~0o=4F|mC-Q`@%ghaD3)T(-*1}kc0`-7^lShA;rk7dLN~04xTA2=g!3FT!Xi}L z=MG~RobVxv;p1Jma&OX8@Ocf=L#;YEAtKH}6aBp{iU}0GcfCyErk262_cEwPoL_W? zep?#5C`?*cH&1*8JGJ$q(YASPtSR)sVrJI|Y{qj+v=51~I?b!}mT1a!EcB3!gxp`{ yNy#&K;e_3iEUWchs~bxMx1)czwzMW^!kbWx73wm<9*Egoe(~jt-v;OB1N;RUVNHzy literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/devices/trackdisk.m b/amigae33a/E_v3.3a/Modules/Modules/devices/trackdisk.m new file mode 100644 index 0000000000000000000000000000000000000000..83bd8ee86327b5c5d6825b8b6241f301d0689dc4 GIT binary patch literal 2046 zcmZ8iU31$+6kR)Z>bN1eB|w0F1Uf?*hG7zDm_G1;EUg_8eIc#uh8K-vt3^{M&d73x z@Z=xC591$|b9NQSjb=2~p1mLE+CjVV>oG)rV;7kGc@`J+b}%y%3j+vuQqF zT;wHoHo0rQvA0>F+oCSM9na1$4-U&>G=4`TV&4%vJoo_nUSqd*ZP5@v%**U@l1)d~ z#v*=fD6>L4ir?@9#dvn8cv9q7+1qS(&U{qT5MrK<%ULnc|H+IUutqs6 zN7HIUqtwzGUr+OkNmgi5^xX!sZnX)l^H(;SXp0@Jc6Ei;ZRodmws>=%otM{_Cg(O3 zKbmA$`8Zo)o4_8gO3;RiCq*{TimPm*840nEU!$!>ZTT$wyDYJ(JDJbs_+}@~7f{q* z*M{!Y^8&P{qqA&E0MARjH6fb+qArNy^wY$)f9Ju*4;3F5pOF6dzDSqaY`x<`#$)aZx0$E*SQS4$m#-^9UbXJyPuV_tN< zms*||4$Q_*7+pMc4X zc$|g?tZ^i(6TWeC2c(Bb2XO?HzTZ^7yeQpZknltkZ^74>jyv$H;~r~{s1hxY(w}gZ p@O+S?XLY5QxPQ_Yb1YiG0?Ri`vHM*AwM_E)yC2P8$8&8b{s(u9o9h4o literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/diskfont.m b/amigae33a/E_v3.3a/Modules/Modules/diskfont.m new file mode 100644 index 0000000000000000000000000000000000000000..00a2e60a76ce8605edb67fd01867f7378afe1974 GIT binary patch literal 106 zcmZ?u^><-lV@Sy?&Q8nED@jT$PG#^fNX>Hr3b+9UI2_9oGjl+!Vh#pIztnON(;0|U gK_Z+$Wd-@gsmOwyKt;jHi8-k$a5FgnGcYg!0EoyWasU7T literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/diskfont/diskfont.m b/amigae33a/E_v3.3a/Modules/Modules/diskfont/diskfont.m new file mode 100644 index 0000000000000000000000000000000000000000..80e2755a6f72237aaae8a038c3f17a1dca106b75 GIT binary patch literal 888 zcmb7CO;5r=6nrg}5JHe}@Z`bY;KBPAC=e+num?Sn2DVUzV(4PTlRwd4B);hf7Bwa| zDcPBwH}l@39oK8q8D-CVeyAn~lgPXz>u@0QgC$Xon2C0473poL;!MmOczzP4_5-3a z7`=Z|318-4)7N@S#9mdc)r(FcQ5|=QD$C*X-_?a;LZ4}M16|I;_%YZ-da3-m;xw}0 zJm-e^)>=gjDy**u;Yx*b+_8g6jjehP<8Xs}C@gBmYJo9<(fvi_uQ7{}INs>gv5G;E z2N^x^TbLx6@y3uwg*0r?{INlFS*X;(41Mu~%40G*{m}kmw%KKgyeEV9arm07xlD#( z#(KXxqEfK(7wO+*e9J(@FB$)JGu3OIM6Cj}jCo%vCniP`Diy5q$!^ CDw==* literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/diskfont/diskfonttag.m b/amigae33a/E_v3.3a/Modules/Modules/diskfont/diskfonttag.m new file mode 100644 index 0000000000000000000000000000000000000000..7414b55774b611262114cf74d82efbb9912ad174 GIT binary patch literal 1664 zcmZ9My>HYo7{*k@&4V5kH`kr*>F-pI(v z$jG0-*pWYhk&%(-vD3SQNRjgX{J!?{emE+(saO^9Y0tY4(F-3dLaYtMrVy>LzR^Xh zE0uU5dac-A0db{Dp28Cz;*<5R$yKWBoTL?ln~ZTIJy9u0AMYjl7&Y?ROQRF|;l)m_ z`G?G`&zizkxinbc!ux|hYT_$7vWT2A{9AQZ<^HBL!*Y3Jyb>1iVSMgTo6R|=aDD`?7`fA7VLw${XFjc zo4JKd)TER}%HnL{#Pi56P*CxWjOrJzfnN?PqB>`dW_`O#LfxFSLTs>0nUYmvUC=W_ zY%`L%HdFKjdiUs2%0!K1;%$YUK>MuG)ajE2-NJ6y=&StPlU?{2yI>FT%{<;yb7GNL z;g}mHLG&0$6;2nZ0>~p0U+F{Tv&z=vjL|rkQ#H~?X@q0YSkW13-l$@%3p9%=wrJ;U zvMMGqPCNvwab{)U#)`u4#*!bB4HH;Kb$MAS7vzautQ^GJW4aQ%SmH{bE4BH51$DcN z-F1=aAt!fiou8VhuYU(CnXUB661xrNj4b?uiR)mM_0p@*oY2`_uv|{$k<^CeN7I8(FyormN8$2WhZ!_|FHL=IzuB9P5|jI(s)-p%GjS_P9lH?v5DPd_F*WftB-0o zZpzkT$`Heu#+f*ytn@eo;)J~=;jJ(WHX-BP?-)?!AAAqLH>2YzWs-lz{mj&MKeQ=L`7ZkZ{LwEQ;CbkZfyuQR@H6K%t z&v+$5UVC$W5i(aO=_=eYOdfk2Zfs~_=&0boHuP$Vv6>+Z4iff4Px%MNU(I)fec+8t z)saqAT55RV#(lX8Hq?d85k`9rc4r2AmFsaC5gWYUt{&k}4~x(G{*!lSFW>BkE~{o( U8x#7;wch@#52vTE&#=hnFP&Uwi~s-t literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/diskfont/glyph.m b/amigae33a/E_v3.3a/Modules/Modules/diskfont/glyph.m new file mode 100644 index 0000000000000000000000000000000000000000..fad2473ebf0cba3e9db170eb61bd27ba859a810c GIT binary patch literal 458 zcmYLF+e*Vg5IqfR2q8!j5h*_O!4J@XsF&iUg1+>rBuz{f_fle{$q)E_{!yKoXtI#( znKNh3?99#6YJnsCou7XY3kZP8H>QUJP?~O6?RDN%g=^{#2wCBLUI3I=);Q(@L|fq~ z8A2hJ5;4OuUF1k79vp4Dm6>$=VT$*LDP}@p8qXd; zLQEvg*p#_gxT?@)C6y7qD`|bLOHFSEIG%Q6tf=O+z2X#Q0-SXtK5wrFe%AGv=e!tN zvfDhxg`?)QI#$EztWIgCyhp^DR+d literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/diskfont/oterrors.m b/amigae33a/E_v3.3a/Modules/Modules/diskfont/oterrors.m new file mode 100644 index 0000000000000000000000000000000000000000..95dbeb47a8ab43b5739ddb17495190a03f911186 GIT binary patch literal 336 zcmY+<-422<34I#|{We{toKc3{z->HVAQnO0 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos.m b/amigae33a/E_v3.3a/Modules/Modules/dos.m new file mode 100644 index 0000000000000000000000000000000000000000..a7c6bba3284648d1b855fdda6c341738b87a024c GIT binary patch literal 1785 zcmZ8i+mhlq48;jO+cQu3B^JmoRosg7GS4Om@RHam$C-xt`Q0Nq0cIYk=w`{*ITG{L zW;XgVI=c3tTN-T|vMQNYt|hf2eN;*M-J3x8E^O0it2+*BNGb&a^C zE8+Ra%6HZ^@}1vwZ7jU=+nR1cB@26UsN+coni;RAo%dt|iwigRK8voccO}Y<=Qk77 z(&=MCXT`arlw~veVM>y)g2L3*HL|D#GHij$U>x2vLzN=vx>2~WzN_!rgxvY*MSGQO z^`mmTuz|eBsUM`~H!3@M`J}2`Idkpi@Gml|B=dbAgu%_d;FMkwdk5S_qkg^>$ z)jgUf2j|%qo3x|Sd2aCdje8W;c4*zh8#_683pBh80)>il1VrU$JYVI&X38o4VvR2< z5RUWD9>g)np-9S+`0h^v?+KRuY3q#*Eap|$UXVZR|Lj;F_c-R>)%o9wNy4H)8{4-z z!QP_`i2-0%aN||71~DG-Njj(;mljQB0$aGuTLD3`a)OmR3S-cIaWWs5#xn25Z!3MJ zUIC2uOffp`3m4`mXM`qnQn~Ib!ARcNYv7slzz3*s&TLwlo_A~d6i)3r%be0yaN?#q z+q#NAbbG}Nys8RbesXbd2k(o@-ibdK!Sk^wsodBjYD%S*zHxcZ`4|Oh3m5&>(zE;Q zbv;BN#Y64gbrZNKJS@GO;Tek#J_0Snl>^lu`n)tPLMLr&&T)PRSzwIztqzwVW^zPd zc2xH#FZmv4y>u1NKaUTHyVOJO%{tH&_r%WN7^Pa6nPv_u+)z zvNNo%`lU2_|N3n(JvY@?FlyLZoF98EZmN_Y^VIO7Gqjl0)$v|*o&#yA8N+kk}?@L3b6qP!bJpJ zTE1Kjjq8tH1AX(CqO6`3oq^t@84s8gg) zs-)Cq5qm{Qz4}-BzH2Qr@=WQ>c5zn8NGn}zvkk!iL48T3%9Wz^?tgfWXMRmLC5`q( F6hE0cJ<|XH literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/dos.m b/amigae33a/E_v3.3a/Modules/Modules/dos/dos.m new file mode 100644 index 0000000000000000000000000000000000000000..362084bc57adb7659bd99f6c3c4b70191298ac43 GIT binary patch literal 3856 zcmZWr*={4(5xvwhU}RYq20~y2MxciPo&kb9_zR}leOv0V7tZZ&Y4miV8F3t9ByvDf zW6LlQJ>&!OTiN%0bBsJ>ae^%GkCMgX8LEWe7)~!0VwatpiY#RMt|G0TDTk^1G z%-W9Gy16lCG=4rgJDr~b-!U7;j4v-{ljrl{bUK;NsJsny<8nNjL-KSumGfJ`x@V)= zi`o2iJ|skBn;PenXD{R&t?e$5%h~XZdPMi0Ud@NIm&2(jx2NBxz4_HkF(C4Bn(MReEqrYCnswa&37I+{IDI8lc5o08HVjBE zS8kwx=Ir!JQi1yr`vs`eWEo1k^U<>xbQQmC{K4M#$7T;tm)5z$`My2zxwTR019xD| z7a{qMO7g--HV*2v@=@Y|Q})+|EGwM#Hm_V_OJm-K?B^;gdSAC;<&RyFANcBIV96|g zX%Y5)8Dx0hyTLDsJg-Q~z8^SS!W5L~<62VL%s;M+%0{ducr8esuVQO)(u=))V#B(E zNpqhh33lKHxAA?&i^{FwVi)?o6%01a7X*9FhIv!)+cv1*S;XZJgFH$tsA3cw;>)pv z>v-D*u=H*PeYEtgMTG;otwnI!Y%Tm+MRyinwJ5se<|YV3Tb9Vd;`a5=Fe`B0#?#}#Jc)BCXkCg3r`mFF>o+S&yYDeBMYui4X`oVXN`7 z#puod^mLtzKdprK{Z1vNwSC{>tkHic&ifAQ9LW|2y1k?-2iEmY*b3D9gX&4|$8`$& zIa@}GRskkL74(pUrR?`A3yUlx>8!|Jf-KXTQEpPJ{Re>c*=edSKGf;-6SWY8RZ`@V z-F{viBPHVFI&G9yH0YCYcE*oXznNydFvWxE)(aB9-W-!?wVt>R!-)G8K+_EAr2l&6XIP*RK2rYi_H*DAU# zDEC&2a-M83w_%zz71z{O&mJVXPEXe1Dyp!=`)`d1m0vjSaLhnVcCx{Y(~DU4jBwdq z#>AuxcD;;9F`io&KNmXYjYTv|?5#yCipg$hcAX+*{6qB*DY7ysQhbPLm+v=|ND;|2 zhZ2XALb`2qIzFxg3?{8&uoVX>$F$Vjyk+2VjR6qx)5&K^SqgQgdkwXWM6!38t4G2~ z8M_tAmC_^+%2$FH`M z`xYvjz~cbpEpZ#NIZhAWk; zkwUP&{xA6&%Iz_Cz233@Pr-^bYB0{V?J_y&!Qp<-hm}ix2n_hHY4P|LZr*J1MxXve zfB&w2gPWZ@`t$|*kM8O>xOwZ2eysY}clC+0tDJtoXTcM#sQ)NGvSGp^O_LJa5PIEj zf+1*W&63H#sb+$;i0=%1=Ey$(G9*83B+b_wcJiRexs|!=Am^O_;W7_k-3D1JG;f%0 z)<=FKhaC;god@MNrVk!;9)9(`hY#_7?~d$zMb<-lWq^VUFa{Tx!3ZQ}7&w3=OOR`@YfzXg0|Oh7#}*ds83kkm0RXX%1?K<& literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/dosasl.m b/amigae33a/E_v3.3a/Modules/Modules/dos/dosasl.m new file mode 100644 index 0000000000000000000000000000000000000000..ca5f7b8d9096065ac9e7e19fb2b7336efa075375 GIT binary patch literal 1160 zcmZ{j+iu!G5QfKuPz#}mMpe~|Ui1yxzCqV`O{^GuWt@gySq4l&u^=+E*XjB6a($z8 z{;{EeS}tJc+d2II*yusz(ka!S-`hi54hnMd&h0& z&D*TZmm4~~L4{qcCO6Wv#owL9a<-DJv)Q7^5sj;a7FkwzR%CD2l5Cyx53Ar$M^r2) z^Hq79ZRSiw$v9i*|CrY-vh}f!Hgt^3Ji8e$HqyVtq%&K+TTTVb99BSo6|^~eSmx`z ze4kI{-ex`L>rGkY*alP(J^HU7vYzn0MRf9%u+ye8Ug}1!ACtrlWt?r?;d@)|eOD3) zsb4XG9 z!K6b!><609P|-#00coOcM^N*u_7-t##HY14#5TvjxMva>KA|H!_fkI@Ui*Pt5exap z1ly`oq>8GZd&Gt^6$F(d*%*}V$YVDCk{1=lyq_f1Bi*}7lq1fd@~Z*YA&Vg7KCg0} zE6>w$8ok!B7ev?fmNBar4NRaD%>~$e1Jm{xoPNgUr6t~uJCmyLP3>Bb)W8pQDsrLL zs%l3SfubKKjkR%fpU-%1Ji%k#Qs+ut{WP6JirSx2Te-o1=MG!;qJS-21b%oqWCs2K zdpzQ-#(Gh^kF~n2roWP>>c_nc74~6TG_~Y8>{IyuZqi<$hCBq$zR6~5AaBGc>?PDA NynEQp7s=oQ(I3M|^7e19`($u?Gw_dccypU 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 L;MNy&Xw<&}UX$xA literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/doshunks.m b/amigae33a/E_v3.3a/Modules/Modules/dos/doshunks.m new file mode 100644 index 0000000000000000000000000000000000000000..2ac6864b9ca63edfc15d6a5ddc25b8ccbfdf1d77 GIT binary patch literal 932 zcmY+CX-?xn5QUpDBaKjm5GR-`3`mHdwB2oDVY`u?pzteKVP7xDEoNXAHnA__y{b0R zL`szUy6V;HtKiI66F+C&pBecxWlXYVdRs91!+I?r=e8Zdn8o+Vj|St$myORC7b4px zvuWEgstAjq2m5s5vuq5>-b4w6F_Gjj%^Yg@$LyM{3>hinCRC7AOr>_SO5p)JIhVLB zIIo!w`0nuYV<~!Eh=;QSs}VoN9@Yigq{6e*&$W(6)xaz$JNF%K zB>C97jiL?BCII`~@3PCh*ujfL7LXd@o%wEr_}amqhy5xxq(ip2(Dp+U>-sG`ZClk& z9>jKVq&Sr>RcXY1!8V6oc8ssL0>Jltob`)!7_8=2BKqDs-za(dROQUS;X9=&=$uwU ztMMp;@%Q4LHr}p9?=O7EJ?IwSI)2^9PR!6T z&RJLoq_S)6!>7YlymOByF%E|*w?MWV^*hF?MJ7(H>rRxyhHpw6_nKS@WN literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/dostags.m b/amigae33a/E_v3.3a/Modules/Modules/dos/dostags.m new file mode 100644 index 0000000000000000000000000000000000000000..152aa427880d813443a521634050a91ac256477b GIT binary patch literal 748 zcmYL{U2fDs5QKYKkfRksC?^OcImpN}yE}?!+L{@&F)w?S9FNEFcLyLOf&4)TAyoI; zil1DctGlaPc7ZKDqv1IoUuOC;A$szTUK~;N*;rn;i9=f&7fIOkKDKL<7F}?$WcY<$ zfYn_}K-Q-XI}_G$c0RUUA)3MW9c+-I=~eFY2%xKDnPZ z)=Tt}?hmL^oj7tQ+k;l0q_XA^=Du-SF7)F_qX`=-m-;FB zOAby?sdLZAD(;FNQ|nGaM<97$OWqOC7CPU-(VBwzlKvaiJUN%$qVc&PJ*uW(K_AIB z$Ul(C#m{?=)@ivotM{_ee7VNIgKNt+zu;W?XnEBZETgGT!0;a=99lE{fvy`5g$%SW z8S5?=4teRCM*Gm7&@Q_)Fv)c*b=>xEOv0gM+9gOXras92EduCHf7KO&iB|4B%)9~} GB+-AMJ-5mL literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/exall.m b/amigae33a/E_v3.3a/Modules/Modules/dos/exall.m new file mode 100644 index 0000000000000000000000000000000000000000..605a56a14b3b41534ea3de34b17f9ce38f6896fa GIT binary patch literal 462 zcmYL`Pfvp|7{*^Fn}m>M2M-=RcreBf;1^g%4?6(MMq>108mJoqS^`}heoDX5eA?k? z(xkuV{r{FlNk~%~&hP)jw~q;t^GfscnMj;?Rb@)*R#mWh+-ZS}YB>J2TFx~mnwd&coHUsT-}W(DT*+&J zD98GFx^E0!qJpmY8EMh93ONSbUCw*kxQ)B73pvt*F0%4E)nlgW8k1fon9!5@mZCit zxy|LH>u0O%2ZiVb76-S%RxlL{KhyUOGdm)hg2H7AnuA=>W}BpJm9CT6Yz>`5TP0D% f;uK{5;TB5r7PBqhCdUnUxBeJ1I-qzNfpGo+GTc)l literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/filehandler.m b/amigae33a/E_v3.3a/Modules/Modules/dos/filehandler.m new file mode 100644 index 0000000000000000000000000000000000000000..79c3c12552a11317521abdb6b188d186bb14db48 GIT binary patch literal 1124 zcmYk4&vMf+5XP0_mJmz{g+mWL^w2{OJ#gT_fdfvg(oCH=V>^X%VH`(EJhiQi!a~1|LP6Gly2_29$>7+o5z{huTU47|$%<4+-<=ofLX*W<7u)K0%)F$AvnhqTVRbr1 z!vFen$e8YiLNjS=kx7L@uqejWYc)?ZVH0#gy6~u_S_!oeL|#nKm>RrR7~@{yR0%EA zM$Go)Y^6k6AgduRV$buc7OD{G#=aj_a#6^i*|sn~WM3}x#j*hub5*U&>3TjF%GO5g zJwPeS{XZb~p-dl9QKjKYVl=alrTH7MNcq!L${H_Cw`6~wNxhRGZ-1JuZS{0}lgX-9 z(iBGe0Y%&1NdRk%jn{7dW-d-$pa1Z~IJqBlSjX5dNN;jIirei(EEnINAWd}s2c2-pvZzLfi=+%7&@gX SA&vE8V2RfYIE@8ySpNX)&euKw literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/notify.m b/amigae33a/E_v3.3a/Modules/Modules/dos/notify.m new file mode 100644 index 0000000000000000000000000000000000000000..578b092543d9b64a9c84a8996d459519b3d46cdf GIT binary patch literal 716 zcmZXS%Syvg5QZl;N-3q3Qbj}*T!;%7B0hkzO=}=cB`HW(;h3COF_)T?i0)kZe7=$X zlcv<_5Xj6o_esprxKGj5sFgJ?gKX!|Nd=z2NXS*+$kS|q3ose_(BiX@C=w(di80U!2-{Mt8` zN{Km^Y_dbX$zVmw2@^oxq#Hy+ReRNFKS)Eq%hGp{;ArJWtv@$xBJ(IrLG!c-9?J}7 zCu??DLOR7u!*fV&Xj_hZ q^NblytvHUkWu77JdecN>Xfo%+#Lw*36@|0}= literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/rdargs.m b/amigae33a/E_v3.3a/Modules/Modules/dos/rdargs.m new file mode 100644 index 0000000000000000000000000000000000000000..166ab55e1ecd7c7ecef45151157a15e025aa7500 GIT binary patch literal 404 zcmZXO!AiqG5QZlu%2JAW=)r>rUu89^1hUzXZoykflTA|yDoG0B$%pY-Jo`rVpKVf5 z7iO9N|379XR63vw8sGQS%w03X|3%_>BjyB* jc_TM@OL&!%Pq_(I8cP%A5xVtAe{iBUv592%$R^Pb*c?f0 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/record.m b/amigae33a/E_v3.3a/Modules/Modules/dos/record.m new file mode 100644 index 0000000000000000000000000000000000000000..8aeb3531f771696f5a098d67aeac729d4db8d5ce GIT binary patch literal 214 zcmZ?u^><-lWq^VUFa{Tx!2~3O7$Uhw=NUMv4ZglMtd!w3JGqytmyUseF zzi;&;;lTj9dOSZ3j8tRbo`Z$E;fbV3QZEoi0BUNiGhXm43~@@dN#|I^KK9lN%a6Sz z-TAA?-F5^J5eA9?7{h4aTx6NZhVpSu`Sm7SCTP;zK9j8oXrcll7{xxG3)r6n4DDn--7S`C&&1N)jbya__ UVScAytvYUzSIS@g2zwTT-bAQW2><{9 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dos/var.m b/amigae33a/E_v3.3a/Modules/Modules/dos/var.m new file mode 100644 index 0000000000000000000000000000000000000000..94cd09ccbe1aa1420f70fcc9ff6c41e1ac0f2a73 GIT binary patch literal 416 zcmZXO-%i3X7{$+)i7*M-1s6VmFVe|emXtOr*o3QQ5%i{kL?hQeqHl!fEBFU#y5;P5 ze&5<=ZfCf{X?=c&GKHLPhw^X$;_j)B`~H<=Al-Ji-T-WhxJ@j_^)Z&D6WpxXEG zol3@BU>Y}~aozICxbHA#`q2I%bgi+j;g^tW?dxA6_sFylN_T3(JOL`SoLMN}1h3qY zVcc@+539gK#j87`-0EbKq7?It4oSf?j(?+*r%7$^l@8YE6>FIs$>e{UCAZbK{*lEU dihD+#%IxoGu&Oh=0+r_yQ4DOHTj* literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/dtclass.m b/amigae33a/E_v3.3a/Modules/Modules/dtclass.m new file mode 100644 index 0000000000000000000000000000000000000000..6da82ea2ad98a1d9e3e731359e9b5de90531625e GIT binary patch literal 36 rcmZ?u^><-lV@N4U&PgmTPD(6JW$;fbNzBZ1%}dYBOBMLfz`y_i&jt&3 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec.m b/amigae33a/E_v3.3a/Modules/Modules/exec.m new file mode 100644 index 0000000000000000000000000000000000000000..130699cb01e8da29500a851c9474ddeb6faba432 GIT binary patch literal 1365 zcmZ`(VRM@>3^o0*;r4dNU&=wU=GF`r((bbXt?`A}%$Rif_1lw8l3wq|7riG-LK4p` zH)SC{iSax(Y9vul1G$qPt^1ONXKl34ZAT(uRC_nIUfzq1I?$7DoO0(BG-1A)OzX8Z zBRnf@x-E^mBjY7!UP-d($@$L(HPfpo^r)JivZV=TWnH7YtRi>RKC8*sTakp8YOg$H z&m*~j1kTpRzfkL~6LQgYU^O}?uq_?mv0P0f$wlAW79~J+?u9`KP79i{z)$UPS*q$sEK@&M=I%b7~Om z3;^$}tn=Jnu+`)@<7+CvQm|VZ`ZFAo%X2`=Erm#A&flDqFR<*pav*b|d2h#yGaDP=BY(IDOq}Q0?mSTWi@$i~Y&$u8mKPPYBHzy?g8u2KhP_2h*?6T*edSx~ z2^Z+*Sa?sz0iyg*#*-d>`Y|gwdEeJG9_&W2_8Y-Ezv=c+D6cX^VFFGU$z3XQJDkB& zDQ5IzLL^hw?kPvB?m4^RWh#=$EL3hGv)mDG%eveWG>b-YZF+j|hylG0=baOV5zHg6NkQUw_-UFv<^lm)BAv!<>!fd z4a-ii%}s_>`AMl6u*xroXm0BscEu|Mpq<6hG1Nd_W~8xkJt8kMQd^w?RVcN4rTwuN zke5J?ynws_a_@EhCRennn0?YA4Sg4vK=}*n`sSCn$Yw`w>VCLOLD%GEPHLI4>3rB) z7qtUiewnCqpuRT_l^Ek-1%KAYoNC{Ls^UDKV_cJTT;pd}@^;L7w84p`oVf6z)8q)q z`96pKhF*v>MPwbfuI|_58{H~_Y>W+!saGCW^M8;kuvTwPh|VKp`l2&Lmy6pGDz5+o zslB5t8iOO|pOpF!7?}Dv*m`X#6jdVID{^{dStuw@FYoHs$Lw2Nk1A;zgR^-ivLk1i z_e8$H_$d%!+@d>A_pbmHu7gl(pFg?Uv-@eU3LI+uF31aAdncvvHi5b?U*~Kq?^DFsqIBWtHF7(~3Wc&zCr;>f z;A~JM+=M{t)jAG>p$cjVg+IW!FDe}|YuS*Te3yL}n12)lxeB{8$*;8#EYCo8QWvr_ zA$VHxTrxm4?J?|X;TUtucq2@dlf>yYo4swJ9!VwEACR3=mxpr~JOjv&g6JXn8&hKf ziT!kpVPg^d`51ebv0sicsP%ew=#RPWwTloV6GeWghJA;+Gaxa4J@)^QWBzuG{gJWX zkFh_Y+UtByYHE!hL}R!&x$nrf^W!c8Hb>^C*&F1W7(qtvz=@z0ZXH3s=7`R7Mmfy| z@}a&5w|0KRnc`mlz}Y(>-+!HmHa1n@R`Wwj-nX4`1F}KyxqY!m>UAG{#fgTvM*T*! zY%OPP4rVwv&=*(QVsKbr&?c4%bO^^f-=V;;rMdYc7EoGXq8Jev)!%xz93j#56XXf5 zv8`k{B^#bBS1cNhgM~#_$XjepndL2yDzD-F5S{HfWt=H!oB2U0^xgQdu8gZ!#Nhb` zp2t|B9!njv4kVRAL9VEbuYjCeG0(B|&{!`ykm)%h9U*vSFn@Vv1n%kiv+RW`E3X6Y z72bmLrx{&>9X>He6!D&AMviTPJ_Y*FmRi4%O8a1ML>!{5u}2*=q-8swTls5rUbBi+M)seh>@T39xTs0i6K7k5!@~ zZuTbNHg#Tec#5-}2OeXqu`}>HgWo;E+v*B_d}n*Sz_``92YJ_#F^nM*>{6*nH(VZ2 zQ30(JNwza^gRIF6C%>`@6AkvzVR<#TX%ESEddF(+;~=BwK literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/devices.m b/amigae33a/E_v3.3a/Modules/Modules/exec/devices.m new file mode 100644 index 0000000000000000000000000000000000000000..2f6273cedbe5be076d99250e7b574b554decae6d GIT binary patch literal 202 zcmZ?u^><-lWq^VUFa{Tx!2~4B7});*XJ9DJ%Pax%SU}>r1q=*8F%}Tbz{bGHpp=%A zm|hH$Vgd4$3ldX6Yz_t{29^AR)V$<8kX9g217eVwKy@H9Q$WhVCgx-&flUO_K%fM~ nj6kf#zz1T5`gw-9#XCBOc!s$G`5-YSh?u8eh-0ufkPid^CKeyt literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/errors.m b/amigae33a/E_v3.3a/Modules/Modules/exec/errors.m new file mode 100644 index 0000000000000000000000000000000000000000..99d2b92d4bb2637ec61b5c32b2f72755698e9783 GIT binary patch literal 210 zcmX|)K?(vf3`Oh0jflwHsGVfA&}pR22(G-LXYo4fXiX>8zX;*+eu5)`S(}#oZ`mx% zO6JY%ODVG_OzG+@1dInhnuR`;W()&kX0bbQUw_vEB+OZOy-}3Y3FBaW5V{liQED9} hMrdaJRXxD7@3HltYEIF!oAO2IR{C$Hk@`{Ek}su-L`VPt literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/execbase.m b/amigae33a/E_v3.3a/Modules/Modules/exec/execbase.m new file mode 100644 index 0000000000000000000000000000000000000000..21a055bb9d91bd555770e9c09e54ad73efe15518 GIT binary patch literal 2154 zcmZXWO=~1Y7{{yI*)W63M_EWF`z*bw!Ld-IYu+)i2v! z-I?*U2M-=SdGhGNv-ko003JO00sH`d0Ac+<)z$N6AepJ(^VI*T=cS5tFNPg++a_$d6wyEo+M>d()+k%h+VR6 zu;(G4so2M1stBz>jPqL&>2ywrkyp>KfNNfnPq-4PUL^x4iJ7)al=WyOzb$OMl7$`% zQyEzpWyZddMUYL$YRcBRk_FXFMtaHX*fWzw5~n&_r{BrKk112Cy3r=zA7p`=>#`RM z`jafiO6rw(08}04PzI66v|p(@&Ifv(xXy=M>u9lU z2f9Z@Qjz(SQX6yWe1vrv2e}fZ`YzZp<)KrKQwC=ESp)QxsF?X8(F;!A&63M?`iy8M zZ@I#Rn{(stIcJsf0;Bd$3v;VbJyTINf%h)xB~BLSsV|IaY1@JA>p&Fpe-`xDQRr8? zv4diKi}zqX26=x^^St3r{6{)xDtIto#wGqU@jG5kusJL7U+sNC4e1tSlmocyDvqI` z+e)ufgE{VfTmT+TZ&L9p7m;tS`MconB=j<5cr(;|%}BLy_c9UkWD=)kG0gi$G0;Kx zU@HA7Dwt^V#2I!-O!M1{p-=7+F|^)ayn9z4oYg-5y@PYRw0Zp4Y9N!=>bgf7cLl z5xs_D{-PO#wEyx6b-Z~Z;JQ8`UMxfZS@S8eA22TfHNhkf*AAlwHNnyjxgK~-JYRC= v>AFGeai0$_oDsXy^#fcHrhVUkI(!o`TY7?zx(HEl6W zr{#7>^%!)R=SfRxBWaLJY zn;p}7=GtP_v3bi-duxag8M(g6Z8#purkFn{3s1<9Ohi73@J(n%!uUHc4!GpOdN@yS m-NxNQtXej>@J@lrt>ff~Tx)KG(!QtLQ`gtg??*U^2;dj4SZjg+ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/lists.m b/amigae33a/E_v3.3a/Modules/Modules/exec/lists.m new file mode 100644 index 0000000000000000000000000000000000000000..042483d5603f7b1d14da36b59e93f47e0988d0b6 GIT binary patch literal 332 zcmZvW!3u&v5QhJaEy651cJ!zhA3*4q2O+6f2$B?5TXZkpdbA#)H?o;kVTlH289x5` zcGCQE!V+V>KGOit4hwqUki!7fssvV$Kv~@G05MssW@OUbD&;Vba%*O~E!-^NlaZ|$ ztt|buveYuiYS|y_lojwzuM5`F&jMS`CvxqmH`r%g-aW3*)}*yIJuyKYgd$059jhju dZw-#Y%pywoS$D3wd5L!pc1M-&Mkpc<17FL^MnV7p literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/memory.m b/amigae33a/E_v3.3a/Modules/Modules/exec/memory.m new file mode 100644 index 0000000000000000000000000000000000000000..fa5ca829d77af9c395f86c9f855b2f4ec4daa03a GIT binary patch literal 772 zcmZ`%%TB^T6up?LjUj}E3l}c@2ICJ5?EnpZkWz@anG_iwNvT*$e5_pff&LNRd#9CX z;!T^*J#)^v50F9R!YNeoRUa<+a01Zy1nY1B*gPU~1{OfBUrPYQtRKvpy_I@rv^IWF zhhcOpI#HVCMnzv}BBzy>WwD;^Ybm+67wckI{&v62o?di87R0#PZ@0(ndQoUiR~R?= zn#yhNSZ`KoKF@S9PsN78=d1~>V-lZxea_KK);F=$e^pbVw3>1s4dQK z?>b)M1_H4I24YJ1zH*~bq6YhK7@i+F!bgPWHb^WdG9D2N-Qb**9b^pxF&Yqt8|4bV zh9bzfhb5$56eJ|{pS!_aimXY^B%nvNYeqp5K{cs%i HXl#IQq5O^~ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/nodes.m b/amigae33a/E_v3.3a/Modules/Modules/exec/nodes.m new file mode 100644 index 0000000000000000000000000000000000000000..8a781af2c7fcf398eaf627c6ca80df29ceeb6c93 GIT binary patch literal 592 zcmZ9J?@q!n6vgjwARr>@6OHXMmeF=;i^?ZskPjw82~>luk`S?Zp4p zM|Pr)ETQiE=XMqJlu&QGdvS&H?{A*gZY9Ap4BzC-`wgUhoG59D2H+_wVai5n08d6B zW2LNA1qX5sQdfB`SYVIKoPgNO)M0&(iXSY?f{Wlb1TieKW~wxr_`Vm8sfn$ewI@B0 zSvA&~UPN*OQfkPm+=M;nAex)m0wII=W_*Os#0b%>BV}E-pFRPAZTIlW@dM1@4PVH z(v&{&`T}bJI?g8dG^S6_Wkn zGWc=Vzu$~BvM(YpC3l)&3t5%tN-+gD$N^Wmyp0^bwJb#?$K7JwwnkAyp71_wP24Ql qMe)HSnsWvG82f1urC_W$Ve+H!%p~zMcasKj#D7Ha3{2cT6M6&aayDcD literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/resident.m b/amigae33a/E_v3.3a/Modules/Modules/exec/resident.m new file mode 100644 index 0000000000000000000000000000000000000000..2dfdfe06955cbde8f6c49ee40fc69f403a08029b GIT binary patch literal 358 zcmYk0QA)%x5Qe8EmZj<Ya9tOr&zQpc~I8_d=o+!O!acPwZ!fYaWY$q_KO&4wL%fxL6m4&E6{ z+lWL&E{rw&JFZJQ0i93EQfXY(rM#CKV9pNfR4uX!6ODf?|If}S7i!Gwswl4(5|iqd m2u};9Nsdxys+!o%kH)lKCYWBYl+LEy$C$fARg?uS;o1XTo{Z%D#V&;|7H_iFU>B3@y2;YN=|8G(lC9#v zFq1DckC$Zma*iYP@qK7Up-F(j3h90iI75;OH4Q+LO2sh}T)tKBPHq@eCbt-;VN02^ z+19Nx%DM7Gkw*>NYp`NOcIFO~LEA;WbKXX^=s{@M*Zsa!?k5;q<@~1ZtS2A=CcCoo zU!CeybgQ?(nEb+Y+E$XEB*j&|v#JgAe#6-lDqjbUUun`C=08{5j<2Gf z@H1j-NH!D?6#P>ZO@1o#HguCBe_bqRPkC`qCcXzG#lzhyn@7LkIeVEco{PtI#(TyO DF?U)D literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/strings.m b/amigae33a/E_v3.3a/Modules/Modules/exec/strings.m new file mode 100644 index 0000000000000000000000000000000000000000..bb9bf3f76a4ba4d5c135800ba0071e2d715ebb39 GIT binary patch literal 110 zcmZ?u^><-lWq^VUFa{Tx!3ZS17+8QLm!A)i1hMK}T!Bmwi^C}xNU{MjyOXOAOrF;{ U2q*&9nCGrRZK|%n^~IKJ!0`GG250#+U1WuHm*NwR_?C01m_xV|QzVrOJUI=8_P-^;G)E86J*8w_-}q^@~o`6kXnRoAml*q`N`*j1m(3_GkC z?pu*}?T!6`cA?p}s|%0oH8`%UD0oyzXc?}@y27(ilDNyKrep(-)v+-ALjdG3zHuwBe6&iyY)5wOh4ttfKjpChUo~#8((U*g2Jb2hS9iKv4X7) zo%-+C;r<#!uO;RZ));|N#AG#t1Y3>szB_d4&7!V9)_U#$nV=K<=`{?zwUEIOo8apo DcUKf8 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/exec/types.m b/amigae33a/E_v3.3a/Modules/Modules/exec/types.m new file mode 100644 index 0000000000000000000000000000000000000000..e3f7d3ecb7c451a940398139b191129005dacdfc GIT binary patch literal 98 zcmZ?u^><-lWq^VUFa{Tx!3ZSn7(nd*PLUz5zK+4(K(+u7EBbgk1vv&q#`}8udHRO> aLPRw@{hWP5U0mbCT!Vr={r!Ln85jU<$PX_7 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/expansion.m b/amigae33a/E_v3.3a/Modules/Modules/expansion.m new file mode 100644 index 0000000000000000000000000000000000000000..620a5ed8c6333951d2dff2b60f17ea9d62d801bb GIT binary patch literal 363 zcmZXQ%?^Sv5QLYDDK}q*a%%ys?n#{(qfT#>&)(colH^HIcxx*H?BrW zs^ud>B1A^&EV~>Z%!-uA>`5R*EKd5KPAPFMDjdM6u)B4#__C&j$Pe8Ci@nG$Tq;&d z_45lvrA7=~rvjHvvo*FsE`pQ33^G_*4Gk=Aa99{eEzJV)CsExRn`O>u14-3w8|=}x iur?29vb)x(OzPJd?EbBaUood~>T2q3e%jjJ0Pq1%`F#oi literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/gadgets/button.m b/amigae33a/E_v3.3a/Modules/Modules/gadgets/button.m new file mode 100644 index 0000000000000000000000000000000000000000..fe09847ec1df46e86f52a9907a1c8e886900c9fd GIT binary patch literal 242 zcmY+8TMEKJ3`J9=zCJ`m+|RT#w&J`<6R=<1OxNd{Oq~dtk8pEtUM?gHHE86oIDAAU z`30vLVAC*Biqq}xeRfg!Q79<29KtB&RoG5hW7ORP@>BQ_>zjOE2wKG^gq8|BA>KKEB@+ozFzi?N{GEbv>An0-_0cKt2T@-TRfjVNeKk?a%_~#-Rx4 zc0vIy+hO=T5&RcJdwdCE@BIm4Z zB#VWdSaK|{m3job!s~OHHax3XECmPN;J)vai7b*GXPOz0QEg{wanR$uORydi#4Op} zl|`NNkvGW*{J(Mw=b3X(v$E0;LckqSR_J-IXDPc$=s3GcMPyv&j#ahPStX=MG{za1 c!1dq)z1b1@(q>fI9Zj}Cu|tD=NDCFtFXWtDjQ{`u literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/gadgets/colorwheel.m b/amigae33a/E_v3.3a/Modules/Modules/gadgets/colorwheel.m new file mode 100644 index 0000000000000000000000000000000000000000..ccdf19d04ce63a38383ad6f44cf973ed8d790363 GIT binary patch literal 490 zcmZ9HUrvKS5QnFgRzz%!4<5o>fJ}gdKW2eipG?tBX+lZ@G+w|ncrI^LXPD*1A&{MK z=l4y(G!I|}rheyxGaZ)n{ejKp0`SqbUH{c+-S&qXz@i6w{mEl%?hd`yr@6E1_N=*~ za_MCc{P#4&>}h1!WzVo5&;5Qpc9V?K7T9%vJT&7;55wdU=K^5y1nxJX*9b9r52`eM zqb)>kgcQ#TF{1&VS_=yW-4nSrxjggAIOn+sqDzzY%1X_g^Vh=tq(WnKgm}KMwg3*z zSVE%07uS`^s5p$u42y!2yxBDzx0v|(jwq*BLKOzmFN}>B^1W^DL$dQ<-lWq^VUFa{Tx!3ZSF7lgu6CIA#+0gHJ1`8x%8M!5O}gDnRD DLs%Px literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/gadgets/tabs.m b/amigae33a/E_v3.3a/Modules/Modules/gadgets/tabs.m new file mode 100644 index 0000000000000000000000000000000000000000..e7d312179f0a534cb6def5b2d864380106a37447 GIT binary patch literal 316 zcmYL@>k5KE5QRsx5Rr)9q{|C<*&RhnKb0^-golMJ9lN4!UKkzlD$&Cn zR~wxYwKz+f1FCXvrI|r`fY1^1APi5Cl0l*(ucH{{lzmB+n-X1-(P~DYW8^87CxDb2 R8?E3AfEK4#C)pql#uv2@GIIa` literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/gadtools.m b/amigae33a/E_v3.3a/Modules/Modules/gadtools.m new file mode 100644 index 0000000000000000000000000000000000000000..9649df1af718050e2f820d70229b9f9d00c1bf5e GIT binary patch literal 330 zcmZ9H-D<)>5QWDIvavUPr9@2#G*lGY%d#cM7+7~@cVf)b+ub!majxb&bLMYTeXVIh zjjY)i<^H4ttt=#?kaYu2NhHhMVninj{@sJeBC~a=H@x3lD(Eh7@W)(y%E5FT@{)0i z-iH*?&nv)X<(e>hhqD?2BoPi4?)cN{+VmnQ8Jbq_5anRs=z1dZn74{yr}nLJ{G{AZ vTp7){vRGT$XShIR=9&tcz0DJU#&_#FsY-n?;};J>e8liuyzlk>8xj2jF*|I~ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics.m b/amigae33a/E_v3.3a/Modules/Modules/graphics.m new file mode 100644 index 0000000000000000000000000000000000000000..a94741d1df561ab3d36adffd92e61b5a8eda5e04 GIT binary patch literal 2138 zcmZWqU32O<3^kP7wYjr1{FdE)*w+v~rZc4ELQD761OpyIoN?S1e*Nx|97;O-f+b-~ zN79ip&6X4KC=UC}RyRhB%P_Vf)3p>m)qfcLc>HY$+lx8Zr4Ht1O-rNwbh%J0tP5{U zrC!V>EKGF>M6e0dO3t(_0i z2cjgEJueY(NCIW5<|fR?@B6*+a4k4W^i8p+08%$biC+I9@kV#`h10v$eEe7YYNeZy zBa|W+8qFrcWjs6usG4^Qqpn4dc>=5x~+*B{KIxaVRPd3f5Xk>{zGOj$gkl zXQN+RxZr?v2|&mjK_a}rwrh%@&{u9Bysk_UX0|LjAJ}spg7Fm^i2H+;(YxGU4E_B^ zy|^i}(z%`Li(c-^YlI>ZDapYG3OT+B6QAv34LQkl`+lxfdXAZ;pU4@mH(R66xobvL zs4o`w!7j9&YGFL%8~orREjPJDk6Lz!88{eaksft*Xccsn%5~$A=q+4vTIj3sD|i0= zwJN*n`dSt1HZmG?y~)eZiYf*Gqls`Y|vYvJnJ@JlL+XyO4ZnTk36T#GA2)<4cn1P#iH|Q?H4B1E{mtl91A@JT^w^=;+{t~%WcrM8XJ(pREdNG#j9^V{__uRFObkaA=c44 zp_8@=oy+%7B5AU=I~Q;0OOhUKy)qxPf)aWZ*H5pHH()M1R^SDVW$ZNp=Rs+Q9~Xfy zE{$ZUQfGW&s1AS>x63APuPS_D@HK20hKT79B62x^pLh*vd)ecN6MR&t-yH9z5b91k zgq)j5%;v9XrZ4Oje{c#d`Mb+;JZsk@5sRmlcsYo9#$1R&ln*b+dxmJ@Pnv`Kr6I-1 i33Ze3r|_;&uOc%N$r#h)dv&_+S&p*_7LM0ir%B3z zLl1lf2gDcg1^h~x*|pSM~E89lgOgNrr@d8JpbAk`@#nUCe z)r5-cT#9@}Ti4Wnq{y;JYeA9c zRix45MS@bdYSA`cCbHj-(`H{KGUuB%vWLiPHD4L8xvYmQ+j+$D%??HJTb)Uzp;9-^ z=Yr6l@*?HZ*A4J46P31RNuLM3vnIXgX_jftKM8^AE96V9!YQqV`hV5^7pcfqwk5f? zfwp{01a=eB1PxBAeyi*C0Sr~|`z&6@3!bH=zH?1Jzz=-Gz~?t+Vs|fy0w^2o^4uW04A^_^S?GEGAOtwX%no{E#)e@u_9M@^V!^;0O`@T5;hZtV)jt8N zy$$>^7T48B;aM;VK34U#ccndJ6nZQSE3BhE#HfxjW*>yKULcxP{s2wp6&(No literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/coerce.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/coerce.m new file mode 100644 index 0000000000000000000000000000000000000000..1b5eb100ab82b71ccb8b21a63875a111c824d761 GIT binary patch literal 122 zcmXwvOAde_3<-lWq^VR7=sJUU<8tW3?Md>lYdBvzpsa92m_eU;N&0V;u-|za{%QTL;M54 Y9Iz}$kf*yx2!s!kW$|%!gK`-d0I$gn!2kdN literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/copper.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/copper.m new file mode 100644 index 0000000000000000000000000000000000000000..3ca1512a83c7f0e6ab2b30488494a37690ca87dc GIT binary patch literal 1140 zcmZuvO>fgc5St0R<^pL7`_ov>FEgOUA!H}%`d!nVvk~Ara zj+xmOx9QTqxn2e77aR@In_&`sD#{!pASV7N@%rU~?S;v%D1(}{z@A-atEEa`vx3iW ziY$+ly+m{U1y1;&X-mDRTob2=`NBFVIqivK6 z%9VaeW+i!vehZEt+1%*{t*(-SyXbNkX|%^4jNM?4!I*IZe_9QNr4JT(eQGg8>>QKD zI!v}I*RH0cFaehP|Au>q|9VdHX9)rnBOr`c$F?rFP=yMIiqAl(s(S8{hZ5BrM@dB0Uh*mB6Z=QtEL*AgWY2hJY%{RN z1E%`@YaYjD2F&(Y03Gy^q6M~sZ=&t1^}*Dv5)%O{U=GE^i36~for|_bxjOXuL#F4O z>c42BB@V#-p|v=2)jO6k*%E!h#3C1GoKlP6cPCdm+4Ql)V| z-trUoAEoEcSc;R4sX$0`@44S+u08QB_Li-m@6}I7|1=qU`v+@3J~DPA7Baoa7;BN{ z-z&x-ZP6E!7VAMzig)Jb9phW7U9g||PUG2Xi5ZJDJ~WyQ7{DDU2~%uxi;-8H(*sj3}# z+PjhBHqT0_WR_}7TjiNd73G07j_yOF@x3g;*#Y5){%wz8_Vl zqNK=fOPH`-NPf|hMV4g6BFPrlTEW`T94=)FBmt3QlN~LxWgaPcE)%KlNlG36U3c8{ z$X#ZuQYg8&rr1vv>;V_V;v!llYBSB}s2==|Y#v_$K+^`C0*Eu*_wmsxT^*C~jrEA>XUzS3+K1(GWELJv_XI->>CQ z_%>_~(hQ!WnZdbtd3=wC(-@3t`aMHDHwGV$s{@_lHu9G9Cz~~%SEB?FOuj|Q;Mp3zm>sVcsj`C zok(ye^o=!~`;e}dD5lH{sf6}JF@MUVL@10+)0|?`4d@%x))-X#$93&(-0DNH>|84C zwS)7omxU1NrsU{6S&2%3ZPQ@C!Twk;AKDPa{p0ih-w-Y0sNQ8Ax-+FJRtsgw4R&L{ zRejccZ$r{9uVubQ(7Bt4^m5Hmvk@AMz1agRu^lWY7|os8+!}ltjqIt}C~PwHCjk%V z6X(>n41a6nY{)%p;9{?kqO!M7!zn-E?r1P|LL2oRU=P&VSwPa+e0buG=lF*n_qzXs zo`<2y@S*ZMwmsJ${;i|2mgUU(SMIoT&kw&j;YqE<4BNH0fz2ngGjE6}#GH2J>x56R z5gsV(kdNnejzp45BLn_burIc&pDzHiy9mG4Nsf^?n&OPk=B%t z$9&+zL+=5~D#FO0+RoTB*`P`@lVEggdPQ5jZ#lETM{DYsp?dx|sl$22*}dyjZ3tmhAW>kLvv2ii<-7MSSh%DPwF fF!G`HSJgG}rxp>L>^~WM>Y=u8)aY*mAn^PL=s@vz literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/gels.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/gels.m new file mode 100644 index 0000000000000000000000000000000000000000..2418c7b166bb45bb44337a7a4159f06d942e6008 GIT binary patch literal 1898 zcmZuyU2oz>6djNkA&L-+s%W)}A{13sR?0&a^`YH|s&)d@Dqv(2vhB-i00UNyO>Kve zxBjU9zx14I<3L+07IV*>`!VPGPP#+qUcFQK^VjEMp&GKND)sJGHC|tpn#W<7=~?Kj ze2?}vOH%L*yg%aw8;?QuVzyPPMr8K1d=Z>h71my?I=l>6Tb->HJd7P9HGtNE;&16E zj7X$OUZ^7<6y|Ezlf1kxOCGkqs*e3q&1g$a4JdEdmz!9ER)zncOF7i5Q zx5UmXHDI@OB%55H=}0zsp08hae#jtl*7NeF{FDU|#K%KTzFGTvF^@Npnd<3zfnV#V)K8#;FqOK&@3B@n z4+wpipL!P~Csw>_vYvs{^I!-?~w+AHi%$VN&x-Q-Bj=V!^Z~(v0AXv zD?eQ$*)!uXOJn9Q;{@F(v+$d0>1755ON`!U$gxYeNstw6`OX>R96KUh**~Hm7DalZ zGDTGXa(3F)tJ4!nOlFe_IHY5Qa!01%KRb+FUnKfj#!xCR=dd{seVv@nC%=<+IVrTx zU>znJ^RP=xK{4&>T&9Mr_d=4suKi%O&c9DaxOfg0xC8Lex?K3%+#U#;S$4%6-qAb}jSnSJ-4I>vrV0LoC3kDl(AbVSH~g zhD1eHadIrMfK;T8N7J6zqrUi6az8{R@m^R)QLSe_n!gnYqxZXmzB58>+`Mga=rVS@ zUe}%GXkDUBJ!jf=djsb&uT9nIJ$&#c_pV8d|5d8iEvmJ;ZeE$HxF~7j+WkHuFsf1o zJw}BFxrVlP=M1R}&eI{sd6;;UZh@$pIqJFQooD}!l0*fA*;&z`IE{L>9#C^{VD`O& z^XeTVN`0m3uD`M5;y@SG)%Yp1qwKnJ(~+N#9mnnD^@vIz8OM%-%*4H;Ipp+e!)p*n ME4Yp90Xca70mb-!^Z)<= literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/gfx.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/gfx.m new file mode 100644 index 0000000000000000000000000000000000000000..dec5235aeb3fc87610a5ac14e7c1364d745e26fb GIT binary patch literal 742 zcmZuv%Wi^D5FIEIVol>GxNrffo7VILE^^VE05w9}v>Sqzs)-MRG}WD-*gvu}7iwu! zjmezHoEb*AfA2s8%Fpq$DxfI~6+p4UIGq5BY`feP$g22-J;_w52WbRNVydM(PhX4v zEh3$i^>QN{B+?L-O{5v?WdEbJ5LJQDJ|{M5J|!lb`6{JM+@O|;ThuaD&}x|~=(SAa zoGG`QE{k=NA=jeB>7ht>S(@kD52WN273&=VL<(qct7I-Ap~fuDiUnyJcI#O(qnaid z*(%wjWTdN@_*3K^uSm0fHx45fIBen|Cho%a?Y~@`e7*?A9t(I_`ZV&@IJyvWZY+X` zPdv^ZIY!F6k@G*+jU5qU<}XdP)~(h=t0cl z5f{TzRCVB9EOz)f8kIKzTSNm7+hrbJfyGb4Ayr3CVZ-17pAsh@$r45;WNW$;0Alf@deo|BCtHS};yi=DGs+JM zoJ9MuJ&98O-csJ4>co*swRX@2HV2RAU9Tg0ffkWucBlvWG~#_fL^$LS9yz-J<03js zM@TvQ!1e6j4xMJ9`=RZLFdak=0c-)t#dMG=FSP6=aN_7_j&t@=nn)iR_EJywJy+xN zu=lY&*oP8_OPxUMXb$A%6RJ)SI~fZ?E)x=YR3LmP+D{4D6~20X94&Rm6~g1)2(_h5 zDq>3dS5@4x_UX^V@=vaxCV?1?2(Worxt9825_nk*;AH?UvFoAO%hhF!)?@4d(4WVs z69>I8B7v6Nh+-LvV0=YKco27fnUG}Hv=9|5v75Ox3HP)u!hRiLgWSHsZUrJ$PFF;Z z7kXhVA)%O4vP8XhJ8;58p~-Qd_}>YAN5*O5$-s}$!5PaxLO;qW7Wh-G?mAsRkzU{S zRhm_nI^<9IQiDX_pNEaV9BEsHI&&Svy)ecU#?tb$+EX{*?|N?F5q|@{!}wx$wnk~r z@e`Byu{{60o#Rg2i?U8YRQz;~jw^_K@$DQ{VFG`868Otqk#;R5?10D{R3rYH)05JR zl%-;2p{iLGNOGnqah%|+7R@ov?c8?P&uAc5+$ms7+9SG-yU{o?$rEFE1sVbKg( z66MQw5c%7~{3sa*mg@ydScwS8%pxRjOiD1}!}&A#n?sg)zNrJ|@@G^UigVy`E=Tl^ zqaM-QVF7&J&bNd0$omJO^-ke_>V+cd#u7Okb=x9z-p!lHk2rNz8Pm18teM=p4H<9tqFdXEB^S|+uEHa_2 z{gVjyIMG0^OZ*;wdyJzXEBE_$A$;ofe`%BGMe?xj#jfN3b$7k6MutTpN_Gs9+vSO#TYG#5l#(3=`!xgJ&Y+$hq9*=iHD%;pn? ztefzoqn=<+@eHG`TIG7pA~AIYp-lTKqV!9VH`^`h3yPT+J>abSAkS6y%V(y&zG7M} zvx-WQ&8fnT$})MH!=JHPF&mASEEETn$V(}E)X$7O0w>Ldv1WdEYUF{U(X4bXQA4xV zJOvkoWwDGgvc*tSinpB=mOai6INe@!c0lh7Oux*2zCdv{o2OTfz6xu#O><+lzT9eJ ac*qJqi-&h4UQ51{9>ISJQpmyKOz=ONX&&nU literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/gfxmacros.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/gfxmacros.m new file mode 100644 index 0000000000000000000000000000000000000000..6870c0b08458b195741eb6b84f2c3f27a891a79f GIT binary patch literal 1458 zcmbVML2uJA6n48&O=aT1fdeON;*e-LY@i;v;U>XW$*oOUoT99Y@Ubl{cHq6bHQqCfB~Yo)O}>?}UbveuDS(42OX#uLS!O8R(&d*hPl|i5De%Nc@3Vb@qr`MybSmlek_2#Wj z^?NR8!`UbZB|s_Vq2lH*!nd4C7p%xqH!r5M3{VeYpP+@$X8Cfp5g>%403GYlY@;Tx zNN<}_X!%Rjkx@8<9KUP4O0h@dM{pglNXm`Ezgd-ND}{%F;E9&PsN4()rA-e%WEaXo zomU~oV52mBsr1B)^(LzctWOVMCrrCSJLf$dp=~F|MP6o6x|_NOJF#=#*9bGayH0f6 zF$?sLo7*%uHRILpnSbPlT_HEfXCJu<7xT~Cn=;AS9&+k;+_t^%M<6^qi6i9bQec&M>6$Qsrd8+D^0qQ1afFz!{KzX kTxLa>ui%}#BNO%8ak=oSJH9ZyoBo`i!E#>rdgue|7e;eK8{7A7Q#)sc z9{%xe8nbRXR9}#v5AeLDKpzq)9#I4klZ$WA=U}U&>v(}yr@*uRR}(UVO^XhB-}m*}v)qln^l1dX$KE=f literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/graphint.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/graphint.m new file mode 100644 index 0000000000000000000000000000000000000000..f6618f50bd9a4e0bbf32412cac8df7b50385e9c4 GIT binary patch literal 140 zcmZ?u^><-lWq^VUFa{Tx!2~2T7&!j_XJE)IE-EW7DPmw?0m1cd1&iH1Hk%#&es<}p1i73PG(twoi^A2bupKk0`{Bcq&s#x zR_RpcbNJh_@lLCFsED=Gd@?UpTBFw{@=jJNwPgPkT~u`ETDMd$b(s(c z$gnJYcX2k_ap#%|SFoXA(HZ3dc++f!VCx~l91tRF{`2N5~ZlnoIsLkbQ@9 oHZUnHjU(3!IWxpI3f8{?f{ePZ0H~QTT*Umk^oR)QQ z{ZLL9Er;J>WKP{Hi`=Ulj2Kxcq@2Azr#e7*iN8Ue* z_p+*PFQ@g&1@9BKU(W8TU?z?q*t)Dr_I>SM4)DutQOv4O^|F}Fm({9VjL&DqRrT

Nh*7ICc#kTX_1@st?vaIOvGT5+y(rOOPrguHnpHKU1VSG8jY zf|6qfrK-*B*cYA8&8`sMt+~-J!O1PI@0D8;y<{v{a&Gc94~3lVCbi?Fz*G zDlkShuFP~DZgO32iU5n|{ixWPocbL!)jGVxdz?r!ZGRG}ndz5zK-2_AcWgMR`?&e0 z`17U>KCMwN$(LznBIKsoZSH1{do1icSz#BL=V3{Gv>nxqdM%7*G(f#(&)Hyr|L%PZ A3jhEB literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/diskfont.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/diskfont.m new file mode 100644 index 0000000000000000000000000000000000000000..80e2755a6f72237aaae8a038c3f17a1dca106b75 GIT binary patch literal 888 zcmb7CO;5r=6nrg}5JHe}@Z`bY;KBPAC=e+num?Sn2DVUzV(4PTlRwd4B);hf7Bwa| zDcPBwH}l@39oK8q8D-CVeyAn~lgPXz>u@0QgC$Xon2C0473poL;!MmOczzP4_5-3a z7`=Z|318-4)7N@S#9mdc)r(FcQ5|=QD$C*X-_?a;LZ4}M16|I;_%YZ-da3-m;xw}0 zJm-e^)>=gjDy**u;Yx*b+_8g6jjehP<8Xs}C@gBmYJo9<(fvi_uQ7{}INs>gv5G;E z2N^x^TbLx6@y3uwg*0r?{INlFS*X;(41Mu~%40G*{m}kmw%KKgyeEV9arm07xlD#( z#(KXxqEfK(7wO+*e9J(@FB$)JGu3OIM6Cj}jCo%vCniP`Diy5q$!^ CDw==* literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/expansion.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/expansion.m new file mode 100644 index 0000000000000000000000000000000000000000..8526e864b64a772427eaa7a96812648f97e98452 GIT binary patch literal 128 zcmZ?u^><-lWq^Q&3s43F7ns2aB=r~sfFz@%i=SJ3aEN12NI;OkGf)I1$^aB~LJ?(P v;AY@+jRG3XM>O z5}ds+y+uM>HC&yq*5TGmgU*d43S8vmHYcr|bR_|3=j4uZtFz5|9Ym=gM)NRQh|BIpmNp^FXRsr8skFn7U?|UAh9Ic%uHF zo)+AP%&in$qEz7txjpXmEo~sl5qSlI_4TKQ#Rmh{lMawmAXixLm}5`eev`Fb3c@C@ c+SnQLadzIdpgPxVOeOwg3yGyUZq5+@0YkNt<^TWy literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/gadtools.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/gadtools.m new file mode 100644 index 0000000000000000000000000000000000000000..b4c4547434fb6a84bf40dba9de853a8b8ae297b0 GIT binary patch literal 3690 zcmZ`+Yi}FJ6&=yELQ9IHIId$DMd44ao%f?n;~)nonJ*5{_K)`E9FgwD>~e8_cCk2Mt?4 zoL!ynUwX;;i^c5p;CQaoI`rPZT+9~uo8LqH;1j+ceL9`LI+>qd@!XnHi=WQju`X6? z=QDAQ8al_bALhph1-80s{l(eI$v@^lalH<08!wM%2QaPFUF>e1TrI9<$Me@Oj<5Db z9b?eSf1!eEa){X0(UY8?30t*lvX6DblM8f$iK z9hfAaBA?I`L^jQ8oyL*gF?)y)*gKKUrnL@jJb_}5gnKuT4an^-5$f*%G1<6|vx!dP z0g&zM>+5gf!!XfNs;ixP^5rw=19}ZK&}E|G33*lOaTe91I2w6KeEVE{qsQ9X68dni z+eV>-T>Jy7l1W)-d6{ac6WJ=V$)pZ-k_0;3QR*Jz3PoRLrb(Xf(ASEYR_d*6s`u)h zID^w%zb#2}>n*IeDqF_zuSGU1L}*Hn(EmGCSmsG`1M3w!G1eM?47CGW;a-^BK-RNy z8Z70=;%#Ks*`nrd5?6K-o9PO6E6%KmmO_%jPB=2*PLMaUw6+$Et zU6!vIq|0*>}SG z^KoV4VH|23=WtJUo{P`FvIEb5zC+%IVgpo&8Kgt%cDwE9nA(}6k73u=uI(HLT|^Y- zX{xh9152K^A`5F_UhJ`H(Z7)16wIxu?bFD{S?x-|>3>_iZxCdxgKDh@rN&fb+<%u$ zSB8}9a?hX`Fn_4)E+nV5OexPN5X{C^9-^wrO|^tOYml)#;(|uu%+VY2kwr#DC3E?2F*a^ zfpBbdEAIrEl+qo!e<9p!J1QRzD?@)Nw=MX<6n5kz_|`>T=nyXhkD>c8XUrhBBRnvi zU%(Jmi;++8%R9kLr(ll{F{zB6)XFp-hz-_CNA8_69?0D0Tzc;&=l(F+>A4D&M@XZC z8GN*?ga#!a@1hc#HM93n@`C3So@52~d8W@-Q9KA!0PLeb;7me({J!FV_51X;@8rJS4g3%PVOWQEpg!h|E1scb8iF>UHxKX!(WsULrVP*NE{bL literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/iff.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/iff.m new file mode 100644 index 0000000000000000000000000000000000000000..217b45e117c4b51b3305cae0cc618b05c316b683 GIT binary patch literal 1104 zcmY+D(Qev65JiW`LM}yVN>G(VZPia`-}-9frC70d(b}QS6EegCt6(f_CGhq1j@L;I z61sct%+BoCYY{4sI@BkkPyTp36FTyh1PxF4!3pL^rtjUkue?X1 zJLG?E`Iu^?!l@RK8Jp{UX~m^-(JfK`fxD zR#OlQ$dNwpW2tH4)x^CJ!+0E%3d93}%v`pMF_`LU&@cQ2VnOC8c;J34OrgX5SeUe| zGa*c|8*mH);!!}&MEqbu=K0#u#9?AV=Fe#M2gCw$V&@*j0+LQBKrA2~L`*E8*~HTz z7IRamewMg!XKk7)Q9U1$sC+asv zbV1hXM6}qhiMk+q$(|~#ZLBZWX|`HdsLK)SQ0&TP-94JMjjzPci%pWJ2r<3eCgtBO zUlG2Z4)vD1ZLv?wGTY@`r9$eUg{OaV)Az8Sc15~Rs<+M^J{dY=F1mOzY9W`odoXGrxwl2VWKmYx sHZ^p)PdA2mra_ih>3)+Y&j{BuU1O&2_1dE0BCGf*S;)MBk0ssy11A{mc>n+a literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/iffparse.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/iffparse.m new file mode 100644 index 0000000000000000000000000000000000000000..531c4a6c1db4d5f4124cb45b0acedb79e42bcc03 GIT binary patch literal 1550 zcmb7E+isgc5S=6>MUfR*l^^<;Z>ahM6t5E$4Az3f%A`b+doPtyTFRwoJC2r){dfbmd3ttF~Dd`C{2DieiB4*=*G=i*%mN*`v*svSvQV$#Ocox2ErAL4F_03aDtDhMZ-h3$J$3|IWnwbW^& z>yZr6OoxBfVDSt!V)FwG6NleJRs|zw0?&y^RhA+W@|q8bZ_zO@?g4GeTYPh;CtD16 z6f*(BS|bNtB+{8gu~3S@d7c{AAhT6n%t;CdHMR)XFbEp{2_D~Qji~=%AUt;FurKy% plwAiC;dB0CSV0)$O>1)=pNbc-SFXkgSJMddKJR#!VTiNC`U}HAY0&@x literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/locale.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/locale.m new file mode 100644 index 0000000000000000000000000000000000000000..5f0f7643e89b4180c7419bef0040f06d85b73d6e GIT binary patch literal 2422 zcmZuyOK%%h6u#p)Aq^pf5K1ZKRm%I7w1pOl1(We4wq$$E%$PP3l9}2QXC&KW%}gR9 zvFL&YAQmhTV!>;{>lgHQ@Q=#(-E${#EG%8+p6@&FbMC}#c{R1D%PJO1N{0Z*j3!C}t@1CBidvgS0}?Bc)<@A~coYp|$d+0Lve{1uaUK`cScdkc z<2cKcl*X{AsLNS=oRk2tD>#UapN>6B`_YKrRvBHSNi-J!Yrv{y#2FN}(=0wHnVfkp z;cNjKLSiOWb#o>&dcWOIk0wQSLYO-A{!tN+;^|>JiA$7Kemoo(>A``iY8{o<#&MJ% zWyxfipX5b67JEy%%ziS6vf^Z_ouX!?b~AJ&JB|li?9w_s)(24$7s)t2NV9RoW?8!8 zCh<9}GpDx+`!GLDvtr(f_`Z9}m5v1eOyjf8EM4>GgSelJqtP@?CXxv=91OGcXqv~< zD2s|T(-|`I;XxMl|A%9rMjA&`v^M)WJ=HEz`Yy)l+vbe8Ro_9k4@-&t zJ)|7n8xaD=KKvlw48n?k0y0hWq)3kAJQ?COSZWjJ=UIFj^|2>YxY67%vm9(-PYRu~ z)UPvKKQEaTFu#@gUZ*Z&{|?>t${$l?t>MEYoG%EUsvDB*6HRxJUe}Ffv)U)(2+!k}t0>tt{zV>w~(7G#m06Fp=|y(g%LJN4e|w0c44<3{NXyOgN+dfU?!ndimB zP4Tcn54e+gL74Z2d6Eq7WL^~J17SAF;7;ZxVQvZY6dByfTovZFFc-<-PUdA{J{0C@ zGPv_gvlV(Zdta(pgZ$pU8-%WZ4pUCh>2-Y9acgb>omHH7ou(JKpLD&@g+x#9cpbNG z0LoSn^n#Au1 zq1We$}~s>!V{>0>-G&I_x5OO3U^R`dIFsW$t7y2xE4y zLdNXgiZEu|7RZ=wdsG;+MO8Amvujn<(zM%qU3(9aH-T7Z)twQhB8<}Z-8P!ZOjgCK z*}z45H5>StFlGan$e0aW6UJ=dBV^15R(1XLuFRl<`8HY|4A{n080|G|m+Ts+W}&-| z*KFFMi}xvWJVi`D6nz99GsRhewBt9zMo@=Dk4t)9Hm1i;ETHaBT|a2>@oI~=>$YF3 z?|15MiM$nfyWuIqDPNPYFLz|*~^+Or3F@T$E|@>>OV#e@&Et; literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/lowlevel.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/lowlevel.m new file mode 100644 index 0000000000000000000000000000000000000000..8a96529f284a4cf40dcb95625fe8dac988bed63a GIT binary patch literal 3574 zcmZu!&2k$>5bl+1Fv3w}MR6#KLmt6)AY8rDj--`Vvto8OF6Xib;u8nJCV+v1pMvMf zBk(9Z0j7UuXIrsdC70&=dS<%&>**PpO_{+yguj2u|BRuyrGs{pT()tk*FT0KNa5g-qO2`MrvQoCpt z&X_gL!B1Zh<2ET~baaAH>jy?td9owt`mMHrnUDN7%h)$A>Y&dS@VET zG=KV#2hE>+#8Yl2q|ENJm^1X36#NJ$e{UZ1cUz>CLGoAg(cg|wG#~x#c+h7N9L+e9>ZpevVa4k$?$x3Kdt!(AoKfYcThCMyLq+JdHWtS-P!?a)w1X zq!l>k4xrMAGR-Efcs|^d?FKXAI}F%vS-Q6YqcxwRU6wmM zggKV8%pbvjyjLhH0b%&B@}R{KdM4hN*1J+XLiNS_h>>dVA5(2!x{K6hqMEjds%eWv zTSV2g1!#+?TC^b5o+;HLfvTa`O0|w5)e=?>dzH&)Bpb!^+hg%unxZH#a0XSOwutd) zi$q(*c(es*ix^L|AO)YRcv@l%FL$D8@gc&oinwItbaMBm+f3>Rji_Hfm8e}h&1X`n zpEEMgt<9@tusUEYO9i5A?K4ts1BAJS{_Re-=<=Y}fJ{#_a;pU<(Tv<_fdS3PjYbUj zc*;h*JR{tPB0`<ZRX5o=1l4h zUiTI5Ow1lLX_oCU*a6{%QdyQ7!QGC=f>I7X6Gdu2BaLYGr;N~>qF&U7y5tad>+x>0 z%$aFfdchLL)_GAl^BvBl3hT8dO=jk4O>LM?3-rk+N<4S5A@4C;=9V{L>Z_KuJ6 z7wG!$kJW%P*olzsX*O0s%O;wQ`nN1-Hmc7oDRHcHWDxa1CspSWlZC+{MUh(+tyndw{Hh;zYV;+Fl0>G z+2dN6J7eh>kmi5xXihD`<%=a%Gik0_=|hT5G%LMGv7lM$M=eX4O(+uqpfP3!e=5k< ztQw7#JB0BZg;DJcI3kNzrdi1AfqpUk^&qOk&?%x{44RXeB9~}RB8nVnPT~=cyvJV% z^G1eTH|XiK9S6@PnqWg1&!K1nM*567nstdi&`R|lGE!ZbOgh5^t@u^XH&a^svND#M R7k7vwwqBa4Gj!ns{12A^5}*J8 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/mathieeesp.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/mathieeesp.m new file mode 100644 index 0000000000000000000000000000000000000000..4fefa9810bb7bf794b72e923dca578e1371a3db9 GIT binary patch literal 332 zcmYk1u?oU45Qb0DP*i+}Zl^;{(pKvz*lMAgAO*q2L2(ibqTuKw`bgfHDrP#q{Q2%r zx-xTUgFDYxJwWF(bivE)a#mzD7AS*w03bHi{c;3o5ckl>#=s}qOkJ#xI+&Bwq(|< z>)is?mzC+-1wB+Q2%<0xB^~9Kq115_%PG5QtN!MFn~yX>V$nZ~hT`A&btteBeVbnczHX)A>I=K3Li!I!I% z-Z!wQW1L8K%2I6Pay@mc83@S(VZeQ5J1zHl~oa?o*{G_x? FSv=2C9c=&r literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/mathresource.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/mathresource.m new file mode 100644 index 0000000000000000000000000000000000000000..22581dd1bfe67e6a563b610ef92bc49ab9e2df86 GIT binary patch literal 450 zcmZXN%L;-(6oyY?5fKv6BEp4>7A<-St?2@lpa$(?%*g~ZP=g+^Wp7mfMA2mi=5Xf! zzBz|2-7!_^b#Cvb@oY5I8@2Cuq9ZR4i4YW)UlF*y literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/midi.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/midi.m new file mode 100644 index 0000000000000000000000000000000000000000..e48273f3c41cc959ffbf0024257cc5a8f3176bbf GIT binary patch literal 4036 zcma)OIg`cH?MMAYRL-g z73vrvu{MSxanS#_U2RqE>GY%)LiK&jgptBy`5$20z|)KbHh z>fp&52y^sm$*^TZ1;V*Dg_=>YDHP{=(vTz@rUsgGt#YojtBXhT>B;%g1=tFxI-4Cg zQ;J?b_+WD0fK|-ep}sgenoZ{zL2~Q-Vm`e=Q0wgRZ2D1K>qWABO&G(KbVy2`qky>Ni$DJef`mFdUZINPw?apvfP)viw&{{_NK5K zn*_0M!8-24jUv=}<%T|?qjdds5cF*Uk>R$u6qon8D`WWO#Z`2qqwe3Rbe$C(PLC#! zPUp`Up&p_x`gNamrKUm?rOr2+sv3lv;@LPkJh_}4d?-6T_AYw1tnSVqU$Qe@#J+Mm zJwKk~xJvGOS5uhw>*=99RqE9kbQjm2EsvXHnE_TWigEsm5_`1_U=u_u3kzHy*rAN&z4kpsnD zK^2b$)t?wIhl?HkGb0yAOS=3QMl6n&%=%X_93>tU@%(SlyTSLo&apXI>E9XQitWx#5m^V`u_!$WG)#r`rphEG!Lwd{|}$LBG_Vx zc{%>S65+}?=l`H|680)nRNS@9`4kMh)-VT0{1kV2ijr{CKy9X`r-xbCGnm$fvCs{5 zZ9rm*V0@hYUY=xwsx%%;kK}esDik2IZRSZkL@Hj&6S}|OHztb_%OG3c=+KY#bfA0A zp**^F3#xQJ=wNBBFw9b?I%t&QQJ~E8JlLMghOPfy=q;V;LQX5!xx!3xJ2USKP-Y}o zsJz42jWw`sgKp^ThjBeGFUZ@GtS`trk$ho69!7#S*VPbxvPDy!29Z@jbM~z!!W6^c z8kUf`UMNkfVU4WHfc0ILVsde>gl;N)H+Jh4 zK!P{9%kajyroRMD`pyrl21@L&NU@8nU~a_Lpk-fI#<#Kb^gU4a$`(npM)FoI-lL9kjnwIQT32_mQ;w7Pk|DH;wm&&yWhIWxW|x{s+5 zAms9zAVeyTB#cXw>k1bSSMicWv5yPJT>bjlxYvX+e~jat3M|xbKkSwCgk&RqIfhyA*Fi3E8F`nq)LD+>-`=oaB-_an z=Wx3>bG|~BxqXc1eE9z*5}oS2s&dPVMAmzc)Z}oMm42D3uRTr-hH-UYkx{gj&%a8A zi#pxsvE@o$mGOJ*qI|ouZ(k#`1);~9lXfS)MxJEa%bSXk?8&H3?Y0eA(y+34uhDn* zWmH=i;A-0k=sot0dyRb<@!KQxjW3#kvPyPiRA+i%wuT|29UM=;F%Nzb#hpbLM>X8) z;pN`*@^OtOqQ*4OVqmgM>OCq~cV^LDY z>m(I61~k39FM3>rz8%o8-ILCmzH{8MR+~y9-NN}Rt)0I;fwvwSmiBg!)Nz@pv%kkNo4*4ZXpFfsp S?hC39X^GQE0Pi1_2d(zTets>%U;6us_O%vvJ;EW$E*V^LU3RWj^?{Nmyb5Wx^R)tS@40 z5YO?wQRexmOOOL4*(;D0zC)#n3Kh8iNcqc@V@^LZO%btWR8`Jm22VXz*42pEvl$4cj%IPEx1iZ-o;*i{YauS;nlr>W z$$mYd3()+^bjvH`o`b4Qy~R^YBrlV-J^GOVoj%BY6#>T<7$(L7@f zR=C=Se*A*Lp}m8~XMe45)fFql<+6#M3jTQvYwur8*{{I)Z+5o-CQVZ|q$5#EzcAgc<)~;GB3tNtKP)1_-qkuK$I!0ZJh$n^z*C*3`+tYpSD|_#| n?^0=^P>{}nY&;RZaFNLNGhZ1jzv3@MxG`O)*?hIi7l`Q!n}J?4 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/nonvolatile.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/nonvolatile.m new file mode 100644 index 0000000000000000000000000000000000000000..df2ffbcfc2ef13675ebb8b69820803e28244bac3 GIT binary patch literal 392 zcmYk2!AiqG5QhKMC_zKX!MoRZ@a79_$rcJ}8e*u&vgo!1%&w$C)Ki~Bd???j{<~?d z%g!+K%|HLb%K0M0Ifk?QITX0`#fbR}(S8q@H*Nav1GsP#W1lrZ9=0#Wu@I3_Eg1se z#oOl7bwJEn^4i&6KlP2J*q>`==Z>R$W7d|PQ=?Vy+un9+b8-mRo!0*$BB}$%H+O)u zVkxU?H5Iemy8z*l)Pg7>9S!8Mn$@zb7PWhg9;DM%CUaTKfq-Q4N5%&Y-6tX|#GI<} qj?nLkvK$bc?#6GP7;uI7fj?0!Gu12S#7NTInoXJpw|DpM5&^&Q&`2f# literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/ppbase.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/ppbase.m new file mode 100644 index 0000000000000000000000000000000000000000..0658e366fc4fd1355a34c862f449aedb232aa5c9 GIT binary patch literal 520 zcmYk3-D<)>5QQgEij?Ao^a*M&df7fgOeQuoyR+;jm0Sg-Rs=7E^yT|&&u$bAEaZGU zXLf#ANk$P}6VcR|SGKMY4M8!D4hN$Bezok@&_fS*+ZE9j;_u#f%T4ELMAQB9jcA1b z`)`Z<^v?x|$o8I*UlG?^pocWjF`UWwHbG>T}@&!`s7cC2I45B>y z1Y>2YCND}9KocBthB>QEJFD}&Oza#Nx4_XQSDY2KIy&OZ8>f;}Z2op@+xI*{H-2`$Xtsg`c_|B+ F{{ez;fl2@X literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/realtime.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/realtime.m new file mode 100644 index 0000000000000000000000000000000000000000..10d9123fa9a7cf6c6dbabdb3bd225a01a99fa433 GIT binary patch literal 1922 zcmZvb!EVz)5QaC7iK3_qQH3fFJ(SWzg(_4K;tF3ztU2jl(TDgf!qdIZrxTxIv z1Uw6`z?Bm(RLsooI&lJ)QoG;m%>Mt(uH(}lc|!E_yZmU$4}%cn7ikv-Az2(H`E(Xv zMvE9?CdQNLC4rcUZ-N>7S-gm|ukqxVkQ!;gssqfywGcPSA^vxjMPp42a#Uu#LDVD$ zd7V$kH*uE9B?Jlq!>5TVZfA=;%AsHr70lxNI-STURyWgRqQfc!{;uU}Et|Qh(_HGr z+Ut2q^esj?%JZBk&+rCMHPS8}pj1homPC5O>YeK}y^(nh^(FN`Tcmf{7|ejP);OI{ z?#6iv8)3%tJX)v>GskXi0ow(?*>t>Aik|nPB+6zbLUM2iBbY>agmOTSK@M-FgQ@CN z1IVkZB>J+D3&;_?RF_)V;fjv``878DVy`-?{zCR;mRze@?~apnd{b4n2gAwolC)84 ze4oeJT%9Z_rvvnG7Ts?K(Ag3CPv@yRQ0VM)V^uQwET*Z2b=RB_=jMp>8ku>LdP zuI8$Y*XLGv3Ohq&P>pcU$BYi}uI8YVGLK&<`bpDK=&+u}E$lh?8~P&T$_?fQdX;m| z!;7Gc72#(pYKtXC+ELV9(Kb}@bcM5#Cq1`erS@zK4Uy@ZZppSF_oL3Wtq{y?LDLTy zcLY)|=u0j2eIxtO3>%-0Pmg#D(uc z5rX}5v=dm;gV7P}6;aF<8Y0u@%Pm>!fsj+3>w!&}uK5GY3zs=(71yd8A*aJ3wgc}Y z0p+-Ky$81FQ?9V=nW1~;R=8BhxX>ZWLZ|^s`s?#p_Pt&@(Fqukw@7ifEL3uN>y%

|CsN#_}HC HM|l1MMVX~N literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/reqbase.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/reqbase.m new file mode 100644 index 0000000000000000000000000000000000000000..1360992399e298c275f1dc580e17f74823b2b01d GIT binary patch literal 3450 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 Bd$j-n literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/translator.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/translator.m new file mode 100644 index 0000000000000000000000000000000000000000..090d52dae5db9ac8f2aab0e44c96f0227a490b05 GIT binary patch literal 90 zcmZ?u^><-lWq^VUFa{Tx!3ZSH7`Xob|Nk!}DBjQC*VPv&!UN?02lGQhgI!&qB7cA) OzK-6mPL3cEAOHYan-<^z literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/triton.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/triton.m new file mode 100644 index 0000000000000000000000000000000000000000..50efa2ec0b24c4afde1e8dce42e47f314508be26 GIT binary patch literal 5506 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/triton_macros.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/triton_macros.m new file mode 100644 index 0000000000000000000000000000000000000000..9c37192a1f70ca3fd9ac5c2fe62a570c6b646fef GIT binary patch literal 12544 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

-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 C=B2Ly literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/locale.m b/amigae33a/E_v3.3a/Modules/Modules/locale.m new file mode 100644 index 0000000000000000000000000000000000000000..ea72ca8196426ee285ebf75550597519415f9ea2 GIT binary patch literal 301 zcmXw!!485j42J8)488bDWGEp~Awd(bl{82)wq+ao__~gH`@Xen{~j-G1zS*NKt)gV z1P7^%Cy4=-8AXzFstRfJ`)1DOLr%adcWYTr#?2Ti3?z!(eziWhNssI`g*-042`Hkk z6O%T+RM%w|z+hj6;3Qn%R$YREua8wGr>pE~S`eOR`n+^%{yT-sTN6!<5I<23BC{ZSjTn zZURD$rrA?GlV{i>AB<~9)1pR;5AMiGncNDayo~5$5+To2(^SRIaV~1?CnaSuy*dKzsn;3ta|F AuK)l5 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/mathffp.m b/amigae33a/E_v3.3a/Modules/Modules/mathffp.m new file mode 100644 index 0000000000000000000000000000000000000000..14f216ffac255a62922b6ba8574622e39f3af112 GIT binary patch literal 100 zcmWm3K?;B%5QX7!)4fDZ;OD9#v$cLMOu@f1cAI4ypxa_yFJs)y^Gt literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/mathieeedoubbas.m b/amigae33a/E_v3.3a/Modules/Modules/mathieeedoubbas.m new file mode 100644 index 0000000000000000000000000000000000000000..6e4e6883ab2493ab9a4fec657da5e35ee6d48b59 GIT binary patch literal 175 zcmYL>T?&985C+$R?iHEPLqAX#P+UqdjMV7%C6p}e!_3F9Z9j6TV3%Pth^SpuO8RsN zU2;ANa|8R)hJS4K16Wah^WsA;YUMKyxMr-irh1Nwq>q+_n~OwP=g$0~L6f=%0A93} BF?Rp} literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/mathieeedoubtrans.m b/amigae33a/E_v3.3a/Modules/Modules/mathieeedoubtrans.m new file mode 100644 index 0000000000000000000000000000000000000000..814316df52b23df7e69ec05321ffcbcd9c7caf05 GIT binary patch literal 238 zcmZ?u^><-lW5`V`$;eDiO-;!!O)4o$%qvbxEKX(c1d6x>IF=;lF)%{d!I^NTbAB;Q zGz3LKa(*!fOa`bv1I7kwfU|)*;B4250+<-lW5`V`$;eDiO)bvMOHWEH2BK63Par=yz%8=^#>y#yvYc}Z7#JbaA;mC3 w$E0GYv|nmEl;xO`0#g`VngnC|mgc~iE}3O8rdv*aei6)q)XW@){|pQa0O{&76951J literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/mathieeesingtrans.m b/amigae33a/E_v3.3a/Modules/Modules/mathieeesingtrans.m new file mode 100644 index 0000000000000000000000000000000000000000..c8fec05cb3018351e550756327e7d85f3ca3a804 GIT binary patch literal 221 zcmZ?u^><-lW5`V`$;eDiO)bvMOD`!(%qvbxEKX(c1d0R)IF=;lL7BmsFqU(EF;pxB zSvEPpm;<3U1Ih#{hB1MvVNBPG0;s%CemayDkYCOS(_dIr0%eAPoCamPA+a5S&V>p) S0&Rvefu<-lW5`V`$tWpG%qvbxEKX$zE^sVK%mY%vnIO_RzZgh{z(kVsiy0wu84yVj z1(XF*t`!A9(kDM1NCxDWgVhxlm4Fmvrlx{Sc7xK6#bC1?fu=!p7#cAAXJB9e08HgB ADF6Tf literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/midi.m b/amigae33a/E_v3.3a/Modules/Modules/midi.m new file mode 100644 index 0000000000000000000000000000000000000000..5eb13745909d248e1192891cf97cc5c2a6a0c08d GIT binary patch literal 421 zcmYk2L2kn!5Jl;x!ddksIYi<*iewZkZV!O%v4cz?f??s)rx*`OSIiqef9CToE+zZC zt3mCx>YQ{7TcML4SZ(`RL^wqF`ZfAL9vw&o(c0j8;6(`<-dHI! z$<+poRy$z_H7<-l%gawIN=(JF gQgb;N7~P6eQ^8D51`rcT83#mNSSqqo7?1Nm0O-6X%K!iX literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/nonvolatile.m b/amigae33a/E_v3.3a/Modules/Modules/nonvolatile.m new file mode 100644 index 0000000000000000000000000000000000000000..e45e23fe487297040cea82e75cf0fe8aa04796a3 GIT binary patch literal 104 zcmXAf(F%hw3;+`!B=xtf4q;Y7=zAR*6r>q74E*}7>f7CM-8fmOA$`}dGdx&Z`5exZ u!9FuPZ-WL}RB~Z54WQ+X^%5+%^Fw;eP0zS1;c~_~i}FjOBr+BL0N@WYvmRam literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/commodity.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/commodity.m new file mode 100644 index 0000000000000000000000000000000000000000..e33f97078c3646f8d6f75dad8e3287ce6d93e27a GIT binary patch literal 2684 zcma)8UuaWT82@f^o86UAtLt1RMXsS6PHWR`!ej&%7w4*UF?0T7pft@rt+6+`mwVIJ ziW|WP*~6H2k9+jVhw6OrWio~g86sosVGI#LkTJ?A8b%mdmw5O4&b^75M&}{tJLi1o z_x=Cwy?O70Jv*q2c)UWiAU7c0auX&}zE1D=>YGQs`si_rroW*u9Y1vDwPd5JC-p@l za7i~C)mSE$r>*IQJ@-i+GQFGWi;YRW;MF%INdsnGn`FffL!$C}l6q`4*!412-$)vt zA=76ou(8bCm`McPBk2X3(udPC@TUfUYVj=;#nhzc!?3GuPC`ebm@SA)7rgo;(cs<- zq&d<= zHr5%-zW0`azNROrXw3!aO~_PD)*zW)(1#k8sWow~ji2|q%$au=8x=@>p(iX`6#vJ6 z=t2#mz#q{QIn!$T^rU?H_+H?L^~7}EZ07R`@v^U6W1Xw#SG2+%CjBO*n`5+T$ZXWp z7roou13;_1qC?c(>8z-rWyNl}AX1z_UfWYXtTm@u4cQI|FRBiRE*!|894g zd-D-5Roi24e9H=3{j_#(n@&>_Ze1OW-e|`Wkpk>9csg&bQ=}2d|EnN3U}B zl`mOdYFh;j8{sYY18Y$ciE7iMnTDn#Et%C1HFc1EtV)oLwPastlhvQ*Io)f?yx2je zw^Ouqr6u!nn@k4r;d$Yhwy#jPu8kA*%XfMo@`(}o1oH^y-d6OQ#7B|+pU3X3;y$?y zi~NQ-(6aGTn~h`;OJAE`Twhs*R*gD%Z7Zx7IxADuIPdq_hco%o$yBzO6DFk&=~>ee zSz}(Gvz%#nxSMZv{P1#nhp*p!Yj}hR-HM@q3(}uj`RAt%yC|7jssDyGky>f&#JVlD z^7lThBUo=^9Zb*AbHMi!bzR52hIzG2;ag=2?Z#YJCgl%I@RZY-A7gGR6Rlw0z&wXJ zirGUNDELf5Uy(|r7)<>UzRUaY_mVRx>Dq_4p%U*yCR63Qq?aWN%P%8m8D)v}Z~#Z17MB`7eq&-YJqpG(wSlF<+v4 z0b+xU7c#ZDaYK4M;5@{{o`uEb9OO literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate.m new file mode 100644 index 0000000000000000000000000000000000000000..4cdc34efaaacac625b2b2d1f84f7d994973c738a GIT binary patch literal 6220 zcmeI0Z){sv6~NDXc3xgmx6PoM3RLvf%DT{|@hDlTN`#U+P17iIvr^W;nvt}2npBRR z*m0Xx1rEZrj-{bt1;3h|H)DeKqP&pNQ{7U=PET+kI4YSLIosECsylCwb>1G^s(RGv9*pAc(c}1|7-afd{tUi-yv*|NXk!w`a?~sSGpLnD|4slN8Y&ZFcik zne&pSechUY>(*rS&<0T+__YU}+JmZD_j>RiwDIEF+V#?^D+~ zA?eukx%);%PDZA7J&MMZ)8po?whwb#6-h-OGWeeRxKUL3w$M2Eh5yXmE9F@(Rv@(; z)sd}N>q1pm$m+^9-W0NXXYzUd=4Red!y#5oRaJDjRS{x^RqJ-;8veMb4R5_%-Nx4! zwc)L#tJ{dw+HkC45v#B+J+)uVipp1CmYHoOKTSFdSKUvPwN_OlYL&Vxr$?=9&ukob z>$jkxGN3fN+YnKhQ(}p{8sD0Gxh}QrgHS*n$cYy@A#EEYJ6A6>p@9J?;6?a zdfNF`{%q^=t$RWpG9a?`v|D+7*|X3Bah|JdfPj9 zEdPC>{d~E-IBPG@i^$$`4)U|TudmiQP#&z`nZHu&!vT@WtLEsT>&Q{1&cZn=>9A(l zJDlx$|LS(v%38J87i*+ych!5ldgomqg`IbOXMUERR!BlVU5}G$y#~cuUCdI8vb-Tb zThd5YYphcm{$O39$5YsxtFT$qqsC^LsS=CU3f1~gSG3vV+RZyI&LfFH4+^k zNu-N@cjD*R_$YaBTqYFrhbx(sPoz8&^z+#=R^VjLs-GRVJ` z9zRm(K#vx&l9SU6TCmwHb~+Z1?N>dRDOw$|VyRRzQM90P?vEv++C17T z0Pn(WHOO1Y8%X!H8v7g)>Tx71Q-u%T}2NJv1M6wd~`IHiY2Cd zQpt&;Cbf{6jOtZJKb;e5h0A{oHgJ=bRk4X=G!u`dww6JR~f#={dcpf&v=iv?T zRrr39dK0dIL3krnc2+`iVSWG}f**np!8PyObM!C^@5?4uCd_6bOyZRXb`&-SyBEy`AYk?#f@4nbluKL=HpyFiVH7Yxt!Hu7Uldum`w~Yyyf?tEwZ{rh?Q>yVP_-*)W zcoMz=zXRvsDUl`Q%KR==emw&5(L4?D(PVy?%)m478}KYV4;18j)^COXf1$h@B zhvwt37ve)e#rY&ucAkdH&IQQW=8xfX@FIK@{)E$qxi)_ao8XJE6;d}#d*E-O^6w>h zgj&BWBHu)0+Z|oIIN_Sg`@0EeFaZG=<%fL$VKaH!Pd_UwpMtw z-6Ni`(0i%m`QJH_K9--$&*!gXHsxnC?K+CuexynaQ+@N%5u3MPXFt+Uzr&?|510Ef O+NQ#I74=j8V)766cA8rN literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate/line.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate/line.m new file mode 100644 index 0000000000000000000000000000000000000000..92207952b4b68bee270d453942b363f5e1c28cbe GIT binary patch literal 1814 zcmb7FO=}ZT6g|_#ag-ntM6wW>mLdhMDdIw;i`1w@sWJFjMWJJ7+6+u)!py{`U3KM3 zkcumD;SbQQAh_}u_$$Ok(Jr!(P#w>EZzeUNqCR+Y-#Pc=-Fx2+xpeLNMeKuGrBCSr z2jn5g@0a@RWanfp*_rF-&Y4F2VZB3UOE9%AjQV@z&|P?TvXXo^E9M)3EX-E&eWEep z;%t5M`ZwgwX=+=^&Ugj+5wG5mS8v3tmwFi^UfV-n+aq4vsaJts#osdA8uHp2@!Cqg zifyD-_C%F}HK&l56|#<%<7Jo?>07FAns+A}<-_uh)yA_6Z&jVNH~!PU@SpZY+V|Mk z-e2WWurWe0=HoXsdY_S3r_JOQxD*bDUGqmeS1fm|6?Sj`S(bTKSolTG}655 zI{;^d%lyF4k!t_vm+>ozDZ7;IYCm~S*`TaY&XfO2S*!MUUQo^u3x1L~q&!yb|9C`M zs&^P|Kew>~?H%_M?mOHkHh_=ZPq~Ru{O#S z)_-T{gQDZxf-5WqL1??a6|+9BBj9g8SCi)wzcGx+i7(L@&?MW&K{7XEE97;O)8IiT zcYlDJ65ktOTjGTQUWC4)>`5`k1Br#bSQ-{27WQIkxP`p$tSAIDV1z-;jA<|?GZ32j zjAfWzwwAF>E@L%Z#39RH@tiZEWxJLiWpz}TXVYC~VWL(Iv(T4<_L@8kd=C0*=%%eA zJ}dHC6&lqWU4d|$FAbSDghP+{O0 zbl+-a5r7i%;_c+p_+CeCCv+b>cGa_@=!O%u13${FH58#YEpPXw3cQce=CTYl7&v6R z%gava`0?d1XsOIJF-M)Yt>z-FFX58^E3Yx-v;w>1InntbNKfS`2;;KfX+3hns4VC4 ww2YR`ruZ*isUi$d={`>ARnfoPjEFGyS$<#1XoJ7MUl7RM_y7O^ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate/polyline.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/coordinate/polyline.m new file mode 100644 index 0000000000000000000000000000000000000000..f254eb35f748a301c5a9e37cdefa49dbd164b659 GIT binary patch literal 1036 zcmY*YU2D`p6g_EUjIxv!itNK8Y4M>@>z2|75y7pkvVx|IR9vNkVKciM%w}Se?bnn4 zp!C(>pg%z9Z;<{IUzbvdXC|8sUYNP}+}v~K&PQIp-QUA46xO(!1-PSwMb6LN_xW_a zlizesu+O8%w4I*-vwAq=e7f3Q4G_8)`+s3O8>|@TH!E$_W4NE)NvWf< z&Kl}kgH^)^EjVq>HQfv6!)mv6Pp@;_J%8~lpU&Ags*9a#Y&-T$PiM5=2=$iT+Tgkp zrq=R{J_>eMhNoc=34qEp=aSR%?sa~-@)|LHlYW!_2Yr+NfWF~QaGP}t-+?2JB`gpe z;%=TJi|2~WnlO0`rjG2>GOC@asK!z6OPTmV7$ zF-*_*0fVuD5LPO(PdZk3r18f&_BHO!@fTRbqMj+%A8M@Xl^N)1tm>5+IDi?6VTro1 z6PdA77A){w_!+FejCou$ z`~=o<5@ft2Wd^oYU&kscx&Ss|1yP{RN|}L2R1D5$1mZPVGS0Z5W*B$~I~AemD+ce5 zSqGL#5}6bjXu^uTaj5__V2X$*ugu`R-1kKi90`9n^wRX5NMjkLWwn7itdSQg^Mj~ld&*iaJ e`2YPVc9R2eDxRDvw5q2!<5meW6!%Kc4E_NmkmDf$ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library.m new file mode 100644 index 0000000000000000000000000000000000000000..7617860cdae83be42156855b5699c19f7da8bf7e GIT binary patch literal 716 zcmb7B&1w`u5dOv;$5w)fgs_JkCSeakH1QxIgn_KYh&ecsfZ!$IB-4u>W~Z0#-AFw7 z3V8!xAmBCN!3PN9n|NKqK>Ky?tQSGBhWh2Js;_$XULU-`ZM5=p9^4B-hju4_>!xe3 z+;rm!7N{b>LI+0&zaZB7u1T}H7|O4gt{DKm!%K+2ap}-aSNe$G1M6vqGih3U`cJ$_ z{kEfgLIw>PG@R3{zFAdR%rE|{p5+%KgpMnJSNe@+VfV&;U)e`S|Al^weu=)<*1P$H zs5{ioXW*2&O?`-4K=cm6IrJ-aYzlMES%?vyUJ5 zGbAUKwlWlGwvgzNY{7`|3~?<#aveV}5uPGZwHk-a=Z}$C^=UpJ!XrOnYy;MVdJtAt z^2B$LH#<@!(ilyOvwRte|9>7Fq>EVA=q87YfU1&*uyxzQX-d4F=NiZC)BZoFn-*lTlfW{pR*QN5Ng@n^=}ZT}~=#x3zAg V4SjsdL)OCtF-zLLKf-nVhKYdbp0gv_+A z#lxIDihA(q(UTV0!=kWA4?T(p@vsMBmp$kr3)@2uB_=!m-j^?FD+b>8=l%J;-+S+y zy!Fn~0-l5UebGN$(1#RYW!#%dXR4fZ%D0iYKOu#wrKd>0R_vZQwWKru82gT0z64}IE5{bE@gmXf=U950XjEqs=>lUUf@hm& z{2Vwn%#rs5%aa?+sTaX5;IDjeGc2Ot`4UAhOrzMrV|QIXL^m6 ztZ0R|OdJ;+o190Gj%_?oP;ejN_Hg_I&JTmv@TNqPS8Jk{92-VQH)77@XTw&%A@R`D zmX~5qdMcB`Np~vofs6lVU5VGh+GQF^0Xj;*L4&_0Z`8z*+3D#&_+w}A>33??`02*j zS#0Tr_UOHu>7*sEOt4Ljf5^Ks40MHqj=X9*B9mHcV0c(}V|Fla#+{kBu$Ql)SKaxU zf39avf7Wka&&_&e!&goeI6*_zol59m;y2Q)G(Q2(URK{*orToMpL37j`hKb1{cQYg z6ie;S5%)RnTij<#?SI#-fh;X)ud3>ix8#EQce6*hwU zfUxu^vs3W}y_YY`d_1>wB{MyNzlklFX*Qgg?B%dmW>y7F2hA z70w3Hj%pUvW>8g^7);hVRpMoSb+H@-AN8ZH-*_53jS5VB!F&@s)`C6wM94SwNV8_( Eztk}T%m4rY literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/commodities.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/commodities.m new file mode 100644 index 0000000000000000000000000000000000000000..0a02dfd4ca3fe68041d29c7ef7740255e98fce8c GIT binary patch literal 846 zcmZuv&1%$87(HoYyvk5qhzwFB9b8l#X1eHNkXcL_6)l<(u{(t(lRJ7LlY}HwtE(=2 zfV%T3x)o@*+M+vvsi*99=osyw zIDYYa$#9Mq#}5XJeEVPmG`oES%Hu@X70!1o!ylb!t}8aIw1P#hS)8L&?-HU`*T1Ze z%)%C$Z5U0bk*_i(Q|yGU7f3sc>?oF@J-%pls3vifPq?ZED&(<$&@_hgVt4I1`osC@ zANn5sFZvDEztFGJd-P3bM)Y-l#sRPoK@0Fs#`~U|N}b>vOxnZJdZq1@7Da(24!%W$ z(cnKx+)sq5d>LkHqGVF?2-d`&Oi~qvWr3&x=bL4sZ6DS+h^n>Bd$9BklzjrR2{V)* zb!1ev4Ol8v**T&OD^;J*bZgwYX2??Z^@M@@5UC90SWi$pD>f{dBoQU*99V@Fy3?A0 zZvdtY{jx>$ZQSu?qV}Xe4BRw*Ez>v(&jlN}1?z(wX!f&x4ele`)`bFr6<Uyi-HJ++g0rJ;~QG3uO8zimIqvy@d`bI3en%p*I_M%l&Np16EMj AZ~y=R literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device.m new file mode 100644 index 0000000000000000000000000000000000000000..8a786172897180c917a172508166f98f6941a6cf GIT binary patch literal 1826 zcmbVMO=}xh6g^|9lc^D|79w~d+!y0gn>bQix-dZ)*^+EIl}E;DvM2;u@jTfBBaJd6 zxwLd)x@ouBbk!f=MH;;DrqD%yLg}KEQpnPq(sUt;QEgApn~`kQ7*g`Yo%`PXIQQK9 zMpIg^7V!qudIxwS!W}Rk>KLHCWj+AP$1%(s**i#34D)-$@TmF{Mg}6+ZP}f}uNuJg z=6ARzMy%Y*Be4bC6S;;{-+5(him_9}T4H6|A+(Jd^Qo$MI}byUL*)g2G#{B=^Fh!n zA8W`M<>R-}#_fD?8a_|5^T8qIh;lGj4Gx$3+W1^KIGS4z4#cXMMe^SM4v=aGb2UcP z=&1#VThLPTPVlSw{H#H&p12eA*xO__2TSfP^~b)>M*Ulgjc5kFwl#?NRBgte{wIEK zG`{*W_$#a(&#FEYiv)L2S=5QplHx9|Fe@)&G4uI(k+>&}I3e5g1&`b)u9}#_5UZSZ z@@hv|9_?`XS@2B75^aL~PY3KB+Ij<9Z(!RBZ(6p&Y41}`qKT{bK}~#QiVxWttE;K1 zej@f`Ap6DZJQ_V`&cL&afF7(e2Zmpq0{Tp?;&<_&SMe0TBe4&5#H+8PiKmCGw zq0s;57wQ?tZ&FX1U83AjvJdT?@-3xEN$mp`Wr31H9OJf2ZjHLlKRRMZ7(=4z@2EzG zwr^-N6j}0AF+XE02xx=$I}GkNBK~wGh!?jl+3MI0TY9tr25rWk^nBZGsk6>=LVdN= zLB%6!y8v5?iAIgnMN(H**hPj~$Wf(rmj#!E? z>W|scr6~{HlfH~dFf9jt+i`svA#gg-RmX#)h7S>M$xqobe`;xX54t_aBiXc(QsO-p+Ap0o;_hrcQP zw%fWOtRV?~x9%u(RZrtx7(UUKh72^`#Drxx8q(wataxs77|HwTwk^KKVP42K;0kf> zVv1Jl{@N#{T6LwiytcYpy8m&lSbDftDAkrL)xt;gPf%tnRWtONOY0?`fj23On37G` k>N?WD>$-zo*0CRZb?>tbDX@w$IEHhH{TbH%QUR#-FJ6-GeE0D8=9qgjqygEbVDa{*Ijk&^%VZ+KTYca`wQ<^ zex<9{9AAA~*~39|Jn>0)$p1vTLi!`=62)tzi}r}BZ<81#m&gIRMdT+F9AMD4_aFnDz;A} z$G|Rx(+#6UlhP4-XR!+0EI>66VY%TSejQeiQ8fhRw_x!sa_4w+=`pYYGf?k%3U8H9 z1(uiXgyUscvG*YbB7cpM5?%>+7?8}xS3Rc7$Oe{Sr8}BVD#4n411g|hm_(i}u3m(7 z-SYei+&u1gRIho7!6$~VQ$nrp`-t|+gMYB&>i_Ieh`MK bRrS4Y04dbC?b8hy5D%A84%cSOz+y@ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device/printer.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/device/printer.m new file mode 100644 index 0000000000000000000000000000000000000000..c7f939b8669ea727e613b12e29add859b2d958f5 GIT binary patch literal 2014 zcmcIk+iM(E9R6mr9k%Nd))HhN7M;c|?8CZ^QZJC47-5KHcZTo)U)Q<-0IlDWvo4IV|tog&!$lBcwbgv-2g=^Tc z&)fas)zDFLJy_p0NAKqUfro({J?_V?j~LJd4cU9y07rA;;cY;teQpN7i$d-}9QD3S~8N z9LsI0F!BOlY?F4O?|VHlWIc*r08l3@tmns?EoVKF`8?-KEhl0!VGs+Vj5YdxQKnHM zR*?^#t*y}OF;j_)Z3SjB5ZlYhUup#Hw&S~;JwVmJw?!1zL#MOhHQau?6Tfl;3ozY4 zM5;^B$5cUQ`2Bu+#DpGNZ+;bdeqZLFFp4OOz8FZ8`hqjL)>#HqM zH}nc%0;V^pk&M@1M&5QJK)WgmJt>jwFi?@GTB;!~C1V2?%%oE9Cu?ZHZ( ze!t^7`fQT?_SkTcS|?CZ?ZEA~R5TR?N$+UOyBIp*!$;%GTh~gt!A%zbnX5VqeL^F@ zQs)AJh12#NX=HHslT`2InEbErBILH*O^g%E#3XT+I72)@oFi6ALr^tuMyuU`3e3d*!eu*q`yiArj zULi{yuad>rYvgChuahMX`Ziu5ze$$2@DW+w_s8T9$e)nECVxu)nfw{~I{9A%BN-NAh9~Jeba(Th&9eKYU(_uiZ7joVA}I0L>e1NX&- zeg?!Q2}l>pcY)Fu36ttY-PjBs;yR=a5;bZvYp` zMp$_VFQy3LTDcMVBoqaX^UYy` z(8svO_2TRS@wwLsX-=O8x-_yvL+{d<;u`ftWYJrXi02`l!=*oUL;BD!b6$II=*9jv zaNeU_DMLN0oU7+>XMY{7&vE_#6|&@s$T(*CM2VKk$B^oYIwL*J-wn^v$rX|i3b%J6>}EA6mA`6X!SuV^|8bIrq%(OXz2 z`h@5j(N9EI=bAsB5?z^V{(MYyndkx0#kuD9cSOgDJ|{X{uF;4iQO97b1+xQ%?mcA4 z6(e9gmN==7u@jwCl4-ll4=mSdOVc&S3WYA&A!E4!d6YR7*25dNu^DiML6VQyMi4UJ zcYV%L=+kYZ!fbl%pwg*Oscmd9E|fS*nDhjs=mccwTZgjahTJy6v+t}mq&8Vt-7=g_ z=G1mN{8bG4%rGmqTcw+n;6BA#fwt#cA&UiFl4WST#g=3G)-HjTIyQ?)af#=l`r0Y%_>64aIc3&R3ySZ8t7E$)}*W9^++B zc43uJfb6inqv)WgLb2LC;QSnvzGYh-Gmt5HQWe^1C|icjts{RL`J)M$J&K_6TJb(IC%oyq)R0J1hFbGXBjmXer$tNr p+g(SN?YL&mX2CVrjdyw5s`!TgFdtpFN#R9}@1C%i)50$~`vuJHj$Z%( literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port.m new file mode 100644 index 0000000000000000000000000000000000000000..cdfd6b6746bd6c1829189367e268a153d044d091 GIT binary patch literal 1630 zcma)6&ube;6#iCL)U6S&38na8!Y1Tk8pR4F1QSG1A}6@PUW>#jy#%uMjvS?{-DP(j zJEaF7O6ehx7<%Zbe?byLPA!xkdg>ogN^ZS|UUKQdh?TeBn_by*qC-c_yf^R1_r7^E ztLrPPi#UN|JRK^NTAASb#=euK=a#ax=4G$#7lV$~%hJp9H#<5+9o zx{osJPTm7%tp*&|Epn#Bd!~J+iv@en68yZTX1%lnLo;P|i0L_eREOqwQ|gaKT8&M| zOpbV+@t7R) zI>sZfX6nAOgGBt|7`IOgZl^}LnMd48!tE8a#`uMY_z%8&rzX3W-|xZiqg;j+ba&hK zUS35|U=Zb4?66BCylZ09xea@7h$V042uC_OxObe*_(;wBr~e)K<548vKvm!Q&X-U0 zi)&iX09tX#@1pQSd3@!Zqr9x*_R7}zEMz=Zbz}kqElPIgF;@H_#mV6TP zkoU%6{mP}<>JK`nKS!JLd&=cj|G=bNqD&|kDZiy`w))vDWrO>FC>L7&bcgZ+pUA<7k-Vv` y(B-?;dAeh~M~>28lpj*Lgju%B-SSj?IS2}^9;`p$appCSnQt@#CKfdZZvF#%-t5}| literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port/arexxport.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port/arexxport.m new file mode 100644 index 0000000000000000000000000000000000000000..423b63941dd5e13ac462ff93d9ef18a2960d0d9c GIT binary patch literal 1060 zcmZ8fO-~b16g>muI5rc~5MqcSaUd+3fVL19#u!rql1gYHg2)0B2j)>G&R5=>0(Dhg zxNzkU@HY_Sj>H%iuKWe=T$#9IOGstB@68md)6Bb{bI!T<^>KY=0oRZ}A9_wfIfHa= zG@hkrQ?>NW4(KhxTw_a|lns#&FBHJCW!p`Gj9#2Y3-;WJ+FaVU1*Db3f zxt^cYI<=Dt*tbvKT-J(NZKJQY)M)~bR!%SV6w6iUJ+3ku#~4IupVr(=S2O#A7N#?i&Q7>yT=7ERct3A^?k^weAAoB0>T|GMNHdobsIqcllfzuw!G zlH7)#_Z`c5>@ReT%%7*<$Dd%6>_@We^XC_z$<`Vzs$Qp8>j0l%(h1yx#o6JZXp3z} zFq!!ZU79qN8yl#gK;D)kn^q&95TpDBvFcD37G+G|5lNj1;WU~2Ru4h~F{wiMqU9$u z5>&>;ES{Aysl^rvswjVy&P^1WESclYwS-ea<=0^emONE3f-| zuT(4Lmtj)AF6hcA(%2!}A+Lr4XR+V@H?LsR<}8Tz z*&>gEwYErDa9O(#%W>WHs6VaY9`ukMC>^R(Lj{Hx_F+!L5Z-IGc*R+Q5ygp|GSe^# zQ!tA?+hswmN-+?LP8gDA?q evhQtkhque}O3E?)neNK{X)vU(JZQ5S67Ux@y8@#C literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port/portlist.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/exec/port/portlist.m new file mode 100644 index 0000000000000000000000000000000000000000..11d239aa84acad00bf86f26d4128ef56cf667341 GIT binary patch literal 1194 zcmZuvO-~b16g>lD9Z5rwG^Pt9L(@eQs3pdQF)WIpB9@^cs4OsHWFBS0bY?O$rQ)h2 z#DyE}&L7|w_a-ikapf;?=gKuKSTv+zy!UlVN%S^v-u*c5ynF8J!{wC)TtQ+V`p$@S zhUr^3p2eN1#kgB4B5i!({K_%ZsdC(*j8-bf9laiRa}JQRv0${Rs&PgyAX5T)om`bF zRimAQKG8bh+GH6SAI3|gLF`>-*NJPXwGC)KHi22@mb`qnB3V_&)NT=HSu$pgw*Del zEnTOshS99Pe{jU7FSD*36LY_pGBEALzbe0>7@yC-C%6;7-H%DnX@b1m$Kgc}>qeU} zC#y#ZZUCGb1Bhg)b2k8M5Ac=RMWJ%gPyG+&GDRTJr1Io$VzCEy$jV9 zO~&;4RxpEd2=e#5=6DJUT2`B5l+j`Pq$(!Ry2diU!{i6HQTetZ)t*Q^g1 zvQULfvtv_`!3|3U_MWij9WxA91$FL*1N0bDJEqf{8ROG*AF<61I?ym`+1uM95N`A+ z@al}>MX%lPEi-u)sV^qOHL89@fktdK91-64yu>Rx_N%}Q_DlRUCH@!PCNfer(hN+$ uO0nc+rcqkc|78fH63OtkY%?NJW)PVBl10JzrTiS{B{!6}vflzl(*6QAv?dV% literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/gadtools.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/gadtools.m new file mode 100644 index 0000000000000000000000000000000000000000..66ddf6d4afe4ca8813163b7a68cba28facaf87db GIT binary patch literal 838 zcmZuv%Wl&^6g_T(8LBAi0--D_|W?L@0|?;aPzLNZlYI;nb7jGVxfpQy!~+ z0V+GbqI)Fx3l`n+3EiT|sX61?MJmkVKF>Y(j6DyYjqc+L%5zi&D@CwO`@-GHvpbLT zEP^x5v-JUl@vY~r06q6h1oyQ&t1wP`k?jE@!W&?FbejL(n&XEfx&zeAl(PX7qpk9j zr@xjg_jqw~d$7p14<|sg+lLCqoOst2?l&yMADtSm|7>Wq)FLx1?(y095~5PqzpReT z!V!k;k>{scs{}itH&)U~wWA{$I(uckLmjaff5blp>f&*})6|Fae1H83`t+dh4d-V+ z={K2wreC91^i6k$tHfJ}zy}Cgpo2z5J@yi5O8ANz?NMRJh3ym;d5$HHzrqTmK{ZEg zo&8$i%P)axoak87-qAzTI^@z57MmF4FCWD literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/locale.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/locale.m new file mode 100644 index 0000000000000000000000000000000000000000..1a7a2c4744916816955568a093f2c767f12b721c GIT binary patch literal 2010 zcmaJ>&u`;Y5S}C^YbvV>s9NPvt-R3+6*Y}lXtfk%K|%^DRdAz4EB3MyPU5CsId)__ zyMH>)JGEHz6uZ5oGtG9DU()J84Ord=Yr zPhS%4?4CyB+C+L+m9;8K?4_;|uc_=rCyf``jBz|WdAmBB?hN;cikeQ2-KtG;e`~Vw zGv%nWd&*c>L|864vnit($1htKEaEuI&JaxAN}?*7U@us28Hd1?=J_bT>EqX!H}}y@{cyy5ZH$E25`3mukX{MUC`@&W_RjvBvQb zOZ4R-_hr3`e(LSe>Hc^WP0>I7-Vw>$2Sk@`MfJz%ej#3o7*){+1^gt57$hF{6n4yAh54 zzp~Nj{GCO9vMRdM@Y<$hQKfB$rsH+V^Lk!q;8=l1mfLmgV4v>0X3MeE&{Ms><*JVG zsNfIaoBmgHK}GlQslQ@csZU-?H$SCDeKP$6avSnFF~ra@3PYj;w!rrRDKWX08CblL zc}^1Mj+obYrtii4Ow27YSHw(FL|NGWMKV^+7zg%woJy|Q6L=&;lOJ1tV0$hHU|mTo z3B3Tl&>GlIXuAzOoPpVm9chJ{_}P5JPE^Eb;B8ppZtIcN4nGfl+r>XoqKr7l1E3|G zru*6X{uV8_9WSuzN%KHhc;KJLt(tG=<{mobg+~HRo0MnEM9t70WM@5LoHX`r%G<6T z&MnH65A3g#G+?#H2w{Np*y9$-f#o0#?4W|!RVi=zzURj}(JJNV6=c{VNtWB;6+ z^^WD+kF8GKF@xZq74$tf?w>d>P=4QZ7@gx~NI^XGqn0wrpbN_#dvDM3EjRqc_j;)% zdNt^G%#gV!`9=8Xb?66FvXYDc{;MYtcz&n_q8$~$z)OxbtdU!e^P}tu&vfGo|KyFN OzUh-;=F+!3^YU-u@H0)`Ql7h#?U}-+9eD1);Y16K4P@uYn-B}cuse}mB<@a6pX6zGf-v>z;KaK-kZu>H*SSvi8GE+ zP*}-s1LWUmolm%BCga8*@1ndOUUIzPxLDf`FSkb6TWf?b*6xNE2~SyP zkkRCQWL7!3UfUuzy6Jd{QClr!uc9zFflB12*O(mt_zE+#c-~AufJh;?uM(#eR{^I?@gns7479|eVcK8Wo>z~aI?a~KJ{uYF=wGyB5PIM zrPw+*zAUxN@2CzxX{!!@c)<=&yGG1h*M>>`l+ObyMwd!5DxJXYT|N)Thd|}tbE!aT zBv#`T%h-|r^3h7=u^V-OHN0(9Y|}}249W8~c1r=JMVw_GRL=VH9v=Xst#7+7{-IZc*tVD^;b677W;x8-@}Q-G0lXAp0AZ|ni- zO-aHvu#0QH2xc^kSdoL+Dg?=>`$?}=dh;IZfg z_XE#zsPs(Cr=fwXJWcGWiM@`cj_vwll7c$X!1vtk3uj_ZGSg5&R(V8$HQYf~A}4ul zvYz4z$dlY<16j+lf(c?BS>JjVRb1j$B}3rzJn~q9?hBjOpoM*-)j(Ewp6f+>;5xFC zo=MswGQ#P~l|&b?+!da6BDyu(^!>A;j|f#N(*x7u_nD78$$cd#5`{tj z#NJS7qBe@J#P%*>*doEp97?=+TBgY5v}q)l2Ott{>I^`fGXopiGgv9m@sJ;;LFAbbRr2qf` literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/reqtools.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/library/reqtools.m new file mode 100644 index 0000000000000000000000000000000000000000..2ff48ba1ce4d3d01d990acff8215a05e5a676581 GIT binary patch literal 1840 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 C<$T%z literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/list/doublylinked.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/list/doublylinked.m new file mode 100644 index 0000000000000000000000000000000000000000..256eab89e31b4ccd9d7169bb8c354f2ba4dcf1c8 GIT binary patch literal 3618 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 l?Z<EY157*rm4ZWlxs$O#;aPT%&L5JBU|;|M literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/list/queuestack.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/list/queuestack.m new file mode 100644 index 0000000000000000000000000000000000000000..d87b5801766acb2acc2f91954e6a42f6f718c241 GIT binary patch literal 8638 zcmd^EZ)jWB6+f~S+qA9|}p=EZs7%^WKzbzjN+= zPw!bu)TC}YnBboC-nsXl`@83!bMLuNPyFP`L0UojH}5_~<)N7e z7+Qz5max=y%iA=Cdjv;y1T#lQd#XJ{y(6!oS1eCo8xkXc#JDGtzWXDAJq)o&*nDt1 zm;pN&n0;7gpO7()d(HkK$5b#s4TvYYeZS?Cy6|*b&VSn4`+N(}H zsMS=~bNx&2bph**eP#a&tm6Yz+7rH?xKqaYP=?=h z3V#eGo95x8! z{4nCSH;^NA*KaR7)uQi&4%cK0k|R{g?OhbUeB$YAL-x=$>BTujJZ2MqO6toMaMA(6 zM>?Y7yKQ7Cg`qi$i%sT6Ulsc$%!^1~pudOu9g3Q~+r+4eGaJ^r>1W6%$jsg;3%(uV zCww-QSuZk`cs`_`BzIvv`aK3syWG*ewQ9IVo?h9%ITs498)M}*$`+h?^*gJ3dkoA> zdI(NaaAGc@m_}giwY6psr&wfq`7NSH^xNU&@{VFoQyiA@W+Ed(2Dt&b$_x3u%gZR^ zjjh;n`~S|0G0$4a#kCbJ$;9Zr9-~^!`8~8@1FBu z^I^OA=M(eIhwH>UF$>u28<>yW>s;ITcY4kRfe!m2&W(b8bJu=JRG}r--{&Kk6S8#7 z?GGokokha>{C1Zp#Qw{z(VJIPJyrcjazvl1DBu916OMV;mDS*bLsIk|bO zvMcWC*gf2Pk-njskOeIBC{e1lb5Uyh1yJhSTMbHoyw#nncMsS1Gd0J+Olx&)TjB%W zs(4nb-j$*{4mj_+pJ%!{UGJ#XS-t7h*V%YQ>RKRRM}14Fv14Q1jn_!uG9E&AW869; ze+b=;aZjsTNR4jKFC@2v2kI|lkMlP$oH`5rPLtDvofugmf9F#3=PY$0xby4!`WoKz zX;8DQdeH)(_M5Q>BVG}oI5{rJiMqgRD!WHNW7%ipX0ULGD9>_~1*wxShJsG=cl7SA ztylTH;8!~w`!RCcrm=fvWz@bGqm5JLxQ8OeD0mlxbkxiE9xZycyKD5J^IsXgtbU#@ zU!oYYeVm}M%QGnZ`<+n2G_-sT?ggCbBv5vuW_wLdCu&TbWa_&Z`%0Dw-eS6Ug{8X& zcK(-rKH++m>t(oO^7*Q7LGBZ0J4#mnOQXvAzC>QPf#5`W_R>?QK_ z<2-_=bE_ri5~-g$vAo_ts(u3=m`IzMk~I^hCuZ`c7x86$&k^g0wXZZWd5HGx8_A_D z{sxVo`98?{q;vO^O+Th{N$1Wx;AfLgncvTVp97x<-wS>^>HOyw_$lyLz)ymAg4;>Q z`2hSl_!RgYcoe*pbpCx6JP#fR&nBJ41K`u(CU`pO{Oix)dsZ-Z~aJLBlUyyn48 z$Zvpe#C!+9+wi|Y)e7;XbBoac-K`&j1KnTW00+98Uw{MM%~5cm`;12ey3f7~4s?Gx z1rBtdayy{=^cXnM-M9-5bT_i#KzIF5;6Qi101kB5=fHvPdI}twk}O5+#i?WYfC4DDR^@Wz$**slviwu zEuvhpspVailugk*3hGy#vdKW5@e;}iN~cXLKSAk3!E@vS%Fj^@n^pkViYyAo3jY!1 z8cG7C+otAUpa5_4Aj&qInlM%q`Zn!AdCaB|+J@di0k+TFElH3r_gSp#B}9Np}!OQq0nng@rz8B3fW0KtTb5?ImL8^v|l0k z!&g`m?qJ${S}0BwqNejg+n9zf2<>D_=Y+CuYW*!guQ!;k`&j5ls~qITQ4F$Oyqql58ivWpTC)dB(~zj&5Y8#9#C=`K zAVndOp00=zSPwOVtEo@MbXzHF^io(pLGoLOc2IcMI?7L~HbmPgl9|nT1JM?WcwWiv zx+s#%m*6(KM+X^2i;W8jyd6K2B37Z0EAYFLh?q7~WOiak`8P`tRn}};)rH`{t!b-} zdBI92;rGS8RxzKOExN5k6sO4aM3zTU$YU56+WK82A;i#{bY^PGDp<3nU4@)p{}4yk zk$ifh#Jco65j*&;lfl;+{Ji#}&=k}7RiSNYrSKbg$_8RET*w@pUJ`>Gvsk$)U<|~j z#IhUctey~+ZQVSEL@K@p)I^OMH|>iWB^j?1HL7OJiyC(wM(ae4YP;VTHA<4IiJIZM zQKMSJAHAqi66|qxq9zfDn!dVG!&c}GL=3Oe^7~~d;Fmn=|C~Rze8{j`o?{w)Nht5+ zv?>CBT7`!J+Gx$>(nqpZac3^4pL%i!cq`f_{%)ujv~7lSZQ)qi(8;uw70K_vINpF4 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/list/stringlist/stringlist.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/list/stringlist/stringlist.m new file mode 100644 index 0000000000000000000000000000000000000000..651599cc8c02eaf95b4daada8b6d173bd3087979 GIT binary patch literal 2194 zcmc&z&ube;6n<-|>Q;!LhEQ|}Wo_Id{3Dx#DaN=U#ZFLzD;wKweQ>B$?^xPqrCoMc zj+0*09(u?n81gstR6{5|v`|Xup@*J&=wDE1DMb(+bPz)6_Iooc$xeMKJ#^sh%)WU) zzW2R1H{ab{r7TRs7nzOfkfYpKRaj`+RXX>(^9+i^me;;*85WI!;CZHUX7y1+>2Nb7G++pbiI6nX!;oM1w0`3)#5<= z(bP-Fq_|5fA0XWuN4l^o_%6Zsb5q}ZCOaT&xz+L*%bU804UmCP)r=(mUX>rJ=w z%n)Ohn6_aFTt6XKZ=7$3Ibe2yVlqc(`aPchA|sReddL@|_N+vFy!S|Us9=0aJlA*& zQBU5;_hM3UKxsoq{0vR;yCJOU5BU`^Iyr$$vVTe7=%4ATrL@2ebkVWm^Nk=)b8~aX zh8={49T=kFh4=AtkrB)I4xh~0AX=S%hrG4HU!P%j)&|cz*z4Gruv=?`;V;-LcvTax zEVOB8XR$xVo-4Ny>t#r`O^F+jJOt;d-yuhkg*IuwLMm;dKI99?1IWja_aV0+E0D{m zn-V`zCWxI7(EfCC`rk>s9Hq0OIeQ7jJ0}LwViWX<_|uJuV6uxgLsra^xZ}r zOOtws^lA`mq=M>{_K-3xI*1o9i!R&EK=@F4_3Do6hXN2(gbJk&98vX^sYd&xJEB<& z>#?s!d!+lKu`2bCu}N{yD`8QkPq7+Eb*vMKJdy{b#2>y)yaHuKI)qXkL@_Jc{> zJf&PO4CEc(&ypSpM;x$+LSs-$_`VBn)c;jVHLHzDgd8PB6HM~b=nB1N3Ew^v)*5OE zwngB%U|n6~K1->3)#2!>`V8_RT5*Cvr%RT7cqn|)3~!;;Bg-V|Ezhck94oFb!jh;k zCpayuIg5FdbLRQn*o(Swmf2Uy*9o83jxQ@xv* zdh+PW6DAytiHRqp-uy4Tb7@RNTGqGIZJ~H_Hv7H#e$4md%`7bC=5Y?KRauTUh^tK> z>=)>NFH@D`R4KXM70a_vKW@BV|#KN>$%^gA$#h|69 z%&IX7y`zt}{AHMr%-weWGny9pYN|F*->a~?UdB3*ohU*N>SavK1vO(bsH=X`Va?Ub z!N;KX6u24M`PVvCM^#llJhQ@>bp$`VYYJBB?ufOt?wIsZ&%QVl6`iTG(|X9#HZULZ z!Psp>r+jGW9c~_|F8b;3q37}`&tj*)2J6PtNB9xWPW)`>xkKhI26e^nuvwj|h{>Q~ z%t2!&UCkfo`~%(HhO8^!)sUNRpCE_rYz8_kG4}|>^@CT6?ciSqI*|#pdYY}X_AzgE z%!^}5`a4cRlpJ4J#j-7nvgFHx*m7Lq?^vEFNY{Es!=|10y#I`rrES~tcHlTgr?6{F z&u})L$W4E0GwtKcg7}^|K>S4PC;let#2QgEcX2+fS3%D={vRqp_zyy-1ZL15^_R6gpN5_d zXq1aerb3CNlGl`sD~TXLFQXEC`2l8HgNEtoodJ5ktNjq=G_;a@&QN}>l|sxaSz)Qx zN+RZ2FJ)WBIATuO_o%l{j6(OMO(JPwO)i0$bX~`7>%)kZ^2K%r4MWgmsh~nB5*UoG zH51LyY$dIz&7FT%Dq+`Rk3u$|4kEscnIJ{x~ZW$nI;aQ;!%6L1j&*<2=_U3k2@ Pw!EBMxgXhkZ>!B;7B!Z8 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort.m new file mode 100644 index 0000000000000000000000000000000000000000..17626cd3fa80b9686da22b0c546d1ee446ceb701 GIT binary patch literal 1114 zcmchVL2DC16vzLg(`7A1JQVQ|a197VX@gWQ`%fSY6kKqhE^#>{{2Pyd{u|2kuI-i&_HRUN-{ z+Aa2~@UG8Z@68U+tJV95T4fJqb>!2^exFu3+jal+|D5g2vF5ppT2FO40sIg4%X=UB zl8yNfdE*iKWR2{RJ+e!_Av@$JvfY?xt7MDZAe&^1+$Q_v7MYNn)FAGue5+`eEN_PJA$wq=s_MXy)L9$dL2fpv&c3hmtG4pUV2T)gE9Z|LUS9^ zSee4xf^(9F6C0ebO{-&za0zT!ofB&n(E@kjgmG8~aQ8MG6TVuc3*3UElZnZ*ZQf0| zMn&qtX7K*p@!+U5)oI}a6*%#5yii!-6r_p+hUU@hxEiQ5JXS#?8XEINnMB8C5iM{9 z&e8B}VghTdN41@02QDrL;b^2%6;B?ddTe{JkAyo-f?Ao5eE7APYsPf~l25)VgsFIaHAkP93Ts71t_7^gydv*-dQ8-d*i( z8n^1fpq>y?=`G^Gi35j5st^|>4jef~`~Xgf1FFQ;7=w8;yK6hdR^qJm&A0Q-d*95w z`F8C0KDf1kR}eo($;+$i2t9%=VE0&jA_#? zTt%8@Dt+!z1Ct8%MG=7=zBnB8cYx*FhcHj#3M2JOk$PLugeV3(PV3CfcEZH(WHx7D zhC}9aGPlErXP&b;Wcp+Vp?_wkH)LKT)2ll%^YW<*)gz{mN{`j5tTj=mx>8?LxX@KK zMtYjVlTuZ#5X37)y!+#bIGcW!Y%w-H12!`QHai2B>lH2TehE5jD$!s=DVC_EzT?sU zh=S7L%UIV)$8-VA^}n$k#JfkI#@x)Qi0r8db2`H4@OD~KcMNZmvF~h#J7~Q(SCWdv zH`5nmJB$=cMmo_5@vlwAbFITnL%jCOR6G@&fIpaur=An=_ow2i?gV^(0)C{Qs(w+d zS(ZPpDD(7LGwDR_-FKL~q^e?}@=Sc3s}|l+x7vR7>Gi|tUMD^?BR)GLUY`*!@7u2Y z-8pUj(YKyLs#u2bj^sDssa_`?K^cMRa`YrlR`VHb8`ck>~&mw)X-0L3D zuh4t+`Eu{CZ|E1|vhszuAHD8|{1A6WSfxVh8$n9n2lj?$g-U{-C{} zJ)l)+^3yt^eMPfq%a{Y^zJ@s%;IXU?xlb6-p*I~00LD#T?hR)bQQX`)88?Yf6GiQC zl9Ab_z!TzGPaeT>Je9>`VE!^^lkY$qDgKDwP?G|hiiaw8^H|JNvFHF3T$5|JLwUYQ zq^?lv?3pRbW}4I4WCd8?n|LH+=ae7>fM1Z_Z*K^iL{5kn?#O! zo6x!0WX=uf+bu8Ym7sH-Nv{ZF-*1Extnk-l9yy8Xt;#(65*w`^Sb@=S8Zm&FJdB|6 zD5ev&1jF@09&5~4l&UoCZOP#2Gb&)%zVG@`AGio3)|SJ37Pw0%mPkVuZ&|kAcwk%Q zW-SPA+kxjg!Dzk=jCyTMu{7snDXk|f&|uI&s{{icfO2+^I literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers.m new file mode 100644 index 0000000000000000000000000000000000000000..beb20551abcf1a1ce88151946ff3f788eda8d725 GIT binary patch literal 1098 zcmd^;&uSDw5XQfbonaD0f`lNF!@A@kC@R5&NDhWgB!Z41DCD4!*>q=jU}k#go^e;n zA%`4t$i+NLZh{XXc@&S!;#f6*c6|p6W`14OUsqMvFuU*G?_d#){c0CW)#4VtRq(N# zKH4j%+Y_u z=yE5xN6!VMO%+L5KeKcAeN&{$QKXKa!E@0doheQslZaeVMaGb+9<-Y|WZ37Um1U$1 z$E`Akmzfcdqdqyra#F;3l*M03UB?ubUD3~Nc%08-N0d`hpR5r01R1w`0*8=;x%UB5 z&%J$8>L!c8TT;%wJ??t8w*z^cWNn34kdD*T^|s)RY?QOO(!bz5T%_`zbDj}v>;46v z!Hd$U5m59oPw!iEocxFIOqTPA>iiq2cEXp(46Y|uft2jq|LBM-%e`& zZfpXpSX0_YU$pAQp>qe?WhQm4T3`jPPEl&{@R+P?M%Wi sG8I-=Z|+x;f&ctX+}DXwMXcRRW17`dXKenYI`8qa>JMV0x+yt-0r_JU=>Px# literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/float.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/float.m new file mode 100644 index 0000000000000000000000000000000000000000..19c1470c7aa271d35fdff2ea3c48651812d1f0cf GIT binary patch literal 1828 zcmb_d&x;gC7=1lcwjB`(5=4TKc90{ranV^}erO z6*He+zA}dcsKfe8f8ZVU(dK*PT(3q`^VR6$u)S(q&R0&^jM!&k*-^RIcAzYfttvzkxH(Z)juc$`gpGezj+x zt@c)cGhJe%)&+T%;@u?gu;ftd2p{WJs&ZZDYA3*~bEgZ{i_SW*KbQ`yKb@be9a*iZ zqS$@sj_l&U4*ajyud<4+`Q|FyZ$;(7YgClyjjNp=7}|}$d4@Cld!TR4S#*(B6RvI3 z^W%JuPI8&Q(XY?hS^| zriph4!|G$=ZDNafi{m@Q4dOLoLB7maiKmDQgW+hCI7gf#_K6RPJ)%RLCB9EQ;gqa) zkdN3x`@$Al|7-z&@c9ufptTLNs&Ic<^#>CIV$BUpA1W-|2io+Iah%UR9LmeZyvW?8 z0x;D0U07bQ7I<<=J#rh?a#)-TVsh%Z1#>A$zt#)`-$P`v$MUiV9R|LGwV0H#mvcmp z8`y%G2P^SD;~R)5U|QGNfQWtmLex<}xQlWr!$3-=%f=+-8+8~6xj5C@vT(P`=4X0zPDX_!e`NQ>$n zoPw46p)Ze8`)$MYvn-)c^|_pY8M{%VaDaC}`10Ij7*-s z#k6$MMZhR7L_(1w*2P$)2>qc8)0K--?51Q9+E7Aq5j2abOsCVne&_zY`DxT_y6J`c z&b#ODp7Wh^@0)r3&55xNhs zXImB7v&KYqCi-O^yLU-iZ^z_<8r(ce9MQ}aC@Mu#7& z1s;d3kw^00*8S2~@^|N4n{V?zSnuGop>AM-Ftn?4J)axxN-WT94 zBjaUJlMHtlq{~YB6-(h^IW*A!wQ)x>cbI4?tOGQ-(exuABp-VNG~^*PX8klz69iWU*g7R={MWDS>S zOAd3WM8PG@JD8U+Co#KAwD~v8dnGcLF~7t7q(p%-=7*TCU&Y-hoB6ck+kQtj~Qw)P#XvXkILTaWc=*om7F4NSJE~W}eH>I&LC@$hu zVG28<3HXd7PU&TwOo6#vog_2C6_Bg9$aEU3QD|z64LSzR#%h?O_U(qqJe_v6mq9Xt zy<8CuP;e%f)TJ?~pZ)MA!ulZlnPFX-6VZMOCNoK;0Pa3U@0_lzL3=5fbqfrUwCE-) z@1z_qi^AKcpp(mG(UY<+yC|56rL_m#Ey$AV#>1c;v@`DHl4qQFBo)i&$DF*I&E&PV zLE9-f9cx0Y6Z^s2AsvB17Hx|sr>2~olPMg@Wz#Y;1Lwplx^dZ+DnGuFiT_o8O0PKS zY`mCq@~>vI>Mfkl<_h6VF+J(z@?mwd`h>s6Im3B3A9Cn{Z^UzspT<@3L zw(!zF&`pr&5_qV42T%SNVTXui*_xhje(bs!_QK5bz2EzM&--J(-3O27XVHVyPO`<- zc+t)G`|{JMIbMpIo?2ciS2J(AAx^c99nFrK+87kghB`t#+Oq)Fi2qPEl(<% z)JZCr+Rf57`eWU38Ko|>MRoSml~?D_m?iCFa+gdcW=@hhppkWc0vWGkkGbUja8dTv z5lK}~SoP(M+J6~)-_cw8a=FS^a{kTmI(onzxi8Df1?IZbV!VQ4n{=hF0PhENlb}Ed zrLrQA(gZv*E87{f*iSPb~8a$Zh#%YiyX3IxjW8FU;w#|%DIX4F(1{YvkC-nQ@?Jm ztr@=Igb#h!PAU_;V`|mYlN*!v7ttX97Yi6MY*(*ZMsVMC(^Woj{V<>0%V09rQCqi^ K-HLkJGyVdg8)7{G literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/twonumbers.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/numbers/twonumbers.m new file mode 100644 index 0000000000000000000000000000000000000000..846af131ce21458e0e49d4a3e57d403d20ebc0e9 GIT binary patch literal 728 zcmYjPJx|;~5Pc?#WlkqV5up?*5Tc+!fg(kOD1rhgMYteDK|v88yBwD6U2AvE9f*P= zMGF2^>pEKM1QOXLP!t=wD=G(`d;#98d6s)D;uWX=Di=A*zC4 z63`4nt4VmGh=<6>u^geAnE9+@mPl(eRkp*o7*tK^i@LlIN*tFMxMu8ae(e{rKcp$C z&sgsYqU_%;AtpV#fKWX;Bc@uY{32$Lesb4~wm4AS+QKtA@V~JR z7YXPq>r9!;Y(Dpp7P@E&gm-v*4{bW(ZKS65yrQVTh0Li^g?Zz?H;^i84ecr7&q#G% zbqdS$?S$g*#+KkC)}^w=osvJw+_`h*YNK7pPOygbHh;IVA=M+b!@h$ItFpMcQC4Yx zVolX`CXh9?%){vId~-6aP~8J;s>;ZwRBqpx_O|Pc^}9O$a$kZ@7E$Pw=ZRaw8|VCN A(f|Me literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/string.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/string.m new file mode 100644 index 0000000000000000000000000000000000000000..a15cda12d0d081e4455fc8795e65456aac5c59ea GIT binary patch literal 3284 zcmbVNPiPcp6#s1;C)2Qqlp<1uPC~F^G;3QaL2}r*R-&|Ph%I=~HmN&Fw(Or_XJdl( zuq`4|0!GN8CyzZPCD)c7dhEeN@#LZO)T7Wn1l(@7o&MhYW_EUysL+8o@B6-a-|xNm zd++<^gO9FUz(GXMukm0=2M2(GiTo#FXKXs``04zO{Bk^-YCCY9Xr(3Jr&r4O?#3-2}J_w;Z-cW=4uQn}2xaPgw40el3Tc;Vc{e zakLt7OqUyrBsiXBki_E)Bf_zzUzf<5qt&RwQjb~9R=9M;Lf0bh_VK0r-727V6J3sz zxHLZ>5lgLzG0CW-QOyWT`jt5{>NR?8x%=YIHlj?%qCHLajO;nP7mX{;KE~b_#>UFw zPS}}4_=|dB^?JD>T2t1A9ddgpwqbPQsoC4<{HE3KtAX@|bgSvq6H$~M?(OV}UFt~z z*^g>^Tp~29+Fhn2?wfi@ru%iDR(dv$hLN^3L|hd zbFK)c_6cLuU8CwnE2G^Jcg&oLko!*cSr|-Zf#-0S^{!rueT=(h_MO&6M%q>D`GL?FzK7!6`>GS;G3MkX^`IoT!OKv{fJVSm7<-BOh7_w)>q+&^4KDwv zgh%%52;8@}zbeOl`lHL9G#v1Mb)?HUE$K<_a$78R-Ei_}>HRZw{{(VoB{JprG?_WP ztMdPo5vg5Y<@@-NTD+W(tMyv3!XguckNXo}>0JA-$HSMfo@=*%qh8Ck|2{{3KiBSn z`Y!b}b%XjI^&RR>>Q(9|)b(8ZA6fUQpHi1{?SE&em#Dv{F67$b9Q9nT-P)$UK;5Ly z(r<%$l725!PvqLqzo0%teV+Oh^&{$0>MZp!?i-~(nqOwrgOuS027jk~OZkR!y#f0k z#iyKX;NTyWN0fESEy|}9u3H_-@dge&p=?rSDDP9;1_mBezNc(ZZc{EcklLo)q0lBp z8$6{D7sSLk&ngCfh7*R^2qJc2!-7?;du%U09K$Jj70|{hR_flOSCjQLHrRfy3~`jQ zu2zfnC0&u%8myc1bs(iH_u<^ER&;@0%^GkQhsl3+DHjWclE-h1Q|=Xx z=IF~?pphb_a2-}DnO%dmn9M$grT3rsOkswWf@NkO(lVJ%!>YtH-~#z7`*EyUSbB|` z$R}a1)L0V&=`$fX;*w7aX9Z_PM#dUA1G`u$Mh3Jw1v@C-j<=_90(RA}2fAA@M&Sfr z$-5~#*b~HYVSBY&m9>^Ra13^3z8oV+%`H!=BUf@?NL2RAE zVc1LaJ&dL4k7!eI1SvQ;R46Vicr~w5zgVlX`3z(1zGc5Kuc=4*X+<#jorHC8le5=2 zxQ&xuxms8*dBM4AH5z4tYOS8BESEp`YC$II-f_iFdYSpz8-j&NeZTnv9J9|BNZK(v IXC&tPKVD7YfdBvi literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/string/rawstring.m b/amigae33a/E_v3.3a/Modules/Modules/oomodules/sort/string/rawstring.m new file mode 100644 index 0000000000000000000000000000000000000000..5dc36b6ad92d82a3e9768409d058022e55b3f4b3 GIT binary patch literal 808 zcmYjPv5wR*5Pb{A3aitJ0--A?PKbg6aTF8?T>;`iAi;rvf`Wo*J)5BB#U|A9pS literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/battclock.m b/amigae33a/E_v3.3a/Modules/Modules/other/battclock.m new file mode 100644 index 0000000000000000000000000000000000000000..ad566f64e0bc33de653ca45b1d515ada304e17c3 GIT binary patch literal 244 zcmZ?u^><-lWq<+!7=sJUU0Zjzt{X)mcQxR!|%rQoL26X(dKn{UX21$;nBSnuHbw1v4Bj z=aqXW-gJyIve(Fmni+};JN^Q2qUXaur}rKFrGNNfZg0lsXxJ{So{MVczvk{A+C^(9 zp)DvPwxHi;nfdlQ9x9kh}_vTgir`ta0`Vk=FLN8BWbO4T<2?cflGB%CA+ x_avQ&;?U+&dHmKR`Esj=#%4QZH$$1`>|D zH_yFqUX&RG(4FVj77&`kqc@Oy02V_ui(&YF$)mhc*M~uKsn1sKfNLuME*{XfFoIAn z*Hw|K4fP$mV^np6i9m<*IN{WZR9#9RIIwDUP?i$A7aW`Ker{W3oOc7e$;L3z4j@2%Ufl_pbX*XX7uQy)}2>6s+{ E0JDrcYybcN literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/bits.m b/amigae33a/E_v3.3a/Modules/Modules/other/bits.m new file mode 100644 index 0000000000000000000000000000000000000000..2e9f3afc8e0b31d0be6b65999b50e6f8fd075146 GIT binary patch literal 256 zcmZ?u^><-lWq^VU0#F7Um}Ul&l768K3<|moJPm6ZIQ(M$N@4s1K)zQ)Is=1*K2R2j zIsA4qFf&B^zh~e`U|`_FtB0fDKTr)z0Rz~?QU-RQO^gi;3_1)f3>?L&B~F`!Ma_rsrmn(fdK$>3oc&( literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/cia.m b/amigae33a/E_v3.3a/Modules/Modules/other/cia.m new file mode 100644 index 0000000000000000000000000000000000000000..a1ba380dc078869b84be37e8928b102dc6a62933 GIT binary patch literal 320 zcmZ?u^><-lWq<+!7=sJUUe8IpV1vfF%ImjuqL?<(^B(<-lWq^VS0#F7Um}Ul&5`Llo|0v`#a42XnaBNu1z>&_t;0EIBi9}uuZ%iu4PE7f^?fV^?wq-Y}Gqrp7=U$w4# zF(&3RpHv@oQhBm&JcnFAm;?NVzFoevpw3@%%!E0PFaT%`6#gND7H{ep4{HIL35^VOA z^*}s|#ybHjPwa8nv5Da>FbY26ScbfX$)^Zb7nqhm5&bNmA&UN6hNTPxL3v+mSf zW@%HjFEp2Cb0a&wS)Mn0KIPUuvqet!9N`Ap-4>bmnZMpK;U2vm;BzpGwePFy5_$Zr zKEM`U{ZbvZ&Rdn?m}v#C2`8PTFXTRNtede{v6ikMt;2(@FskoCb@=s9H12Gj!bY*) zXhq?>KvrWFdEG-UP3TKTRcr6J8==1)#_c^nW#Z0O?WlejhEXm0(+v4@@<*X5ro0(< W#)&e`G7}4F#XsJUwp+*08u$l0c+SQE literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/disk.m b/amigae33a/E_v3.3a/Modules/Modules/other/disk.m new file mode 100644 index 0000000000000000000000000000000000000000..cf02a9dd31688740504a63a3e3222d5ba7a94c71 GIT binary patch literal 422 zcmZ?u^><-lWq<+!7=sJUUC&$ncZ` z)du8e=9Q!tF)(nY6{R9{i@;TJfK>UF<^okD=H%oj!^~m8qJpO=H8BOGz|#e6cM29Y zTu`?_lmuX^`2U}QqXDGdjDag9vp72`u{afMS{~4k3=C0V(gjSKfJr$p$pt1EfVvp~ DjuK%( literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/dislib.m b/amigae33a/E_v3.3a/Modules/Modules/other/dislib.m new file mode 100644 index 0000000000000000000000000000000000000000..fa46ffb88664f7b061bbc5c5777b68790ee8c2e5 GIT binary patch literal 544 zcmYk3%}>HW5XGkrCP;`O#)AhB9z1yPV2trwu>zh%iJEwxvLkG=?ULO^@qahLnT3Kq zZGU}l-rH%f|I&pGSU!X5uo(|2K=KRQ^ErUh9=)d`H{^W4KmZM>0XRbSVV#QlI+NOD z8aiWi0z^^&)TMgDoQ#kyCQTt(?%#fj+(z1D+7kLorehV)1`xKhWL*p>Oy=(znUw{3 zm-&0S!*V!&w*sPKU;9;_I1W%LN8ZbK$v<>tFz7FOKp&$bJtF6<>$46=6;0vTPKf8L zjy2PwTqLA$GF-iKhZIg}793VPF!Dth4&)<1Nnq>761SM literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/dispose.m b/amigae33a/E_v3.3a/Modules/Modules/other/dispose.m new file mode 100644 index 0000000000000000000000000000000000000000..8a01bbf0f2afab9a6aac37cc4a5813cae8541b1e GIT binary patch literal 114 zcmZ?u^><-lWq^VU0#F7Um}Ul&oPMDU3<|mo99|9S3=9JLK$hQ524)6d|Mv_m1q^<% tex-h;4D3Laj13G7A`C1H94VQ_1^LCPU?Uh9fe-{(a#M2|{{LrS001lH5Y_+y literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/disposeelinkedlist.m b/amigae33a/E_v3.3a/Modules/Modules/other/disposeelinkedlist.m new file mode 100644 index 0000000000000000000000000000000000000000..636bbc09604ab26801920d5b9c352e53fe7cd43b GIT binary patch literal 172 zcmZ?u^><-lWq^VU0#F7Um}Ul&LVltD|LE&7aQN+HU}gyLf6u_8?ePDP0#L-OA)SFi z050bTmdpMBhk*kko5t|}L;-_etY4{LDbOT#AZBV{U{C{ME(R6`k(A8hg8brCSD(zh j?9>#W%;FND3J_pqU<8^1RFwl1^GHohVPN?GpMe1Yngb^J literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/disposelink.m b/amigae33a/E_v3.3a/Modules/Modules/other/disposelink.m new file mode 100644 index 0000000000000000000000000000000000000000..c38b57161fce8f28639da410ab7011b4ed84a475 GIT binary patch literal 122 zcmZ?u^><-lWq^VU0#F7Um}Ul&oPMDU3<|mo99|9S3=9JLK$hQ524)67|Mv_m1q^<% zex-h;4D3Laj13G7A`C1HJSmyQ1^LCPKACyhU}G2S8ohkv!UNJ-nP%2SVsjZlZu&@!4oM6QXADg=|FjSqH zm^*asQt>1D1NsjtF)&$}d*Abon>t|2@qO={^Uk@~*?PabiFuUQS1D{=H0k%7{~1ty zIO+{7f8QTZ*5350g#g9x-M_Gy{hHW6zUjBt4us)CMG+(JRGne_tRP{a>}^D zYelu`V@e?z*Z!^tO(mR+!;h?J0>X3tJ6z0dv~IMqcyJTXb^@aihDxmI3pHVyK3UG z{!`G4S^sOMUeKl4`raUohCD?yID3;TEKVF&xiZ}sh4$~lrV3#k4~S{g7eXSl<&~9I XU&1L9i{e-m$EIbYw??J`c6NYA0cZsi literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/ecode.m b/amigae33a/E_v3.3a/Modules/Modules/other/ecode.m new file mode 100644 index 0000000000000000000000000000000000000000..c29075dd602bd8c1e9b588fb3da53b50b27137fe GIT binary patch literal 1614 zcmcJO&ubG=5XWbmwXUH^4n?FCTtW{`f9<6xc+iAYSWB{1Q)>^kG1~19OtLZCYAHol z@z7%s^$+mWi&~@?LHr9m^%z%)v_Vp0)wT(Z?>AMxkA{`f1C25yJskT^9maKI$wx*7IU&el zkDP2KGsK?5CO1W^BH9tronCZTb2L;;3-X;HuQW*7YbH_W{Q-5>MD&)3UiG41H%Ft+ zCMN@mAlE%|?ErE|kf#Ot(Icl@$v~$dhd3EfJaX7is_6TuGe>lipDsHZ8E+^+Nigya zBDp|r=U7GGJw@68+rZkyT91sejaZeQM0BIXvMV z$g&T{%bz8jLn^m9lP_4UKfx;MAeLuAmL8Gi3|Ar41?#boK-MB@R8OO7nr%R1SJQ8$ zK(6w{HdVNKanrE%uCS_hmhIyn-D%kL-Sg*Q|IxR?z8Oyw+p9IdH=I_l4ZR{o(+NGK zZoPcJ26{(bVV{f=EWrdU+A&e14LNb2Nyg&$y&dZ)mV|YXkAADD*O5_2{-1S_JFJ(x z`8(|69lq$h(Wp`4vw}xS!1Kp9@xO&neX>fu`j(q@09nzGXMA$7hZ3->tF*mGqt3tN zhAvevPkD-wo9pFWg5IgW*UP8j)2vz~YZfWkF@f}9?LxN*Yw-nz xZ#-iQspBnvS3`U`zGN?2s7Unq5av?Rw0U1R({~7yvSt_2KaNN}%?x8izW~*9gsK1l literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/fastinsert.m b/amigae33a/E_v3.3a/Modules/Modules/other/fastinsert.m new file mode 100644 index 0000000000000000000000000000000000000000..ede18b7c304ee1514a78d2063a51e309b9bb2476 GIT binary patch literal 302 zcmYk1zfQtX6o-G8(v+4WMHg}LhTsP8AW@PVqBVv%IuyJRBlHs68oHQ{xU%>rI=fxt zqEDckL|?$cr1mzNc!rZNU(Vm|;n6;H{KoSi7&&NJ-f>R=_Pz}|h0|!metDqeW6{|C zTr87j=k}?WjC-9``bHR_F%X@hWH6W}gHvXxRTws_40R$wG>L*PVHy&aDN!p+tXCxJ zRf(52? zMB$%36Fyhg&#cA0ARdZYtOVwnDT*lXxz5;D1J3<`U*;;SAW)wJwimW0+;0uykRwfj EAIcC$vH$=8 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/initlist.m b/amigae33a/E_v3.3a/Modules/Modules/other/initlist.m new file mode 100644 index 0000000000000000000000000000000000000000..af86f770c0f987f60bd977c846dc6d4d1253d47e GIT binary patch literal 116 zcmZ?u^><-lWq^VS0#F7Um}Ul&Jbs}J3<|mo91#r)xeOc%4FwD!TG4@l1tbb(a}+T6 l#rl={l>&9JFmPq&WtRA47MDOxV`N|ivzT%i{{LrS000zO5Dx$V literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/isdigit.m b/amigae33a/E_v3.3a/Modules/Modules/other/isdigit.m new file mode 100644 index 0000000000000000000000000000000000000000..f869920cbea16c7145a12568e9aea255d7e67c67 GIT binary patch literal 122 zcmZ?u^><-lWq^VS0#F7Um}Ul&yndk!3<|mo96Sv`o<-lWq^VU0#F7Um}Ul&`hKAd3<|mo96Sv`o@2}bj|Pte`UsJzc(8~PgM$2l zMz4l+1_q9T{|O8X4RAe)7<#I3=<$K;F~HDci9?SBTu*!&%x;zf2ESOpQom9L76!h| eV$YP+ypqhc%+w;F4?uts2tj};nc@F`1_l7{=Qx7^ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/lowerchar.m b/amigae33a/E_v3.3a/Modules/Modules/other/lowerchar.m new file mode 100644 index 0000000000000000000000000000000000000000..096898d68868bed6a78fa281e754b0f2505a1a0e GIT binary patch literal 148 zcmZ?u^><-lWq^VU0#F7Um}Ul&!hWF)3<|mo96Sv`o<-lWq<+!7=sJUU<-lWq^VS0#F7Um}Ul&e14$}3<|moJo*g!AX1ls!*3@8GXszRdj<}$7=+Ia z;wv#I$WLhWi}fq@D`j8@>Sk(SU{C>K5e60pmfZXlpb!u+GBAN@o|25rVx6Q)5XJES HKLY~*%bFF_ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/potgo.m b/amigae33a/E_v3.3a/Modules/Modules/other/potgo.m new file mode 100644 index 0000000000000000000000000000000000000000..149afc74a9cfd97a98baeadf1199dc9317669597 GIT binary patch literal 260 zcmZ?u^><-lWq<+!7=sJUU*z0K@|qB0+7Y5Ph0N&yeCsAtC_>i*V@WqODcLs8RGRM6?n7xQz+q%zDXTC$aDk_yhb2 zVrzFl!P3ss($?Z&on0e-;J_}k^Y+bqJG;8QQ%4TNu)mTClVo^5@b^^Oc%6ZS$Eyqq zVN(SKx1*l?dnM;&Kt5vz|{Z994M!e2u0>RT(e%@GyQRA961`GIyor0pfT1c)7qy(84ovnzu=8Y zxa<)Yt&y!W^-LLqBm$oMGo brm(^Vt)ROHy#BH}-OJxBQ~1fcViv~-d$Wsc literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/readstr.m b/amigae33a/E_v3.3a/Modules/Modules/other/readstr.m new file mode 100644 index 0000000000000000000000000000000000000000..3c8884bc4c209e7e9b61bd91aabb1069bfbdb821 GIT binary patch literal 312 zcmZ?u^><-lWq^VS0#F7Um}Ul&=6<37zv$~SaQN+HU}n(rf6u_8?ePDHk}d;}3Q$x{ z_x}%_oc~w+*8RT*6#oNK>G+Fbi9Ux%1p@JPrSWAfJID!2dl+ zgn>ujfq|ibL7xFA`)9)1|6hU|lo%A`Co}@ZS%BgW3>+ZyeeN^x0qxiaRry6l{-BdW zE(3>Pg9bwa1A`9C1Y~iLiD?WB90mV@D%e0gm@E8Z{YtqQ{7MG7|Gra#D4YO4HI(ix~d@XJ7yTPJ~{V literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/sendexplorer.m b/amigae33a/E_v3.3a/Modules/Modules/other/sendexplorer.m new file mode 100644 index 0000000000000000000000000000000000000000..e0977d67ed898e9d8c0b89920e2cac6ef445368e GIT binary patch literal 602 zcmZ8eJ!{)g6g`ez{1QYON{13UJVK2Z#cwZx)=os6U`vkW^kXP(iXW+qZKaY8B2dtj zUs1Yt>yRyU$=DyzAyYDjPVQ{dy5|YS&|Y!xyZ4-|eN(wxd#*MX2-m)-Vs)A;DB(?JzvMc^ZgL1%)hT{T@dgmgE~Tg>tJ_Xml+B1DJ(mC{C}8=+ zxHod*qka(T(2zJqjt>=SB|?4F3c?Yv9O+^AAEnXo*4X8LlLy^yXa{fK+u7^(Ku6KR zp|&|rvl;I7qT62W@o?B1^4@?S*;J;p85VhLU{w!-?zpd`$HC~G4wYFW)Nx!H@OQ%s ToiC4@^i_C z=H(_0{A#@7LG{-HIkZ&fBZ;BJK;l?pq-%TtyMUb*>U>a{C?|y~zbMrBDbuFW4pDw> zqC^g99e!n;Pp>xpovdDhf?|B9G`#`)xKN%(tVk+iL@N&IRPB*8$i z*uvl=^6u!RMt$pL%z}&zvq^o@CjwJW>r5l#oI5kM)J!d8B?X+!=Ha6-L&2 ztZuvJK}Ifx(mWvXXwY@`-Gi=aTbif2meatAh;veX5q*Z+v0lscEI3k+!AMFZF_5SV zq@l#F#C3^+x^LP0?Zb}ct(f-Su8FdBq3SK$Af)U&*D?>RSQ%$g*NO1At&TPG KE5e^jeyo2Os3hqC literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/setprogname.m b/amigae33a/E_v3.3a/Modules/Modules/other/setprogname.m new file mode 100644 index 0000000000000000000000000000000000000000..f6b7ccd315cb7705928f6097b00d0ed4682363f7 GIT binary patch literal 228 zcmZ?u^><-lWq^Q&04Rfj3(Q~!lFELe3=AI6nHdyv88{RKyc*IN81i&-{$KH1_fJHR z!K)#ifgw)8T|t9EK%c>*f`Q3zCj&Esm;ZYP4jl#sw*m$Mpg34e8z{yCHl+b(7ErGe zgssn@z!ua1B$0Kf0d?>cF!Mq WCFZ6ArGbDE2tk0UfZ_jt1_l6G1}hu@ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/skipnonwhite.m b/amigae33a/E_v3.3a/Modules/Modules/other/skipnonwhite.m new file mode 100644 index 0000000000000000000000000000000000000000..b76af07f45f4e87bad4c4b0a7cc55641e14b2c7f GIT binary patch literal 202 zcmZ?u^><-lWq^VS0#F7Um}Ul&3Vxyg|0v`#a1<~I2xvR}|Krt=&cKjVps-=>|37IA z415Z@3>*mz3?V@5QNW2NY6lcGD&RsB)c}gh6!4;n3IRpgg4Tje`#%9>s$Z;Msb47r m3j<$qc4mQJeqMM+W=Sdo1TZo%{{I7HvJ~VOGyMP0zyJWVo-kej literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/skiptochar.m b/amigae33a/E_v3.3a/Modules/Modules/other/skiptochar.m new file mode 100644 index 0000000000000000000000000000000000000000..019e2eb18fedd79dcf946cbab5163643f9106a4e GIT binary patch literal 138 zcmZ?u^><-lWq^VS0#F7Um}Ul&{C=Sf3<|jn90d#l0$vU23=B#z-iEadJZTIJTnf4j z90?2zd_ikL^#3a$zF(|gsb47r3j%m5!7r(1|~3zD;X%JQ;=WG!0`V+ G0|Njn!WXUp literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/skiptoedelim.m b/amigae33a/E_v3.3a/Modules/Modules/other/skiptoedelim.m new file mode 100644 index 0000000000000000000000000000000000000000..311e62463f5e275480aa7ae593995c20dbabcddb GIT binary patch literal 230 zcmZ?u^><-lWq^VS0#F7Um}Ul&>VBdB|0v`#a1<~I2xvR}|Krt=&cINop!@$1PXkcC zDxZOYOF@@`BY}Y-2QC_)!@v*(=S3l@@qmju0@dijd6r0ORN$fpKs7Ma`GVGhZ24aT wvdu5nuhg%UfrWvuI6Jc-B;VB~H77F{=pGPYWMKUN2S~FN<-lWq^VS0#F7Um}Ul&l76B8|0v`#a1<~I2xvR}|Krt=&cNVOps-=>|37IA z3|v8L88{Lc81xD_(L`hlxX?tn6m-FAxe^%uuLH6DV*N_}N`bbpFmM%TXBLEKWR|3Y Wt!7|kVEq3FBvX)I%<%s|0|NlF87Wu* literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/split.m b/amigae33a/E_v3.3a/Modules/Modules/other/split.m new file mode 100644 index 0000000000000000000000000000000000000000..7b747ac0065da17a516f76b55325161676e2a13b GIT binary patch literal 672 zcmah{ze@u#6#jB|UXJ6Cqkn+J;!vc$>)=ot6X&y>|(K63AKV_CXsG#{u6?$ z;NV}Pf{1QzU4+(`YfoAP`$CeJ_v6c#_p-TDuV4Wa@l(Z36qDAQXde&-I5pJ*T&*1f zw#biOLsTz;CRyuWaH50gLdRA=Oh^RC7vKr*DZ;Q?U}vHOPr~I5uG?722r-_AuL9BIx$i67S>u|Y9iSK%s3X+BScTNJ;hyeV0KqBN7xoHy-uq%}S><$%sBTHE*3*mx zZG&>C8cB|jn9d0~;X6rGLn8~m{ema`D*$ksrh-wV=_;^CSa6%&Rzsd1_sFM((a@_F L>%7;+XaxKKrR#P) literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/stack.m b/amigae33a/E_v3.3a/Modules/Modules/other/stack.m new file mode 100644 index 0000000000000000000000000000000000000000..6da6695d88790c78762744a242cb79ecfd4ad163 GIT binary patch literal 486 zcmY+9!AiqG5Qcx-wFVIho;|D=5j1%50eYw)LQ}Bzs1llBi?&&s4d^Woi3#bRL{_$!9GHQPx9rx8MF!EXG*+OEy z^-z;7lUO|`>u4n0;3PN+a;A^bQ`v&T=9@npbh lU^ZDw-DWCHY~nNWeK+sj?e032blUcEp{RLYuDcfnz#nk8b7BAh literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/other/strcopy.m b/amigae33a/E_v3.3a/Modules/Modules/other/strcopy.m new file mode 100644 index 0000000000000000000000000000000000000000..b81a541f770c57859720ab0115e2729eedb66ed9 GIT binary patch literal 156 zcmZ?u^><-lWq^VS0#F7Um}Ul&LVltD{}eE2JN*BnkjubPz#t%?&!C|D|4-1`|9@2E z4>|!wc?26Y7+|tNYZ*Aa8qyg4UkV1Q0IBqg^(*x&Wnf|8C@v{-&M&BhSi;D_^#2c# aDN>RjTvC*om#&jml%ES>GW`F~zyJVjIV<-lWq^VU0#F7Um}Ul&!hWF)3<|mo96Sv`UP9afj|Pte`UsKgSg?o^gM$2l zMz4l+1_l9;Y8H@cg#-o$HW1G**00pB6ez;Nz*SmMkXq!Nkyr%e0s$isf&g1GSm^(M G1_l6@Q5ls0 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/animcontrol.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/animcontrol.m new file mode 100644 index 0000000000000000000000000000000000000000..ab1d3b84d7203bf2bdabc58bef0be48d0878a4f1 GIT binary patch literal 2536 zcmc&$&u<%55T3QS&SF-n6&bLQ1)ItUtGKa+a)_!3r8p=d3Jw?G0!lXV*0EUIEALt~ z2q71N#F0bK{0S9TB!qnD!ZAXKT#&ecS|JX_BsJg6d%LEMp@$xL(%YFgZ{ECbe!Q_? zdt+yvE)b6wX!wON_+*7i6B$1=-Xhxk#h@jtKF<6Uyjbxk$Bo-($Iiy$8kL<5r%dIo z;dP>g>Z;pqcN$+)n%>>HL#A_u@}gA$mlLi6&fXffh^)ZaBQk@u$cvC$!Z`tLpU|-J zUSlx5IlcwwiaU2Er)phYBVsh$Cn;*&zP~^7&8#-hoyLo#E7;C8fqN5~5XX8?tN?+Z4XS6xo9PJU+^p4VX{!$o_cfQ z!75hn6K(sP_UU-?;*d{HANniEkO;wSx3ZYuJf* z@ly3Jy)9lMTd^diB>d7wH}xwgMBystWx-xc?Bm*4yYQAd}OuJx~IUUuSy11X=_A8MIO#-#Z2^*T;Wu zftEl&0(C%dffnoIzeb>i`uLR3<*{yn=CJ=csNERIZ$N5D#@!*&%ap>CACZmjzQVt% z2fc38@A(9IitHO4Oy=f~m@~oUZiLJVzi<@uCgod)M6i-=4cdopx9NLC8E6%*_uUS7 zwJLUcO1Up85ZBqLG_$b&$e(UuKZ$+n_I z6Fx`;p1}SmRPYeqf$xP^qh8MstF6Oc7%g?=Y(^G@|6st8`4Y_Un3v(+EqG`Rx_Upw hcrxGO%(D+!^W5+V$rXDB`n5l3wb?J|&zaf_`Ws(UPI3SM literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/button.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/button.m new file mode 100644 index 0000000000000000000000000000000000000000..d6160aa5123261c4e5a22dd975805c7d26e0110e GIT binary patch literal 2214 zcmbVO&ube;6#mv)C0ntmOCnNH7P>YH=%84l=n#Sr3UY~STsaga=0V~Yz0A`3P$g?#sm-3e2y_Xy- z3w7>VigH72oFZv`)*4PdtlmJ8)8Vw&4#88G?k;svYyCifoN%0aG4ZQ-VH>sA+c?h( zBXc*OjGw0KY6Fnj+c;f7>%p_#d8aGMauqTHW|D)RTbB|Nj>?U-mB@U|#;!E$vwWWa zFZ0>}ZjUlQc@`;E8D*`gzNuxKw5%piS6IUueO-5!hzrSsq zUS@vJ?yG8hDi&{khcY*R%Z`$osT?Ug9P^9N;8%8J1CF+uVb#{D^Up+9W>RS@Ia}$- z8cQDxO5c5Djp-4)V^vm1+b}0qt>^7zq#Y@jc9AE2OHVLll;6xfp$D6lEZ7Ot*WlfB zy_DnfMwH?GeEjLjTC#Ssqwd^n&(I@VWv>{H=j_TZsVGaeM%P?e^Kvcj@@b{f~)GOj>sXdmX>^b4J*I`EC>@wJ+b`9kNZj(+2L&%I>w z{T%d{{dUI}F;a-CFLKjY!FxozH=CnpUo3uz72=;nuE#B6y*V1K6Kljjh?VB(KaW@@ zZV^kw?}#4pgy=R$XTK7Q#HYjp@nfRH{a=W7Ysk~&Jzhw#@OuKhj|E=f5iH)&M(Us3 z<)6)GH>L7Nk}}D24kJk_`pVHcZKB}s1GJFyhu!^lzY_@g%VVM#i9qbdqNB7V$L(~Z z_HLj#j2sOhoBmvtD76AR67f{cfT3THo3OYOi^EvIIH)Vxsllmi4b~(UGkwpL2kEDR zd_3^|Kulz^^lWyN`GO3i{ntvFD8Ur{G(ej0kn45(+fnx`raJnc@9K>xu>)(y_7!kOyg^EU)B)q Y=!oT48V3Il2!?)F`cC=mkJ?lG4?EoQasU7T literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/calendar.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/calendar.m new file mode 100644 index 0000000000000000000000000000000000000000..6e1ac49f940d1dbbb03bc7b7afd6ade4f778ca15 GIT binary patch literal 1778 zcmah~&1xH06#hn<*b^~zr$Gb}1~Lu`h}N~z;#J8)MhSL}JI*2{n-+U4O=QuLG^YL3j$KSkc**j&bo zPb8ZE@LapdXB2-ks|K(-D!lhBVk&=SwW3Z(=d4bbr&MkNDX}_2$+LD?YjvixUYd31}UOam6 zYCT(jwWFr?V&55&&1m*e`Kp1rcsx_WQgd!g^!h#gt1>bPdweO*w2HdIXJ^7e@mz1E zhqlh{Q^_uxmEHgPk)C{FI2p!%Z z5ZeAwy^cZ#<1_=lmbYL$Luow5$|Mf@E%0X_5K-8|p^QH99{OlS|KUbnxUbbn!V%uALF`{!;HZSRLU zTX8E`=!HoVbi(a4Oj7c+bQ#WsAGFf$pwAmqX*gJDMPaZ{L;ZHRPoDZd!G<;E%qgw~ zJBZ`l3^`)ipp{Z5ol06#J!W{BcMowb>FkLURq%swhPh%D;Daw zsv;ug1LRQkV?@1H>cNM8fE<1ErBW}Il0yzDi9>(y&9XQ^>v+)Yd-LYao8S90Gko#Y z{uaGM+&&_DBn&=DVd6yE%j(xeJAY}kYE(u`RsZ9HH$JUCK0md$SIU&Px9vRTcZc5- zEf-67yWUatH;U7@`%g)?Z&GG==n`d_6aB1DLahU$Ovv+WT1ml~!WF<7!r4CUozbxR zU3D-;GT9Zjt^KFtS87}=6EV8Ivlvw$zdl^F(qAuY z2v<&KMN?*(V{C0`=4o}ZLrCo+{G_C9K=(GiH;f~fXrNk1rB*Or;_;+m{QejX7~W+W zsL2%a6jN?1HQGWip>Lq)&~0=JJ%etd>xiy_3_jUATS5lUA4&z}B+|LXHHQ5B&9%ZS zl^!_LALC2DhOaK!ONUnDsEb{!c^2t%Hf6QwnX-nfh%so;zAc)zM0rbiuIrdcH)i`GN z7w*u;xyn<<90Eoe=q==*C6>K?BTu)d;##zV^EB3$qyB+5+2^2xOR(%8YI^ z$&`xE9blbS7kk^p-IwMFNrkB@#R-hgS(@S;O$u9h4ov0KHO{HGFeee73-_qPg{*RJ z1?}76vF7mTSH*Lw-yG>Tyq>uoI5Tf}9Ywq&{-|^Jc@$A~=B{-54v4Oct(@Fy&Yu zM6i-{2d!qk)9@VD(J9+=4_Tg?T4#yOSp7uVq*+R}ogk>YPOa|*?3dEcP}go52E-jaK@k$%43Wp@h4=dP*xM15c14Y0aiYk avG3G_V-$+)ppoHw1GmMVvi=XDU-U1sDQn{Z literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/gradient.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/gradient.m new file mode 100644 index 0000000000000000000000000000000000000000..6a758228388d3c5c1ea9150b3ce0a1908204d037 GIT binary patch literal 2242 zcmb7G&2Jl35TCWz>DF4ARj`nSEZ9UwSm4GM${|8Mq&O%h3QjJFOR97eFZN1nd*xk2 z(?jJ-~dXTxO1-wrKVyw5uddoJzNmURR6_KwcUo%F+GOlPbrb&d9M9^ZXU4=i& z+6JV%^y(;$isJ#*Vk#ZQ`WmmlBud3JmRpJ5YZE-s%ke%xOZ&8ecNK31ZwYS^Zyv9S zS4Rd0>i*02={3~-{Gs%%B$!K=PXTK1Cs&d!l^!@VnBYr+hOaIavSP1kbaM+f|4enc zVqz_Nrr2=r8G{DxUD33q&udkgrCOQH#xYk5TyDx)Q*MztOe!8sYW~XUK~9*S4en!% zLZ9L?=8>cs3G1o(EOB-UqsDc*e`$m+=CVwAa|9UcI6*~QNs9I+=CkzOgHMkeqsH+a zp02r*F*#G`F`#$XCuf4~Cij?QPSNSN{sI=Mo5H~e&jtj7Ug#Y7ZcFx&H?0w6ev?%R-&M+nZj`u?yOL^TK&ISi>YjyWg-l3i?y$o* zDt5}i6n6uwO#B-QR#u8~J|)uKUIK({%67fpe(2ppB0$Sek<2eV-`^j&u~?)9%5~i^ zblUEI`dz)=s=0h!9oBx5RB5UD|?69lmvNZ7Lm zFWGi9)ik*7$n-k)?oq+*_FF^W4d0LYeIKLN>4(uuS8Nw#!8L%NOaOPkf-{D_Se{}W f8UEMf^%uOjPI!dIiXV-Pz#q0f&WH7XkI~a}StGV+~J*b?|1I`?z!ij z>wI+Q@Fra#J}#3N6%&ZCn1qM|x5}UTiz`KcQJ5<~IhV7R|FryY`SiBe(u@zxMr&C9 znL>0olV8ppU+?&f{XFUVRZ86U+Th`{Dv^3HS59sR$Vql5jq1B^gx; za3)|{)>y0(aJID0EkIr$D+ufGHM zPm9k)hSHF6X%)WQS9lA!7wJQB?*P{OcWH!3?HOs8`YQ3TC1pP4%xn7w2pX`53 z*~0vv1aumD0-Y+%7nh)Q=puBYFkj}OIhDr8znRI*)b@{75Wf|RetUUg;n zeG1}N`W~s6<@i<2)(}+q(@yvid=>$MI5CT!xO^(+yTkQdp;-Hf2n^x&z&xtiO$*WT z$l^`Yt<^2o6kf;~<>36gSfwDdq`9pBYEys$J_amlQa91;$p0{sWTO;Hk;3dXIq4Mc zn0CcAzvRiny)Y7_9h;U_=`jflG)|EYbKP2-Rr<{B16%EmQFM*h8hx{C!-CA>cPvVg zhQ(?<5ZO)E6Bx%eQa8wsKvmLejw5M+te6$#roY*#@@(OrZ@~UNU1FVXb6_#|hNzUm zYVHt;yw+LqIo6Nq;SLPy6jk@z=OX5Rl5$e1&BOiZvsBAbNAUv-(t4l QhKF48DB%%!7akb@0^s8~2LJ#7 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/imagebutton.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/imagebutton.m new file mode 100644 index 0000000000000000000000000000000000000000..859e97093295b40b9223076dc1e96a064a4aa113 GIT binary patch literal 2346 zcmbtVL2nyH6#g7X*h zd4Bi(-7PFbeAj_5*fbQ_4;`EseirTO&&KNoGB^p!q0*JVWu)F>eF* zo6(81P^MIuGpl$5S-TIbl!w+hEkd4qpXbK%3gsCkPc4vFee9eeYJS`t&2Gp&Hc8qh znk1uf1bV-5d!vU^^Gn*#`jhxJ^d%!_*;lqz`gdCwQD&s9-6xa3<8`qHh-~bfEus1F z+5RFgq-N!A#JGw~RqsS1nwM`brRB?fp7xYk;Ysg|lfT(IXCki|nWwBA%{XW3guKFn z!jeKuq1e-Bj=H$%!_4Dak(QCRb>?~xSED4WhaWMaP*x|`D{3uklWR+?AFxCfe^ucd z3a?D~QJxZO@vXOThqOhilFFn4DMzwM8InQLct@Ra{dwnXg>gN9AaiWX2-%A(ol*Lo zQ4!H$^)b#iXNEuF2tUD5RCW!fvYKSJwz=nzsji5r+%5GCxkuzy_>iFX?HA^j9331EM7M{?D!P{hvh~ca8ja$r};P72<@RpBGK0Iwi zjnh5(b}v^CJu=h_nJkcsNEM`|QgkBk@yT3NM9p^j#>{C1b$Q2G#h6I45@g2dp~$ev zo)Jgxb#X6G?0E4j6}1?55a~zd(Me0*D6UdU*gK@8dLa?-=k!&)jeG0Myk*b49I^iu z9r-R^8XaqPp6KGk!KT~pxK4-|g5o@v-IkyIJ%?I-{H(D49;(D|h?V+y(j=Da<3E2S zmg?j2SHuGG7h=9X{_8Dbj(C@76OV{ieSH2oF-!b`m?36}CgncSXpUqL&>|$Q2>6Ng zE$JqffTbLa$pp1tzwJ7)t7P(Luzkm~)nhT!$TN=uF_rVRc3hZG&dBm77kt4bLR9{X5DX2J6_~r`lF!xpLb};L30Li7-+&q zy5AeLg5G@wig6X61>;`N^IC_FVoPoot9>U3n44DU1R;5`b_V7JzkLw)h6748xx>Wj zf#DL}yPxhtc+ZWriGKIYBFFH=JtfBCm}9Ym}97&FK$2BhLxm e4u?Z8C_3%nm?_`v$M$@0#DUbLhe{j5$#B4+Pzf$3#+#B`x0iS? z3^HBCE-(l0_PDFij5FFQqbcTh0ZnC13^g%YF^U*-G3JZRfRr%kRmQchHs}{o_6I~= z;&3p2LUN+g6IFkS`p{;of_cgur9jD1Y>Gw6QcQ}@`xvb2*VW?**7bb1fPZ(HbvPAu z_AQTD=_AHDo2-CEl$FR5^+BX$(%J976-#o(n6Fi@4lZ?hgKs3G>a|qfVvOZd9%lJK z)`KiPVwn+}95A6grQP(SX&PIC52qfW zu-H4-hs}PGJC(K;h%i|(|W%^)gzZnVu-%+v?*!k|<0W$E~@X+PyG#~=Ik7##or literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/password.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/password.m new file mode 100644 index 0000000000000000000000000000000000000000..9d645486f24dbe30478722d9e76ac8f9f993d7af GIT binary patch literal 2542 zcmbtUO>7%g5T3O+_F|UQR2H%-t9h{uauO$Nq6nnYL()*PM2Uln5E3eK+-B>T`cGMh zCWyo40-R9Aq2hpgKnV3vMLy&L;^6ksGeQV)qEeA47t{*nVBA#8H*eRmlLiUITg{t! z^WMySGjHCWU0iyV28hS=DT83G?^|ncI5JvR?q+WN0lag`G-bcvGKdkJcakKAj)*YO z)4982rn_g}AEG*qO}o2B#%+RjKsQE~+~!P2X^xog&d8#BLsZ;7;D{Skpx`^eud;=& z_0T1H=&;vbdf+~+>&7%Oo)owW9%qX_oH2GZd1uD(8Tl37By6$XiD1-jyF2nIfMcjdHI0co>O?EZv7D zOHVr*jdN`9mwi4Vd5{J@E}mh|1DH~v1Ske#j4H6`neyYkg}Y%Tx9#5JDCkGwM-%hT zC8FcT>3YGoC9d;~Yb1}G%HxLeZu87d_ojhtL`$DPJ>2cV|m zKjCZ8xws?I+c-F+ zx^bEo&o0Wf?28FP*53X(*k~ezKU%y#YS5b>iBM|j))_JPtdpi?a(@$H++wTO89~$^ z7E#$1$|X`h#X5>UiDr05&!*{w*#bUK9yMF@&Sg?wlII8CBPH|eC)roDQ0@^06rm(2 z!81OAw5~JvJ`rXQlW9trx0+kPH_25t?6oOmVY?Og|Q3ndxhsX?;|BUnMOS_A;mD|3+}?AcFrCeG+&lB&L6vaovT5 z_YUQ45&xes#CMp?+0NdF!>?0zw)1!aJTu$*D+!(k{}Ma}z6~zGcfk|0okwl(IP9|E zG3XzHtGRV}3xke16#5)wg3=BR+yQ;gMz z6;gD=W>Lz=H@mV*vEr)q7AdZmRtwdYGD3!MDsI`0HE9vSDzQ?s3m3{3N8n-76ppnZ z5v4#`(rl~2FaSzwGo(Y)GgC-$F|e1WNFUw-ct1Q;_*AWGHy8IIcob8oXGx3TtpwU9mW0 z#;=f0+P)?vH5%!Kdfj&ejptdVNU^bhQsY`8%crn^olaPl+RA#_vQNqTG^~QXi84=A zJb(4_da=Yv5HWOH#yxCNs+Jn7wc2Gi2~ecFgiTPMe;?9en})T~C|gw-B|w_LWP9$I KbFkO}Vf+o{7F~7# literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/tabs.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/tabs.m new file mode 100644 index 0000000000000000000000000000000000000000..852857989d41471eb967b15c12ac79aeb8207e66 GIT binary patch literal 2006 zcmb7E&ube;6#mv)D_gNBi&29pf{ud%OHeHnd22RX58T)DKArlqYcTU%MMk{7K+ z?HtMm+@A9%^w4wYwa|leDLwSyLk~F=d@1dv5FdI{?Wo_IT}l3R=`1tvo0<3CeDBSh zefZw`5~d;T7Vu014jBznfbmK7BVgq(19MhoVE!50D*3~g)#s-#)$;5jifUQ8D6U3d z0yE|Nz4~TY{ShgAw*CsHdIveJ<%w*KN<@}Mg#c?uh^n7g`;)Uqew#pH{nhX! zo|hK^Ie+bF3f1SYH!oUVC(8gX0+gUF+}p7%tw!|pNIg`JMt91l;4;eOL&j`mY?Yze zKN0NWgKyK{aKqWa@E2vi_}Rqe;S+lNoj+5f82FHVp<-2Wn?4I}?F z5-rAkd_L~LxSR{d|4#sk{lOshSXo3mx7t%)kIsj&Ut7-#9OYhQPo$g3QX;wkV1SIW z7|&z88Krn*Y?MYKbwzM~Et$KCyfI|k2c~3BndnDmvY!%vD+RTD(}nus>Bk2v(aOOFB*M!TLPqhc$_K+McjK3qKbH%sjcvYA zXPh@nM>eSq2dU9rlb777+?gFmb6ukGuVVB6Phq8i&z(D=RQC+y|VHP@^+nqCjF2+L>JVjJ}n(=cBdy#9XnU6DhZvQ!xi zey4ORgMSw(iERFy!h`2d@w0acG|KJ?GKrmC*^Tkc-Uyq>HMarUXPW)icD>W^J;0(xeyiW@dYzuw zWH>K0T48LTZdeS^@S~E#I$oy<}Oh=8a}({ z+%dIHQwvuUlPcUwC^$+&^1*_)vPS{Iqvi**p)--1zEo{x- cXm#-{uO9C4LbV;a2Y$cVlBlUaZOJI@KUtH@fB*mh literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/tapedeck.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/tapedeck.m new file mode 100644 index 0000000000000000000000000000000000000000..2b77dcd964b36143ac9db80a0e7cece591531075 GIT binary patch literal 2384 zcmcIm&u<$=6n<-OoW)wXt6)`Dv=WoZ2n(fgRP_*{2&K4?5Cx|f-~w_s@z$}rwpUpj z8V<-vAaO+eA5@jNfE1xzx%HS^j$Ag zxkEF=-^)Z_34<;#OqR&_w*D^B=1&GKTeVScJ$z*;7@yW3UYx3pg>|Z^4OOAa*6<$D zTy?GQg?{~e%F+irPsmg^$dOegaJFzRI7>Jc()Jk*>mSw!lN}OkEh2a4$@pB4tLsF( z>-JfO>JOjpP1Rfj;vcINURxyf(pAgTbg;v3A+hz_qnY=V1&%QntAxHJy(7Jip8aGQ zQ#Yon3Qfu@YnSLQy*SLmb9|siOeL}y&+_;Sgfpg@m}bZLFkj#?=ye`5ztEsHv?a7M znu}IMv(Zf8v=EQS+h?btU1Z4HsR)vDxpr9$@R2}cTCA?2Kun_~{uf)CYFoR*=) zCs@71*@{t^DK6_Wk}MFfB^LOEJWk$=V4FJ<^;9LsQ)j-Y3$w0m6BxUd1$Xj zI=L7AGSbMfoVYjsO`La$-jbY^56Ej8(VD ziu}GdVaU6|Z_5hhAx%s{9={h$WJ5kNIhmnSAyJg?w7ZR{ z{RtzNSBhM+KW+y>}`lLwb@QAL5k!dX}amSbkl`Z@Ij5S8Ph=84ozx5 zo>Cut5>|cm50FJ_Da$@6NZG>TgX}}`AL!~!AGb)s61tARb7v+=KUi?WoqOiobI&>V zcRp@z-I<@E8$=YMH;7&XA)lap`-u7?#Se&#V}&MEag$=VTUDYUQ=by4xpx1bLKU;4 zS&D)emXrV$l~e*$NK#2q5lN*iTh3{4R7ab2Lvpef%^gvz_;GQq$L6fiC>?6qcwqSx z!QV-_FE;<&K6k$LEK#y_=mF><7jMRf@lmk2XHMKc2PE$Kiv0D*alr&)})!!+>zVfY~(Y zQ?W?j=MHm+kO=DJaZ(yZjK@0V+CW%^Y>52iKJk&abL1Z_5p_?Y@L7Lm-N0XXHg2~* zCmPZ-_X@@LrEee2KPSJt8r4biG>?a!F}b!#0``ZE$F9Dq9xl9cxoMp3Ox(23;f1HO z2Uj0^v@dsRl#=+r?tOXsCN+v02L}f@-z2o1y4qA%F506x);+6Ff#%;?1|Fwe*#uiq zT0M9>nc?A`gpC05EY#I=0kfp52fG~1=B~pmaSdjgyK_oL?+o!wI_SBwTfkREMx5Yu zC$0?gn0LiBn)+t@!af&Y)&g{fjRRhnaguuCBt{Omc`we6x`9@Qp1LL)$?jR5XjrOF z*WjG!!CC9sBXPc9G2@<9q7Lsf9bZzwH-zeOyvdA}P$4B$M#9+_u>-5I&WQ2V(Rt2nGiEcb^Dct#ryZ`1f89xWj5gnP+wQ~uBEB(ee4s(V-6MXiF^qsp%SW>cw z2tU4~7U3PU6ufalco}w4$)Mgm)P^K#AqSzs!Q$=<194L)NOrT;m*d?*;s4|A^u2!g z;ofAj<2{Mz#Vsek_P#|&=Y)!bKbN!G%NM?x`R2gQOoh(P%-MRe^Ye|3zK^^M%lf>O zsok4UMg>O2uXxSm+xFL^?@>D6ev!eP%D4ad3v)8xJ}Y9@F#m=*k#C>>fLUPv3Udte zGt8ml8npCdyxOAvr!5L>Vbn2(TI7F-VYJ8xo^KK((4xM-TcrGfv5yg_J|g8y3feYJ zHO-A?$*QlRkM!XeLi#w=z$R0E@WLAnCM7+z>Ct|QR2PY$BUoLlEtZ!nb(5uLXbP|~ zMWkV*No|--Hp6=PNl~D(T3!d$M~dViRHQDfn&l>|2oV2|y72J77TDLwZ!TB7l>`N# zdCl_l3JNaOmP?J=7He^A#VE91tJh1brpv~PLQxu6G8>I@)hsp51{{;p3PmXF@yiR% z+R8Fk_@9G9VH#Mdo8?s~TCSL@l7|=mS*RUOKyp_`G0d7@Xa nmZo8IX{EAOHyiIZS61o`-7GgY0qMk&qmP4AV^4sU+Cl6;{lW#f literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/ticker.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/ticker.m new file mode 100644 index 0000000000000000000000000000000000000000..5a0dd974289aa4f1fada31510fdfaf8c46392392 GIT binary patch literal 558 zcma)1yGjE=6g?ZGtjiLDED|K(DiLf<8Y?S7g$TMmm@Ie|UNi(K!HIG{ z43mLix~qW})kjUqqtW2RJn2dPply1WRuk?$7os;}bJ?g3)M6%O7_pvWQjs?6_E2Bw zVPEkyA*V{mLLIffVBv^@l7abyWs+RjOJ&V;+Hk`xo5zr%lPyYdBDL(a^~5yuI(diK iVsSdi1(QcAO@-{RP)_Kh?Rb`#i9F(Z68&OfDv=*-fP8rX literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/plugins/toolify.m b/amigae33a/E_v3.3a/Modules/Modules/plugins/toolify.m new file mode 100644 index 0000000000000000000000000000000000000000..411db9ee604dfffda4bb73cac5c8aadf2381ca58 GIT binary patch literal 1686 zcmZuxL2DaF6#k@LJ6o}+ixEWxQLlvxGEuT=$SL$7$1SKKk$WkpBnSL|7Qk1r1X5QQHz4y(VZ$|#? z*4C$3f*c4k=v+80s05qBArUK=nrCfWnru=`@VR)4)HGsSWVR))PA-%abQ0h(Vo$FqLk{hICNz#&WX z2XJh?g0URau@tv)JC=Nl9BEZ`5!-qtPJ)b6hwP_9tJ4-0LqV+xn@K-CpF&G&wH<6s zcygl+lv5Siz&m3u@>&ZYaGIP(dG+HBEUQ&lYgVn`{?s{TG?0-@#LSw1Hof`sT&DR% z{F>@hO8Y6@h#X`PMHE-Liqg^DuZ|mW z8hkCfJb&^6-Uqw> zNmfWE{tk=D?*ggP_Kz&8ZB9hI_PMmvE3{SG7qk`HV_KW`Z`#u4qH&U3yO&D`zS)m3@HwaQ1A_=ojU7~rWA(i48-(&nf&U^h~XY707 zHFZml=Z1$A@lrqG3;c1nCp+PPAMFL#EOI;kF!c6Qlz8?FqQ)@r1`4Ex%)QE*e{)CP ULF9V_#m$QJQ+CM;Jmci}2Vok^@&Et; literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/pointer.m b/amigae33a/E_v3.3a/Modules/Modules/pointer.m new file mode 100644 index 0000000000000000000000000000000000000000..ff300628d758165d1a60d0557cd35a6ae62de0f7 GIT binary patch literal 74 zcmZ?u^><-lE6C5xD@iTV%gIbCN-U~mfbx?Pi&GhbQ%jsmiz@>lN;rJ-6H{Ppx1!Wk H82di}-1r-J literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/powerpacker.m b/amigae33a/E_v3.3a/Modules/Modules/powerpacker.m new file mode 100644 index 0000000000000000000000000000000000000000..11707c155367d9e19391dd8b675505ee45164cb0 GIT binary patch literal 260 zcmZ9G%?^Sv5QK{+rr^aV@f{TKC(+oO=d~ERFgkBgcW&(EM=Efx z!zrj(n8=5|qCNT;JS bP$7$CHdj;*9{G!muwXJ9oH8ijgZkoL@9P9Ei57_SKrUc{951h}^r;oi-nO4cCx-@+h#|oo@G* zn@7--own85R2v3#1=mg8R2%g3`+#mgm$t19l9^nC+&N|2Wwm-?=7ZfE{cg=(v*xY` z=(=h;2f!Y&2iQL};VKbvDU{5G#FeUiL5@=*rsq6>-|P9)P)H)CNcndksh@}<-lWq^VUFa{Tx!2~4NF!22U&%ltGS5R6~P?VZh3>4!4$!4ck<|Y;Z8H@~k z3``6H1^JnIC8l literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/prefs/locale.m b/amigae33a/E_v3.3a/Modules/Modules/prefs/locale.m new file mode 100644 index 0000000000000000000000000000000000000000..6b05461c14abb1dcbe4366d4c8bb8165d7bd196c GIT binary patch literal 1058 zcmZuwJ#W-N5S@Vog(y0mq7#CK-vGZMNr4oEglHlmU}cY;m29uIyBBmNH5COlH8m9l zP}3pNAyM;D^VNknYx`oXSn}C^Z|1!>qrHPWclYTM_1DMYWjnoGAiDUOc1}-;Dwml` zS}#Q)O01V4{zP(A&S(d}i_EQ>=+}*@g@|bh?51{z_mWqpDOaWxw1eBG89ylN=!zmp z1VopCJT59zYJuu;-s|Ni8bXG7|J{c`wuh)hMqG2vIN{GrIoqVnT#l6JMEYeE%y#S= z8PEkXUaQ4~mA6e9)*(u*)eGF$5lEt~rEtDB8lKbqR`Ch;d{U=7c@vJEk5ds=ZN9SM z2B8kWmGH3`BRTO=E}5-O)jHdBNmL~(y<4?GTH{T0J|%=R*M&Fdao7|;Nj(@gRjc;X zP4$4P_OseG|C=)H0)GK~YRhyL%u6sEsZpr3HGVbpC6jL2*W->JpA+-j9?xxQV>&0h zK;Hqy^lEWN;5-q(2a}<$bNYaCj z45z<^Oya(cIrN}kDeQ&$`-scJz^Ky?FpZRE>hyDrPn>>@xrx*75qIXKd;6pR-6l6a luG@6z;r- zvc*>o5RvERr?$#}wN3s}y>}bzLJ32nMhwt;KCYM5dOTWg7NgmG%#`DEjZ-^Cm6UOz+t literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/prefs/palette.m b/amigae33a/E_v3.3a/Modules/Modules/prefs/palette.m new file mode 100644 index 0000000000000000000000000000000000000000..4f0d5d4addd0fd9ff37d527996c5896f3fd00839 GIT binary patch literal 170 zcmZ?u^><-lWq^VUFa{Tx!2~1=82JAG2U3YSsU;<;1x2Z8#XwQ8d{Js~YEfBg3Xspj zzyl-&Dom2|bMlJ{QuBa{n80EI6&5IB96)swz#>2;K$E#3?1I!}pakOt5CJlYfg`}t OC&bew9z+2J7#IKx4kLB| literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/prefs/pointer.m b/amigae33a/E_v3.3a/Modules/Modules/prefs/pointer.m new file mode 100644 index 0000000000000000000000000000000000000000..02dfda59d7ca5f92f463d197531d762b8187ed9f GIT binary patch literal 300 zcmXv|(F%e<5M0F~BqAarBKnB_AgPBSHLQr9By-b)C^@gJzS2Lk-7^>Nc4l^V?pCh9 zgckg(Y=EtSNp}f$RRPE(Qs?M~q*!1O$Cxc`!bTzy?+r7f+ml^f79Gw2=y68&5O;+# zlX%TZ({D)3QNDDTMQJAVi&R`v-eES##kWplHY`M}^sGZ{Bv2%&VypI!W6bI)dncb} u)g(53Ya7g{(eGgnT^5ecHuU_!U2KT(e+*Wf!|p`5v-S4DdKq#f3h)EQ1TRJa literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/prefs/prefhdr.m b/amigae33a/E_v3.3a/Modules/Modules/prefs/prefhdr.m new file mode 100644 index 0000000000000000000000000000000000000000..0fbf1e7bd4efa017a4aca4cbe60ebaa6ca9edbe2 GIT binary patch literal 140 zcmZ?u^><-lWq^VUFa{Tx!2~2-7*PLu5O+#@gNFlNYK?6BUveRNCxY_KmjZ zjGA_#bK{)fobNk-u5LDU(~KV1 zNZ;nwULV@3K44iqGi2}bsw*}2R1le?+xw!)j%Bsk?y{oKBgYS>@0{e_6Q!EmkB08E z)2}M;N}>yNxEpDytD@{@AdgRmpX%+l)qm+{L!bVk0AJ9_0+`&vHQgeiLhiFvJa8}s zkVG;OJ)sR=M6Qa&BMW+g<^qV32g<3L2AFC{cKD<@HiC?!`5#w z&oXL)YMbuVM_Lxw4NP}fs4nH{W9OEFDqt3JLonnc;($G1c| zGLSKH%C(HP-&?-{()KaUaS4 mL-+x>MMB%~l)xc<9Fwd>=p&~$+JOC^H=5QOs+-~%fgc5M3u}h^h*eiUS7@960cG0SfAY0~>o2uW-D^-t~cQXbo5o9AEivQIB9##(>a;oTi$WtFdLQtbc=PN%ZnLQkrtj_ zmU%rTY4rFCL=0%ud9lKh4q&hA^a|h6@0-T&JM@eGj<3zEUZ&MNCjwz76*}92`%w3( zF3KH(jz3=&bzLlXAVbtccVz)7uk%|94^#24O`7GadE+B!e7r{=sISq7$>uh1 z*QJ@-w2}2=4Z8r9`d3Lt_W`RK)(5NOu=NynuF)isdDo=$7&%Y5=Tgds6!izzzXniJm}_aPdzj8(v%U{>10O0M6L0 zOWi_oh8^Hc-Q;KziXqqXR9J)o5~)O5gj_~ayZ$6p@rVb&>qSZANe`<)231%zn2eJ^ zXpLi_qn71}^N5F@@BpE1!u z(Dgw9yLG67pYl)-dF;U?sJ#cN45Usbng{5ceC?9DhdLh2%#%d>u^JCi6?5-cw~`O7 z9nB5%ZEq1J~!FD`E(k=G`g^EnN)A)(aj502t%MVhF!rKzB~ASvT;Lorvlv|&%yg?kJc^aWC7X(dFU(kWyC|M zM~q?OaDNgvmJ#Um5TmL3Ff>+ln(duQTqyZ=cH7&a*uPDF`bxv%klAgR79wVQ$GnF+ P)NvS#3)o$NUEui-sTMun literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/prefs/printertxt.m b/amigae33a/E_v3.3a/Modules/Modules/prefs/printertxt.m new file mode 100644 index 0000000000000000000000000000000000000000..6eb46065b584664816638c6421fb9939e15f634c GIT binary patch literal 886 zcmZvaQE$^Q5XUcNE1?urAs%=_d;&Da7!yL%qQ)(j(j+AAn0Sez*3B%nS#Z;e@hSI> zwmZj(`amShzF+SC|J*rj7Wr@t_IYRz19RvBI03wQd<3YpDr>2CrK&3}S6h5qLgyCA%PLbZ|^EuF6CY=jD=#;xjsMtpB!# z|MSD#rB-{XvC4ryu8-B7u8qn7)lRCslDfXH$OON*2d9Q?)jvaqNX`sd%d)6%DXWj{ zyi)bTL@q`b+bUnEvY@wA@og}ug(5)FIKKAI}2KeB!Yd&V7H)ARPO?*UV2qWaoMYBik=;4U;7(l?TP=QHsUN@d#W^iURI1P_zDl3i(C zz;0TSx|E%@E}ikeUpg+fxV6Z%^v8!Wj9T z;#%6TFe!rjT3Vxoe(yLJc3OBnp~hQ~DVI EN0ClcO#lD@ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/prefs/sound.m b/amigae33a/E_v3.3a/Modules/Modules/prefs/sound.m new file mode 100644 index 0000000000000000000000000000000000000000..94a6876512dda903ad40a8bd73312b0e3afd6b3a GIT binary patch literal 282 zcmYL?(F%ev6oyYy5F!x~5#e)mU$~1PQ?Q$^WUvVXb2gpetMwGUk)55a#@IRg{{KIR z#YqG+7|-k5_|$m#J|P$efJWO&)J7H!GE$9fr0Jx<{}dMB!BVKEE_wg3(n`t)NLSnn zrT@%FwkFp0HQAhNL!{HCz5m#jSS^jxZVBz!5fj$%R_W?P0YajMDrLo8eu6hd5i9H= iaJDSH-cpty8A}1?S#pU^QSOSHi_THc4sm*BE&y+I|2g6S literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/prefs/wbpattern.m b/amigae33a/E_v3.3a/Modules/Modules/prefs/wbpattern.m new file mode 100644 index 0000000000000000000000000000000000000000..4e2712b07a28e755e7c088d67549fd21e06e02b1 GIT binary patch literal 344 zcmXv|+e*Vg5S_#eB1M9z_&d?vm^>s|whQrXNt58k#k4bBV-0rNM-W# b%&Ri}yuh#{^fZNFo$uhOnMIG0yolouxvD&4 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/ramdrive.m b/amigae33a/E_v3.3a/Modules/Modules/ramdrive.m new file mode 100644 index 0000000000000000000000000000000000000000..d8692392a65d2481577b42c47a4a5c4fc150fc9e GIT binary patch literal 45 ucmZ?u^><-lV<<|@O)1JOOHD~F%S=vX5D@Ur%*hFIbTNQ282&RbFaQ8GNevqS literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/realtime.m b/amigae33a/E_v3.3a/Modules/Modules/realtime.m new file mode 100644 index 0000000000000000000000000000000000000000..94aef3c8329d62aae5fd9e24bdce7d84beea0062 GIT binary patch literal 176 zcmZ9ENe;q53yN0Ad5y0Z9>+;7a`kVaTyoPNNl3T!3osV827^l#{Da6TD!rnie=# zL_zLI+xB-o_#Fv9{c5i5`6_)9k%wi_Udc7HapHNuvao@B*z*_Me7U))bhlh4E12C< jN3t+SjxW^o2A2w7hgxe9$?fdGHqhL6m+vs$tiOK%=!|;v literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/reqtools.m b/amigae33a/E_v3.3a/Modules/Modules/reqtools.m new file mode 100644 index 0000000000000000000000000000000000000000..ca994bdbddd8c0364270f5aff2ab680a94194b4f GIT binary patch literal 454 zcmX|-%}&EG5QGg#C@vg$5{fu-GyQ=>DxwCc#LZ1M#lrQ{^+u??Jgk!@2OqxKnf2I< z)yrI6lHETL92n8Zsdw9We>WZYR+uau)gWwb1hr=4JyvTtv=G^-Y|TpoII$k-v27Y4 z;n}ARyEHePH|fY? z3_K>&-okod9xv;nVtBTp_8?_a`x1C#9T(^V1NE1^mzBIJlg@bN99`fQmn0oZ+kii&-JQC^daR&Rt(nIN8y9N)8Lc^1U%e!Tw;*3Up!{JP O76eU{NA|Ox{{8_FOq)0W literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/resources/battclock.m b/amigae33a/E_v3.3a/Modules/Modules/resources/battclock.m new file mode 100644 index 0000000000000000000000000000000000000000..e08d4f7668d762e0c5ccb830e6673db521d3e947 GIT binary patch literal 78 zcmZ?u^><-lWq^Q&3s43F7ns4#z~|%`65{OR@9gd8=<5oR6;n@2EGbFO$xqJKD@rZS MFD*(=Rfk9c0Lb<-lWq^Q&3s43F7ns4#z~kf?65{LX>*wg}3Xv00Pf9E)$xY4GD@rZSFD*(= IRfk9b0E#ONsQ>@~ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/resources/battmembitsamiga.m b/amigae33a/E_v3.3a/Modules/Modules/resources/battmembitsamiga.m new file mode 100644 index 0000000000000000000000000000000000000000..04d4b26d04fbe48c09d84357ef6f0d855edfec88 GIT binary patch literal 226 zcmZ?u^><-lWq^VUFa{Tx!3ZSxF-QPOCMU;`5MNi{_+aN?&v>6uzu6#( zrF2qP&h`!|dGwh&ayh{xzeXI9G8hxNzwkxDSfG^Y6S{`Xgb_q3-xgyd&P;$H`hho` x*)81GzK4k1_<-bKN9dLKF@0jFo|4!+3s8O{iOsVTv*$s)vUvVmke-#`feDQCRN4Rl literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/resources/card.m b/amigae33a/E_v3.3a/Modules/Modules/resources/card.m new file mode 100644 index 0000000000000000000000000000000000000000..9ca40ca96ecbe305b531d22596744ca6704efba9 GIT binary patch literal 1790 zcmZvd%}(1u5XUz(KuQsc5JFYeLvP$FKEW)5?uqYBe9oF{t#!EA&PB zEPbNV`On0T4YdUF{$_Um^ReqV1K(DgN}h*5s~5GyFB?j={;HkFN2TIfb{+r7ZisKG zmQs^NlClq0t!Xy@&Z`dn-ypZ?VnS~%iqleCwEjAcub1orvP~pUm-!tNrFa*=??G!4 z=gBOcE%N(WOoDr=4ZYcHF&D~_yF}Y@QRLZ|+afIuP;9GCwkQFqVgGKmf0_N{#P^AI z>-$RsM>yaJ6;iKBle$6AE;3BgyKIscNnFIpp7KkI${Fi6t#8sa!Hy2)&`FBo{zf{6 z^~A-eP;Dk;TI0Jv|DCP>>YVt1m|LS>R zbkR3@;GOBu-UTwFVDL8HFtUuTX$?VMj(Yx@&NKC}QUx?l_zQK{lem~M@ zjyX9UlP?rE*NS0})=(5yDgsxE#`Z#O^&Qt-Qp)VjnHcdV90=upm{RWp$sq=3;Tq4? zW9{`3NH}|2O@2WBA33`+cCTkU5m8vSY8K0smPQXrJ zt>r@o@Osawx4Z$IPi=X&to7LvE^!D4Pi_gFq~O!D2{U`DwsQT?gxQ_%LaoB;_BAU3 zM&yTeFX+Da`ji;+?UGxj!CQ30-M&6^jUGjQFdDA>)rwm+jx$`FeRV6FGX_Tgd0y2$ yJEnVvudz@%B~IY#o+Dowa}0}mrFM}eeW`|efU(olJ;KNBJ^kz~Zu3cc#PA<-lWq^Q&3s43F7ns4#z~$`e=;Y_<>k5?+P*2WGOwub#EzU13N={X00IP6B LSCNRU0;m-L75Nef literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/resources/disk.m b/amigae33a/E_v3.3a/Modules/Modules/resources/disk.m new file mode 100644 index 0000000000000000000000000000000000000000..b799c0c16eabcf517076fd74df4d903f01d41899 GIT binary patch literal 886 zcmZ{i!A`O3)Z%d;$+*j4_BBuT-{}Mhd1B6HlZT)CMeuLKIItf(PS6_%uF% zCr_R{dGb>K*)By)oV4lgxBovoJ6*%73Yw!hMz3l>89A6CNFRICAn^Mz%u|XsE<5g3$aW30?5*46F}pXzVJK52 zIhR1UJ>N|>PFB+JwdyA$o|OZ>bqe(*7o5+JmE!$5UZ$bszd6$vP(BX?BcK7dF`Kyw*IN8@TVf8 zGh|BPd5r&)u$_i(na4WO5>`gSE;aO`W1bn9F0Bm6OANM6nzN0ag2iN71Ke@AfHSOCkB#yfs|}RX>co} zZxC6IQZai2vkhG^G6nJNjov4@7;)DMBx)zZ(yOHsG<5`baqnY5FNuQK_!F~DN+QnFkq3w!oorjOu8r}jqSRb+$~vekDW>2to(`oqd2pd zgES88$9r$SXN&h&IETi5evcoxOrH+G*$4Cv2Y`+9NHt-}u@)^;-IoBOW%@!_xZXMt z*A=R$c(BJvE~pIGf`^r1TWq|^Nh!DxZqx=OG-gBFCM(;c$E^=mI5Ew6SD13`F-mLF zWd`@e#%{@dr>e?KtLQ>>tbH~y58@MfSGD+&F!zpFu|_=QK71O#M=dG#EJtP+>z~XX zk-{!osq@eDHlpE>I_pd9;ACeGW#Y7}BIUi2`wF`A)$;9SF-sH-Cv#cyswT#-X2Sk(Xk literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/resources/mathresource.m b/amigae33a/E_v3.3a/Modules/Modules/resources/mathresource.m new file mode 100644 index 0000000000000000000000000000000000000000..7ca7cd2e0d1f7ed5177c01dde74d4461e0309cb0 GIT binary patch literal 458 zcmZXNy9&ZE6oyYr6)7SP4pJN(92|U!R^tV{KwH60qK#UpEwmMUL`O&8M*oQQmOzq| z|NC+dn=J-ZqSv|>h50OWoHw%WccLTD51|ku6PL^WhhWO>TtPb$q;wpYwHGS%#ebN=76i|p4V z>S3OSeIW~HeP;XP31iG<-eT$Y*>KHPzGHh}k{c@bM$-@1R6cNCyoLX5m7~A!+H*NU S8Wq*Rgl|Jv4a_JEw0HoI&}1Y4 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/resources/misc.m b/amigae33a/E_v3.3a/Modules/Modules/resources/misc.m new file mode 100644 index 0000000000000000000000000000000000000000..a303a9751577301872b4d8ad2708329100d5ca7a GIT binary patch literal 214 zcmZ?u^><-lWq^Q&3s43F7ns2aBzqVHfFzS|P<()6kfV=}t51M`PzVD9A4mmIG}txB z(-A5LQpt>@(#bO<7^0F9t`Z_9^8f$;FF-N3AXisk&tT^u*I@t9AZJ$w1~H(_FQ5$2 pDt~8GDWK`x3|t^FKSy7nQZNuu&&@1O)+<-lWq^Q&3s43F7ns2aB&8UHfFxs(Yp{Q4kh5!We1Lz5yMMeVNC7tk7ntYg d=<5pNGcX9L7vz_u=j#=v7U!21C8w%GgaOUW5ZnL& literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/rexx/errors.m b/amigae33a/E_v3.3a/Modules/Modules/rexx/errors.m new file mode 100644 index 0000000000000000000000000000000000000000..232d9817924be022a03da6fae1b1fff5b56c0879 GIT binary patch literal 846 zcmXxg$xg#C6h>i}Dpe^nlzE;6l*wtsw2VqyAt;dy63e_YZv;2-`MvTNTk^RXO^a8T zIM%N=oqE%7uGw?d{%RCL>Pw%cu69rEM_=o>kUzLg)M@8rkmd-*Ba%g@fWs+KS; zi}!fu>}*(0zb5v%{b$QG&fh*v_9Zd>JfArf*xOZ%3wYSEg@Irf*-S?*I?zJCx}=lIc5^={u3>JC*4>lj%E` O>AR5Wxx|_E*!l-tBYx}v literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/rexx/rexxio.m b/amigae33a/E_v3.3a/Modules/Modules/rexx/rexxio.m new file mode 100644 index 0000000000000000000000000000000000000000..ad9b74bce497c63fcfb0e97d97681b705cb74be5 GIT binary patch literal 674 zcmZ`$O;5r=5FM~8sl<~9O+0YmfQd0`JaH>@F^#3I{XpV{@KKNmmMoZ{Cx4&^qyNA^ zf^W7}W7JKzJ8$Ogo4327>6)}o>3Dj{0@78G$N!y*s}+%qm&@sVG)v@y(yEm6@nf6} ziBQ+MF6Xk39UGXXl!%HpodL66O~$jy!(=>P@D6QqgB+2E$$f|l+-IEh?uXD+Ds-0& z;$Qk2X;hLk_#i|Ym1X}ct_+4sb_4mtNz%V%l42eAQWm>A>&m!`HK)FGEmMIrX4o+; z9}%N{%dL5CkfA(kE!PGrV&?s}<#w)oD-@hrVW><^oLdeueBx)nU5grx;5x%O#So4O zyiK(EX4FH=bvl=kh<>VwwiSe6v5P&p5N;zwyFhp|(A66$#US)iW-hUR(L%r;*HqQ; zJk^rB5N*mg_!d?&a)+NtEK)z7y- g>dMjS0kXPnyEwMs6a2|KVOF7Tw+x#P{yzt_4?I|h2LJ#7 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/rexx/rxslib.m b/amigae33a/E_v3.3a/Modules/Modules/rexx/rxslib.m new file mode 100644 index 0000000000000000000000000000000000000000..ebe194473c85d95f9703123067a06f3bea573764 GIT binary patch literal 1354 zcmZuxJ#W)c6un8^)CwIsA;t=j!hjG10|P@{CnXU{W7)0<5>j}z-Nve8M}AI85kr3q zVqjoK`~t+tg!l!BUw{xoD)+n>Hx0o_q<8K)_uLP^w$t8$8679FERbXH=Rq1LIM?|6Fc?kK6Ck)h8jD#PX(ia5begb~`!myMHj_oJ zvzkXD;T~4v?INFYYb)_?&e{LOQO^mo@mQqcYKAY1Fiw}_$QW=uoAM}2HNZS)Cd#?N z73Rfhl*>3viT7D&WmpJ#l8P~wSW$D25Siq0xrYRpw+4)ii7Z5LBI8$=doM6i7;`!8 zFbfKCm@FJ$r&$pP8si3>LqExK-MKNIDCa7@$s-XaS)g8l>g8>biy%50>Dol^(2IV3 zJeiSzFsVu((&-o!bSD2k@(oh5CDkWZ>Dz`$h&~5NJo%5?SJr_l-M)>bzB5a1-&w^3 zM5^YG$uYb0eOXfdWEB%iRp(BBsfmJAT|mBdRr)PXg}#GCe^^)H?|ao>)$Q)>4!r}< zA=-q4!oF+SEe4pNq9Sdp>uZH+`+GyTH5ho$dOEUZ`@4$>atvs!uG6-(M-_@WMwPA7 zqwl!dgEO>;im1BKc#diWn4p+r?4R6$=R0mkZ)StL>{;FuU9YC6^853tw##~+W9xeB zWxdM?9Cn9xx9`m-H&DTDAMCTK+Wt1<{g%gjKtDV1JaC*APXJtl;}v`kzT1CV@*Ci< zVBX2zu-SRsnfq11FYp$sd%k6(I?**U88-HetB0=fm<`M2yU!Fd X7R2=i{v_lX{u$omUoP@9 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/rexx/storage.m b/amigae33a/E_v3.3a/Modules/Modules/rexx/storage.m new file mode 100644 index 0000000000000000000000000000000000000000..fbef7908191530dd61816ee290f2f544a117846d GIT binary patch literal 2348 zcmbtVJ#X7q6n(U5nNi%vb&Vn@JZQ*}E=KIOOOT-yMcJ$=QhAgTB}HLSAC?Kzl0Z^{ zQFQRsAJN~@sav;<{T*$G3>`WYaL;*8WUe-_rwjSzV@m`sNwAu7UzH6ILw0B)_|<}4cx-@{GBTeBi#LFR7d$#*EDu5EmS z16P$C+34!3i1Q2B7Qt~k?Z+u@3}wH)%*V57R*=`coB^-E^V?Y(k8_4wuzt^zaX%?& zVg^(EF-Viqq)5;eE(^#zR=Lm-wErYy>1Tg`DT+n(-=i!mvY2G7XNbIr2N&fy?8-3D zNAYl!9jLC-bHyTz9gQBYqBV_vzKZT^^ov#WnMS|7MTPM-s=udKh64bKGZ7-4DD6%D zLYp=5;n{pbuU3A$ALm+m&bhlh2U-u~Yrmn9>A zmEOBlv!6}}JVd4U!!+qHh^hBpJSdVWca$C>4cF@5+wpLhDc3!pJ()#hlb=yI=#WRHBLDW2L+}dlh z)2yFH-Keeo_ky0?X!ve`SjMlR)@eJGtWDccT%L16n}B4z6Ec1aAED}Xr0tMjWhms> z_EExOi0pNou#E(IYwV}#hc>*lH-f0XYIj?{7j>et+JlzelPy~wm3D>sw%Bj z*9jZ02Ed5ZR*XRyNEb7ZaaS=ekSZyZN{Rvz*gusc-Ka}dnDdd!Ss+Z=vz?Bobfxtb z=X8725EiDcYpcqgL&uKq+7cet+Ej`=ei*4UxCcm0tof~VWtVP?FBjQ+-gV_GJ+VnO zj>8C4s0O#{HR?z&fat8hqk6rItg*WVpkfSmxJ1}953jo2X>JIZNfVU)P^<-#M)GS;3;e#>pq};^OX9QeF?_jvDc{% zH7NaWkNmK1`_b#t-k{&{J?2yST`42)HKTd@*Q_3eU8$aMwQsDyf~@PefYVhQ$Qo5C z1G~iJX23_M+rZ9Y&?Bh{`2hf|KOV^-+l(1G5TNY-(n7yF<6NIsB@@dEboQw Ucgak)U9y$$<-lV<<|ks3@*1PD(6JWe`9E&PAz-C8>@@>BS{QnR)3P3@)iTsmKC8sd?!o z83+Xs4M9L7eT&mMIHBrceCM3h#3C4n!7Vc<2hL&iEQYbs+(3Zqlb@Uo(&+?pe`sC~ KGWS0N0|Nl0q&`9b literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/timer.m b/amigae33a/E_v3.3a/Modules/Modules/timer.m new file mode 100644 index 0000000000000000000000000000000000000000..873c615d5b061ec77b5216d287a236e8b18d79da GIT binary patch literal 72 zcmZ?u^><-lV<^eYO)W}FEKX$*5O7RM2?26BID<=*APnc+0th20H8I82IVV3ko5MY| OB)GB|Ec~B=fdK#p#1-WL literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/Boopsi.m b/amigae33a/E_v3.3a/Modules/Modules/tools/Boopsi.m new file mode 100644 index 0000000000000000000000000000000000000000..0112c6725f2f639d25ec878444c2b870a648e498 GIT binary patch literal 166 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 LZ{p$@!QcM@sA7mM literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_debug.m b/amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_debug.m new file mode 100644 index 0000000000000000000000000000000000000000..efb98bef03d54106d108c6250398e9ee65cf6cd1 GIT binary patch literal 30450 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 MP!1|`O;YOr0C={_j{pDw literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_lite.m b/amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_lite.m new file mode 100644 index 0000000000000000000000000000000000000000..b7e28bbf305dd92afdfd21f9134c77c3a062a21a GIT binary patch literal 21630 zcmch94QyP;b?)r$-QCO8idxAuy;fQ4nqe54rnrip>ME|P@>ir3iexBSRszN1N}@&D zOKP7;*^*%xSBayfhT*ag4@MCfK@b#y5Lkv#6h&U37f6BOw#It~5g3l@r^+mh0Xw(ZJEXI&3}#}qhA16K+#*(eqLKTE5!YC{4v z+V63nRq9;Ug+3m9MyYT7!`HU_ft?!sHx*a^E%I-x+Nqvad(?t)=VjYXjxO5Xh7TX(jH8fu(U4Ul6VHUA4W-|7EZP7VFDcN5PA34e8 z*{kG8t1UUl+2r@sc}ry+8xns=ZH&ubBAKj7S?P35Dw#|qV)#p>R)bdZ7mFvXWZJG- zlU5Rb`o{8)iZ zaw_54s+(R8;$Tl0mFy|ap1yxq%sz!2eLm(MV&<6EblzE7y>-Yp=P5`hD{#4Ttf0y< z&Q)WW!bq+7oKK9p;#;#K@ff^(-bu5z^M)GT+M*uszdV0tgfM=Krv032(yPsS<+#SR zN{@S-v{;PpCm|Bu%#l<7A*BhLvOy2c#65o|(&r~v>(jfb$1D6Z$E+{2wiaJv*=9d? zpukzl?my*u@KmtI-|0fHIkXZTLfcIaX?lz_z%t5!w_vm11C$M@n~!#S3mAVlSr6zP z$S;_D$BH(KtF>utQ9I_(z#l9kmlfU&29!I3n%w-EHptfLf#kFOmoJ=oN=5)Amy&O_ z;Wx_2JtH;^+vJF?u+2akw4f>*|B|7-&d^@Bx-GTtaFx2x>47b@(T_nA%hKbZj3Rh3 zu}{o&QHxiRKa76WYDO664vw(fJDgsF4W5s7NbL#UbCA#ydTYS!X7yk4OIvgOm*-%G zkV6k@vi+9|O1M2uS@YI`+0j*LId@U+ofw6W4#wSIk+rzok7gJZM(@ZPl!b`O0>> zQGd$FY(h%=oo;7Gyp(>4^B-o;XHdpk=n;-DnXS-b8+@ep&f9fNR{I+CVVQ3&(RjmK z4kNu)BB;k!Mo_dAjZ?hwDZ=de@cs7{-sddaT}{HGg_UZvN20ZtTh2k zjxp~{s0oQ#*BM{EN3^V=tQF(2PLEf6n7B1}Q4bJA)jB%njt1ktEh6_WQ)-hjS-<5) zS-o*B9XB+!RX|jGF^#Q3u+2Au!P4pOJ{|8GC@7(KRGjq1_Pb?9RC zIFH%B6xo9FxF;)C>V@-;=jr(x{bd<(Ueb}`56tQ(3tD77L3qY+dR-C2>eMUKTTquN z;8Bf6*7c;0w4i2D&)r}2V^i}baYIL|k;rtU^B2J7uk23Ik1~-eP#|-qw>UTl+*$EP z#J&u>+DN-cH0AVP3VFjSxiP9`u9E3>Wz~2}>zLGqHt1ayk4ec~7mvA$BonU%l7!Z{ zI)e~++R*tInkyr0tg?jqW$)})+6*x3Ua==VA>Ua!)!d|5@yj_C{fM92K#rRGg-*Mb8SNl%Y z>W_GM-Yn?5LKzZv1vQS|4g1^^yGKE9_R*5}O^#jk!kzJ|sIIVsko4wKe>9{=pBa>~ z9c|{y_c#y0>MdjGj-CU&7E;1ka0>ku(umg1@k`|{KHI`tu`dNlVH`{8l$2`4A9AKV zg@{epV1@(SL)uCOR(6$)$ETIP8>!>05VhcUHAYxhPq?#WFgGz8v)|AZ@*AL)%DeNm|`nvseBnq$C>x)L=q2*P{b;8V~*yrWw zzdaUkJwfilt0Qglh?xbxQSg@R3czY_;s7BcArp8ZZA&JN6q&)1$q{c;WX z-9U1HmzAK#hrKNHf{{e8EIr7XM#L+>7_{`|r{lgI1|D%AFf`G3>)izZJMWGi@qi1lCk4l=W&II=2=xGebENoiS*wn_|i)9@ztr&xt2L&6}Rl*Nua7Gj> zcch&@NK@9t*dNi5J75<&*Fg(`R*lx+d$!G;advU$oj+shj0W)y=S)(E{YcJkyuV5A4?=;^PJDS zVyJ5odIuu((mTqo0i@Z2JfawKKUJ60USi+kKQYp7_d7{Q{#xiUg{M4PHFMvz zs6HCy=x$YQvGzEuC0j@q)!%bfX9H&n8reu2DkSmbh-=Uh|CmzSBHyXGI-Zs?qQm+C z=mEhq;he}qx5`B+k=E=F*o$h@9`;Cj)E4G^dRIVUTpK88J%pmK6kFI*PDE+Ydccg@ zh%G;?UOZ1`_hz)^X%=kS?}uJHJgEjZjg+Fa#9k}T#c{^mwCQq}=I>z_(?Mi+N9L8B zmMPD>0%#5s3tTX@bLYl;5Dx%Mu#s9sgyj@7D5>O-|PTC4Mh`y674jpP?JUyppF zU*xs^*!y)(o4PR8^bDOpRSt zgJ@AGsBROFY9+x_Fs)lT_rSQW(@{LmX?@R~H@+j^mWG$WOjt-kVwWHt3*O?V;J010 z>9BvpUc6YrEVGVb614jqZ?0gq#jr%ewx4@#{JH$~{fsM5J#OG@Ohi zp1HB_5Qb~BFmk{SI!>UA>e@4y(RkjJgJkotYMyf-dcfC(vNB_-j^i0;TPbZJG4tb#8q>@}x2lI(ZA)NvymJlCI-@5qm3F+~NsDGFltq`Q)8%0Wyb^P21`9=jd`u@_J6j zDUY0@HE5qyR6nK`^TeJ0pd4R;n>%3mqn<_k^r%?j9;AlJQJtZ9!xUCG4H4T0yU4_v&@nZC2$q^IwkkK8oI9bByBUc94uE>_qszm#ruly4Fef zwMF%RzvlOyy8dhXuE52)^LL*@#2Jwb`MP|09_K{9WI!8snKA#KQprLB{mIQ5N;oxp zul|}>vO)U*ASASUccW!lIL=&0?oz5whhxL3>?Cd;M_2 zrzP=rIkgfmyrX!4c2!BI8D~5vws;Dzwd`{>DC043imI*k@3_w*vPo>K zgs-$Y@fCg?7>pm-s?bYI7P=}dS*Q-IMc+>0n5mRqgg3;M*jFe0IM)FE)!2NG2l^?^ zzhm?y)W@IuwbWN>afM%57g!B2UtyG?F*p1=%*IczhezI7X+OeCJnCUOZ{<&|=HsB* zomI0>#1pRWn?lUcL}DI(g8Eop!e#8YUHA93$i_>HyUTO7$k;)xCC z0li=4&jWGadVchEzm@tGps6_~>@xR~L`wa{@o)!L2w2(j z8}e9bnXil>{d3ehNE7!-5qX*Wa^5w45^Qch-H<(n1=***rcVUqc~hR(v8Qm;vD+BS zu)D^=kz@ki7v4Yw2qut*x@$78CFBI3yV2M1ZPBrU+cX&`J@+y((yvwY3V-A5 za@@AW2xK&-?);E3w)m1SwPBYVyj%;g)Uw3+5tzis2o+odV;uu}c0tQoU_+Q3w4vX+ zrg@Qi2ld$H#BBRFfjkMryGO*ou;0bZaOX)^qDy5PV<0d6iOKMy)LUnCMYBN$> zF%m%Cb*{^Kw!#r8d-m70zkVNkXeu9C9d|Quqi{+&px)dak}<+Nm|O!nj8x}v(x`7^ zVO4`OEbJHQ7PuX&p@P=9$pVVlnmb!;ovUb_M~l2^jXM__3azoj_pD0P`cZwtS|zIA zulC26?)tATw#Tmn-wsj(5>I96h2&l@ZqW0dK^~`9?;9GhzAIbgie3+Il*u_t@*99T z%s1o(~Tzn-N8dQ7RO2u0jz z$-BRjXMgBNe%DZmpAf|3Lz{l0&=vS&Jb!l}Yo2mqUF4r~im$?6=BFuL_RJhc7i^R{ zMBzxx;pA2<9@+*an6KZv20pcHMvY#$o}xy54KW9J%7SzviCr0(a9`4r*~8&?_=Oy# zvCY8zCats58WyUyQYvWa01ItLMh)^@zc_yHcxPeNJUt|Lq8YhYYh z%Y!>Nb(qT>bGBRS!+`Ni}T+5!TPwOFQFO{(7Ze9Ld3|8xcEleo+|6#mkB(s@ar|0lwjfb4N6(BDdmgs z76Zq6_WV8RJ;s?^*2zJuAV$-0gFYPb1^jMNYrtm;?2_Nd`1b!$PWyTP4LLL+IY_)K z%UM|N%2GCEO6VrFP$i{CdMS9Pg)a)n;Qa>Vggrd8VAO2;TCzr?S^`fMk}#`A;jlu3 zSZS@`sD>1S1Nr?U-hHP0hj_mVV z!Yquv`M>@GXJK%sSMEk*5{KaQ5pj*bzY?vH-wQLo&<##l=%z$n-Z#?WSX z&xKSST!FE|mIE3!&$z}e81KU?2h72bT@B9>dVx7!N!^Nm^lo$1qV%ecWWV6%Z#ur=v2yTO?_-Xa8KkJ*;SDtG zk#Ywmn4_n-H_chP(4q9KjFlkrvj0dwr~Nl_SCPYh9NO~c2-jZ*3vyh$`ZZW51(Itt zzu)#5ta?L+^++2UH+{M@@W!^3Qu4Iq8J8z%l(quH*gO`qpV=9pEc(LTL8sXO$(wc#%c~u3sAanUfJ~94)=>| z^~otB>>pR&f`A?9n=!bR1kIxa{v(_d z1GLiXv5mSt%fV@J9nY)7^I$(3_0Pk_X7Y~gHtAKGAEN@I2Qx|DKi|jq;1|CIuDQ8u znE=#x09AKasDgod`JPZ2KqY~T_vY@73+Fz{0@U_fVuGkzgAg>kFxD{Nu< zTxOpYx5VU^MwNE9+0fTT`po>m(dh5b%I{hw@@WQy`87L7aOCC#?irdBAe-&PC!}z0 zz5_h!`>JMF7_0jj#(3(&SD(eL(WbQQ1xp*b-Ea;)SR-HM7!O*0ncrl@%gqL*eh>d< zPR~ppDHUgC)Uo2x+2hAcGwr3x!zYR-POFo%lcmYo(?NOmc)9pO`_sp#XO(jiV?Ez} z>*Ak1yc#q94jH^C#5$Rh>AxergfxNl zm_92*{T)%x!uz2d6ehe+?as`dgBaMW&f z)!GBD%7WfCKSugK67a1-o6I>R&{2c$HLtqL{wdNoT$TDd(m|xStCG90ZH%{d%2f%p zi9sIfm&(Hb^-&(5etvRVDYgC`6~jONS;r>u%*~9?mL_LrpL=d{X7X@p9G^Nb0Ydxf z?6HY9sJji7sMrA5nIk8Tmr5b9>Wl}_xe(f*%A!TNSQ?+5C1TYv7r@pU*dxbF$4{QX zj04E&lT(E1oDHD-{-?*EM+N&AT4%;f<40!4j|%ip185&-@yP7tbLcQLUYt3N>o=W* zOMFN;ZwXKSmOXF>*ZJR9~BX^X9=5F@*Y_UY3j;mF;{kkk#PL0pZ6psmK51a*L zRIcQFa(Z_B*f^L2riTJdl{{sSRlse!062*rREiQp(+ql=oSvK&F4n$HJl?YDtD1|< zk%{pm&!P!?&2Ix-l&TDVyR z&s}j)qcgL@eb-n3Rmr^#?hVYQR{*nua}ZjbHZ*KJ9HD`hOI~J5lSf7Voh^6ip_Wi$ zv+zokNylGRLF$_9)05LjVeBA@a64&NnjRaPpxtRJogF_#fX=}xJlaY{##92a{1NS~ zax5K&?~IJQQt|M3iT0;Dzg`84N>pWzl%NYefYru%Kt*-B!C3jBr;DZ1;o^~JX(-m$ z3@!~>Z724BJvlk6MVrqXj0Woo2mt@Th3%548+@$a0576)3-UZG&%^TECC^rQ*7CXT zV|jic&+p0e4SBvG&klLYUQ+Ef=4;>O6Mwb-ta7+GBO3jqS6Q=jn$Im)_?;gTx5P@KcD#S{q z%2AoA$>~EglP`>`8DQgIgUUWXSt=bmF)p9w8<pI-9ftv4G|+V_=YOZOJ5H{J z50z8395p9^X!^Q$#8N!Nw75oVvs>8FpgfWH@!U}f0ohIMsVy?uvv4GoS;KPt0t zbmUOa?tQwnX5YZ>uvD|JJ5pCO+&K`|rMo}h9hU692Xuk7r!1$n7Rxo%Yw2eM?XK@3mlZ|`oSmm>Re{;0hEb5L3)vNDaD>fhD_ak!vjzB?H*(a z*b=}722fFa47}BnIV@!U5d1XCDIa< zEb%m4@Y{sfPkIys2lI*b=0i#mk3jf+$7x}(D@{q9 z78aIhH<1$h4ol=IEYVWJ5-dduLPMO~hIO=*utZAi+U05Y^}q?2oi;*cUC)$4Zs7v(av#cbCzxMJY*1?3U8kMUiQmQrp)* zgif@K$z#{hNRMA8m(emg+uu7v9S~ofyhX|hEwNDuN$9k}ZEs(%@#RT@=1jyfxCZ*< z@FG7kj)%@}LvxJMjFix4q=X*B5+xRvXdz(8I)3_WoWE!dqBgBXou3r1Wmeu!0n{+1J0H zPEBQz61o=-d6Z;~`~8}4go^2JU7h=OV=PfqDbm{g#E4HQh&czJaZv8%S>J&{UOquNL%nj!|wqb{{BDJ*%E62 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_notag.m b/amigae33a/E_v3.3a/Modules/Modules/tools/EasyGUI_notag.m new file mode 100644 index 0000000000000000000000000000000000000000..ee4efc41144144d1e36839b6a804ea943a63017f GIT binary patch literal 712 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 J$Kn-s`UlhZg6jYP literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/async.m b/amigae33a/E_v3.3a/Modules/Modules/tools/async.m new file mode 100644 index 0000000000000000000000000000000000000000..f2b59fbb1ae6970acbfec9d59f5f1e5dd3d31e24 GIT binary patch literal 1066 zcmZWoOG_J36h6sJWf}$R18k9^(p49hZUPnxRp^64idZV4EmEW_b$V_lQHwVmxc8iUzVEx=nG9YZ z8GthY!Va8X0;WC(xZ`Usfwnqz4Y8#clKCFoCS~LWOpn=;wkVvi`zNM zYU~^3_N$2eZuJpU+hd?$$kB7eo2bZ=%by494}UM61kvSKDQDCg&P~KonTD^3ZM@+) zc~CTt;C422=N;>J5Zy!d5;`cOgNp0mmCGeqeT}aF$^a~zOU~B!c?PgZBSiQ<-(;ij zdI9P#j)wtjw!oh2R@?%DmNKO~sL3jfdY#XFMe)IIlfoNsjW*E;r3aPUh1 R#N3;IB;l8b^Ye;qcpr`-ptO-n>RDxyxzG#J&q2@x(xJa zfm^p0;(&F^oeB3!zq9a>Ck>K@p(@BYtKkoK>tD>ly_9EQRh~v!kK5Tj%_*N0c zLU^FHdC}&evOiwYwnzP*)(;u)rsQM2rM@X=N}FM*?E|zYm1v=EU(F*^+7`)2I*&6g zsjrB!Kj>D8IUos}+31za_KcxR@142qwK3QiX93>dP?fMD6}emCr$Jr0m0`sVA5yED z;7v(=lSnBo6_Au1c?+dE;gc<|0utJm@ME;t{%K}b2pim`o3{QslpSfkC))CzLtg+~ z0vCC|;lx#c7Yx5nZUw*%={ot4(T^HFVtC&0qHtNP_z`J}G)}rnx=y-4%8-&In>E`q z2U9z7;`{eqUUvjBHIbV%^HGxN$sJ8gQ`t*EZ}BD`-hQBQdLlR~skB2-p4vgfed?~e zGeGILC6z}VN-<6%iWz>Ae(1iXsZAU07fxyy`+QdVtgWeB1xZ>3t&ggUv4i8-an80Q zvu&atO)@yi5k8T%t&&b=N&gmlkxZ2Pk<04bw~ymn`t7vM1~Y9tDROH*B5Vc5bI>x; zZp~#0Jv5XB6LQaRwo!kxV9lQ!{=)Do$7wJClQ4^T35E`-pQLd-f!}+1%LbpvcilF8 zWEw}V@NFJ=5MT2%e4(L#>eT!|0KlZORr4i@2r#;E55U|I={R|eJ{hWdHRl4 zJj7m`)6q>wCzoo~y3@KNUGu%_iGzGCu*1E!TSxr$h1n?bY<0fkIr_wGeWkwYIc3kU NKQkKf69*s+f&U9!Qz-xd literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/constructors.m b/amigae33a/E_v3.3a/Modules/Modules/tools/constructors.m new file mode 100644 index 0000000000000000000000000000000000000000..c10219406cdd18ecc8c901ca4b63a9092e0688fa GIT binary patch literal 328 zcmZvW!3u&v5Qcx#XbX#qrL�ckoaULDnVk5)@=4s7Wc=%{SF>;MMMQN)7XJXP?J&7 zfV^MoveVtUS)DKc=1a<#i_@% literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/cookrawkey.m b/amigae33a/E_v3.3a/Modules/Modules/tools/cookrawkey.m new file mode 100644 index 0000000000000000000000000000000000000000..50416c1702851f31333b909945d85fbe61c7dff1 GIT binary patch literal 1020 zcmZWoO=}ZT6g{u$M=BviCv@CcjHeG7cRQ1%i^Y41Q{ghcN8+UsmwH9G#Bw*e&d)RJ9TUIV_{M}e<19Y1TJ*S*F)j9xfUiWxO# zw7MCN~#KRheJREm7r$#JEVMak<9>pu$R$XEMelLZ>mrI@>O+CssrHWj`&} zvl4mJq3&?^DT}a*#cmanA4Xg}qpZ)^wgzRBmDQ&KxU z?SnQwqcY86b-P}zIFlvkRk`Sp1qO(i2enTOd%%12Vz~ai@v>Ci*)FW_Y&x&=)#|2G zlVCKZ?`RF}tksp;Clgxt8tawvM%k%l z%DGah=G5y50>nK@dn=oIOcZF05lLZWDfXuB5Vwd)LK6u(j)_0SFXAWhjrdG_B;FBk z2r9xLs25G<-lWq^VJ7=sJUU^mQ3H{B|-hGdTLcXJFB1C}2@yP>?@( zP=`UE&7*>W2`rZZl;hB2P{?KAP;ysb)5-aN!*AW+E(La<`wR#CV*N^iCb9!DQv(Bo s77+6>urLTD=NDA^WEPi%sDGs4@kkCO81i_($iX>7U1S2>&bh>K{X&|Q0{6OjEKPLV; zPEPLe?h<1z?dmt-!hPQH9+#`zyBX{N^gp2;O>X*po!iGi1`f;@CSTov=nmLkQR{l~ z&6NdTMC$My-su6_bb?d5j}9HeNJy>PV=Dy$SF8aW*nS4NI?Ze&f0h ze>d`Gs~I(^eIP@&q&i^AXj>xc8}qtQPx-fx_Y4G#D9e!ff%y3k(Bn@P?ge6yiru~H z@#>{=PjwdKl8N&-T~CT9;nyuUqwMuD3ZonjdF8TI;ghQZ_Y2kiBu`_}=~VSFWw;bR gRUM1O&xN0KJdG0RM{Unn&5bS9n;XNQm!)X@12dLtp8x;= literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/exceptions.m b/amigae33a/E_v3.3a/Modules/Modules/tools/exceptions.m new file mode 100644 index 0000000000000000000000000000000000000000..dae2b0a30eea7aa910e7953ecf149cd6e3403f8d GIT binary patch literal 576 zcmZuuO-lk%6g`86!{B0S+3F%$FnzddQ7*C)qH;#0R-q|6iZIR$qXPylhJK0AriDR^ z2>L5++DZg&Lk3=VObo0C=e`H;oO{l@FJCZ@u>?S7K&7biQl>S=)z>dYXpF_zrXfPw z62lgxi`+!I&&VfzKz~IHiZO;9-6aEHL$!c4X540E)=f1#0dwPXZn6qVr7Q~h!qZR; zo4_jbbBi6Tzz1cGVqTxIc9|8McOA4iC%X=qC+8*@k^I*O5A1`=(XS6){_(kUK^+k; zA0QsRBRW$MRTrvy8gN3T^eDnA#3wu1vkcoJTy%``L{o^3cnV48?vp&rr;(h&Y$Ah2 zos0Jn{0_aW`&VhJUsk|dgSS+=n<8kMc38^i&iG^Mj&C){c6#KvrcKSZWm3AUz;>u( zb{y|U0V@?0J*VZ>I#jRuU9&-Ezizs{wqx%RkYKMw0I9-Q4}dquGs9z?GYE04c&6)k Qz3aIUKT85clodh%-|IiCX#fBK literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/file.m b/amigae33a/E_v3.3a/Modules/Modules/tools/file.m new file mode 100644 index 0000000000000000000000000000000000000000..e82b05a49b451b08e713ce16a17ead77d5968c7b GIT binary patch literal 942 zcmZvaPiqrV6vfXZQHL19*oBA)4MUKk39}J#QK19_Rm>zr0~HjEcG9NJ#E?#~f{Ot^ zh@YSm!Hqi$E?gE7aUlpUbTis4g3KcDJnv;P3F5$gf6qJj_wKxMrFsJ=5Pe228k|yn zlI=^oAp)xi!+wh-u2qkby1XWWjL$u-1Dv&1tF^KnD>kXnb43xYLh4`(FxK~P+H+^+q?k?QmhA`jz-~x?==WFyrK?DS9;SODjJba=a8DHX zf9tuxKAEz!N{Su&KkP>lJ9CK10(&?-fKGPS1=YsgIsJ@^#4a+X{*k&KymZ}vbFMXc zeYpE)Mjijn>+&{>l}4ppnLC=U2ru&X^fQ!SM*0n3>= zDSq%?y^rX6A%M<5)bk0POjDINsw%!A%1vVca$rE4Pat9E-ed)7#kH)mbv^WV%);|1 zu=G3*oMiTBFO_Ev3B|pRW!+FkAfZa?Og?NIf=G)C=xmXhbFAB;yDgXcg literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/filledvector.m b/amigae33a/E_v3.3a/Modules/Modules/tools/filledvector.m new file mode 100644 index 0000000000000000000000000000000000000000..8f191ce5d8f3cb08170c74df92e945cf2c8eb449 GIT binary patch literal 6044 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/ilbm.m b/amigae33a/E_v3.3a/Modules/Modules/tools/ilbm.m new file mode 100644 index 0000000000000000000000000000000000000000..1bbfaebb474481de3ba65aaaf6c758a1a00dd19b GIT binary patch literal 1894 zcmZWqZ)_7~9RA()XijLxrCCU02zfn^u58V^EYpys!RsH`t!r-^5FN%yJJ*(WlU>S+ z+hR!J1L1?Bm}vaq2jeG1vk<>Xln)^O8Pmijl4UU@C{dV-5Wg5g%FgG#9%GA_ynWyI zd4Bi&{=C0?yE`+Oqzy!#Wm@})&c;I|oUI5(j772U4o{P0&e^@GT9JffK|S$6IBlus z+{2|don&C6K;E=87x4ix)QH3MXi)I{9iFhSLE$FsC9vDV<0QL#!d}#Lrav`K5)sfX zEamv+>+7jnf#^C*!9&#Y06E3k{&YN}M&pCY13*qZM)nNu%>XH{QCK{G(YEcC;vGln z4ZM{xk~yL;ibTiQA(Gk*3RqMjB}B4txh+OajV5B5KG?hm8$Y*UidZAMXCwZtU^B5H zu+w07wt*!r6d_5LNC2X+fgE{m!7_xM2oxDMQAq)}7x4ULUo?sq%Go zoP5oSuZ&`iI$<8Lx?$aEQTE$M*dJoG6V}a+MjXPL(D~Q!}f3 z;`QQr^O@)7%*cWvZp1U9>1vrmO|K74tiw1C{!O`Rj9uyH#-38g1Wf?0Kt`>TlPBDYo%$wjX9LD(oU^KuQ5aDn8%6{GG=N- zPe%l2)+|!s!9};@ovjYutqz`asD7N^W^NSwosR3(bZ-LQ2Nn~?ISLTXUx~NVhQ2?c zsxYY{LT!KWQc>Ou6#91yGDDR1?7ItWBfMf!>P0dRU@_BLOyy#`PI>zg_e=zg+%`BH2r*X z_(%Jrk+-;FQ{9cRGkxQw2EISS*X}P(jJ|p>J((LDD!npQt>l4{I79+9|Hp89I~Fe6 zf4DH|SR`Q~@D(1#vDj0|=i{ZROwIx%&932F96nh(Voe^&6Rv&Xw>9iWhc)xBk)sU8 J^=#W*{6Ef=2TT9} literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/ilbmdefs.m b/amigae33a/E_v3.3a/Modules/Modules/tools/ilbmdefs.m new file mode 100644 index 0000000000000000000000000000000000000000..57e12e417ed98517113bd93eaac4ab4f85dca8b9 GIT binary patch literal 562 zcmYk2-A;o*5QV2m5e=z?^up&*U!Wk?Mt)487haK-VoT&NP-A=7H*aTl3JM`J=i9Th zXL0@T8OCsV%wylls(^Mn0eqI*HEIQ4_~oi>xvG1v+5td^5$H`Js;omdshd)C-+8qG zFi_p5b=kC8*X4CZL;+*himFTNqW)=l$7CuBNG zeqbj~=!L6gghrx@q%Z&J5kMvCC3829oTcjq028Egf|v9N=y#6?r}MfB-agnVr+P_` zz(S|SPTn2Q<`G~5O{g D^D}Eh literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/inithook.m b/amigae33a/E_v3.3a/Modules/Modules/tools/inithook.m new file mode 100644 index 0000000000000000000000000000000000000000..05361cbf848875021d63ea290c0d35a323afb8b1 GIT binary patch literal 178 zcmZ?u^><-lWq<+!7=sJUU8YNm4Zz0cy4c}&!Nwy)M|ARsX1CQSX|Mv_$KKE<>fK{+CaAoFYmSp7T kXM=5IU|?hb*~$p!34p|P(n|A^by5;b5*Zl&|7TzT02TEh^#A|> literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/installhook.m b/amigae33a/E_v3.3a/Modules/Modules/tools/installhook.m new file mode 100644 index 0000000000000000000000000000000000000000..eb4df2a18dd85b349b97f30dbde875bef0c2e993 GIT binary patch literal 142 zcmZ?u^><-lWq<+!7=s2oS%F!1<-lWnf@_!GH{yz#L{E$*GXfz@n7Tz@d`Qz@sFn`V!7{7M;E7=$uQQi~ExQsYxAQj_CzGK)(f<}osWOaX%b|3M@G{jU{o literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/lisp.m b/amigae33a/E_v3.3a/Modules/Modules/tools/lisp.m new file mode 100644 index 0000000000000000000000000000000000000000..34486df9ae2dbba2239e1f9c7b55e76108306078 GIT binary patch literal 1736 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/longrealtiny.m b/amigae33a/E_v3.3a/Modules/Modules/tools/longrealtiny.m new file mode 100644 index 0000000000000000000000000000000000000000..a05a2492dfc9a7c7044515ba698757afddc84967 GIT binary patch literal 2552 zcmd5-OKTHR6h4zo$039|i&CTr#^R&eu_>-xi1ejYX;Wz_Zd9B&sSW03nn(*p#x6u$ z`2$?I5`|hs6m;XND-m%eMT&wOH-cGYF~o`EckWCc#d7 z&L0}6I+M%QQsfA!XRIqk{fI03ap$&-vk_O$QS3sj=;w0~-!;W-UhekpRMqh^|A^N! zbi-@=$g-b}k#-GP<8*DrgmrMlR^0X80oUmrWSi?m(xgT#Xf|tm2S{f2S|tNC;&nP^^@e_Yv%|F*KH|7~T<|E{ua z?eGVUowW6daqVsK-T%vctACmA^>+FEJ3$kt(5jtlUiqgc?4Ozv&!u<5b^IsK$-%l5 zJwn=GMLHT)*@9KrpzpUPzLDH#jn0!S?$$o6wJ2^Y&+p#GTFptQvdp*DlgDoPD$!ja zY(^R6&M<=42L0$_HZK~dcb>=~=NN2Z=pheN`RL=3p^jN$Os+pl9BWVoJ&@c@kv;Ej zM$&Fcv$%HnO5l-1od-E$64hKHcNUdtpB#KiI%+ou_bz6%(QRsDkMnK1&AqWdW%g0p zD9k1kiG-Og#tV5PGuM|&#`8vg;TKQbXxJ%ML`D34lPyvXThz8>5nY5FAej_1mcZu( z&P9?)a&4#q3`{Y{iz&7T9>N}kUE&p~^ZJ5b$U;-h)0t#J7&#J(qKSJXd0p6tVBd&4PxB?G*vgpnzVX;2Q{->0pZr;>PW_*HyAQK->3 z-ivCn_XF+vZ3|t-d-CSC48%joEaU`)sIwW3ZPmao!FvPJ4^bd3Sg{Kbz%41v_Y86$ zB4$M$ExbNb{)(~QgN$L<;3NeXF}2T-QOsopf;mcEV0jC<1L1w7LkJxP@aUuvG-`AX Ho67#5d!6aQ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/macros.m b/amigae33a/E_v3.3a/Modules/Modules/tools/macros.m new file mode 100644 index 0000000000000000000000000000000000000000..df666f640231bbbf2a6b54e9bf694d7145cd8c99 GIT binary patch literal 306 zcmZ?u^><-lWq<+!1t^0ZOfv&XWxr4c1_fOP4yFbmPu?%quM{Mr4;1mJU|{vz$-vCu z?f)JsZ;vL=jV2G*4>D09mx0I7fk6pG8)z^ncpP8=*}(`ES18~Iu>>6$u*(9Y)sjQxQ)D00Y_XV^28ibAPPiK{z2qP<>b~^ ztc{mb`YU^;badQn0V&%3|>vrA>$4>44Lpj41?dd>`u}7U&n| zdcY%f865I5y8v4PFTWwjsPp+g=$gqf5zO;N>_CwF^v@Lh0+tGCgFUhW9$qgOX@&mh*#FM)QZKNU(z5%1&gFXNN literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/pt.m b/amigae33a/E_v3.3a/Modules/Modules/tools/pt.m new file mode 100644 index 0000000000000000000000000000000000000000..02e2a9a0cefe8122a86eb74bb75be5dbafa58e8a GIT binary patch literal 5252 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 VtsRfjS60mpsai_67SX6u{0~PI!ae{1 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/scrbuffer.m b/amigae33a/E_v3.3a/Modules/Modules/tools/scrbuffer.m new file mode 100644 index 0000000000000000000000000000000000000000..ed183bceef16834053d178175dc52646931adec9 GIT binary patch literal 812 zcmZWnO>5Lp6g|mA3}G0;bQroA@XbtG>QGv$t*E%jq!q`EO-t)S+;miubVBKbbOySZ zMSegLzn1=nS#;&9xUAqp`~}jDBDxV5TH40@lJo=T!Q;Mn?|J8(_wKv9xU_&vK;|2U zM}|^wd=?0e`s6kwYY^QwLl@Z9^q2dU4&=#==#w=#emkZkOZn&HdV)K4C?mT8Yrg*A z3n>beQ{5G&YcIx@QDEzk%KcchRQ4dF7^6Xa969PTrW3Aoh7*wD3=a}htRC~AT7#oQ zigK#kV$DP?+N+p8OI=U-uzFet64gFhgOi(dlM=;i980IO6%V5+6JMXQW(l`39c|WXQ*P&FY1L7=lag-sA^g*2)@#s$!Q$IiWTLb03z$Nr)MQbBpevF4z6M1cI zhWF5!X+y!I)vG9StP!hIhv?0jn#KuaW8aqvPd`q0NAo?+FEr`*i8ml2xAk;w$+tIG zp9QwPNkAF`#AE@Ls`DG2Ejul9L;F;ZjnSH)w(RY$(Q_O-;75!9Rqxr|b82y6xN5Y! Qi%)#6C*C=)MiI~a1F+A@IsgCw literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/simplelex.m b/amigae33a/E_v3.3a/Modules/Modules/tools/simplelex.m new file mode 100644 index 0000000000000000000000000000000000000000..28cc33738890aca804acae74e52c3636874f89f0 GIT binary patch literal 1782 zcmd^9Pe>F|82@%=v}swwLr909MWhl}S0qAAM8nNhY@}VS2*MQ|Wo`epf51A()TyI% z@YEqXM1+Ee5W0zn4xK!B?h=Ftp*<`y*i5hAH*ZH*p+j`+4ZnTg|L=X@`}W0dPmWL% z)mMv8obd>iD9~d}6NS6ze8-Sm1!}t+)PmjV$Wq8XC6||L-1-xYf;d*U1x|2kr2bg$H;}QWV(2{Me8l zED(h}X#mpKz#8z9eUny{;>$$FM^Y&|`JHsko6|Wg>~NQ`;TObSgY^EyL`F3Dk?=a~p za&-RpS!O9bwF$%t z2%967Fv<1&zV=!}ehoTK*26MUV^RpxEhgUbkCFlAL9{Z*OX~+NLb?K`%@gs@IiJ!# zK%W3^0YL!Os5`(G@Bruqy5au=r~-SyXW$i308)rF2wVr?FPHKhJF?299%8@BG)~Li zoF|=|Hxau(6PrY0<^qzN@S+4%=Eg>1#uPdNt;T$EDluk^4ogYXvE+`FD4vfo6&sDA vAfmHCFI_OR`T0u5EcKW3`AjJ~SAJ43yR*nOp@7ZUA*Qvm4QGlxz9~ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/stack.m b/amigae33a/E_v3.3a/Modules/Modules/tools/stack.m new file mode 100644 index 0000000000000000000000000000000000000000..52ec776911a3359f26aab4f4c524ea4e5f466593 GIT binary patch literal 528 zcmZuuF-yZh6#m+tHAsgb8H$V7MTFSaSsa2@iGrz%)IqVLrAnzDq@{Js*v((!uHevF z#2?`9EJ%h>g6F$yB0_!e^1b)I@7{M@b`I*>m_rgKPYOe0j=sm~5y@}low YQJvAfLI3YoOgTndSnK9ecaj450fBU)-2eap literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/textlen.m b/amigae33a/E_v3.3a/Modules/Modules/tools/textlen.m new file mode 100644 index 0000000000000000000000000000000000000000..e4f872c2b33319d76644410622cd78b59582c7e6 GIT binary patch literal 342 zcmYk0F-`+95JlgTz*;L8lysQX3#O!?00byP!JCE>HYrvVL?{xA6uRXGoPh&SB5@0D zkdiVzLYT3$kr-+0@A=<<{@G=5$~tWgS0Ia^Bjm;VH1J9n nU01VuQr(w#)su`Fk%)V!>>;nm`EsmURU|~Q7QsePfcNkRTtY+7 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/tools/trapguru.m b/amigae33a/E_v3.3a/Modules/Modules/tools/trapguru.m new file mode 100644 index 0000000000000000000000000000000000000000..d096bad3fc5245d96c92da038efdada1b8c75c7b GIT binary patch literal 220 zcmZ?u^><-lWq<+!1t^0ZOfv&XWxvq>e~fAv7<6*}-|$=a@0Pa1|38ku7$g)p6mtLn zQFLH10`lS%dI}i)V*N@LE006mfGvNRL literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/translator.m b/amigae33a/E_v3.3a/Modules/Modules/translator.m new file mode 100644 index 0000000000000000000000000000000000000000..447b91d8bfdb4cd865f0f8e732ce7b5772abbbbd GIT binary patch literal 54 wcmZ?u^><-lD=A9ME6zzQ$uH8&$xJFrEUIKc2qh&Jr!s^xVK)g?xq04tW@npSyD?Wx zo>RODz9&ngnPqP?%oDw|1L7m4cQ~$AqHjaWSb*v~Pnlci3fbsj6g`yB6UY;}2RB5C zI?0YljqSiSi|PwwWiBoS$)|H9WSiW_*{bIl{)4)3+T*JrOSiQc8k@&Iu)dz^5-g)0 zhDyd81e}Dd+vTI;J%%tY?}PPRX~F5vgO9K2yR&Zyqo#>xYx8`II<;Wu2#7kJ`z`wC E7Xg}lA^-pY literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/utility.m b/amigae33a/E_v3.3a/Modules/Modules/utility.m new file mode 100644 index 0000000000000000000000000000000000000000..68cbb230ec935d16534bb4a9df54454e0f40ad1c GIT binary patch literal 557 zcmZuuT~mWF5WK!Pp-=pl>iCXewKMi(+VTTZINL}_VmMTOySyV-2+E|1G~ z1~<@>(u%r+Y!K$klzVwx5Y`}`kQir@BuvCc7S)5bnw17bw8F1&7>r`BG@)mfo}@Wq zBO+Kz7mSP&t!*I*&*lbFZOw&=xyONQ@zrBz$g84uB4S{E5$tX5 z9D3eg>?iMubGqa5E`7&+`u*KGJ%BJbj%W*Nedv^np615=qb6m!k~Nm=!y6VPqJDBC wC1HuUZAV+IM>-G1T;H6Asg4~Z9H7{uM*i-R%+gh6#GjuV_1@wli@yQj2W}p?RsaA1 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/utility/date.m b/amigae33a/E_v3.3a/Modules/Modules/utility/date.m new file mode 100644 index 0000000000000000000000000000000000000000..44440bd0b519bbf2f7c5061b8eae7b11cd38b865 GIT binary patch literal 152 zcmZ?u^><-lWq^VUFa{Tx!2~2r7`XobXJAOq$xqHsNi0cZU|?YYiWjFQgOq^SOu3nP vAT}G2&61H{S_I;Nd2G2UiIs33M{a&zNd`=gt1>kap^~Q@rjmhy52OSDJ?j(+ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/utility/hooks.m b/amigae33a/E_v3.3a/Modules/Modules/utility/hooks.m new file mode 100644 index 0000000000000000000000000000000000000000..b4af0430dc07b75c4d313ef90f29d24699dc97de GIT binary patch literal 118 zcmZ?u^><-lWq^VUFa{Tx!2~3O7});*XJE+4&(8+(SU}>rIe82~F%}Tbzy=iKNX;uL dssu@K0eL*drAcrBu)IJ@Vo4%M8VE!{1OO@<5<~z1 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/utility/name.m b/amigae33a/E_v3.3a/Modules/Modules/utility/name.m new file mode 100644 index 0000000000000000000000000000000000000000..7b3e690c2019b811b3be35d1ddca9365e0ee3a0e GIT binary patch literal 250 zcmYLD%L>9U5FCqwNU?r~zmc}71lpuD&B0Uf(Tkv7{2(6}KgU0+yRpTr|xhA=9mH_2ui}3P`$APlBdwd*NrlbYPZD3Jk_@F z+T^ab0|RZ-Kf}HU`<#`HtwkmgvhK`jQOSYh%OcLoge3_WQ+7Jy6=T<`l2!+wS3gzq M;-sP!8$JN|0>+yxjQ{`u literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/utility/pack.m b/amigae33a/E_v3.3a/Modules/Modules/utility/pack.m new file mode 100644 index 0000000000000000000000000000000000000000..c3cb3220cb77fbe7ebc1613ace9d78ac0c07b289 GIT binary patch literal 424 zcmYk&-3o#*6bJAl6od>BuOg^?6jP@Rmx|jcuY8p*y6CdY9;-*{?8_x6`~NuSY>r-s z8n)n`uV2Jw5dlO`NIw|Hu96d98qUU&NrV*NNJ++-oR{%Zbqhlw8(k}8v(P&eQlKCl zP|8&@6hBWls$PEq;#|A#wV4z?uN4SKGs{(AKAG$*5)?mMm9wN6$s?F0vi}qFH?~Ia zEm+&r+MfGtW_!u<&}H`z>% literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/utility/tagitem.m b/amigae33a/E_v3.3a/Modules/Modules/utility/tagitem.m new file mode 100644 index 0000000000000000000000000000000000000000..034557ab7fb46da6600942dd19dbdae66d72dc0b GIT binary patch literal 280 zcmY*TOAdlC6ddpqVvH-}F}wo_4??glDd4st(HIx*IDkj<2;KINa@*YDl%yuDv>%^*M{766mX!MiWlR~ V@~3f=m~+f`E<1CRxwE!mF+Sh4E;;}J literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/utility/utility.m b/amigae33a/E_v3.3a/Modules/Modules/utility/utility.m new file mode 100644 index 0000000000000000000000000000000000000000..a93823159d8e66ebe3d2946919e1212dc2619602 GIT binary patch literal 156 zcmZ?u^><-lWq^Q&3s43F7ns2WB>fn8{{LrSC@sm%$tFK$@F@Cp5&<$1^0-&(YTvA|a#> QHC_*BSW#k8r8-y~0PMIQC;$Ke literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/vector.m b/amigae33a/E_v3.3a/Modules/Modules/vector.m new file mode 100644 index 0000000000000000000000000000000000000000..0547eeee33c00549740026bf06db69bf86552153 GIT binary patch literal 175 zcmY+8+X})k5JcBo>H3sk>P4Y~1Pm7SEru-=;;uAN@ar{dL42AyFdSyJ)iq>rCwI1i zz))<<1{>~E>M}r%OMNA7jT?vvZ@aDTy_L>uVI6>a(n{73vb;sJpcdz literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/vmem.m b/amigae33a/E_v3.3a/Modules/Modules/vmem.m new file mode 100644 index 0000000000000000000000000000000000000000..75227c5dbbe6f7e660ee028e0d400e50d75ae09a GIT binary patch literal 114 zcmZ?u^><-lE6YvI)yv6DDoQM>WB_rJ5{pwA!g3vRa`KaXQ*#*@nZk12ic(X7Y)+7P tSz=}mkj)5Whg24%`lo>;!gAeHO9B$pQ-d?BQU##8!%~ysx`AxY{{Ui>CFlSE literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/wb.m b/amigae33a/E_v3.3a/Modules/Modules/wb.m new file mode 100644 index 0000000000000000000000000000000000000000..f4ab1d611bc5fdeb09a5c8bc7c4cb500a3cc7ed0 GIT binary patch literal 142 zcmZ?u^><-lV<^ur%1%nnOU_72EKX$*5D;)oNpUPF2+zz*$uD*W-{W!bWXB|(V3{1y`?xID+s7u#7;rertr z8`JHR;I(FYA|7jIfLw0xWe>6%^p!Ob(=c)-5z4@#sN+}&)m*r2)p%sG6%dnvhS;cq zS@4yz{){O>i-F#4^Sr^hy@utDPeXT7&DYxTD&2=0UaJP1x8+$JSlfX;g6QY5JSIwB zc{hs!VFef6QNTfmXedxnXU06Eoce9OOC=MF}K zyZeX79coN@fu8}4jdf>S6dv;c_N-c<_}7UWo2Wrr+~N$QyBRb#CWz|}g>h3yF4$S$ Wk*74mA8=L-TMqq?nY4OB_xlIIKc>F` literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/workbench/startup.m b/amigae33a/E_v3.3a/Modules/Modules/workbench/startup.m new file mode 100644 index 0000000000000000000000000000000000000000..23a4c2fa876eef6da15325095ea70e6d50b378f6 GIT binary patch literal 264 zcmXv|%L;-(6g`GXNJ|$jTC`}a>LVQ zhcSlt{R7{E5&a){T?e$!w9Ww!E>OzsZGFRBk#a`Np_$N_4&e74rPEqBRquc^rP7>% zJeLbfO{gDKwam!qRf<}5rdZCI&}NrO%|*lM0A=`;_(DrrwuN}fmK4WkmJ}!prOhU9 fxEEMiADAOB=y8dToAA8dC%1SV#rJD+AQ|`p4uCX3 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/workbench/workbench.m b/amigae33a/E_v3.3a/Modules/Modules/workbench/workbench.m new file mode 100644 index 0000000000000000000000000000000000000000..2fb69db0e2828024ecc8a1a74f0a92bdce69850a GIT binary patch literal 1462 zcmbVLO>fgc5FMv(8bVc7Rn-Fr4jd>#s45kzDugQ8i5uL+apZ(raIrS_CN=d(WIGAr z)L+3*;>>^Ghm@IJr%46s0n01x%)Wi^&3J5Bb`v&1KDWQh4b;V^0k+D1L!K6y^mWV|6~ni1HP9 zIpbL#QbkhZl^?OZyj6kMaf&M6=un{FhR0r;0+h$5NxCOlYo!dG%AWTjR5iV1x_iT zdswh4GVlFqmhq&J9V5(nnUOssCOyd5eEH?j$M$**gt#Ey_qp&Se*? zS?|Ldr=0PG&r1rLp#;ZJI6VH#;kyS8tEhiAikO_7I%<5Fg?t{T0aZ!QIWDQZgUpad z!FmDW|N2jDfHUM)@ck*ib4{}bpL>R<^?GK*rizKZ=IZx}eT<*1P?pjCWDX3AP`EZ+ zePG)i+!5~1)xDP-}AAVhfBa`m>^Kq0|U!BaV99qTb0GHz0PFpv+jgQ`HX9CU&o@thMWjIt2M(7HZmey?PTBChocBppJQCb(B zmiO?0{v_0S&=dK8Ewd|L>fgC^-qZ#fG8=vK3)M*e&g@R}pNH@ic2|zOnngG0**~18 T+0BqA{`FB54l|Z54#mMAe`YWQ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src.lha b/amigae33a/E_v3.3a/Src.lha deleted file mode 100644 index 63903893588ab4a729c870d659c1be2ac5f79114..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2618056 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⪙a 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%0Du(h!{g8vJ@ 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%0AY)zy|pqVxTVZrXaJWx!eN3SQ;m)$%1 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
-P=zW%G2BCbkc?=wnJe8)^3== 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

+jSadR2W1Cahego%^o0{DGb{Y zYN7z&fng=Xt&fFilfbo3ouGKg2uAdD0fIlR=T0UNJmJ0^HlcLqqap}45%6)@AL7!^ z?Xp@iXpc&z=*KP)^ILjf9^o%?&O7v`c)g>-XHW28Y}TZO+dByoF<@pd`uJ2 zDoxltueB$4T)}P#I6sYb$xwBCKJ&2lalJMb^J1wJ<${(<&o^?$f;0ZEPIeUk$UIA&u6vgI0arCptr$2etJu(c8NS z>f@7~KMy{Aaqw`(9gOrTP|IHXpuY0Nbf!Mr2jAV>C78!E+S-M*49ogcJcoNAqX0eF z?ZJ}MLm3SbruSgIRu6NFAhnhHn)d_~A)d-ZpHmE4TX}TfJApx1>Y*1HRKr>iiye-I z8!fWBg-)XTqZ>XSV66(+!y*lbxCPA8qK0&bn4!i_2OYFo`YkMrrZ6Q9(Fje9O2HOiuzyUhLb_S*7df7d<*@xd{IFf|N zXeU)5b^_FPhIXR|15>+Zi4FlAdXmc&lX!GD$!j#C&)~gihyYq42oihnYquiKw~GcD zS|IdT#0CwDT?8}kWjNn0wh`AYDsJCi{|UaZ|N8H}b&Gy-VgHG80aMb0TOR+w&n&pCvnn1baK#7` z47`Si#0WIqybla3!5#@pGx~sl6IM9gn@UyxOfM~9Z>}e&;Oag}+Lk7ZfZUE^gwh;- z;?7^l$6NA}2e*h6V`tvw1^(^eA8zhFmhs6ygYmRw{xvGxGnfOjDozqt6EN7M4awKa z#bkWjtRl;-Tq;euM`x3hQFNe@{9lk~KGbJ?`DT3l#d;85umWloSDWeEC7n$~i&e`n z-@Y(p6v9;^-rMT>9?Fepq{akLA+T{ml``Yat#YX`d}DZ}?SKZ<<=xggK%vpUP10yT zpfj$7E-+f#60%R$^6Jm=jz? zD^xqbnaz8(D(AwBVVPA{y1SO44o8bU+JNRw@@PmmvuxSe4VN-nNJN%Ki?brC#d&>= z(&oD)A`0sNIrnlRS>&^bXcl@bD(+m#%O&m7EJW2mFq3q*f2@B1mYhA9mj^y8IKBb@ zb)YVDX{J?pK3eF{;%f8;E)AiSJXfNKapWRZr=CAhLrnko^}bWJ$E~hKPnU8jXQfDI zUPWI_P`>BE2E2!uyKG+{IJRg{?^z7D`p?A(-x;rsc6*oEBEO}{okpLEoY9g}HrjYn zgC7&;umt|ueiyd{Vr+EB5xBf|MBZt**Gee9`-V8QhLPtZ4^X=^41Q%I??jeZ$PBKY zbMXasEO6<>-NyU+Fust11M@ZmV=vK!aQ4|>q6uzHF%tM27h#-Z&t9SlWjr&L&!Kl& zq5_P`EErSp^H8@V1X$bqHK{#50-1SMs2ej5Om5y^x6=eDL|*9+EJ`!g(+tOewHT>{ zFuP(PpqZQD>@Wc?8uZoeL;*r46W!;KpB*efVFpL%1a-3(6Wp*1!IUI(k%6H0h*wrz z955(d?m|JK%d?aUbh|L5Y&CmbQ7s@$95ymL#5F+z`w}t^oSK5;XiU|KgXc?2vDx6+ zn&H~Sp-amqWf_MqPVIz_!$&jRs*;TyY-D#K#({{&@NocnO29`IY*z+dJW^_f<3Qpn z3bdi(P>RI|jMEJpN3;E+35fuStTfv=p1dSu#lz-;Ndj{g;-EC?S{zfBH6pkZOTie9t_NF4Zi@#?kF{pSJPl{ghP~ zE&DjgCU@1!#c_u35*WK7knhlD`kDx2>ZI--(lBM)+LHSwRXe%wSu=1^2>Ta zfkaCPYq=n31@`y$ce-%Q;ld@s?eD;?`12jMl(jYsYOfFT+4ipARt1dM*p22^2QF(| zDj*mX(s%|qc{T`du;*7eL%$g_Xty8au<(#4K7;&o&%KW=dTOa)X6CSw!joJn(;%Oy z?-86}PR|l|qwcUJhFB$+P;`R~7gENBf4>Kp_WFri6sGLMoI7O>48c=0Ai;(afb)5YbQmSZ%f;YC{vNsCZYw?J$*ITn%`^!RvkO-1U;p}&#g*VD_dWPBBo z-eygr6%}&kO0@D26IUmcHA<+sy-IuIv~kG1dO^48O=*R*)=qdFwMjm*$azsz0m-~F zoQK%cTU>xbSPp4yY?VV$HVp!tDp&4)RXbJ+Q79{>-3R9cHDX&R0Ki0wc9ZAX7A|nC zYX;jk4ltRoiGK>`ng9lKjF)d?5dk3{QBkgzcM5p;q&gSVJgr`rav?E50+5fCv!Cn91B3=Y_R>PTZqxh@8d#E|!vQ9~?1Z!kT+(3#+Y zYGVjz#HmRJ1}pCLjRP2s#4f=DEI}ekXNHEN*2O+RB7%g*H&9@K=71zFvBgNmpwL<* zo1wyBP>pQLAf_4(8^LVC0!D*Yqys2jiNgbZO0S481e}M$T~dSukgmS~ch9N^;dPF) z3Mg9_T%Ul*(}0<1Khxa8O^_NEPuFW?vcGdS#cvxLYTk+2v`FI zOyJ)3_sCG!b2AA64;t9Okjz8`aMMH+B*&VFK!!V{Gx2~Lwi<53C5Z$h<3mUmsKpzu zxK5bnb}NBx2_-P?bu0!#5?>@+(ymaDP5uVvcx!)qTl~e4u*P-(LhUy8Qk-HSY_1Uo zn%$jV*IgXC$qHe$M^rfAl_4w%Cg`S-gafWEPe^m)XJ}hpgjUIdNu}K9PDGnnWW{#F zh{m&!NKIC3DiIn&pce=h2IV0|+kDEg+N;?!8`u7C4wNIxPK6!i`+#}*F^9zU{AIQ1K!)zl*o`S=^3)#rP^ z$-@!h67ID{4Ns>~+fEfB4NB#$61!M&+q27If&BIK3Q_zni%tXazz+7i1VJuWN=nTi zZowjhN!OCJt`tNn4;6qwO=E2e63|* zfFr`#9zYPWFb}mB0Ud>~?eF6lf`F|*!2aP5p|`-|4A6+3Jh;a(@zUXV>8@U@r$?mie)prL!<*}+yT|Dh8DB$8h#NRZr#pV7 zQ=5o&Vy9JFvV?pwR9!wY_1hPNgUvSlLwB3bMFQ5@-@)++r4pM#0P1Mi`2|>a2a(GPKy`5br*oN0vKrh z1t70WhFXsS+J1>Sa{qf}Z?$y%Quvl6eot`e8O|GtBw4fq}=>;aq zaq0)9*QU|?b;&-+vo_y8uct?aX;r3YK-CwJMzKa1IT$CAMXgS`-<2icw^Y?cH@~4 z@>mTwASR}Ja~4OBp)F|sMU7+tD;Yz^iDb?gnb-iZjp3=z8ADD-N|@}H(USV?r7}y{ zKU=ZWi}Blw8#wDr^5pj#?e`gv+OP0^>7V?GTes*Z_oZ)D+?TFSm&gCdXB8JE0^`O8 zUqwy0hP-`S?f;T@zpLzyRC=2-u_A3p(6}IpQIHWDx*&CAX&tN)Uw?9SJ%YK)1>}c+ zQ1(bp3>Ml3Gcc%9Tsgn}PtmRPT21c$T&!Ef+N20q_-0!Gl&VnW!^ z6GEm1y`CxBbqQ&S#aL##yRLkpf<&xfKAO^=O3H`WjMJBr*S@F)gRXD(3Z!|}qr?>2 zi%>)~`5pd_-YLI^HViT5`L<3z!9~As^^1pYH-vKpCX?scX7WB0F}Y|&Pj&`Sw}8;= zxs8nN1%eF=5aZ@L5Q4Qw2fL~ek+D9BNZvL)Xa><3|06WGMDKTTBc@|qtFmTiZK_HS zdstpu*Psv*NNC(e35sz|1HsdM5D%#XEyC3l1dpH}WT=s5sjD}n)D&pLu9V0=+*P?N z)vhGcxad$aQ5%zt#x^IR!OQg?Onyjnh8-m9swpRf@_j~SynL3KYt>N2jj_pSf~N-} zD)fJ<6|Gk7p>VI|4oD<;#Cc8*dyxs{QL`~O6yzEy~VA2KT2-76Bgh=@l>sv`sB#TDwj z)$c!zHFoJnXV5voZUKc3#ecK}{;!`raAM=4f1LqItw{vURCb%9)B%nj(_=vLwG9AL z%ZhAyqu^X^%qgvdgY=TB5vGF8c`3}Nh+kYOMS6;r?aHPdrO7Zp=cJf8pKP6`W|1XD znre1$lvFms3O!+PJNB49Ot(BiKx8TM;SMMr2%QPG?Nd2%Mg|12j6PM@jA5du!SWL~ zoK?i$KPGM>>8XBTOmsc}(#!hn0r|~NXs*p;4gt^g`oPn(Klk*+Q;{f;>egU`PYbqB zDtbateR_gu;ps_FUyDvpRAtfWiPx{Wr)Qt_HmXn0KBQ08rzcX+KRwaXWR;nnj5htG z%NC!W)En<{dK%f>)6=NtoSsHA@ANdHIMn%(XC&fy1E&rC-(9~+`%~M7doRNwoE;XH zjfWzme6q8`X$Ii1agEY*XC*r=jEr7(BUN@>7!_?L@yuN{F_zRlt5ANR?WYIv(h*9xGJPE6hjQ?K%@d7TgS-?-nFl zjvbAuDLG5fhrMyt0i24!&BvZas02IPQVD5X?S%JdKp{vY>UcXEQUQ$@7W5<4(bYnY zq%bdBH?-5Ilh<l@0=83pGb zI5Qg(=T`c}>sTW~Z3(W82z6z0Yec9JA*>O02y~Etp%H zx-a6VK;-=q87EG?kjn#A&dnJ|AdfMm5EJ>-PtkcjdS3JGX>shL4g zZ~`$U>%k+$+)FU}>2GE;Zb_#hwEmpq31B)H<3o>R$>voBCxT%vYx znerYo$l6M@y1{NS+@8lL0Xv6J0(LQIHL#N*BUS4bGtwba+vGFSg6RnnM%jqB9y+*Cu){MK9`Zm%gi$<_ z6Bflp{(P7fPI(pv(Vr28l5X~`q>4dhMg|LIw)%y>i`*jP^Ztr#BBRT?%Hz>$9cFvU zW6}x@`RIr5m6sVu>9J{ZA~yX`z335Yg(iz{ixzv3+JuimYzc3?gr(2Bho;dbN~A8g#doe5avrAWjxK^p*oR(IfU zKKQoT<~DnP>cn!JJOE`fxw#!csWV)T3>eI+8-q=-qRzem3Xs$|%hI>rEDMNB5FX4p zE;Kx-8=+5J`G8PRofmT@!Wdgem|VK-Z%Tx-hNrm{l#PJZ4p3xPmuyvKvRCa8O%|um z{96FAUgdIF9x}}^P8ZU%sua1hWn$&+l(G3t&aS46XXf3m6f5!m#`tWxW;aqehn{m0 zWec{d`zOVy&MTJP$MCivLrr7Ev)kA~|7oSTfmBQ2rYpnS4TNR{i6OH#WtUp$IM2DH z;RSt<)4GV;#vUV!D@NEZx#=vqRBay>DLs4Q$U=nh=76a!2(RX@h$qNi(UE8CO z0M`(yi7gZc#+ulc#TctexXe&CT$QlKnb<26uOCDns)M;~a^h~UhQ^Z0GE6KBU?_Pv zx3FIYFFl~EB^77T$0h*m^md6GbgD`gjCNh9tsumiS7;uAOS*!Tn8&~0s&0q%m{nH=&8DUko6Hl@!nLM1mzX|x{=|e#v z)IQb{ir7~BSW!$9lHmmRzbF<%qP6#_#+jSICa5290;_%)5y{CK5QZ>e;)NGpdVii@ z>;I)6zIBU!@>-vH>2>Yqqv;tgQ?Pj#$)ql;) zG5p~+-}VoG{$BG%x_y7N1e%YQRy_1?^X+hqD9@MoDASLYCY(hf?GP76q$CO?z6Y8t z{p93)bb600-Jl6JIYAwY>EV*9(L+k2p&W=RX0eATj8~_q?!C!4HKC9NJlX9GVLR5Q z^2fy{w8n=wCsZ$O{7e;E?T!6Sse7UMO*R6(C#Eve0fn-KD?(zSLE$LLm5`6n^Rb9Hs>B2JcvZ(fp}v`H**7- zpSPiDXiQo21+L*7?lN+}1Xb0=uuC;xKqDW_-H;8vUF0ipc=#rh%9?Gz0&eW?wqYpc zQA<1*!MIBf!8|2T0q%7}fW(O(G`A2ds*rseygIy^C)pC4y1j*_9W?)@q-_fp#o*UkqPDE=957eNGFo37Zw4&;mmg zL7%@NE#HIf^!N0+Ydp(CuFd}VfttYu;dZ0<*?yx3CjSBAnd_2mZjdH+|7lo-41o$b z5MF7a!#?137Lc~ts@LpOj@==3PDsyCg5e?q<@JyaW60L8VEHB)0m0%KsO3KV8+@!k zzJ2Q!{pK1i9Zk<)P2gJX1gHAsufFH0p4I_$2yy;l30zLkunJfrosJNQQjc%oCOdt~ z&YvGI$1AIfJ{z6iyuvAUb2)#CLq7~Ax6m#-bY(WO!#$piPT+>AdRF^^v2vt^>JhSX zJOdfeK$17?%GDu9OtD|kxz~`uqiI7uF-+T|Ia`IeASs7g`woJvu(7ZAC#> zuWz7$s9##++S&|ceFk!W2J&DA@^A+7Xa+Kxftc%WtItfI)@J&&X3exz@7Jdywn1Qr zUVl%Xjme3V9j}6rm5k+T>op~i9mS5YHfeQ(BZC&bm{GJd$w~Y3)gnQsL#4&?EC+kU zF2_=R{akD(>kcWFf(*q}V)+p=4DCxe&MsUNsjldoPInWwRt<4sm1UaYi3#BSEbAkX zP??)xQull8ZI)%Rp=L1Ipj}1!x9PP?a5!gj{s7`iCgx_?)=p4dRW|x$Hhm}0;&Zr? z?L*8XPg^D;mdfFO;h|#U^uoL*eSH6lbi(t4)@cPQ@A@Z-1G9Q zJtOkW?2ZN;<&_^W2}qrj^%w}bZ|n$w@)$QtJoFmh!Qh?#5Y~n`M||=UHDoFnO9;(F z9{|ifdC)~)np6(Ca62XQtSjl>uGt6fi&IzuS=S(i7m;<%0Zk%Ax`ab5=hvtQ7(UYn z4CP+%iZ9K5>P7Qqn-$*BB47HTxt?KFd?KavC9*}YlDIE8*-XSI|wV+Zr!^Euhs3~ zI{KX@7+@`hxwiyE_MN5S>(hJe9vE-w_e!X~^KtDvOYPpUy@W#OpWkIEFWzB4ps3n= zloCp4(n4vpT7!F6r&DSQRagH0Xen&hxM3@!P3QUu@&Fv5!l&q2l<^bl%%+Nard&8U z%sl?!a5{xeB#!BMM0^phWSs+(QKMW?Ydz~$I95!hua?@{(ocPIJE^R<8qI@^{b3TQ z`-VyIo$dy1KtP2HCey#%6KI%P1W)m_SctBiEYtV{eUJm(t(6b3(Md--D$^scDCar9N@~ z)!n=Z3@&Fd0&WqQ%^5NeRCaWF_PD^w9!^J>$Ha=M#RLPQnJ`UZCYUoDh-Ts3yqw_j zsKt;y*U_h?$TGlre250FCA|7uvT^jT2>GYJYD`t#0w=-+P-QWLJp5njf2XEb?pG@(ka@!`T zpL|6+!^`8J{MI*_;JI;9%uSDE!sf%Z9DDITowhp1)`H!!#W3Ep?h(?Cb)3yzYQ7-By^* z(7wY~L$|(8{W_UrO^i+E25Lo!tv1g=U{!Bsc9>G-Rwq@@+21ts@_0%6ZR&iTXRmQ{ zWKk|mli4#IO@{fEhM_22zs+|;e>Fa#mf8M9LBPP)gaLlV3h(SWtEz>$t`s$HuOScL zHRGrn!U)r@W5d)C{*_?1y$~J5gTbX6Q8C1Zl4v*@P4KWoR0(Fg578y>vbLoWU4mtG zLyb4F_4x@%gbA2fF3c4A$B3jG#Wz(Os}WhKFI3yhYzV5mlo@e}-O*{m5D$?A zRkJpmEq+ae?;ARY!rW`&Ne+Hv5*&^O{_x-7s{fH6xOIzuQuRNypz0*jSswqnzgAKG zjK?vaCfKOHzp<;OP8<<&SI!X;cbiOoRTWY;dSO$=J0G)3a}UCLw((o9QY$e_P=&|% z;jeIrkXGg74W7tW>^VsRb=_7Juv!GHJ)YqNly?2`Da}my^gq95<5GN9P3e*?w%yKT zx%h;jdM^nn{H+J@oxV*bJYd+f24fPR1V>7Gv@lq+G2;M0h5JDcrZUpr00#yiO0=)o zp4Z+0`;>sT=@BKKh6Z~m&$mJ%HK=WVM4QSAFy+3&r5SXvCLsL`XXq$P1={vUIX;Cu zEPBmeU5z=wMRf}kHE0kK)LL2kHq1ZcAcj&Cq%{TBkZ$$%BlL5(;EJNM}I z>shz`T!`(6+)k-Yr~*YcJbMV0iBy^|;R-=uCQC_f#06?|39qK`x33x4Vj9A)i~?PE z2@Xmio{=2f#F%uI63l9kS}_RfFIIH~xFuE3<~IEMQFKDrSC!r}lrCNEuNg$@u^G7b znIWKA!Q6#2*-#$}&^bxy1Be?< z+Q|{$BdF=;O8Ze^KU3D1&*!MbfCVUAh{cX zsxx3UdWT^*mOPP221Xv;PZ3(s`Pnm?iz!Y=htPA#y~L1CP6(EiUE$^kCeHAvG&&u>JvzOC->whp z#>4?ApS6i2X$SfZ$*S_+S<+;=*F(Ifd-(im67@n@L2V1FGm;K*_T19o-q{2)!IW;2 zC7i&oT1Z?d63OJ>y^37z<(U&o)VUxI-%0ieJ`Dh&s`>B(Fx=npbF!NV?mYBuRY>kU z^i2sagyJSmxpIiR=p6BC(b7%tLpCi31^oDk*xebC>rJQYO zH}{(0-ROKpmnhawp3S}9Gg6i|jGdm0;lcJ2Z3G!fAt|F}rn@CzwCw*$G@NQ>TMoJ& z0b*%q@!YL%87VF_tzO2pZtm?te+Y+yp^SB96uAh`(8k1W?qLSW!DeaAqypXavREOr zr(k5ELiT#Q2^klZjdtBo!!@26mvm933*vM@I>z-o9rCK22FKY4P7UUXw6x%~Iog7_ zv*Vnopn4s~dDx8O?9X4DdyLsbSX-??7-rzqJG^3zZQ_(0n z2S^7D0tuuvuEfNc9_0E~7r)+UDn_$9n{=pOb3AqOFs=EAxr35913vPs0$~P$06W&M zy3?Rl>enEYfTt(sQ!H(mK|rEebh6o`cB|)2yx$dOpBp?gvY6JNJFp-mOhabI7B&Z< ziz@r>EoXBNw<37pf@><@0^HROwj~TPw1~(eNt@-y8?u(6>?a;GLJs*>F@p}Xh~FeB zBDZPRuZDSo^}N9$O0Dp)6JW^}ka0AduuB2!Y~AfP?%ZW`Fj=NyAHd#2FU=efOlDDb zh@dl})08C+TLJod*oN>E;W1v~DYS2nbymZcK(5Ov$`Yc)Y6aZpo2LX_9*sA#OQBMrn~U?2ktC3seb`B; z_sFw^9VcsHCSXs)7R%e3=NzU260@RewgA^c+c6u8Q+cg0S#tLW9z}@v|4$JVuG^t4 zliW{g^~0ngHlkqO5(}USS6u+G?^S@fxYyFd{(=m!&gB#eyVzQoomj1%0c3&Ef^jWu zGdQth)DA5qOi@q}QBc@tBW2Cs zdER&_f&*I_1e&=VgQa;shid_{l52qqCY*|s&I?T-?+k%E2ObqmF<@l+L6<>mZSNWQ z%cyJ0fD};6JF54L;(L+8s*8dMX2*v0y;IuNAr$5*4C`;Pr*Fu4U~;9M{GaNbQAJvM zE!A(_Vl~{cqVyZ6L&$88uO45HkFH1OC#NJjhNs2rbQ7(*z(*nOeNk{dg3Sv3L>6Bm z(VM(_bpcs8#PEN2k*a|Psi6?m{Nf)(b){+u3{%C)=+c5yGm5{%|@4B}|@J|%?gIi_GR1!ExC;Wk1V=>1Iy8D=X)V2DOSY=v9} zNlVBcu+TKTrlUniXU7;cl0KlN+B`UN)xl1Ji1WjD*LV_rpGKz6gUSO5htgBU8Qv=J zLs1YAB{2m{N7CP!LIzx7%rB{)J#4|%`sg$jNAd*}vZy!&cF?ELs!5tZkRVFi<@i{= zO3*Z)eAnbH?%=p8Gg0BNo;f|mf+5!xQrqbJ7XfH<A$~z3yxZ5MnRB z)?9nEzUn7Cd1WW_@U_*o+WMMHoB=040#EL&uOOd}^CCd7*#R9o{C{Cv=ry}3)q|A> z_4^$cGNaan1S8rbZ;r$Y-e0}nx!-gr3yB0R8oWgCp%!HQAX>lQzW>m@TPP95-*K7; z4+}JiBszp%AWW3~ctg?z-iywj4UCg?NSHW(AR9jzK;bRhB?(9}nj#_hSDa)dz{Jgi zV_D{tl}we$MMqXU0hEbOR|-qyFJ=k2 zyFb`$W3c>T42WT~Ia^@@mQ|SGGZiM_Y=sFb6~29Y?VUWf{T@8F;U`D)A1Hq&=RFt) z^Cy4eH}yVFrv<%r%hu8Ymsj(yr_Z{NGJUQ(^GKg-E-IzZb?;#MyzgC0pAWo48yf_u zxyWAtbvJzzz-oxUC6Kice@h_iPki|c&TM5RK45&TvDAf$WK-k{f z*kDjFw-X3xteOH@ed6*cfvi1oIgUWqp9KGMoOAZTEJP2$WZRk)&_jT1MG6Q)aJLN< z5Sn(!4MP(Qau;u2g27#{x9}x|L*$3qWpOyg7~l=Ws{uo7Bz6^Ix9efQv$yqf7Yg3U z%5J?7h_wuA7hQ6w^Vxo%!f&{zUk-1eP`lBhcDN*A3QGm-BD>dDnD_A>f(Wxri0bMc z-GS;SG~*d)ors$_AaEi8O4p>5r9Pu5f>;j{D1syFzMld|VpAkXFeCCuiH-6pZWlKr z__&{qqys(%+_<2x+zYy?)v5|hVl>G{^UC7@u}b6RJGSgpwsd?tzIZ)7A4lNH+4U4G zvnM!0doG5JB;cK2;x+UJ(G{>V~b?}ViYq&6bHN89=6<=8iS&FDk zf$%4n*K_kUiqec3TbcXu_-JxAIu)h*{N3{8a(Z)dHO9Sc1Qxk)Yj|}zI+{zsNOWRV zx>?lO6s`g)YXj`u@_=7hC(Wa@Y)f5fEpwqa&;Yvq+36B&2|zUIk5bbQR#*1~ctP z7U$y=Tq3HYbIh?HHESWO2jaB3c`y%-q^wm?<0~(=xqhKjeS@{cXxWYtnD`-F(kno z(O6}jrU_?7`X)#uR&|i5b+#tA&IWEKZ)*o$@+4x6)d&!}9>D`d;6WV-=EkHcN2BY} z>6EM+R3$UTtRhG{n+jW8;T%%819Mb87AtvIt%ACUAMXEY=I8JJ*sWXin=5KNoqm0a zn81kY@(=zy6&!s!yrHxLw;-4A&{X`%XXcznu%`v_ELv_vU~SM#K(F@{ZrsG5K(3z6 zm_fp@8Lmzy#*nuG_^!kY66uWDunG>Q7f@dl*=~;Nkw*e4C`Sw!k(>KU<@hxz6;n(@ z4^63igEGyIe)=ntP3B18VecA4jLR+f7mu&=_ zgEn1B*v28$&F~r%TPjeJ0YdoVITtm|mRhI+-ZSyonk~{#ccI=KTIV;lfT4!@{0xZH zCZEv(C(ZE%5K!6@Uoioxt?*SAklX^lhGXbc<J5UyRospr z_zGq1MOzyRExfx?byBvrIu*v*h75!;hoYC|pUT>#45Z7fcC3Pd3_U6+{<>CBc*s0ND)TZ8rnNqyxE3G5!DhYEAKqws_9|*Kj z1CEKhqML{8>+TG=jD|ONS4S@+(H;JQ&8jl0w9UKM-!dZIA@8{N;4(7ZEAO}y;xaPX z_uY|kMw7O(I}c1`HiPE*e8-&x&k*orzVpDuW-|mbk?%Y(aa*9M<-<@b9S0-gaj2CJ zgwg0g)JjLf$n?N19SWnep{SLPh0)nq)Jg}#=wvWzrK3^PgXK=GbT|Yr!%-_85229p zsFevash5t3 z(IvL1bVTYlBK6V{5xk5@y>vu`LPn%sIwC@mMxsZSuGtAqq7lNEgcb~lMz`h9g$TVk=4=>5xk7ZYUzjwg^b8*>4*qL z8j)2W5t3Zk+ohe<44su>F}RI4ZxUD;f56bqHk6EZoULGB2a+QAr?VrGfsiQePAyM1@sK$tvZsdG+_*x-Q60lTQMDKRl zNao(^at%5HkLvf=-8IkNb3`WVF5UZf{ik-j4&Lq7Db2la?{+__NAQ|~*I-+twm@wz zVCi0c`9bYr{bB9lYCyuIwYGx1>dUJu_4SAAD~~+G&MsU(0asgD4jzd*y9lIA&>Xnc z=)nWh%5tcFXO}#V5)jF)I(wHl=STO*J!R+B>2!LDKfTBSsh~0P+xXvaJED6%?c5`a zqI&{=bk5`R=V7c)KN+7256Lt>Vut;0dHnDFO2q)Fxo9%&KD-=}-v~F=)=~DiGJ4-m zhSe%P|DqPc4w83bioHYj*ZLd<(9!AiYHTnQk?|;f@>5GtYE!}OLhCQY^D!&9UoPm$U|fLxRF<_NnwDN+G4Lk0D;LSBFrsH!@9E&6$a zYxb>fyN&S9!~XuD*@o%$2Gn|k=)07Hef9eOJWDg&i^sCzIBU! zKg13_Dl~DSIeJR3#mnRWZ?XG1J|DQ%7_GD+UR$lt>ZP$ooylD5W3d4nl8xqkP_ z>**A5?REqvehTvd5+$r{xVkH}L&=Bjlsu&C6OC@bE6Kqd#g#`qHmIqRHwtXIM_*AB zb?$Kl`3S&XfoSH^4@!h7TM8b-ckKDpGt;uwx!l5iQnaf1K{m{JQIo>|w)UIwgo%ZY z5Y-q>n-7NCBqwor3o&NUFfgPT^yw|lb{RuyL_gbG5=LBCa!JOC8cItl)`7fZrjm-4 zun34gHz_;#e%OQ3Af!8F<&c#msNDvHjKPrA6H&}EEWE5BNi*07I|)ybwhBBE)ep>| z+wMAwT%#eHdQfI{oRkHvIcR>mmW<4%(&<)E3o&OZG?Vp}kp4zuIhhq0XE7}Ygo7cmg3(xrXvDo)x8K-ePkY^?%-Jjrml=TgRvnK^N;G1@v zy2^$|F`w;s<0Mot^)n_nhS_GJqA=Z|zYFf&4mQD%HD99@yiY0E3b(nb7%99^C-$nB z3b*N^DYS4~HG;sFOwS->GP1JbCT$6625p2aRD#16Sjs|G@E+goLjgey)+lwMLgc8A zs+!F0h@x0C=@hM+-Re@+xNpPzZlbC4#Q!Y%;-w(m~a{O~X#{WY0*t z2Ua(G4uP^CZ?LvavGyNrLO#wK3=u+PA73a5rp+a69=vR2QNNzL!GtaDu2aAwj-Hp~b4O=R(BBwf<7IVx^4NA~)t^-aVMz#QO%WW;AyO^$2Ofe`2eLis zYTYBTD;MGSqr%;2C2B{-os9k_r7Asli|6U}5WUUnRgBPcN6p|H;=Cd=mN+t_}CdE@F?5 zGe3VANX{4Bh5{fmZUp1^KC=&SI_)@^jdPA9B7r(wT_Bi!sz9l8p9fx4>SLt9CO%XDphJvj31 z>>fPd;7+jh4G;oGFwEu+!SIaKhNU?A3;IFzU+3}pzcDuSlkxdSXUAtk=1T}Kusr?` z+7)9Y^8{njg+2tv;?WwcM%J3v=bFV#zpu^qJ1w8-&0PP;U?)cC&y&O)X9jOyA3_R-y4H4RcAMnhYT+-u8+syJZGR+7h`CKIV~IlLO67Ev>+x_lEkb$;(q&^zw6d5 z`boe2BeVS`I_AscKmFG$I?fha54JSupe9VQnr_37o@>G)3J9#f_4@iFTY*WJT>DNp zw^>imWN!&yhwq_wUaDpO@y{&npMA9Sdh`Y|vMGE8AHzg-37)i0&dI|o0+cK*pRo&J zba<{4{)KORf)Zu$FV<{7#3oE$~piyry9UouH`k+^d)6l$_iYrFOG~#^~eD~3RVy3Hb9cX zc(IkNE?xwxW;Y2~D{-^x+A&#B2}j|I3F_J(G+~j2YJ8W~$#AoEGSvI2kk6WGR2@s} zE3@{-;}2No%yX>P!yXEz4D9LnSe1jXzJThW<7cc*vg0>x9wc{sob5SP^?xWY1NHxk zcgTMVrwaWlnUN_eBf|!JdEEQ8iak;f7h@R7QD)#5Vd4vYLYS$pV)L|H6rc@KFx!Nb zW({q8V98D6ot1kze%+%sf=^n3=ErN$$ z(KxTmlf&x~xJ~X;iw1&Fc;Tves+W&vZ)P9_2$iIxMJ^iX@2zKz-$GF#j^yR`C zGH7>_+5Y;PNyNZL?hdvfieh{IhilG&)10vw0BRSaH`-uU7|w*MCdnSM_CIo){&8@{ z^piGacHBHozl1+-;_R`NFOPrq|6JIt%?@ND*eD*X-CuVfGoH!fy<%x;1fCzE1?Nn$ zE9@b2VqC(X2+oDM1lO;z&R#8M-yQo|hp_ad;td#7m`hPR=GYf=f_8E@6@%Q7jtVJG&Y9)-hO;sk}3pU}& zB+D_Tk!Whr9^)~j9P@-B$FQ>7gz7I-yCy{CImk>!PLd*VtkoQqD@wX;G}QH$C+*J(e#31!X%{}P9>{3 zLejELAedxNz6&YY==AtvqA9VVLv)gXNLp$;#pD{teyRx4<311F3Pg5EARKf0r*aSV zFM6*U5=;Etk?1mldU|pls5jb{m$&iTK3vZRMWLsn{>ixrs#QOT4tSZVONjP=h@D$ zCEfRYtM=7e@=PTgYl|Oz;6QfJg{aNeCxH=4d2egb-`|7=qrIfTz+(u75j^5MG3+%6 zxS4IjPz+fM>krEoULE_}zT1%e8GG>lpd0gID7}0H#UzGpwR_Lnw9|X02FJT3`HLvz z4NJP6J%lTb@y$62>@=Q|f~mbPG87IqX=ib*QHJ8Kfn9#5?>eIl{=Bh^2u_WiW*cHQ zla=mvp)@+f3}Q8!{PZcbh^XAl|_Y;GpI&hoR<-_mKgVm!P}fV0}M*LYC7Q6?*@p6mlyUTe0J~wA1nl$@}aa z=AMZbU1XUEUR6%6=iY}e_~e{Z7~Inw(Sb6DB%GdesN#t_hwK+9xCQP2l_XV%$bG(v zCLdV4?8pHt08YPcS^@|y2l7y1vvL>HzkzqhUgVJBjT@XAUNM|(h~oqnfQ3UQLGx1v zjwTME70OB_wzYwie{N7)e1N7S$fhPh?fpUjpt0g-fx&8i5*V!R$AH0B!~U=Nt-0lZ z(ZNR3J4Xp&jv3o6wSnbjY>NP~n|o8x;dByue!Bta;djH`|J$vvTZsTIMzXvHfMON||GTa8g=WtAum6zQA z{}KA0e$xLXZ=JZuOh!;D_~=&`_C3NBaNn<^?_H@tGMMT25>*bGZ7X;y*6DUQx`FzD zdIE-+hMue8R~GLcN&*dp85on1w^FeGU)d#1C}+TMIu(R0hj6=uyWG+1(WPFINPbUX z`L3GOtJ!|rAT_%J8vs{21cZ}=;N2$y`>nuSCK!93_Z>x2i-#WDAGg4*J#8PnfHIiv z1qn8Y9)A;z`4Y&NKly1M`ag|6Gc1&Mnp>j8_{nCeALJNm0qa)T z&#{|H=+BN{t&a&p-qvx!wbPYgqJZURGhm2JjmRKihcn6!T_zF69?o6u3ILCX5~{`) zFRo5VEI>c+8+#fA$&!LfqacwQ&x2p$5g*_YfqpXLS$I^471-|T>dQlnIolg7k8f2y zIMHN?7Bp(Aw}FzpYjfq?FT8cn6z4N-}H?;ZYcJlKws}o0Q9ZlIl!)`#bP4M>*Ks$qHdS zC%=9BXC*4_FJXV6pY+go7WNPhN+=R6kN@MU$h3JE;naaJJntj8C{Y=d)h;KiZs8WB zvIxp8jlAPZ?UoVsr4ms#wz4t`Qsh5)0jJ@bk)4wjWYsn5Ao?p*Gm#&6{2f=_%Cd5@ z>a5_c?%=ciHtd=;FI(E zvizc4J?0eQoQDIddMgVrK?6-sWw5fr@kSvoZFLih9>W}E8=Iu+cGyK42dv3Zc>W0} z+sq^tEE*dx;fe?@z_z-<54#jsz}mu=w2*;Pq+qDN`_3Tg0>*^El17>({^n;JM@>$+ ztO-!frDE`E)@;Gj$W}7tnQ#!KGcIh10SnJf&k&-^q=*3pw^W3JG)*_sfTR%i6{&!z zN`nmRE@BPYaaqwrc)-Erv{8`=2#a zDmrghilVb|@H{AubBPIqUJ6dR7=v30Ea0G*p7@cKLL-33lxTx(8@R|zQ$mAWFg5p` zuDH?(h}_cb^N@C)U}okqIiO|4B~wmwpP6smh?&X8HX>H4gO&Q4*B2u z(f4E@^y1L$HX4Z;n2bh&Qx60iMsOGi>Y|hQ`|!9yzqz~(qyt|qkN?2#dsgl}d7BS2 zCzq&Bx-loib1^5kQy=w&tWqvyB+9~&pCMuqaXy4PBx~@;%)rp+)w}Z}`ICVO3yFRg#+2>!V?9w@1hOkg1LLYg?c1lYGakpNH6Zr|ZGqk~8(e@l5oCyI@AwM_fzc#|8=vIl zuy+0UPHh}YB|BhBz!(pOfh0ZLobZ$mA-sf+ZkboT7VJdD%ds~LAo$X%*IRWsRa{U1 zyqvv*_BLc=!JM8lsjaUJc2Phh{k#3}S9zoRTe$JkPd1axo>FHrtQg^B1k)XW74@P&)EqqJWd&LOrY4lT(-ip1v6;ZT+g2lSq5%+u!~+w_o>#&X8ZNm+p4ZgTr@MxLk$J;j!3L z{s{aU(NAVe=G(|;3ppmzujTQt{e_D8k{vm8-z{;a;i&#+c-Q%#!CKMpck=^gg?Q!+2mbQ-H-4gG{t!3{W<}h# zO@TP+g`Pa)Ijd*jJgOtWcsb%nex|pRCm=Y53D1Dw(__0!@^0}u6;2VL=@iMacaB^d zL>OW2xOqCU@7`Yh_qk`r=oR`&&txwZN_+L?#q|1Qx;*}szxP31qtzWk|7mZtf6yg< zSC>D7q+*i0mUj2{C%?fp`%$o*^pl!pFJG7Aw{O3MUDfmw2gF}~RZ%M$AlUsk4=A*e z9cX~mRu15M*l&mm3cQ7a0&Ah55N=FCA>^2X9{QbHL62OcA%PI3$`u+EhKd=RqA=Xc zY_cc}(ZXz=C=3z9?24^0C{36wLt)UFFu{nzqO)p+L1V(04TU`lQOFXkjzD6?4z7c< zDz>8@y?kq0xbrTyqYkylVms>VAvT$&MFg~BJL-snW~`smAre}#9d$%QGp8bnZgnMu zDN|T21S(S)T$9fDq{;b&ORdN?z9KF>?02Z6LMgh-? zZCoQ+Rk4w4RC)83l3KJzl{Y^r3Z%*#bErV7yv5;GAXVNB02N4;H_s^wMEo{aQ^Vq9 zXJzgT1CSU-8K2J^c+s;y0023`|BWvk&V+0l$f?~YC%k^HnizcpztfO?J_4 zpG5?r&jCS?KsU-}EFcsd)@LgKknM(rH+a$Q!+9B`IpMazKzLIKuGJYt*B9TR86;sW zZ80$np7YQImnk!F10H7K>c!R~138|NZBh)Pl;KdqH4Q`4-n(~sc>%Y7_}|B{;FK<3 zhSGe^osRaPNIe(|Av}-HkOt?g&EB&HqIx9SSyJSxZxU1(!gkX{nmZXTFNtZNzOve3 zLauHv-8QRCOvw61F>h?C19a;4*#0^d46+xs^TMrsD?96 za-bt_T#~rS!R+j121-3Nn}tRjpCP}x##`bnJ;3Cxri`4NJk7xMdYlkRP)7IQ5=Wo} z#`RVkO`qs4{hYZ8Q;Uu#R%pumh|N#6CJA^xg{9B90HpMBNsf+rL#FFv#r+Xpq>f+_ zsx_ht>LSK9^yZ8JN%0DkCqvO>Le3a93izF&2#|2tSuzy96XxRNEW_YCVYpI95LnKs z_~^|D6OGERK1@XTA-m0>2g@{4I1VqC41*~}i1^H);r=i@Gzy4fKpWG?AP$%6@;<;g zSdFnrSftG@1ZQH&obC{`yb%c%EJ`>O@X&y$d=Zc~If|L2DVy}JvzyhQKzLe$h|e}n z0^we`6^v~NL>tBMWw7BxR3L0;LWGRi1`GNHI_Vt7NP_aNNQ(0 zHG!mdc7PK|YiEq40;zU>Wl-o4)eHScV5wkySp`t4$gaayE|@?27?GywC+9(?(@IO{ z%fvS=kN@mH@y!l|_w_d`hk+fzzSB+M$q1^BY0q4w-KIXU)1L5pbY@8id*cFR&XcS8IEDlnvxVyylS-oKw_x{3q=o0Zv!5^Sfxx3j

zqbup)jv!S@JFYe)42PO#Uc2R=6cwmjpOzJ+(CIUV`t32K+q}1 zg8D0_@8Rb@*xYGodQH~ppB@;xne$wh#X4s2Z>)Xi#f$EqWT}SeIIQG=c+oJY zR47TdcYsWG^72qKOUpiDrq1G5)4X=yF`&i3G*$G2wFKNZvjEVX0iE_{z=>_ImjOQ5 zT-)}!6JQ>^jHN?Fa4y|y9TV8ag*l&{_J7)5ai=8kq`Q}N8za3L9`*qbAWYXMp1g$K zG8t*xP?fUT&5GW2Znw+hSs;e%)4!QMEKBvR>v0S0e1CPSwLn&aFbemqwco% z7n`$oKSc|_v;=UCpqd8r0d(5aF1Y2@%`nS$n`3<%9|L4BPPG9A3oM%Kc^Vc>d}24P zs|*k1WUyjb23?rVkIzKxKw(Vn2w01sclJNM$L?&>*L}C?E(XAR)~lBL*shV6y|Ek*jP% z7N(1Et7%?4b;PpFK~<{&&g;qG05fe|Z5vj*ich~Z11*}a^!HP|rCD~ju{YaNfI za1dJ4By*ROV3L_cUZMu7jM;Q{;E79);9eonlT$9SyJAX=gp>5|mFAs=IrSU%L|_Vb z-xax})%&1?Q#O5L+wMReHrI}Hji)n7`<(-Y2KD;DRZou?Kim4ex%r~G&AM~JSegl7 zn5h&-yTVFd(TYCY+I+mTzQ#3N2vpK=opgl-*|`IBIF0qB{W0RbCmKOU)ljjluMihu zY1V}ZkJv07yoP%u++MnN^V;>BuRiRZo-Ov6u-QJXobExGK785k-Np-bv5g4WUhEGJR7-r@{c6zfAJ#ujyW?!v zC=G;;JM)ZJ(LRuP)%b%gDY}s)nEqKDIw648^}5i|c(U2NxA|G~*7EfRmyCSH^mZB} zQ#*ZQW#t-<)F3H`5F_XrCoJf$xgG@h5I#*8o@mreGI#`9*BEJUY3W+?!RgVUzsqEA z?bGOB(B5w&RE@NX7tQr|V;-wHEca65y@g-i&o8;MafNU4?+1r{Xwu-!s7MklWiY!V zvRRhRD}9mUAZ>C$tdcgkckxPMCk5K5_l8%1_hwT<#7Lv#V%MY$;)xL`y$Up5%5&eV zo}EiV(MQu1yLG9{F zD9C}UOT{mV@Ji{-3`FMp_;YU|R?Nv?4^rAN!I~`%oCD+4!UX%{2r`(y zd>^e7UExndXP>OBG-mVVhs~wMW$`*6ySBGQKTltCc0}3<5PZkv5!w?cBUHo})C%T= zjtWNdG%Od`8Z{{jL+CU^*G0x^P6FE}E4Qfvajojk?5FouxU5?=wGxyr0!@Pw0|Ex0 zWt9LfF>ym=9C!tx_BJQy{9H#+El$gDxv6lVAzI8QK&S~);`F)d6Y1cf!%<1uZTELUtgx%WhgNTKL6rxI1nUa0Yf1pfLnHAHXshu8DItgn5n~wYs9gsgpM{%zfy#g#r6*wv=j!i1YXvwdQV4toO`MUZ;Q3K+EcW$4{K-4Du9 z3bCls`30MdM^7=UJx00+4YffjcyS@l#tTv{SD zDatQIwEg+xoz>3_7a4f=&eOJ$r*26VVi5rcv^&FNo#cd>NcB8zDcvXBcHcE9M_6sv=YizsGg{TB$ zC5&>2uh_k|rvP9S^+6G&8Zuo~v{emf{qd8hJKH{*X@_34afoS0Tv)x|yka`7X!42y zq3I0Fs;I#g=m86adXdpx2<70ftWCnWpl#$-a=*EMY8puar3B+?!g9k{tJ;cM-V2&L zLMuIa=5>a%MS^;#^^WRH+hgzho(>f>Si z%uUwO7BB?n%(IO#zIuY`Yyck?BDO z{R0$Pum@;13Ye+w*gD8Oky+QpTschCxC3PE3RYf$N@PQqNe(;y^mN)E@>^gFvbrNk zG4rbR^qJR;Z2hEZq)u8v13|_=QlV{{1cWgeuvooQOjC(U8t^_|-zdg94x{zvD-f-x zBQX@LWk6n?SDyrTwHyS1a;nxT|HKtw9|;tFc#?5S#6e3)(5C?R#zV37Ct8 zgt+?$BM2D;qZu)>g1Zh2ZW=sr1v)K+XJ>B`##H?yu*9K45WRA{Mn;;VF5W!QjnIWI zPFLISGJwr6SOCmyk{;d~2D!`|Sn6i}5FiW;$)F!;oYGY>R)ek}b7ZRRmrU~#$$Fj8)v9n zyGJPIAdz}*pPie#^Ch4y?3n2Y+MED%Nq(^S5(8Wt?QUjZmjdPm>8NW&oMD^x!o|wb z3o;X@ReIgdzV+$ssyc>&^z6);S-NK2J#iDL6A%$ZhcYgSKw9$HG`k(ihQ8A56A3RK zccIx9ZXeiILNSSxgV_xofYjUvnirRmWMV2{4q{!)*JuS@z=iIwiAED*1`I7Op8K;upvEzX(4Py0E~=?iC62zn;85?E8e>bvis5yaiJ%9^vffPJ@vR&`F8i@gJcU&OaO26dWw z#Lc*wc{gjudFKSidjsul_V;x38A_-`@)>~Iut7N4*A|Cmmj{&#Ii)IoD@f80&C>2~# zZ_hkHKvs|#4Z;;zOoTa#Vl=^RlfH%ep#f~y13hTYv#9T2w);ii#YmV+n z1Ev5lsCz;TE>`0g$ABfj`$INPe1cw*9kc0fO%IcjD4QnyyMKO5t3>wavb~s06D?Cs z4EpD+b<12kB>HRNjc5IXFh{y>-HSA@!ovfpc%Ih;ADv)8~mNUge z_XEt1xSU9{C{Ixp0z~BvQ}GaH(#lrn-Z|iKU)BqCRe&EoOeRCZGvR(fgeRkUwA(#! z3}YQd0yozxpTGz9)!h!^dAdih<>=XyyHLZ-)1{8t?X_}H1xC4D(BFj&>5&^S=uWvl z7+|s?WaQJR38psNUYSJjk=jCiV2X(HQ?kd%ImE!n=fvyT>mQ$&nG3Vf=qKti6^@kd z$%%utIyP2@#9Fmuk;t+LJQk!Z*DJQSdk8)ruhcs`c7CO@VU2#GQrE5uWGapea52B% za!odf6g9dSN}~$f4pJw`!x{g6!gt|F!44Fd2*d)siZzMaYKsxIY0a!Vs?8mPeZ_9x)e9luLZ59Kc`WZd=A{(M5!8!_BZM-P1w(27Bq=wLGVy}X)R|6zv+4b_0-ACy>PS6Gu4>Vs)RWpO)R+0_ zz#K77V>~8wM|NjiD~vW#+PMC(0MSjK_4eSvyy+R!HkcV?JAolE-+X5UFqeS(Mfw?R zLHrB&s+%NYhtxG?Y1=>ffs+HARn)z0m@1o^#=69S$2%yube&FGG=q)&axZ52$pBfQamPr`VkdB#xQ2*Ml9 ze<{Yx#*aF(ODlT0;e&%nBOI8cF#&01(3Bz6?U^og2aAu%9?vX!6<0cDb-l(lR5pq5 z632Oi$c)4bLw|?gf!js|O4ym-Y#m9^TT}~=V)k0OtQV|gb2ilArh5il-2zgZr9?G;fzBxrZki`u@V_GwNHtzO4)83m4iyUD7|7e9O;@A|{lk>z6XDHSKioKM zc24#LE^?>!LT&{t^NRY)AmYu4;U3DL-&`FEps8^h|Kx2YKf672n-P5ZB#V8Tm3ErT z8d53da-6n}Y_!Wa;3$sIxko>Icgj}KsL+UyVWx>Ya1=?6Y{3yCHCE@J!44c3#wTvS zV0VpAb$Z6WaZWFoSM3+vxMGcM*TNBslDy&{1l?@^j6KYb!Z#{pZ^^c@OnTT4GaC7+ zboVJq%peChIS1Ht#V-_9s?O?+toZw&P|-%-@Q@Q9f=(?Vfwy10fU;@xW2NQqpa8=k zw>0|rx8BkM@ew|un9D!oEj_|U2m?&!FNzKA1a(xgG-*4J<{8<|V{Q+l`7hnhvBRLJ zqs88ap036|b0~N37Ev~Hbz#SN`qdC6W6RnOgrw@Mhir^)04n7Z(*moW55MK0qRyn- zbozX5C?P4xKX`OqA39HK&9z==9&4bqzzaaBgd6maj0K#&i}7%%L=q_zBgam%^tS$Jk;&j%a7p`MRSh zv*nujB;}Ulljw=uD7ixNqI!cytJ}jNzG!0{AdJiOSq+UxPBDhF(&nSEHoQ`$ScXbb zpE6V_u3O3K_mm+gSOumL*HF^utRlD1S+{MYwI0-xCb$FI2$X#itmfgp0aiyqH5a=S zRx2HhO=;6$w`F8Rr?ZBaXp|qKFd5gvFy+~{;~Z>dl;K@g89OqB%S5U3uwYIcS<&&s zpctyCfP^~s*T*`rP1dW_dz1AoBDlcYhu@|Rot84avyz70OfOqG?EM6y%dl-~D1VO= zt{n6a=TY|`sqF2X;1J7O3_A9qc4uHp#}&fGrb}VysHD`yl{Y#gh0!QBLGJiCA{6{< z9wq^ozHMm5-t;p9U8&rgfh*;Ny;3Lej&x*n31qGAqeLIk?j@+ON`8P~k)-d*U|53s zpBMGsWSzt~!cLHx^#my)V`Bke+JM5vf|ChYGJTo^$NKh*z;P<~y})rwEO*2MdO>E7U2V#>l=&< zu5555*!=OU)tR@b)V+?}Ay0CH6pkFcfl7pzT~~+dH~@4q2f=W}!GW5DLX43WTk5-x z;{(p1f^#Z5VpB}_;F75P!*4S}D%b;o&g%lJd{-!*RHsH>gW}}mDTBX0PJ-jiX}kd+ zkD%jR?9FhTvj#%G1P|}zxNAO#Nv3nUK170L#WO{(E41XS=)Rl@0yy>G?|(%JR|dx# za^sPcPp{OV$SALb3H7ytFevMo=L2ho*edE7kxmNhEwE}8NI#~?MO{Fc6XKo0K}YGy z5o$Uh7Z}ozbl!|p)1t(9K7Ca-FOIrL;{N%9Dv-201ln0jAULSM^%qdKsY{Xbd~Dvb zYIaAM#x!Sz#hq7`cr*jAJhA(>9TZQ9t{5AB#1TwwG0*0^FSH4f^vT-R=S{r7_P)Y} ztJz%BAt2K+NH?rVM>@;dz)J;1g^pNg2-=Zm%EF!Wq|06oWniAKYK|MzI=zV)CyN=& zt~17p=YaK_zsAmoPpTpi72E2E!o&T5F-evs5<$$;Mh%y^HqE|mx>q1Of7D&P_|`zr$@Uf64 z#_7(u0YBW0lXI*m`X0V$hi_cKEZFYT$4hp%K26%;D)yH9TUjUV?w(q{Shcln{DJmw zo%dBSCy45Qjf22lnNVe+b{2UR(PDRY#X>&DGz`_%K1_BhcQY1KYFCa+<2~$)sKK4~ zn_W~&(tp3|4mrr}ff=bBhqOH%ptgI&&Y96zl|Sr*oZ9_z%BT`yqBi zGl?3R6JBQzE-9_4&_eHuJ2Ag8uR|TpD8vsI%F`}ko*LGIcRB9t8OxG&>WS@jH>ZE% z@QeWG{}Y|h8`RUbKT3xjCHR*A-tj}$EUL{(0!1yuWIQo~9#rC$2(v-@n{h-v|3!#G zo~l8dFGd+VI_+fadU5I@9oq^HJ2*>m4L$ruKn0aS%XW&60uyWJSW>6^v|3m;0=;E~ zBuG-pytSeD4VMFiuac*0)#c<^$blK-3uC#QP&wEP^QrGAG(z zs`NjFCOiQI%q(CKTO=iBlatHEiDh?XSjuE2<&&a7Gsw1{S6eU$X4(wEARr`up**bo zU9~i0e3=vRvE*NbUHc)QbKA{kcc9K#r5Nhjsx zav-#&SY=`N$G%@<_kty^vAGy4?LfM4(l&=oEl6gRPwGK)%C>W1csBWQQpXy^SVMt9 zt9_|@z-R7LIH`A`NECsvI8d}#Ie7k%7t9?$n#F2`?$AG6dKPiOZjw25ESQ{omMkdN zKkR8*LPdkcwkrcv3PtaJ`Pt#itikRcU^aVMubRv5Nwy*@)yHz!6gBRDrA-V3cvIxV zM9ni&b%23?P&%&1M;?whPWfpu+4&qT$bBd$4PaN@5{WF&?sFPknT=kSZn99US)du%LQ^p7|va&Kno?d6Pi_N_Z!uypK1=3NR4XEXeY7nOkbBK!23k$N2oZ)N-L4Whths< zomKPX74d;JZ+Hb&?Z#DCYPo9H6FDTOd$4NLjS7cD;Xqw>Cy9V=3C`>~ACLRxn#li` zz4s5U^t|r-E-6|jZZr<3RXa*z$1fpT0J!(!*Zv>{E>^^10WM@L00CH%GM8FnfeS1` z{1Ps(#ERq$f8?ZTo!U(`88_qUXvV6eN!3(| zG_BgI8q(X(_nh-Q?|UzR<%*&yrxi#n?tS0q=XuU^p7Z-bZ=7O(Irdf}}usM9J#Q^X*R+#S6SrA_JedZ-AaAU8H}1l3y5C10h0B>@hqrh| zpp&<&CImDYupyU<N(ZZJUZj|Z83Tzx_YE*=4{uN)dWpzeW1t6M;I+;)N+C9o!8T) z5pzdn09}VC&ba$NTHnBekQ(1S0ydW;ZNDCBL|ROLDTz$iRyKoV$ckcnSVgTTz?&NC zk47~IW651CAS)6tTxik2qh&jxbsYer#3lk1q^Qj;SxTQ@??OJy&%L{f&>$g4y~Ks@ zrkM?T3_eSFtGDnNBv+^_rqm|G`ddB?w$FZq%%=Hx!V6Ka7`)L!oTQ|#aT7^7d;wY> zny*;^QF*(Qk0y6lZc-o8^3|!i%BeA^?5jHQn6aYh5#2D4TGNnWx|MQT2;njOWfArZ znZgySwk%;elLBr@3WA>Yah0xDs6?0lyi^x~OnELDTFE(ohmtHAu=}ss3+?O=7=rP!cq@M=l1a zIKFVk*W#5Y`o1HL$+@1}#v}C75M;Uu`f;FJp>gg-zy`H>kJUwyYyv~EJT+Az=9|z&FgYka0f$w8U zOV&HBzVD7qiW4Pqo=eUlF8-NzP)L+CR+Ut+M$*}?=;K>ky7>!4Ga9M1Kj;P>8H#?> zTdi#AN)Wj!o^Vx%IBIsDRC`e3de2$OO8db8N@1p2&Uy!>#uI3lU<6zRAy9e`MQU>g zNWDiY!d1-ia>8d8P*_>!A)M0?j9{7kEX-$G?nz2F7&{J=>_Y>8yvg8XxDXh;j%bwl znlJb=TG%_D8_w&1;ys+2RV#{h5XlxjD8Y()Ys|<`O1Hd-C$=Of6%hEM>5y{^2;(V} z?V$t}0Kjw8VCo2qQ`tJP69txr(OcfxbczYinvtIacng)CFmzlTSkj!yk);%Kl6GZ$ zeN$<=5+UgDQ*cNGl4q_D)zz|4NuaY~>7Zk|Gz>&+<`e_Z3qs&W&oKAd4s(v`LJ!Ek z=6Zf)l!s?8l)x=s@0(o@E$*aPL*Pa#D~dah6+d-VMfA|q3$(;<6(Dj7P3 z5Lu-Mr9)OYogfHTqNI=^`^!q%-!J^3ks&p&EgZDrL@JcZ+=m9S#f+7UB5X%ab#l?t zETSrMBi(GtZ{bjEabjmn4#f-yNP60AC`l9HGWsM0vuzHo%9hWd9}+gDN+ac-cw84x zEpY>#2Crt=5?`zSaUC1Pzu zjy7Xo;@D&s zc4VK`tZhjvM#=^3q!2-wTuUNy%3fT0a0!Fe5_5FQUec?yVea$y_+C=Q2ii-R}bwF%z7qRC0^#I#@smuXqosU>ZXhRs2)f*O0LZ12^? zH=EHdbit^?GIF5jK-CEk;C)9+T|DuToT}g_vb1E~W%$4?cFr6Af%Rq*D2>F ziH)P3zVa1JW?dxbUmRnbdvJ|u`4@=iKu)zksP*{*4Van zqMj&ns9{H=iRx!Zk1FTWDMa*LxRrO&<(T(isdh`kr`K{p>_o=KEpDffV}E%cLabNE ziLqCEAad+QO9{(Y3ns@mUb4m*hWVHK5NOeMERJGzjHgMaLaDih7tw(Ed^p8PCqQTg z}rE zp$NN`w48#bu>iFamgyu&!hcD;eDKmRFFKZ%auXbgDZ_p>ZDNeh*Mp_3vCeiECsrbaIX%J1;_HK+|8U8p@By!=>TU_#FWQY67s1kf@ z$27}a+gJ`=-Q|X4H$qYimYSm%!YflHtFA>cM1_#}B>o6c5HtanK*X4+P$+{^`g(#g zdFp6I;(xp7jZZA$TB}!%Kz4(!-4QM29Bk+zjt1*nyU3W#dxhICq*t)(WN#x$umg$< zO~mVMF!nYfeA)h@+rc;8D6h+bIfy}w4R|jihG+>p7X& zmR9#Kn~gVC%=D!B4!C;H3)H{WBGY@JD=&+FuEVs8FU44`9>Ok}wnv`^Tb`l2r-utV z&j=tM<>d;aG@lsu8d0uXZYkxI69cI~S7pPDyXRzwLB9=O-QgLAgZt)=rwb3h0K;}` zhq=u}G%355#8ny@2Mo@ipidkX&%ShdECOR8Tilc@-rn zxN@{Y(OFsZ;ovY*5TNuUy1(A`wgc(xCrdD${bUA|U}=csD)Hz>phMFU4ZTvr4#eurzATFypqOVli?ytLn6O^G3N0F z0BLK@hdcw8+NLls1EgER-K3rIZ_^0Gnq3Y)Bg1LAg4{KY__VPbW3Wlt&8mQt2+7Jc zd_|7o3^jr!)O`~o*MTbzHk>q^dC@@wDiWW8yVz>JI01zd3#w$0)H1!QSw9LUAx-7uUc>(LxXs2+AujQV?%eZH zcRJW5QEWE($+9|oT>E38)=plam9$Qn>`-KmO03)rGH6%T~mMRo~*Qvej;gnql^L?P3Zo$06I^J&yU(q88u+3Qd=Vpn4_qux@8k)0 zQiPYHy=rmcqRKJI&2@823m8Qqe;$RdEBG`4F$&l--j}Wu4lr-MC|T&KLSj1wAbcNCi+pdP~p;fLzP6EI- zS3lS(!x3&4)P|i{8i~YzjRA^UhXOD?+q|i!&sTN~sOyaH=%Qa4dh|rxq~!X#sG5yI z?MmJfAY5amAt^oxxdN6{WROXFAWq8Ib9`@Eci?*J#EC|LP>f>Rxm*DS&X)DDGy)>I zT$QYO(Mdp5{&Qa64hA6(w+mU!PGHRRCV})05*s7c#nKw70~6HT?m9*sHJWj!QRp6Q zF7n0ksqQSV4l2|3y(XJDGYxFfC>@|2p5k(ywnA=j%?pou9E~hA(QZ;_EHH4+*22mW zoup6(+L(?_cpWUhE9$Wk-OZ$7Ou zjY9AE*WPu1dy2AeG%xtOAvN;GkbOC8jf^6j>fsp)cAvG6pYyWC=j_?f_&2Y!+r+ol z9>3_@-_Ze3TEsy)YrKsemL$bAAp<&2yX5*0*Fwh3|#;py-JnN$*P}$NtJ45%B)N)$PqSZdx9w zvv=vP#d$xQS4fLGLb<>j`M;Lvz>U`+&)h}Dqv!~o+ocXTf6v>~B-QARblD(1D z4O#>we@qt=62!D@lkqg2?K)h+ppyxeMG>`wR0&o(aybuJ0k(kc1tU!oWHHgMzG{h8 zV1tWZyUEDKKLLpdXY`OW10szl4m4c*NYoxwOr%0#z3IU4%Vym%IOwMwv{1r9| z#FpYS?p%_1glJYoNd<)8@^;nK>f%a(mv9?wD|5!L?(cfaSsR}dC_CvBL`=F`gJ993 zhKSc$7Ww?4d3-2I5Bnlqz*ui6R(2oPrVT>9t>qJUvegnNWaqs5*hQ$nRW%Z>(_iXU z&rDkPHMiH;R`<77_9V3dmbJGfn`dZbT!&8sxLY_=1)^*8LPRIuXkk z)I_Bcp=KxI+dHLy3aMJgxn-U=ke~36qege(}ZVGk{PPYz7KC8L4S904Rp4n*wE5S%H87;8?Gya>1mvBiY&dmViKq znO13}y|%##^W(ymTYgj;!)1sTp}~Sj5-#Ad{Z?M5VImt{x77=@)K=g9V(ZyYn>!Xp z!V5N&^rq@L)E_ZE#=U}O5Cw|4&D|A6Gu@*trJ!aDOg-Bs@^&&HINc_KAO}h4y=_fW z1ny!?5EWRmm=e)v^&I}Q>Dm)L>R5YUqyDP)h086_8;1$P>r;)n1DZhGL;#Fchr;A= z$bqy)N_0@jm5V!K$$D*`ei5)?d&e&2oRX@nA!(xn|I{h?3cKH4 z1&Np|>jrVlWF$e*0hXL(K>;J2Q;9Wu%K0 z0rn0IT>s$?HrKY5lHe#E*Q+hCD-la`8Gv8SN`lHVh!jF59~W$1kRObQOwv9;DTM&W zglZ?ke!I=kY^-OKjBg4ltwEL1G(Iz(ORB7J2@j#m6`frbk#BJ=qw{absl-<3Xq-Wp z!%^Z$kn4p00hEX2N_Jb3WY(!!676)UB{MrN;2N(jQVvQx(=saAoqO9*Ec)f+T8~fW z$cchwXU_buh0AN2Jy~Ok+F}ZHNTMjrn@~(WCZ^!^S*Sb*^NwH)MtF>(bJW4d+UbXd zLuzLQGJ+dk9ofIz!0McN8UdXq=<&1yLgOT}$W&Qvb~9Guv`0Z`K`-d6LFtgSe1Mx?8zT(QC+r==Dbg;>44tAsJm zC-_xyqU*>%ww0t!%Y-b5PHG0ASy&zA*-??p(}urC=nrPi#KeSc6!zJ>v6kW5Ku6JU z4jo4HSy4~KCUaP@@jKm)!?>cF$p^nS`383sTZH-vcj;T3u0mV26&px1hULo;F zo@6+6PZoiblN*EV>|NP1_C%o^f|QA#j`OD(Z*ZJN;p&U{DGfvXE$y7j=IE-VdYwNpTGbWpMRQ`YGUcFRY@L5n zVrQrH2+6*W=}kXYR^!_v&Vr=~IXrk*OI0ZZ2jddDUhv(Rz9vPo3nHZ;?T&axq_opa zAqhsWv(d6iPTBRrx!wJFI|sOXM)70d#tX8Txr}HhpZ0<2q~ReEMjmjn8_HN=NK)@H zI*j7Su|t#<+RA@V@!vU9*+`M23L>fXo>5MS^9`uKVUs?4d8v6uI?5YATkko?IYDXk zK|()$)AzF{bRduZdd~>&DM%kBx~h|N{O3BPG$2VWJx|dTgTLU#^?5Xp|7;qMW4BFW z7q^jZml+Jpz)dm3PRWfkuzlCT`vUlhEoUl2lG)@Sa@HzI{1to+=HFR@*fK%FvcElA zN8>HrMnPpz$(aN-db=OG9L5bw$af!dB|30iLx^fAAK^w6?c%32;1x-) z-3TN2iC$=lIPw$xDhT6ZqJt|qK2wf{VXO74|44>s+PPIB8Y0|?CkH5jZ|>c0 zy>=6=t=QT!cbfTg`rb{O(p5?3LVz`_l2Bbrs{4_nQ)Ep-s2006z86Fv)MOhIRrM&rIj@pNVx&y*w83m z<+9-oSRhG+_!9=1sT=nm5M0b%cCuj`*}Nqj;?q&R((T(gYf_F0UG&8_p=L zL-_bDf9DTBg{}dAm~c814rns&gKqxI6f?G^gKVixg#~bZlKKsgD{osTjN3b9D{zIU zh-Feg`6_FGnbXvnA<42;ci$j|WGLf=X#m#N)<%It;?Fx3ZZU&;^1Ml%Fj9Ij(!Qfl zwl1(H0+sp=43M@XYgaqw%1Lz9eUQ*wgjV!(+so&LmseO?H4YIKOx#*7j8Xnmag?%kH*Hm&JG)9&Y5b88&wN9GxZ zf+Z$%$+zy(8jP*w`j^VWu9Oc7h2(xHJ7o|#UpzYM(GrysWvoAQv%?_9K(S>TI0G1Q z98qwY$%3f5BY#~C%6e7HHbgal1hWcam|qzY28ZN1w0LBk82PYb0^`SfydFqk_57Rr zIU=C82}_QCBwjL4IimQufmSKQ*Y}EZbupIa6r>OJV_)pGy~>{o`}%RWk(zLy+p#jK zosKWjaM_(oecVkGHjZOGryBa((Ug7BKh!tLE_a`bdM{_;+$R3o67?9>*L}gA?JE+VECC($0Qbr&3MPIY3L1iSXp5xd0l4e2e zNqrI80x$CvmCtz@y;EBfbSh<}+15a4$30fkxIzrhIx+}HT0|JRJG-18Ybe^*T4*oD zv?-=WK?l-$q0&kI+{)JyCt5t07>2f~e-|AN=aU=;Zyj!IU`pg>0krDGvGut2$JS+_&Bt1P~py?J=$SHSp3z5dtJJn}A9&O|zjk9FbH4i&+GR6lP z!aI**{DW(}q>AQR)#t=~G zE)tS#uHkvy>1W|74LI*-M9CrBuC{^TnzMN9Djg_EQ9xqd!_`+eO=CY{`rr@-lFp5| zB)^=6N*bf zrNh{nRH`hw3@OIFmqXEX4~)yi>%^o?LWGPDg^Q#$xqMLO+1Hm(iO4BrZF>#&Cc8?g zHs4}Nor^K={3H&H4h~16wZ!A>?aTWgefE$=`{+P3-^9otgYYKCRx7}wf}Q5X$T*G7 z={JQBM;&5Ewk0GZgRscC@uVk9$y#L|y^6uboLkI_xF)wm<9BJ=yvik4x~!B8>#z@I zrKw9#zlRSakqL)!6`;w|$3-i*e(y{6z&QkO5zPaZRZ$%M=<*H5yk+U|#e*XvM$4EY ztu!&{=xLE+H#yE3aVbGZbdIFaB%byr4p^;d>}Fz&w?v;L0gEtiN!QZP6)(uhC3!

2u-QgvzH2JRWm*sVk%-v-E>6wnq-ik3!RK&$54&n2Fsoae(8t(I44WY_3((b~ z2;lOG%$8SWOsU@K^_7gn^y`xZyv5wawW*;Av~^2|IVfIp-Z8r2wo_waCDMb5nl&BH zNmrn3j75*-qriNHhD5ZQoiAO!(_hu+f&K@!a-zp)Y?BG~xRh=?ybnP^x`!OSEJ3c! zAqg?ny4)fW&DvdR!U;eq<@?6%soW^92)d=KGt>mEA|w0(P%bT*L->Q;;X z7=Q9AbGS2)Wgi}ak_sWpz8L@rnv`R^{dC#ff!3QuZ5+Ci0o^*J0Go1m5e6{ zZt5MQkep*06_@IGQf`XsScu1!)N1q(Mur6ztWwT3MUXRx@c&h;0vd#KV3keHgNi~C z;Y5Sg;7Uu1L5&MI|C^-pnH@a;uCKi|0ulmafDQL>Uuv2QOsmG%!l8 zuv1DW2?qj?y;(E@+Cp)11@(?S5-eakK^X04*`z$>#4w-eXo?2Xu_6q}lBc#PN4{JG zp*5?!IFrL2M8Dx~=!R_+Fe0xWe(4BWI#75fzVD551d+b2?0YHJ zgxA<{FvyE)mvb}Hmy`?5iYK^=7#n9fN*Z-(dhC1nt4iVMXyRK;bjNdm2&Rk!n?tApH9;~FCyYYzaXwIPWku5L(1sV5IQOqJ~%r&ihq z#@x7SSbAIYD|cA<@zcTA3fnE5gZ&>)z6N^>%w%_EUlGnSm>fGT(7Y4=95W%`7XD@6 zVOoXm1&|sA5&M4avk>+D6LHM^c!-U)@nD&a9>3>BR2A_z`K0e2-2=EsIpy$)IB=}DxJMW?A{1kFSYwxRaa7rer= z1?8Qww>bGjshXq%NQ)JBf^gKrtidL36e&A{VUEQ|xx;tRO;dw+C+D!}Ai6Y~;2qz^ z^9h#CT>iAoI$FdkF(~fYBR*|I#v9uxo!+yV68T*NRImtN<1%B^mCJjL@~0cZ)Oy`K zdkDYNspLoLCM1c_&|cGv^|Elj8XAgaz|jQ_=FM>*1j#sNtXUYmZyj#pxdzh$@V$?% zO%m|4oKUM=BP0i7J~-p!UPJYsHcVujX1q}KTq0fRx!)dW)ZI5v6I23l1EYLCZP{fZ zfczMhbzm7F*a=P=5+d6wVw`M(BdaUY(dQtD0NV9evT%!3jc zY1Zs>?cE(S;Q(<{a#wctx$~B`;TP()ntngDsI(1#`joT{5&{szo_&mh|3}S#9*V#G zdH6r%`TwfFjicHlPhK6Y6&Gu@=3~7VYm|DTHur1y#y0R^W^XFq(7JW9iIG^#ckaKe)p~wzaO>XNpZ?;#Z*P38v32ivdK>q?-T%-*?T+B_PkJBW->(Q> zPi)=$Mp55*toPH!lYCp``Cw6B|5h(`nEfsO{&xKRvi^ReaqlY|bxOU_JIVLI@I>R@ z*XC|GECcR0|Ni_heaYH+cpNHfm&a=J z-@NzjiSPdC>&2r(&(>;1^WJy(`^a96e;?JnXMeBuV{^au_V4reQR=+?>9;m&4?n&4 z7_EP`*uM9jqQCYC&%dGPwa4}zj3L}`uv!@%+PDedFiPctqW?|j3`H{SWWN(=HIy2q!=od4k0HD~K(u-JO% z>wC4w9{UJ`s(qYceXQfj9s~aHO6{Rfyi&XO*LrDNkfZ0XQ0i+MH=qA*Z}Z;U{`~F# zWa7I&@|#1C+SnWKeEZM7UHj10FAcuMs0{i*>d}?jkGu_}9^2DOeTz5We&MZO|6BLI z^=hqli`uVS?QcKPy!Wkt`WNZt?cw46nzg}`#kZcQRiD}ndA@x7xmM*P^!1DM_0i{P zpBelIwEv^;bNj<;f3G(8vSIC)=fC*}wKMEb=JoZ(w^*NVt<*mBXZXD+yfmEtx^R&h zfBn_kLx1hPt=mJN8(`hk_QP+`?(fn*tMu?5pMQtH-{p6W&tD#D-uvAla1}UQ5q7F9 z&weMKY3zFTJ3RYxJp1u@=5Z@m3bgSTMaLya&0t$SbYtrb7{XMf}Bmp%-BJ@hQ~ze=g!xnHT;Z&KIaE*Y17$ zm0E4^duXA)$lAP8`-7i3q0YCWSM9NCul0%VKKz#rv%Vo{3_oTVt55y4hp&D~rR_O1 z#lAfnJK`hEKs)0xu=S&?+V2D9AE&KpYwPW@E#5!E`@g4ED6wcsI|n?fO;e}G>U@Wt z^L1a7v~#+jXf(bPAKs_E$9%r`etqJ*5B=R!`u()}UHsxZP&Lu%hXdbhwY}PY?Vxty zB6N7`oo_LTkA39fT66u8qlfI%;KoNEdAK&b{UlF&cAogs+qL?afA*EH9Z=4m|7-UA zBUdl~`M>{iwA2do6+*s)Xet}eaD+e{SEZ2^9`k)mRj3< zdtS8V+v-Il`Khfnx6ok{tMR3wU;B{1rKd01tDf|gzhT>}RiDw!eXN+NGWNh4*|c0q zYAVGBlB0y0kqh zg5@q3h}EynU%5UzRrEz-sJ=%2IAkUC0Mpf0dq~kPNPv3USFbND&QD^X+1$aYyeRB4 z#k+bnrhj-cGo5_%h^T0djn89en04`~KXsP4#lFVbr_@S;nlAUzzisU`Uf;f(p+ii^M_yZ{m z>2!ae&8m3f20A|8jukgBHBdw!ZtV0mI;*ADM<;DrewHQC?>E=9EI;10ES1>~wjTM| z{K9hK%TcdSy|^&HxLg>NE5&?}f`>+UZT|VG!P&x=vN53yE$N9$G)6}ICx%sSc4|Vv zwQ`u8_V4yDOb#?AR%TB&Ss77UH5T@6;=(4epcY$Kf}#|bkt69(x}hg@4)8R9gm z{mYx&C%(t@I)+%j@e#@hkQ*vEe|B}-3!*l5C(`Z_aVO)0o>} zW4Ar~`sSP2&6ma7wCs7F@73HWoSG4h4v*YzBak+e__Op;OSTr zfMg2E3f&pPbw>L>(ayg1vT3nn5- zs6}~FB!K(zQ63qLEiNpss}9YeDURy_EGc;82?KO1Mc?Y}!<|>}_NgP{LgSoFyQJvX zEbBT;XKzkky*~HTpB?ZO3bV8mBAsL@$*@r6?m?@GpKx;z^tT~ns!F@j?L^@u;{=T2 z?xLrggUy30_wVbU;_Dp=Sa+FT?edh4`H&?7TATdpaI)S~f-s#iBpY!xy!*dLB8m!p zZM(BB6X`x>a}=~7b)Q{1-h$~Puk zo;j4n&;SS~mz*FysV(!AT?Dkli)AO@?acDd$i#2{R0%&Es&YYF+1K7QtgYgTmJo8K zM+xEerM`h+*&eF6Du8!{e9J@+-VlFD1%)bU?rDRI(%=&%H0~lyy}>CJz02V4#vxSk zHhDxa0CC74K%MlM6u{89J=TU!xa7dzDl&{NEWykQslU|k7dAH6<@jWtC~oH<-3?b5 znek8wUs7a=a)pUpV^UN_vxQ*VT@d#u;!G>-szdxkUU8>SWuF1&>aMToA8T@LI5uE~ zjq364E%Rd_J)q^j!D(a3j+u5bWy!%jQJ7zDT6&RQ-@)_`sO}c?>-Ye{@)i@M8YDn! zlZ3YY%2+*)KNp+$E;n8e)Mxs(88!Yb7hn(YP(U}3ezA#^0o`11;dh}fVg%$E8?r*lp8`J@xp7UqV4&!}=TZUVP4eL`+qV(oG zb+`@YZ*4hm4KUa;@)hgqZ)9YcgM4RymvkA$;u@XeL%asp)!l1xe)!x4=8M(^zdT|U zQb(KYE8IBxKh<&g#_4OEBTT1-8|us8_E373*w6?5+f|=);85APIUbfiJGVUXVjK)T zDi>zxv2i;ajqfew(>J!TyjU#H7n4^f7IF3FXMJmBqdhh|KlfZQ@QgRNaD8!sT$kQn z&m?RCiW2BhKSbjWp9!>3AIa7Y-japLlIn{H$+~PV3X#PU2ei%B)>;-n9JDTFBt-6N5qWd>uXQ;_|htR~p6S#I@&~Mo(UwSg@m)SU(TkId&bI8t<7X z=C04qqVL%!1-CJ*N>(YR!bf8MT|#4(b_&kz2|Yo@Afra!uU%hS7C8^5@o{D*;L-Z_ zO50A4a5N>Ihx2;)5K=%Rl%Ufi$~t{>a(;IH`r^_#fj>DvB<|oG47gZ5T)~vQ8Pu-$ zld3{+3O;?m=7)1ZPH9e$pmedlWALh^5L0OA#_0h&TcAqn}u+s^WLR$%dnV_KfbUy^Zdl}6kLAnBReC_|4&HbuFD3V zqa*GP>`6RGfV>q-Atemv*62hUuq`3s2>XHR!4K`CP)rZ1hz*DOiM;kl3rE}!8-f} zzpvGGA+Q8NK8I-hhUe$Nw;TSLG?sbKrQJpP&SB@Hh+v`v@6f3 zX96K7O)q#34sv5q5=xkEqlykZU~M_65^i4lP)3Q>pzXAh4 zBTqUa7rCT+e@91Tg%b0n(sua#xbwcTVra7=)zAu${l~rAa*zuDq9W)aqVYiZQ9M5} zJAy&y@fWCwaAG}Q>9iPd=}4@f&FkzF`Y%8B;r8og!a;D^4u*+SoN$Zg_52F_=; z(~d+~l{Mm9^ZBLeyDI7`UPhd0Ir2)(0KA3HWeK30YZjO4AK99455|h8ZJ~z5DB#Ws z>j1ar8-df%&T4rBfj+{lefX0&8eNUife$Vh(T^>%rkz zvoAw-Q?LD?*qs*KTe}!Ne?bsY+Qp!2y35`8DF>LMOJa=VakPe2uLH&DMI%+d(N0B% zPQD;d8cA9@W2CbGzN$)zWs{)gHsa>)A(veMr?aLRXtQjKt+k=&q$L`pF z$xN9`c*#~~hw;22)SKqy92cf5@v01t0qAkeJ8GSshoHB5fa5ib;H9Z zbP6ZuDPk%Z&_tiIyCos5PxW|1U)$O}G<|mT*bKSnUgP{=r%0z=Yu+)(ZcgukCwc7f zSq4jdD?8y(x4^?ysW^X|Vxc8b63y#`EhXzlMt0`eX#DRdxzW$S=sv-tTU;bLj>jD4Uo2WHkelBb*aB(qK+ zs7szUS<%9x)DpZw5X7J=aFh>zfEt74$9X#K6W5b03RNDg!qHU-(&-G~DI8s;?y)1e z^6q;&k}LI2J(AIB9&o={I*lt;itgjsMOYib!ODgle}nfs>6BJOj#cS=HI=i_tlU+t zojaSPj6oF?%hPceZKfutFl25%NNW@vS;=*m92wgPF)g?O3>Z)&zu7q-nES?45dGJ~ z%p_y-r)jRuT_WpNC}KnQ1Tph1wpbX!Ix(%*NQWFcd-L+lGUBt|44Q7%PGMtTHJEgv zt83&XRN82@|D^>{ueL)IEY(EN_oyQFmu=wX*dgn`%6ZmCZ}nMWmV9 z9hAEwmtjb@;?6?s;>$0b&+JlkU_}z@mUh2RvQa*N(@c0$iI`|AKFXxzB>hMfvL?&s zGiYMTmvl212&zqq((n|hxJ8x`TWf&_60zlnUuat#L*G1mt746J&OKU5e5VO#2_8Zn zmeF~rDCqwE5iPdUu%ki;jPqY*FA3_g5u$bqlQYRtDle-5$012_$xL9U%1Nmkpg1 zeeE<2LKhof z;R4mhilvF0FU(w7zS_{It5Y-2U0wDQfv;Dl7UIQ~nWcrT~6Yo{7gXLbghMdH6gw_2%%0_i$?ApIXf`^7`n2tvEOUEWRXrMQr2F%Q-i2w zyQlzcK#BtTwTq?L?_e@0EmJ#UDTi^~>YHy;_Mx1DvkwG3TFC0uuo@*lnWA^5)DJ09 zZsc(xftOuUZ$?t)lrm3t`jdGg#U`74JEzT5?6YnhNSJqo}Lp6i%L)LQ|5ixmOy<6>W%tq_ibzEd0z1N)LP!Em>)AC6#L* z%!9N&V5JLR*nh!QX>2MZ(6u5xhiwv)kS|E;nV3l^9^+fOO<9X|_$CAL{1N7g1l3_eWxH@R4xGeYS_jzdxxExX^L z$t1oZ(9AefqO+!=Dy*PFK)2o#Vx?2w7-%x3+2z*W28&b<)CVKudvRm8cd?m{W`a zEGKTk+)_@^5`}5kBn2392PvSgR8hEsei|#TxaJ4mGzljIEiZ^v2zgOTWqxIKd~v%m zl@Yh`Z|T5jCS$l286T44%{p`$gkce}Q4;zry@MEm6&$^|@xHae3)B)wb&>KE!el-c z#gjus4nwDkcvk6y&1JwDlU2C5p_wlOrZG>fCVT-$GLH$a+X zM0Wh4sase_TKg}dQ+#=BVsUZev&pI4-QrbKCsRYymxYx^)(&nrZnsQ7g9*mi3M1B=^E%%cWgW;f*R}ZTOvsqSKtIP^s%~>RcB-4b{I+q&)wn#j@-@5n^n?m zLwl*~plQ5*Yx_;InQ?OVDABWAGfUkk7Ie`7Pq;%djH;>n94LU=IJ@PlJQ=D zc^$}Ma}@zH<`r70^|`gpUwsfVSwzGOMi-Y?HfBNYe)8PCFmZEcZfL!>ftw%kvXgK8-+1sy+eQp3YpEytdG=e{b3io-fSIU73F&zn`8(;Ay-tJ^P%$ zes1Cl4DA_vaAk4gxyuua@kR24zs;4GXO?HDN~}(Oh9qS#`&h%K&kj4>$VoozeF@EM zslXR#J#^Xu3mHHeB_{wscIKBLW^#12PjH+P{)LvQosBr&$&@ zfBedKt6a9|3s-sX*(56u)cg~x!*WQmbzIr>VX6xVwhhszVlwm#hCNXG9ow!w9^gVv z!{7>g=UXUV`yc-|g>uyE98Wz9?hFRahGSWpwWFZfNxMbmT}7br$khlk1f}-u*K$RJ zU#XL8b&t)?b1kU5eB#@2yD3VB2QUQNB3r5??O>CnmIFp^Rcd^=vA&-OqQ;OJA|s0s z>l5ONs*F?vmuaJlG&4RS?b1YhYtgx?er9)bdS-TNaq2VIr`S0!@nCxKrXlw7)Qigv z8;v2TZP-fH_5B9)ROQh@0NW#QxCm2Yh^HM=zRsi&&JW`jQ7ztxcHcpyw-PZvlv#msBKcy7zgJo`S z%-g)&qcE8>jsA&|fivpq^4!$m67Owh6KiV=Wa{mYs_XlMYQ4chXV~ZGk-wyFLOUT` z2cRe%?+jg2SQe|~Az7U`XiiA=`rvKjtp4VY)N1;@W}MZ>x;U%M;r`G6#Q3WG{d?uA zmdrgiyL6{B&2C(i4(h%<6P6oX%d<)C{}ZeZTs#!+d*y6CSXRXkn#Svl)p?bmcpYc9 z_Dc6*@5#-AHGmo5e`hgsR!bCx=$lu>rfgO9H!QN5w3QKQGzjld8tosrcu7072b3f6TK_rQY3vXyqZd`RDXr^$ z>@NS)xto4S(SJzM|Aree;t@aZYicZF;tAvr>Ad@FSkh`xA zwg!Hp8Vs96yNKtFz~t^AS+8pmvWai7*j&?nHOw7td~Rk|0kPIen_Tq@h8-K1Ygc+2 zk6u?1`}}5lBTL`dxc=n{A+^N0njK`~oQ2aC6T?LTDVS7#xQTOSS(8&4!7E&dmSbHf z&NT{)P-VLs52TLj^=L^!wB~R1z>&4q=aQ86NXXnjgdp!h!6~M;aw0OiC3*CreOKC6 zq-oJVW}zSuX~mJqSIv}CZRddkaXTS#PMy-*B92_r$+rMVrO6z%TaJyw&mn5ECQXAn zrK|D0WkLHy>8YdEDmsF!*rY-VbIuXJWi1URe3P-W`HNn}rI;xxulOGRZ913dH^ zn0`(_@SjSL(6BJ7eQ_a;cGNTeXD`*J}D5`b!GN|5N3v&9;tixayZc-a+D& z|Kc~xuiIlDUlh7wzwmLZATzt-V(}z9((UqyOeXrj?L zVzvd(y^261=E&@0Fji^_wOkK>Z_;DG4WNM{47si)7sKuGX*|5A8cYR)lu|>={bamJ zCI_OjF`*I_lzf(LSk{6mR%iuvI0C=<7AMaqoTAXb2%wh7^*}N248+Dq1L1AJq5!|m z1Nl6Q#A6%5@nw)u2VAkt%Z-@F@;*g0T8KVo9O}KX(@W?V=q+i8=1lO?=RxjTl0avo z9aB>}(LvKFX`Tu)RaSPbVWCDUA#y+lu^#J>WN2m3WSdwbL#-JT9MnozzyljjnwZ$v*{K(APR-An$+aw8?|o^d`Gtw*&)j@DJ`6WMdGqBb zd#(J;72HT*vFUSs@4y1g);ISFrPAz-DSjy>@taZ7r*oo>|(O-Xyw4 z-=Tk8V(6~d(s8Arn<%TRY{G-uX;U+3lUa=bZ*ELs*{3z8Wx$f7_O+1)xt&hQqlGTe zB=&jrVtLHe ziCgkk?X=E$yY5g=qbNO^wz&ioX;JY&P{IdU=b>5Nrc(@&D^cehtIkDs#q)|QmFn2% z%{E=tecR?c(DYMDUc^3{E`nJ#*Kq_4y=X_!H_>S5_aFV+U1@q|JC2~%OM`F=!rNq> zV|WqB%9&ot6O&kDw|cB9rZ(9uFqq)7!;En5+`)lGWLNoMm8Cw2ZOI@R!xM3Cos2a- zL%%l@0hhA=0Vp`Z-#cq#}W@`fb@2BpGbFZZRp9$DT7$FD>80T zT4-e*JU;N@UPVmyep0mm3H|d^`ls2OTLKcU=W!YgkB!X$UIQrGtHG2Kw6&kyi6o7GX4$=B@hK7wmj^nX^H^ulzeYA1XSM z+3NY=Ecw6nKX67cGm|A1nE_X>yGxZ8-eNX6>72QR<1;R`Tj0z`Rw-|)T=|X0_To4> zfVY&Uli>=C&O+K5n>oe%2$I{@m{^qC=!30R-+%Sj7`3O03B*j6&VCpvA{_3SaH&ne$ZsOoYiE5$>Q ze%m*VolIi$u|5|?Q2H!_@+c93`Gu*u-e+>QI8@Gp;p5RuDs^q@8ilH*kTtpskq~5` zQXIpQ3ikVRce1d@m}5)ijbQj4(`Qt6PWeO*#(OV1W$J{Q&61aw64~m0o#`=aW)rRK z*%H?FCKtW9@`ep!b#1?Y;F8yhovhlx^;grM=@=mL1bW|i zpmqc*Xv?J_-d(feamQ4;w?u|b2kg>Xp8{uJ=hFb$FhDYT!BgYv7yyWP9F_@zGbKgS z_|oVwH{ZD^)que_T5z1vCmp^mYq?ve78mEqrgx)#V`p||j?7ugyQpt{jW+s(3hi&u zjkXCOq+t|NcKl6q+_P3A;%0a(lAIbZ3?0(9&)J?$JL~L(QRKf%mQDRm{lW>F~$#lJbapaBBOZuZb0{uh1xH$U8*-NPPE^>X~8y7CU zQ7@k271w5>mO#Oqn0Covb`?puB4?j*JNTs5KnI2(w7*Zm5K{;`{dhrdsK_qar#Gx$ zJ$r_MoLRKV{uj8i>Gu;mn(V(((U5Tv+|X$-*gE_dI(8t{1-V$aNP$(AMHUF*H1Izw7IGMCsJYHSOea zj}Ux5boG`9gI%Ac^f&Byk4ZucYH2#;_nk8#*@Z*McgyKwEDj543DkrMU8d$juA9Y$ zz8P+6WY8dvC#81Nh=Bth-mvX}{59N)bbQ4b=+FC)8ssK(a&o&NQU_)psTVGOy*PfU zxOn@G11FY=dfa{^svb~PuR8Wuao2h!a|rY4Lj+~CI`q*N()pkONT{APkHQhtBb3lv zRiL097duq!Kl!DX=*l%glhqWm z;zJ_MpKY0~%tY*=L#Dv7QEnOhwoZW`HTrK4yg|CZ{sXIi9EPWlG7kjBhb85bq_oP7 zXpA$>NwEhpM$UNH=K6AdmHEC~z{=h{H~30kxA#x18cMRC`6&*~d% z=}B4<*q7ByZ>afOjkRt@u6oqx&5ka9gFIf0(6@WQ&>ur(ByKU7Bgg4@JjtpY4Gf$a z@s-EgnU9NRlT=%xYn&E#fEqgtxk!gaIxXzE%p7+Mm6JNp^DzOt(BvZ(VbPRz2+gC1 zh)Lb2OSO#HD_)T3dcB2oG66L-i1rj6J5^ihuC;__PFIc44;`R`k-b$jH%UwSMpr4e z1$LbfRVg(|B>n26p>ZX=S~0B>Fwz@aGd@r9*@~)^eiD~*(Rda;QE^{LEm{=I-K^w3 zR93A=i6l39522MrPKk>9QhXsg!;?Mp1V1Mn@;Pxz&yt zBm(Fym6b2$%9(*xku-tI>r%5&>L3h11V{(7(^$GnB~mjNy`2sk9GITQD^b&062_;8 zzS^(rEAL5QZreA#1zql2h4)k`>!=IgQE6N^*7_Qp7u>jTsd4eC#?y^YUb@tHUChUuqSDrAn^bp+8|N+! zG+y68#Q}Rzj7OMbZHz)Z3`WQo2nW*k2G$JG{dISTKjvfmi87$^$%VO}X(Xu78n)yTl#o8fO zc+zZzP9t;I9g{uwMYCt}bF!M7#TSlgXN`l^1Vxer6U?@|ihhs#mn|38%oIu3$kKG% z&a-mzWaX75o79s8!6mD=jSx}H^En^u+|NVxzoZOtOqq(K3PDcVgHxM57-m@cA-FSB1XS9ZHcdvXZ2BoT~B6qXrxy+842?+EI1e*B*7g)*l73pp(w85 z8w%J&q%zNPiC921{IpelZT7_O={=d(V|<=rbO$cT`~kLB_BTwxK79Z_RBZFG-duMu z+8RBNKV1G14J}qi*Yd=3I(nPD7KmH2CC!Q&r*V!Ys4$iLPv2ZIY(bm_D<>{++`n#K z!J|Cfjt^QoVeZV%>eeACpv}v}&q5$}Y zf>!Rp_E_lOQz;G?kvd`K*>mSFJmtNC_=+cLkHJGSCgEpaD$&;>O?m=vjIX;e z9@_gttqd#!PS^HcX^^%*egqtj`&;t0T-ngN_g{z|8)dA8G+pwWns@W_QxN}~#yl8OsR1P!u;a*`B6zEbINqKXxK`QXuI4r*`PD8j8-H|n`yEeZD^CFdZH9N<|9eEp4hF? z4T}5u;_QWCn5U_Q;@o-bZ*7`T@q_-&j%}%dR8|b`Py53Tz|M^c!CB(2sUJRO7c&N=V%LH?`%)u+KX^ z?rjIfO%KeuY5E-%%aG4ijJ3s&lZ^<5^j?{rxhyMIxD%5rrY?{m=^5{2fxObZv8Zu7|35E{WE>V|qa{6B9Ir%E=CT-@3E=~@& zmTt^d{K4TX&4bJ|CO~nQc*?J;L6mOmY_+2?e7R_@92A=)`L3I(_9bY1gy5T-d-MPo zJ0_oST^fQ%u35zxu3tpsnNYSi85_^wmeA%4eL;Er^=2HAEpceJ`qb-6hWygV%l7Xu ze{Kz8kpVrEH*x|^hAxOg>&&s5EXsV8rGqS1>bVAJp9Q+uMj3l(-fql-eUNH$(1o~U zwURR0X#%M$g(r=osiQJ~j?;Zs=KC zI=p4d2VTU-cyaA;E4_%1@#4xRW-Qbd)QFGvqK*pyG=-bg9r8GqLoC=p1Z0>Q*5yv_ zjYq6GG}F^y(Rb8m>X<$*dJ)8Y3F;;nxwP+op1N(`TH4)j29GP9j9U|fTb4fALPty> z<@!WoH9&QmR4*0_h@-!B{doYDRpKHHVN|*J4nAGO$i)}?b=r^@I<{CYlB@S%P+FT* z>iqqd149p%QQV=lsn_F8UPZ=fFJ*F2l{Siba~2vF9U-I6uGV&cV=zsnZ(mmw#Krb9 zqOKQ5mk4>zYAaFmql*fHrslA*K1bu0lXPuS3I>M3`q;pb&OVU^a&d5MdB!|}t8cIm zJ21+Clzs2g@L;hR8xX>V`iFeOs3vWc;`fx0tSGM);V4ul84{5;Su6J9=LrPYvemNz zCO*`aw12FaLSaQTiH@N)h5SP@q%MG>?qEA*?2vdaeJT+;7ISyi_MT0#?pv~?lj}mA z*o29l@XStLTU5#QgoAJpev)eX!FiBZE#1*WGKdD(0ht~nt`&?#kdf3j?~Qs??w8&p zkv-0YyCjA)ymrTT-PdEMzJ==0FnRuTfM7(>60X%T8n?-1&{j-;{p=m%-+t*6wVHna z$G>r|Gx%|qiFERBtsPk|Q~xoe)7>oMs7&QKFXI{q`74W!OebY>74PCR2N zim+Yje67BQGcmHq9jFz4#n~Q-{Pp_c#LNoi+Fx0S4nou95A5&PPt{GqBxP7N)ll zFLw^~K9wDmk7D&Zg>6%ro-UP2>mg1mJv-K`*}=V^O0mI}JkCL!f?fZ&wye|pJ}uaL zsvcG9WFDZqUgK`}6Sv9RSSGhQlf9+JUH;y!v}o*EcirQy!EcNaVr%+_pomxdw- zyMP*x#$5yZGx}ig*28d6up-$y%g9-uXA0n;b?HJ0T&)70#!q$+@cW;MHT%KN#2DcB zeC58TCMYZIC2 z!Fw?F_<>uu(huJFgt+hrZrn;gc;n86cej3gZ)Z3|eX z3Pz2Ee}51$PQN5~HbUTZ_GdM#)6h*;J`)|fj*80@TJm{2{Fa?58Mx@IcoL{JQHqR> z_cd><4fg2>POek_I6V#Lt0jx$ohA&5*H{c-h42HUnv2t`a#eD31FXH78(3DJqylRV z^ElzFQ(be;lyV>C(JCH`UeuYuk>UJ6=UaZg{?f~1XVBOrf&KR=`qU5cBNiQgYZ8j&1B+Kpo; zwYjLUuOu_=nKEuAlZ$wawIn}k9JF@wmw4}o-AiY408l({Z*J_!CaAw2{JnO?>_Yt` z!-K-zVg{TW3^JU+;tNy42Ke=B+T#(M4rUPHTlm()DwktLQ55fM1VOLWf()FqzUlGd(Z?&OLQejN{`8AEjpUjDkbT zt(-nMYv=uBDyptr-OM*=AzHDvd57dD`xRQCr-_m6dfZ7gRPbPXud9saiHWRy>iujs zc&J|?ZbSb-Qlf<*JeHx`8ByMaU2523ou+I_@6t$|8q{e@`#m=^-aFXqISSIFGb1OCkH6LFLEh@CK&PNTd+8BeQ)Qu2r{ zOgKaT7CoCfv#A*NSr2~P;s#^sASy$DFZe9FrHwr<+|_0tAvJNHxzZVfVvmsltwm?`oo4f02$3F3e;$JCVFm;taMKbBQ3y9nw@@cpsvYf)gjBI>I<_>2%FFB1J<3NFrHTuN4;o(n?j!a*6Z18_ssw<2cAT)c)B^D7F{j;#QAgQ&W&Cfc{(#4rs_%VoHBr$N9S4#v#7k;cd;C@Hq$KdAAm@9%d3n83*J4`2$C4_3BT59Rj^2l=_X z6<$%|#_@?AbHeyuSr9cF9vb+4gzv`*ZWDhvyj18gvaj_hoIQ; z!Pd`R8+wv-&TFlev0`D94DZ)=2|r#Tt8blr3<-e!D^IR8&ka0z*6bK7uF5a7WPIm0oiH%0ovPy_9&hLGD9-N6mTGd_{?DzU_%*^tDaD?K-AFG9Gg+w25za zHy%!V+X^G)HXwOVTDgIN2I=SVShU=*R{d~)o!tF$e^p*-1|FuB$1Qg@S(#S$U)5#P zIOj?7N)C3Oi#2KGQkkH`Y?xdskJ z`P*4HoGHTQXl#5`5jIFu!*0!!@PA~gpC_iLr_r6e?4M#>ZXI&hklhM}+jCf?gY7z>HFPSfcT)LZ^Xa zqaw0hIg~t5?kGnewHs@VQ8Z<=fj}ek9WY3qayji{{i*-R@cD1lYc>5|`4vT^-xr_d z2-^DWvp@9B%poe~I2neP6PyM8io4|c+2Lf0J71R{qzj*&K9!XEp>O67eKY@P`DXsm z&(bMt>5lwEKg(`5R)>!)P{;I0rgV1Zt#r3Nfr)z`eP5+a{6kSKKYIjWcA1c+h%_Qmp1UO?7b#WG_9n?|i7bVG zQ$3;qxA#0@r((Uz6pWS&kMC1R3avIl(MVH!%1uJpjw+gnbkfxoBzD>(&1QROpTw=I zfV9Mrmee`Ip5N77b}vb*npcnb%|m&AIEus?CO zt8Dx5R(H{nktnNnHMj|4=xo$6u0E6htHa`|k+uE3gMPcSH!X6SVPi+>yzLci@D6v< z?BoBmL->O~Ti;sQ;0Bb+7a4=67nhcAUYRFFf3C@;x~rsq86P>HtXuUnzh%pR$kOZg zGhfj1S5o;d9Nbvog2~qYVC!@LH^L0jheX({zDh79SJm;nTaZ;c^D-s;-a+{}htTV$ zF+*z4|JHel7&+Y87fF^}=?hzE~2J$i(6If7{j4mPlBrF1+_E zF^JK=8}W-%rnV*-sKZ7Et`DHR_OUZUaRT%?yvkD zm&i3sRm$gQz*a~I(Yfs#(ok%!Z?@Jd4+mTS;JYcia(7VXd;5-#265RH7)xW80A%Q- zo>i+#_g&8DzwmEoft(>+1Ww(jz_ly};$P?+s)1bD zJ>^Hftu1as14G-lH`fme>i9sGKFi$;OEXI`813?a+t~O?BkNc1Iy&|UU*zN5;WoD= zHS#RDR5hA1Y`%XJX;Z7AQ<@vMutT4g_`&J`BbkC~>v8m(4)sb&AJX*oxyj|3`MD@} zU6~`+(N#gWQ>3_soo{Y$;s&fuBNf(6rl0%VBL}77s<;fJ{((lcX3l6Tzp}Pw>3>u1 ziv)o(RGyoyE!MgOpT)fT9LwU7?qK(p9Nal5%*5U~BEOs-Z~5yBGm}5fdbHbQ6p0aW z)l!Qz0(MiET}}r=DFYzgt7lt7n{R7nfAzLH07=xog@rd2C+|bD@Nwawlzp27d@GH( zn&?78oZwr^<*ofsm<7S;w3ZsF%qyLZGu#|LF*`FoGqregap~&J^s?YE#3-t7X6+4w zo>A&#{gh3ya>ET9b6!A8q89<|nvAf(Z#y#*z_n%3O1ZB61mvS4MJH3iXy(Q(9c^-? zNO!7qa7=vDOIV`=3~3_T%0ci1@%i;!5JDdWjnX_I zb4{i`Ru_tV%XsNZbDJ^KQ@hwgZ~)j6+n2U>XQct(qG*H#4tsKzLkZhdIb@F=v7)?P~betu+;_EK# zR>F{k+|{vbVKR7xU2&VhdpqB{Yl(@h@S^&-IQ884`I7fBKr7;ED1WNlxVqN5L)wWp z@Ak+eafe+{dFjWe5uQmd`#bi=NR++lWKz>~t4Do#Vm{gW{ zLW!zo@+l9WbpXFQsM_xfBw}q6YO<^yKu=3Xf40_Fbg48qWpH$@bK_|r30(+weN~65 z4rtPnih%=YtDuO$0X@n%P(dO>@~6w~?@r0pb2Uy}gre$GKW*I><;!3Tmj226u0IWX zFuEKt*I0&1su>~g@d9arv%9+_!;Z@ag#VUmshpwi(be4Yq?ku#UgO<8+b}EJi(3z4 zlkz6{l|!2($VhBiy}K$O)Z6=qMl2KStUWb0uJIVX9<s6xs%+2qw9x{te)PsOyvHjr$$e;@IzZ7q2o;EDW0pun5Bw*C zDm}>MQrDzQ=3a^n5tU0er)Z)Klko>Eos+VY2dl<9hoM1GsXr!dfJ_*6%8Wba+cmtC zJE(xm3s^VDW>=k?OROqafm%iu+iS-r>f2oFtXUbdIcljV)wOYW%ekp&KJ{%RVF5bd z+9z|=HaEa*qB;u7X_>f!C_o>0u4W25Ob3g6DpUaEL#jL&)L5Jjm;0vjFzH09SjDi> z-z0igJ!+-GIeXqj^9?*4^!v;EKaXf$xrVPpG+&&WxN>dkw|;HuHcBhr8z@f@ zd6TGn1-FPXWQ{vRt@`yn(l9DS1|Dkk!Y7|)Ym+$*&Sy}!&+WAEpIAGr&l2`BR-c^b zV$8YaB^^R1jefAj!8C>H;&30A1;I748J$>Ibio}o9MvoTHtofbk}E}Po*yy`DX{Ct z?M3^ZEXpMTTsoB4tV{N+=c+THU^>@vw{ZOtt--L9c8b%}yzSu)ObFGj>XD$W-VYNl z9z4%|e?a|I4#MCl#9^*DDhc7qx2wc=u(V=9Ob+bNBBB#~JseOqyDzCcOMS&)JtxR_ zP8LK2Uy>N!Ena|&Y1gMvb#3wNzDpN#9V^bCAAR}?*?aG@E?2m(JHvZvV)`=asb-4{ zqobqe8^!gdiTcvP%E2M5QL#XZ%+1x}%C6LE^|O78VQQn(aMKs}<9ELw zen@Q46`=vJISGpb!%Xy>LSJi`w*lUgXAhW@@N;Q#@;NRby)!&GBKdIg>crf0Q%mwa znO~fFZf0&`w%~o=)Rkg#{>qf|SIz&Iy|;~xG~4#On!weSD<231_cnBgI!5y7B6bxwGi!0N_15-Qv$C~qV*m3!o*p#T9yImvbcJ7^ zZR}!xs_6332ljD;KyOb;(29T8qqu5Vz%&X7y6}qIxP!%!XnhC$SJCvBWf9K|#y=nF zx})qfG>Cwl99h!W-2qD`=>XX`E?s|J;n!sap*Cc1!3?Wxj$E91al2hxN>l6?3G5Ni zp_r7p3@zQ8umW^qzM(AwIPtYer#e{?+?nWt?0Y$^XjX8)PnxmO=c7ot;Wrtn|JPW#ibnYj3mqTXGHcq zYyG%-h;4C>8(kJEoRb&B7{!7`I8d&A!qqf%A3=u2i;;Scu`5XHBxGopJxO~bkcCp7 z=}8Z9nWK$5jl_^G5?p=Z`3r&J^2wP;op-I`6sJsQoR;37eiRvp@{E;0?4#wnOPy7k zPovA<#Nx(z+@B+kaxB8xrgT^Y5V3%9@N%86%r$vQ_G}TN&OKTr4q)X2$jg70siw~x ze5Sx$Yi>eX&C?o_(v~bul*_~9COKd(RRwi!zgRA&3F_QRG0kzgeFe&)YtCI4SLp(Pi#IG0nR& z{C=_A>%0;ROdX^y8*LzLwlFyl!$eo$pNbC{15&qe-6Oo0gHnzqC0^?abota+ey?@3 ziPS8M=Ei8xo;F@?HrMw!*&1XcANIB%R~GMN?@u?@_8v-DzP^cTZub3QbK}9oJ(Hq0 z?|+zmH?wo)gWB!Yg?sm!+4uF$#)I9;2gJl)&pz&L>}@tHb9*ST4}I6otSXOWvx*ZM zIITX}-P?Y&ySmeCZb=|y03K~@If8fZ6+Q;+YKytAjn6&n2es8)J03MY51Bux)$V55 z8&CGO8*4wHW-ib&awT9g;Va~PF;N^mwb_rNh`8O3b*n8_^ZldCrhJ*pEr2d+?BjSxLUq2 z`RS7MO!u18M3l_NsVb@tv&q*>_ij?ql3f+bDlkgTy#ObSL#@H(4ts_u{*CjaL3yFV z4c5qZr2DG53ur6l`QSal`fBb4-=8`9{Fz^T@j?`ILrCa<8XqR{!ukOmB0U@(6%?&l zAjAYyGsA*`0|HVq`NMKJw{=aaoWFzRiHG!IEdi^;)~GZaj|NAag6LHl`6;)m#i0yY ztM+JQurXz?_2M>HNR`R%0ENv;@sxg!D@N2XrKPVSL$sCULA#2J9=qki5607;JQj8Q zUsi87to@6i^QCv1>+F*~Oyz__fF3KIqi!#ZbrB^4PhzuokV~q>AjP42^+Keu+iIb+ zRr>KKPO8<-?cJu=X;!Cjk2mX2)G7?*x|6^zAh0cv$zVgk9wnMo;_77UKxpc?<}9C2 zS(iRW>73BJ&WX`^#juQWDe#lAQ`Sp)e;(*6hSV+FE;gs}AUE%Zu8__axmTk~Yf->J zp-e0kRsk_!QPE_ih~2IgX>Pllt?v?OD}7czzu6NA)5W4}Y!8QpDocKu)5KR;vQb_1KcUowo?t zeZB7B>oxxg21$as54-phnwf^Hmt_7?J0a8|9(TEaxuF!ldYvJzSNs?UQ+ziH7Y;&A zC`O?yW{FJ=&Vz=5+tI~d_G+uV*e5P9f)9&}|&>Z27RjOKLh1R6=O`rG}X1l{O$PNo$|rJzH660FyrVr9zDQrv}|nVX-DUfn@x1aSDU@d5C4W4 zI%{CApMUf9|M1J#uDzeNVYhw0Vxcvkr%%sBS4+twu6%EGPLeM#+U?`6U2w#foQ@TSoeb{n{f``iH|;y4*xt)+~P% zbcZ(4W#?UUXyHZ;bN9tuo;qx`%=(RycTc`%^pM@!zzzmC`K^(FW!yP@F4`67^|;Cor(aUM+l|eKSKJnu3bu*4QU4 zZFU%Esq*z)>D+fOZX!Y(?#1$3u%-{5V(r;?ifi)pv7){;ZuV$QfwvC0@ma3Ix^Uhb zg<84N9X{gvW*lsDXrTfN2NUH^ zL?eBFGsBHZY64?}%^pTEJh;PM!R`dAuO^&ea~BB=czgyKAuhr`Tlz4&0L;!DYxL0D zCB%RzHN;-dy2aVzJ^W-5YUvGEKui2lSJLvk zhnpAYFdK)MZL3zyiymi%FOxZ!17ZHuJUXX~VFV?;1KFKC;k8xn6v7?qytHdWin9Pc zwChfXODm5M7>ciyIf6dvfemu!GTA=V-U9dcqxuA)tIG+#5b?x^8lsrI5Fn07ji+e_;^Y_j6e zsoBeVfxLv({j!63ENSV4wmbXS&XQl?ic{?go0T1CjK5{_<%8}a@?ay%4|7s%Yd0*g z2-lLMkcb|-nGLakb(ouq;Tlepv!PfjeYm)AZ{ha6SD&6-ysnxY8&ofP-9by6!PVA9 zX@)BO${83#4Ve4zb|Qjs8}pETFz#ixy{=N}$2Nm~dfYnskdxlk)>*69s`k0uNl;jS zq*wi<4|ZkEujxJ-O;Gf8dC1*20kh(SRC>IftZaXt+^^j(vGCyhK(|vG>BpHnOG^u- zne1{Q^QX@c9D%sFxR9(}^v?VHP;2J^u;+y0!ew_9ZgOYg_FV|kPq?o3K&;NLwW!jC zPw3?G_hF3u!14LID1Mo!8NXjAvzo?v`R3vc^27yQ_4HOjBxjo5*wfT90K9l3xi2BP z{{~<6y~gKZOwV{V+5EO#Pl^?mktRoQm0cVj+|mW+@spj$tSTd%y)aSOM&Jlg`S>a} zv~=LM1*%B7WDz=@cS->bjjFjE1iuMQyXd|}X{UI|gO=Atq{(TEEkHox!%>>CO-0nU zw59F@>=@3d6*DsWm~7(3&J4xdoo2HQG?(RrSwty5m{sd!$td}s0lou$~Yt*!suA%MVhslFR!T4AL7 z7==?uaNugV-oXi`N(N+ltiaTYafLYQYz0}!VrOPXthcqjXY3`lmMCNgt@DG#Cix&A zP+=lw6WK9aj-@OyG9~1>BAYWZ9-PP$S#o5634cd;A}ezxO9VC9CWoxZx8aP&;470C zXn4B*GF`Puj=1xOixbz!k$O4#k+Dr_CiQYItb)=B%$M_8IM^DCKfph3aYtj1WhX$9 z=|C>cxN7FSA`6zU2Xy6P3p<0BTCAT?yCfg6t1uIAnv|ks#i2+JW~7v6Fg4+~vTNge z#f$;0Jkm9*G<6g!mVdf3#eF~gJO?Lxz|lacE;Sa5Bg?fg1acDXJ7eyYX-6gj>k`J( z2(LR&pc#m!An$9Cps}XQ&xadpYt1bNPFSpIK)0aio+xSOjBLiF?#hQquP9cd2Ten&Mq~k2g@*Gpg$c=^cV+xTkF8I>A>6`RpehSO! zHEH@ZCU=k-M^AVfXL2ueC6iM~=2n}+QY3z-OrD?Z(I--^X4>q;+S96!qd?}BJ{r0i zDBZ9wm*Z$LNF{B$EMda(iL*~UXcv;aGj*IYUYJ|5+4A?$fbcet&m7)czZY41f-)Y> zcFC-~@6L%Yrn$VeFT1s<9@DX`i&bq&wiv(Kb;SGPyJ*_h9Z4-bufxnWyLa5ddJ*+a zz4c#LJGU@(^w2j;GYvN76zC#_Xw&Tg3nDs;n-Sp*`Spf;Q}m+JjM&SkPn$dqd7OO0 zxCj~^{?4do#!YUHPHly*1?l=?m^rPUfQ05c5)DnlWt1buuSZyx?2w`#tk5#OKA?@0iX8XSo(uk~m-XPX@Qh z?dul2bhX*N&j$iRj(NL^?r~$=yC67qh;!Jav%=g8UU^-sT-GYDmnxS_oGs^8@B=i^ za|Ir_JU?5GNU+yh!J>(AGCh20EePspsU$q`C(Z9Am7isHjU{|i^2QBrIEr03N##SZS)}NQVdmKz`?5tT)E9leWYWD&@NgFP(ZsY!3ZClmrV_7 zF?A_$Nt78_~dB(Toa zyYbM3vb+>d-Sa588f6VLUqz)N9qP4v?ujNG7W};Jj@EFhwR=kYqvI71#uqMQZ4_l1 zTG{zbZ4K*SdMVo&#`G$|EtItx<{%`!@cU~##`9W`ZB)!y+l)*u+cB?oPd${y4x7E& z_YJv`28qPM>!q7`XX^PTZVE!U2(^7378Yg)1PU;qxV9!pUviFu1PTBHJO@XvN0`Aw zrFRx8p%VFRgpYI0U5l*4{?-r|HqLH{Z@7vU26$cj=#oE|wSdGqdlrml_ItWLnUR$Z zrg?3wbLqu+y?O9j1%$S+P1!6-;JwS62cA=0^7@l9a%&!QKNlM5mYdff^JpcR-m#rp zlW8vE<4_{x70Z4Uw*9Xum2ynZg7&? zRS}I*Oz{LRW=~u@+n6=7z)Wrv;k2{L9M87+d>R21BSTSGldCTAh#9nFJn$w-U(`JfZq+mgAj+<>Z6sKYo7v?EVYI zu6oTSWo=@8p~uSgNX!YsSscyM(!XP@@Q?n(*RJX3Z%$=}NV{t1UwQ~Dq_3wM!jWn+ z2PrzU~u=1$}1dRwkX5e}yPbn)7MvRgn{qJnZ|j!*@O;=9(fC zhn2nEz2tqOsC{^^+_S znx&X8mYYl*HL23LO_@FMPuaPpqNC8|Z>-3ho41MaZI1>DS8~EBEtG1%U}NaF5T*M0 z?LYm&A1|zDo(wvN7bnm6Ia}418+oDg8$-wWnBE5$RPdv-@o+--@A70pBd-k?$Gw!tDXP( zk7aCJNgm_ljz2GJL7T>07L-cwA9Qfg?Ic?(8+(r$yFV=Vt|#T)*gn|emXnp zIHaJ*>Wi$znkB9Jao@(9KnC3XYfBn(qD z70KSsN?7*pfjOx9;e*7((qLnh{WI8Tu&MjnoK2d%?%!Dj!LlG)gmZ+?#hJZUSP8Yx zhi@w1;GFShKD;p(PQiuMHQQ%jqqxf*TsulE_gQ=poXfpOdi~x!Mo=>*opUe}+t&Fc zWXw;TQj?K7+YMNqH4UxsJ{>PvlVo`@TL3m#Y>c+LW^MfWUZQ&Qw8 zGquqXxEhb=`|c*YcNnq8Ad~Wtgvm{6#U{19N#XtNP4Ze-KgT;moRadzc>SxdS1rqA z1lkdSwj&VU-wgp`EN!wr$8*YpDn;I$fJ4laAz>sg;`WZDPL-EvAR4c4qc?nrksa$# zR$-pKk7KKkz189U-CEtt)GQ*-!L8>L5!kh)$@LFn{R6K*yuVxh*=ehk65|N$av}>V zOs>8gtM7XC;eC4baGMVa6mAXi!7B+Q?bZ2N4SDyy!WEh0>=RHSvmJC#hgZHU`Vp7D z;}YJ%Wo#s^aXN^DSOjk6=)lIVY^FT=mQ5~g{(gwMi4iTR@3{&sK&&lIM+~@tiZ(fg z4`7!@Rw8|^Z*^WhDzhf75cc@d`pd^pRyH?QHK!sE*Dn;Ajs>_p;m!L)V&4QaW_-3P ziLft2Xgo{qPiTjZ{;H*%zr;eRh{_Mrgo6B`kj`yI^W8h1X^K?TMa{RE{ z{^~PCD}c*OEGs?MLyI`(7VzPTOyVZP?f6>ocW5g;Dc`-naC<>#P4LA>bHn4jb-<|& zH8VuV0W~^h6&LsHn`oRG8V8ck%V|`;%zWnNw8rh+7mg2|U+O(H$_#Fe+h)zggoz=S zf8e^qMhIpUK4p2Mpz+M}sS$A3OHKFHp&er!#_@GR2}BMtQ`?PB3_au$sRjDs%@xH0{ftf1onu7huu+2AfL?3 zY72%|8PNeA3g`NB(fU(nV=AV)tNJsx{ayMqrCqLS@6ULZNTH#sdIAT(r4457j(x0_ zcpKuF%6D=k4}Kbfd9(VhYkU}{y&|S?+NA@fR#~dtuH32It=uEtPWHA?l6I4FkEMn#gbE^;bw~X~zSH8D$<0L;_rKsjQOT*2i z%;K%a$dFUT7aT=fTSRH#914F}V&ufz6=H(2Q>8=@hmCvLz}Ax?ZHF84bzDiU0%M3~ zS56&H^ojlKGGd`5H9YNMSB95Mg9$xM+Gr1>Lg#u|h0`9^_G3!ubb7WP4mS6zqH>_UN^qP5awdlFOz3g#IRNw7*$@7WItS+#;ijMWu00)ER<^jT%DKsd6f3 z_!R3eGQgDnPaEL5-(|fsMP1YyJEc!){=YCg<{rC<`k7|?CvZ!<+IjzPoX8q1$tw;dnYzCNRvo7`b ze`Ha#Iozpme)b#=1lTi9yPcs&;?n@o@E$x1@Lw$N?(J+?TulWH?H#R`VW7FWxwVbm z$D55W2wADfY}+e8Q2aYxw28HBcenANX)k09Ay{py$5>^Rxru7-SD$P&_mVlk5`>&? zr2~cdkNhC-x%FUohbW^N0X>?8S-awi^N=BRgGDr`Rf6P zoU@+8g_*AdCQsbZM?Q0iznIq!OY-TK*9UVd{(N(1=cUD*&&n8nP-76{yIam9rgX3w0@URW zLAl`wWuYGicG>S^MWq|&O9K+0YYy@ofY2ggU^t{lPznj51DES%wbPdh<)F!|r_nc*P5I|3N96UV|JhUR$+t!&5>cBu*GwiDXP$QgUmD|aI zIGXtA@C!`loEMtlhYAz{N6cEfJuu1i5ju;0{*}+=g!acK%xXiO4p66YDfAznBAoQu z70S%l|DZp(#ZOMegfE;l(M=iI#!jrDd=`hBwr|uPO<(PkZu}fB%+j^kwsCgIMIvlx zApx8;XU|@wqYX-_WPSCdYwRHgP|oH0iWa(M5@TFZHO{Grle?H1&XsIe_GcEXS%m>e zqIV4$wC7XiLq)l6F4~`%Ire9P^40rB@c-}^uU*s6zx%KM)~V`=zP454KpE+fioi3&OQ-j!$B4z92#Jn|gdPpk=a%^6rJ8YIcX`FUydO1Sgpu zY(}SyZ&Tv^eySZE*#+zXFE#>ey>{bc?Xhw@XD}-aw0Fy9T*8${UCtgT4%nqy#|~yJ zgz&MG2WsQ5U-a!5PTCr{jbqv;mz?OqUD$5exv>2?x$2zL%qQ1F zs|mzo=Nc?4FwHMRgBo!7UvNzi{t$|kYT=^o#3E-akNXPv3pv7BWcg2Yhq}Rb&$fHJ z1m0s0jSdlg2rLM+&fy`=##M-2LzIZ&d7luDX1wGqQ7$MHu;P&>?IQ?)VHo?c8ZL23 zSpZPB8S2th<9T>`Ru8Nk$F=X)a#{#Xb~?hBOzMt-4q*;tw}CSl>&d~0UA{ZOKA0-1ju_pXOuJApp>?6`fFkzhMq6AxV z0AoNj?nBk@ic|rs+BCFCDB|^P5lgHGhTj^yF)Eo9gfe+_-kC_SVk37sa)B?M4FXuJ zB~TLRfyR02^K8sWCP_SF;|<-7?ZQ^kD0Pxp0Tk88MTy)m}at1LfDULFe-q1wFluaA=41WkF zJMdNI5@xJ0eK;##DDj+CTQ2amRqQ%NrlFcl7l5YjdPaA*E7w&uOSK@BW6KS|CUQ@% z7t4dIlh}msIR~}swyiqu!uf~a;;-SH@1xSm|(6Avb z_1MU@EPnvcDChEtuzdvlP&LSRD^GYS0(1^aOaGQl@&EBJUAv~AU-{>Cz$kZKllevm zjQr1MwJH&lfAjC{`W2Bs*m=l#Nn{^6()%Kr0B}w+*R0z0(jHL={)# zhlWn1%_QX?=snq~CJ!&TEwYVXlieiw_Piy>!VwH{sKFsPq$J=_f6G6+5E4cRkyV+J zJLVo^VY1=y>k6dJWrm}8a<1e4p=;;D1}kyRVzA*P8M@FAgppI zEdR?AoREdLX6}2)1-{S{4|~5{;T4BlRSVvLbRQw6KN1jx;x|t^0ZFf2)iLcBVy1D*7Dpw9+(24@$8Qub zD*j9>F^3>OtS*qq0yE^MonsnJ8&M=+D#SEh}m7%}HJSGgUfT5DBbluDm* zV4!3#>DCwpxNOuy zS2aECoo1H-*OjswPS84I;Kmrn)x$Smm=;CHEfUWe_9n3K^(xWY^Mi^hhLEjX%?exE z>Dv8xwy_$}k=B-elu09N4Dx>D@L}kEcy06)WJoci?n-(-(oYWpQ8l0=k5(#wqC%C^ zPUxi-kDX=<=hJ*T$@Tx#Gk2qyKFUtUjlcqLo%bp9+vpLLXtWMc>GBB&YPx>@$CkD6 z_)prR?9@wku;q#ZP@WpHtd0PvBI~}2xT;h2UL>wf#CG5y?3v`qCAmB$Y06oN(14Iy zbn%aA;dnw=quaO?Q>mhS0kGGGO&Sl?BY@eCLB67N z3t^-twh0RRG64$#pOQ4Xp%HpU7f{$*+ruWuxx)VX4a?|+9@8{lvfv@FLX@#M{?ny2 zvjKrGSq7$|`b%k^Ff%hHHduUXUhue^aS6wKZ=S-;J-z^xWMUGsNPtp%O3a|FU^%A7 z9Ba`G2xp+Fn9DJ=^7S<=Guo^#e#6Rl)`Ux8p6JtY!7G`_17C%s29k+bs7!Y(9GECm zUyG1E`yE!u(pO*EsR|D8hy#$JA(&`5RUzkH_?gMef`57|hn)W!+(Lnn5sV6L4WB!H z5kQG7WA_7_Zh&gTd>un(*rHm~eY9b`!qdksvAO|4|Kcfwu_Fxbh5~8_y>6L`u>G>k5N~70 z3+ZtXUG&PWyOq|RO6zu|wNz=EtY>UIDrk+p*;yN&n5_j-iYwN2qLedgYzpw$F2W24Bu0{Vhjc~G~#l(X=F!tYvu~_C>Om(D7)Por%F% ztWm>M>j5y!-D;;w_(I}vD`u2d?2oZ3a|4`D&?3A@H#*wl^2ca`$=|$knZcHRDdD=|O|v`mY`Aev2e;Q?s}#k0p?Ud1 zX=rB}UuyA9XX`9Y{j0IR-#t?JK@pp{ovS}or^>ZMBPr-&M(6$5D{Z7g19t*K(V3VG}VG5bE@>qX_e2QaZ5BqOsjL{DWnHuzG?FN{wCbRyD3%f}Q+%hAXtt3C!sSNmg!(%NHwbeZKov?_ zSBWE>2PIMQXQi(-3h8CPOVLOrv4t=XP=Yw!R^(dH@PC4l=K=0Y>F zN?ZkCLE=WC1uLsEQ&Dv+9LQ$`yzauurW*;C>QSwMFjA%iFttWSrG2_}R6$NIdb++# z7-+eql7UQ4H-#UPE%Tg<&aitycwciNwPf7Z{H-#!%)+b}=7^k~SWvnBNpfaD2a?BD zlN2iL{BY+{oEgK7ffS^%c4Z)aPTbLWIc1=PM2bK15PKPQVexO7wg11ydqO{d?oTN? zW6rnBW4t{78umtkUaWTh_Af*~K#zl{l>T|@1-PS~pkl;e_kef>G10(}4Iw;@cs8@)DiP7kk z`}a;dd=|+2*>|SP0blR%l@teX)<3yC>i78kY^S3CY>eq)-k$BRJ=#Ps%V{P!&)dou5A)fcPP zdr6t7h&pKrYYvWEY}#M9P@BPflSTFLLfYEdakm2F4_lQ3;!7SAY4TE@t)9(8Qd>e{ zFJ7ew&$eDHH+FXL3$?9ugE!&o=T{ZBD5<3mGx20~)o(B8`Jirp2K;GNaMl^t7xnqI z7+nvS#_aA|QsL~q3!peylo2jU_T<3y!aX*J57i#?6;pcv( z#yG4k@(j8)`m4sJ$F(KC-@aR^-QoQ%dGGP<9`E=0d!M{CtM(z^*#)b8NZt=WtSl`o zxSK-Z_G(85G7SPoJc5~F#oTRO_@JYR_ z5kSN;FIx88@!QIiJ@#AM_zBLBm;Ja-k3MW}C7}?uoyqxuY2EC9Z`KMZkn%}=>23fO zvqm2f-bW}tQruFD078KXf|lk;D2DqaB0ibOfuH>{=m#D~+d^Kxy7|GKyXInv_s9vs z6(-6lAGbNsakvYMivf3}pQsn}lfa<*x-zI*yfi+CIp7`e+PlSi$HW)d%jrTsq_}>AaP#PV@;3nF`pLow}y=5 z&yxSSEit66n*L&?U#pxfR!%q~V0#$hQh}f%R0gjX`KeU~m;B{+0d<9S1pUxoT&|m= z!mfIykHs{58&fPK=zhks7u=TX_Y@8SZx+o>%k{fHGV%`y3T&$&|hEV+_lKmyKrU>w^MSmN3FVkQ57&tCbR zKIBt*PQRxQ#SFQ*ARDPCu-mg<4NlMgKeuOorw{p5p40E?Loq|Dt`R-Wt+amYLUtd~#1RKjc7-WO}k zOp0%>w~tY_eb)LDhsuqO3OSXmG-(es}3ZJ$zBG-A5SzOcib{akhws$K#AGXW7Y9fa@vm zsE6wwn%?V5@3PW=UFl21E6xPoR%_>UH9RTXk>OLkfjaM9A6sSaPFBjZCe@!UROT1& zR_1H>D~PYkJnIJg(X+mhre!W#bA?Z&@;?u}D#ev%Y4T{W43zD}_+@vm`8ZkB8B_gJ zGHPs0{sK!`J~>H@3JB)@U}%_?LzGxAZqyk`y}4*n&^-fImrglH$;$00ZJBCC+CpK9 zdJNjP6=oQNxwRqpIDI_>t=G;U9i$7Opp|oIW|f$P@$*eqDPdXt^94}4gsH+lE4p`j zP<|v<{+y+LB@TNV^Yig7_HAB!r-$>UzZfn3#aQW_BL4G*l+?etr24(MklNgB+Ay@E z!RzI@i_;4Bb8hVrFEBQ9=AhrzWtLmwb}MG*!t%9K*=1Q|f5J!p=u`MZ+OB8OpO`kf z))G{MV|gc~YMEwm<60`!f4!_hrgSJ9^%JMnnABw!di_ZpZAN##To%9BTov=&tlhu= zNwi&zr$pO@Xi>WLXG~@Nn}3)KZut2-2U1!8sq9Rmn*g8tpK9m4 zT{t6`3kaKAef%CG=1-qsg~NE+qE9NItqd_cTrbTK32KHtBw|}y_>soK%nX{oZ6P)m zDug#8k`K2uS-$q7=UFVxc$kS9Eg}iAFtfS4S$#V5zTFz*X-{Ve{JcP7_38Br5t!l8 z8O~N(E_7uTG8lz?+&!Xv0k~oLF5n5s@=o9_TjZw#c`^$^_x!kTr*10U11QAWEBu2h z+Fat$nGVOZ`TJvb(vJJf2V7BmXStRViEn|DX$u9D`*IW%C;N857uw6GX&9wjF4)A` z%)uaDyB~Utq}QXhydJIMa=eE2;_?hPGtPXlu+XlR+O_oU_MOroOT%Gqkfj~oDXF1W z5ChOc>A;^q~JXV$el*_V*#u78=~4y3hvTs%k5a&DEd7Q4ykl`kq^ zCL3FXI+@1>P>lcR$>#3N+MP5jmnrT(Z0;u55|W+fgIzNrH}1?6n@ianx*%ePyN=fG z#cJ+xf0I|U*L?JN5q|mn#_pm6Cr;dqE?ZJ&tB7lucrHNMeX=s6p_B($bAX>Wf%e6X z)x~)SZ3vIS6!If5y|UXA60Gz%%3px;jnzOB%M&n~hV|QP;9^M8UYOU6D61ni)V$4B z!`*RIb9AxCK*rdBB?te7Nc826-I|lge&>4@z{sME;1W!+O=Ah6;S>6^MknO>1*kA{ z234GGQ0a@Y1cQooYJ?z=ycQW{tNCEYMuY*O-xwVkbiJ&t%|y|o#7La@2yp_>eAz6o z;T~I0=D(yvZ|*$Y9;b{jYC!%lz-Ah-Wf)pB2R_n*0Jl+;wvKFkU)%VMAwzM|54=)o zwdS+S?&oFs)z*`>8=p6Cec5E)>ywPNG6hB}c}{_eY!2+wF@RjK&+ZrHH8z82&f1MH z99r#uI=C2%3iNqXmx9eSKPNOD2&YerQTAGBBcBFcejy++59#-9`+eVjujx1Ydis6W zemCs*dMQfP+LAuh?%D5E{bt)wzwg*@b}e}}Ft=$>5XI~W^7*#Gy4}?C9RqX6z}#7} zFYEe!mktSq?poqqOT24|_pH!8`+m>9-?Q)cvqJYR@xIk`-)dsF5xDF(>bIfyp`lH% z+*lKxPh!K0HmqpFTCie-STO>vSn5h6Ewo};R;}@?24K}%xoVVLHS`Em0ATe;Xw#Zy zMA+)HWn8oR)(oXJYfaN?ZDwt1TK1+P(6mBLE7Y_?O{=46Mb|TuuUoU%t-f^wux{wB z8<=$ivu@;A&)T$ZScl&Recf6aep^lJ;dk1m_(5%2cQgta?fY1vJY26SU$?a{pm#s3 z$#M5~c$>U^-d3lZ)3BKq3RH56IrW^9PE`ZoBwx$8JoJb6jrWsf5B=wzZf#m!Noxu{ z?_6MTojaUURt#8RBgSgr2d^=zXi(hsM1O zy)bSp(Z^F5TUO|drigKB`zGQ^B zZ7sNMRJv_hBy-o-Z(IAY8}qDw;&&YGJQ_LGTRa;YlI82`HOp8tJTNxvOYA2e4W*j3 zMqRnSzG&GOE&HO?y=aBf&LxW#TC_UU(d+9AR&;?e#IpfdFaQe~dJ6_iyg(Ks$AYy9 z{}X-j-v)RgBgBF=7&jGVnfBW;Ky$D`ctu7B=D)orwCz~P5pa|oJxA5iHf9QK$~Yo4 z*y-jpbfP$c3|OFE98XZsN$X^`qE7zM6;>$pQyjUm6TL%2=XysQl1ql3a|FBdu}y(p z3}Rp-XDO>ylQvvusdqB;oH3nA1H(G=8rpZQi=E5wWo#6NfVIhoMi?eWz5Djv$J2)y z$-`i?L?47gri|ut}37Zbi*TmDP5eZ5D0wE#=H)j!%f{5ay5h=9302*-* zJOW1*XF@qRfoq^_d|e-kMW@F_N&LAWMA4t0*~lRNe{Sc<1NmO+}|WyFE_R}_6QgFa{Gz>QFOAc z?X~7hcFgxMpuDlSk4DRFhH{%8zih3NY9rB$;jKf%R?8auY}W>lp;-B{auC@PiZYmp{#ZT8FN zuRdvPTGB|uldX^>uadNgOy7W6s4M(ctYW>vjuNo#V+ltG9kNr5))c81AC=ZOHk-)} z4p1N0x1MZnf_;(pE8Ck8Yh$m$Jw}yeT}3&rvbV9f2>~8%Jb1Xt57gPl8FJ?h+W=dl zz}I~uh}a?Ym$=4v%le!Muw6U~*IqAugION7=bx(3U-ne28h;LT*^5=Dr?f)7Se4>; zuA4tB12Yj!_bctTbrAQQqYzY2G`)IAy$IK0%-;aWMyj`JAtEKFBNDyfV#msrZ8M?w2!|cm@Oe?)FYB8=G1#JsJnm@ z#L$s8h$~RIuaD|-+@Jtzn_~!lKb+`Wd5lvVIjX2`1+8EB}QqF|AxIegM~cp1b%U_%oRM!R}_?#(cGkH02c8okPxgK=m0U0FeZ;5n@pf6RbTL%kLWdS!KjWt4bpjiFY{Y?ay*^2HMBOU5~R zj$Enk(@&5!T}RJ`?4k=Q$dFExPAC}UNsd40f*>p$uw{zU%-N$|9|7Ub4wbTk_{J#i zl42#52{}c})irdXNU$8Id$Em4#iD*Uxu7GLLNYkDwAE3ku=Wu1bp65X^?E&3Vk6Sl zb1`pZ+}Tv2E0(clicGntrCCuw8DeP*>#fHQYG z`;6hCQ2&Lj8A)=@Gi`RHX|6m3!lv5g2wg(Kapa2~wlvmZX(vdhFCeJ4IFqItW15+T zz)0?i%}G}Z`L24W_QaCo4YJR1=2 z^yz|IW7Ik~lULvK;!?JZ5uNPQ)31=v%xETl^FlTB>R@=@CaU;Q=%Ex^w!rtI@x)w) zsAYO14LwHz1M}@j@D44X&@#iThMdxh+uUY%P;gDn4`Jp1W4EIo6BIUS}MT}cI%F#C%moQFb_&}7{* zAu8r3e7)u-cL=DW&lX-V5q&x*Hn8`_7w^^QzA>lL$lEIEx_sM}syL)4&pZ&wTVygl z>S&HrRG(6%JCay+=wD$FdoJ%VhZERPIlVhDRpp4K@1eqs2KwmoIpG$uJBEu zbQqU5Y~mortBvJUI#ARhBde2d#Yja+k#oG$azjhiXv9opr;+;Kp)sL-m{Nm&UR3o> z^5?iepc8d#ED_G|*h(zwJ6VhE2!u0Q33dI8=ofR2;Qp;>=WwSC!mL8i=A_l{Ot#r^ zQb{esyD+wWqU8B&U1}jFaEs*OvG`Rs-ZOPR&_JAn1RF-+q5spM6Ud>ySKF-MbYF)gg>T%a6lJ z9Jfc!K2cx^4E(`b|8cjcP|=?x&pt+++T#nmqhQf^4jARb)2xUYtD?#rZShY3FCe{e( ze-hA_u+QUB6CST-BbJuz7+DY5JIL@?r1x3ukR|Pa$aEFmc$QkbE6L$8mlb_uDJT)Vn>1l^VzEb#9-VGgIjx(aZB;;f?b;vVTXY#^CRjQ)1j0$Z)hUmvW*gYMCrc zzPI!}w?Yh?E``Ofvcv`&@zN%GivJ!5l3!fKoW43kPELg3Y+&V}M#cmx&ES*1+LhS> zlbZvKe{)=-Pnrqt{59KcZT<4KYx=ppq1{%y>2Shs>&xxk#VP?1{>A=Jeb2R-?YUZv zSR1fw{Xs&7iv1PhR+Yc6OKm>u5F=~A!C*eOTME`hT&WWx*%ENec5wFzh0N(a zj2pMMJ#=7qNJLP{Km{^m9~MJ6(vbMW9yU-Hn05#*%C_Q--pF(Wl&*hqD>Job@y!tMjZBX2^m{gd ztfu<2x#t}=D_LS9XFAW8(x=7K^wm=C-s!Ep(rkACN17Xf6?NQ09d-aQ`g1f z6d+N9{;3Fzxf>>Rho_}@A&Q5)w+Q=`Ze;|Z29`S$1CnCYtcI=T(+J1yEkPW|_a_GotMtz7q2vwmB zAzH*)k*h-Ktv)^zT8sqQ%q5&$KAWPH5i9p;T!GFPC{AF$@VT;ZWXVFNJS`aR#R@`a zN3o!$=wHT&{thLB2AzV=XUU#bsdX*La0J{myV0Xf&Wi{>!W$hksBKoMb!s+W0A@`1ywE+ksOj?{i zFO+^lkoJV=+c-~RAh5jorb--}gtfjG--QWJk?6{L7j$wR77|$Sqau35HP;>jp=B6T z3F&lUu8XR1Fwdc^I7Bm=zo^fCI_p(ZiG5l`Pni8CeDukf0P{7*uwJkv-!F0?2OOIoC8{*7l75|qmi zQr#FkDy)jUXC#?MYi-)vfQ>`U&?;8&-0o!$xxyeQAUAa~GU z^GZbg8vh0^xviPMOIhpllqPW%8)$aDKKmp}pgzG}@=dTT*;TZmYNoeQ7=~b|Hb2p= zM94YIO6sI!g$%dZjS2ap8AtBoYCWy<8e)sQ2h=@5F?OCw=GGs~T_4lfbNM0{&ZTCU z3Hb}UW12C_r4h|Jg($D1cLp}1PsZ+}sjio^%@QmY&a%mzIUeQV%kE*+2@En`ME*yG z5+Qr8N6Z2hTb3X1M$nirTA+Y^#NE2n`4xhXV9Q%mG{6WdD!=*0*}6Q5E+pCTJJk(gFz#Q{f|FUqANec{xj~>_RN+e$X;)eCBmxvu5v>gFcVZ0yiMJmoa1l!ocW_aRb%FrWFU6D%y8zRD$G ztrB`SeM)l4mBS!~=+5`~g4XO9xL5_9NX1!eT*oUkusD+lNMzJdv2-zQZ4dQ3i8GU^ zW=%>x?^DFQH!`#)Aypu2uCZC&MXj3ZqQkuzf4o2Ivu{jE6V_^!xZvt~5fPCqi$KKzDT8{Q`HuAi2q_t|rZ{pLOQl*1S<*S&HLC(62DZ$1r|1THvH97`InApb z(SU;-?(H!{#TZSz%_mp9c`yMybQLfqPwCE{?Mwb)_9XRl?``{%wdz8(^LOrlcl(l5 zc$2M2j3tBQ5!ax$Iw#4O7j3Q(XM<5D9Q_l%jU; zBAcH})dg6{E}3d2i?@~}6?EwIEa`I?RUy;ejI*}AONZunImyNDX6}}nr2N!uN9=1J z_4^09aVuhBmoibnO)nCI{c5;FUwT@J$(=LyW6NkQijo|E4zKWEb`S{NU4TPPZ^&}_e{}z%dTE)@N#5h zkCK(-{tY`7{qsG(sr!3M@cp;%Vvo;NP&#YcQ8|Bkl$MlgwceF2Rz(?O>5s7Y~uEnBDkEH?W_P>j2MV<`R( zw);jvqYsGy4CXQ5q3>{`$w?_V@%Qb9U%nmbx;iSh1&dE`6-w8BS*8Mv?{dR0(_lYe zZK6A^ZPPz-D86m84?V$p^QpXR@MIX->l=~mqx*I8l(?$6_V|9EZWSW#>_RKVorD{5 zDmVZ6YTMG|B$!JbHQ4`yvb(4eu=@LUck!o&{m*iD@u!C5ce=Yc5o^R&Zq1*~rT>8M zE>5J?6zYs@VHPQxf6Jzb!oJ*3ypxzmR^AJel&0g!lh`JPLXOEhiOTZxokVRu{{Lhr zaj*Zx0t1C@gx}Fl;wTJbrl8b(_dAKG#^xgI+bYv{5@Wt}-!I)D%eE}6LJ>E}C%$(XaNEdDvK+jQ5I(dffk87AzOqWK3w<}#?b`dAOK*_U6}ssx=oIPF}2PT}2j8<1uc{J8fNZD6%9v5cO84C|lZY?;W(xJvVW9)G~Ii&bb;^nQ>QPvlGDNyy$Z6 z6ecJ;p58gHmdbl^_cDG<4$ixZv77jYq;GGgfpy8%Ke%Xj4yqh9qwF~cH2E1GpLaUR zL03mRRa*$sJ4lGiijW4~6Xyy};v^$qc(CyhX?y4zOQK3U&t zOI4>#X&@*5JVCp=*L9H2KT&G6nlv~v=18PfA9Hb(Rd(1v;XJBn#eVOw^?F$m9kV0< zEiuuN0u%HMsZN*gEWL zPxrjkZuR8ypC0cQW=;#YhN(~_gm{^5QN-e|>cHVkC-<*cOQp{|`f*YdWdoOeg&&38 z?hE|WKE06}7H#4#3E_j#ov_hy=QL@RP7E37t_^G&6vzg(6Nov$2PgfK^iS16@E1s> z0hlX_BG5iAy=v)t;{8GA*DvUKj_sc7X`uZ3m+&01iT9}lbk90{t{J8gU-U1CS<*|| z7lR?NIU_8{fesWp>>eDTd>r`>ywbu*)<}TiI6~=Ro=coBJ}?GkL>;28fTPpy@S@jN z4<&Qinqn^LbqIDVcpN}+)=WW{wqY+_yQhv2|0!f^?v!%t3>IeC;ESKMxS6)g)yk+( zqO2ikE@6}{<;%hg{lh~Wz&XmP2DGtZw|#NaI)`EhkOXJ#OSu7x8xL`bv<>zV4+jA~0wx`Qd~wt%A#EYZX{*=fAb78h zaH6*rZyTwRcGg9&0L(fy2#SbANm3wiWXho;)i`p~Jw8g&*W%rLJ$m?xa4%)i<)ch< zO#H$d_^Ht*!mtKMl7oI{pgub2`$~4e#iYq)XZU?i#+OQ)og>EbU#JLX@}xQ(oU;=9A(9MXK-;clvFtDcG?UCRb%XY(vdWna%323i5m(ii=aKC$$ zr@qxwDm^_`*n0)GzeLc!YWeJM?G;f*5c@tZl@Q6X8JvQI`!tn|N;FVd9<~tZ1V$$| z1B#P4mT{f|y7fq8`MTSA6=WU5=Abi=SSlF+IMe&&loQ9A(hz!z5uuup7mD*ReAQt- zRLfN(1w;|enB5)|JKfbfElg~NU0L_rn|?tx1TsGWE@j|)({h|-fy5;NwD!HH(YVpe z$zVdaGh+LQ_JXnkZca5^y-wkgl@7@FI_G$i*^#|cBtp`h_1VziuyLpk+UtByG@-sG zlT)<^A&hVi`cqKeXjv(9NPE=!s^ez?!{%9HqFc?6lQGk1mdob{X3|o>N6SwsZfwD< z!hM;dkXmXXj!Nb_VPc2tb`kr+abTLzgC`rT{n@y@)u`+~-rU#=&uh)yy|s;6IY}sCQ!A!sjt%EQx3tpOtF)4$I%nVl&h>wBTa#bB)f*kI*k}OVcfB# z)Cm1;%!NuZKp!w2Rz3{3^wlspYY|yEbU5l&8)d+-DP=8tWva0-%tndRLwH$W6JxC~ zUIc%ToN9VTyU!HIFbfizT%)fS>I5vB6((i7tH9_mQcJb8jtbLx-J+{I^ztL77K8Z!Yqpr z%xB>>tuJA5M_!+H96!*>=Vn-I(hy3KX%3=jE|2yo4&@`nw)TwD$EUnatuDOg$e{Sr4;vxfoW4oX=<$cb>09ylBb z8Gi~XvO^6_HI6d)kuBHvsSU3`=48>txqppFb$&zyA-UGB|vU1Tq8P0ED0ErbP zpS4(`V&NIZ(z0&!vU(3LH2FQkn8V))5!ZOLYa|chU#-9yFyT|o^QeP~f!Gq5RN5_( zwd7v{h;{TsDaiAW`!Hd$WsCnoDSo!EA?r>Dj#mRq=~GDA-v1F3ezJYug&YjaW@&r7 z8Pf7SCw7%QNk?^j2zgigr>Be^dI*Y~4p=SOWQO7%GBlITR`2LSw~KGEu6|u=+MkfB zsVjWXf4=({jZxSCp=;OlbM4{PE2o!D?TiEPdn=dRM~!#}bj8sxw^IpB+iMv)?@v%>pQy)_v0+t>^xW^NLJ!fCd z6snw|#kwy|(zDZRGfW9Q_;|N|%ln9$Z($k5NQ_Be^}QcD46CnACxd0Cdoy0j_=i13 zHr#_`rJ3L=(cF8lwEYV91R3>U>OrI;lx6M3sxM6FHByzgK%y#VS$6SH?CZ@~GW%wIzNlu93z16y9No(j?Q zt;37RBr)vUi-bvm@gA~asFfEH4xLn|`<;+0$Q~K^8MnKj2~0Spp|k$z=T7b z0ZV$*U^mIC0p66Jz$(_}IyN>WN@DKnEZ0TyAr9|*+$dUnH^RB#5EG^XV?wSmB=dO| z7e_$zAqQJ;lYz&4S3|FjLJytfn5$E!Ko9w@hQ2TgJ+NnhF5aC;n5m4Kr_AjU;6Xw; zY)Q6>pr^^PJmfngkb}T-$P#oDAx{%)rTPEHw6p(r;o3F*{HLWa(awG;TL!O~eruCc zwev^*8i%TVqGGAiWYxa6y|%qPGoQ3C+u8tP^1f)ZMaZ;!+-ZN6l(k>Psib)<%i8wl znDFv&PbAZ2TmT}xB(Iedo8x=SDV8yCJC^4u}%pMQ{?eo^)n0i!)u|_EFN*&v?m(^ss zY#--!a9(>Aa-NX^X&5eJ#=s&oqnqGaGbMg!vm2+`n4rsKuBZkmkGehip!D$yVaaC} z7;0x{NP8KbGU&~=yXS2)_n#|JDR<$@Cn7M4H&1$EOI(8LDJ33aQ1-MWYEpnkT1<M7$kiLzS;F`q z$4MB2XlS-|Q(Go7QP6i@jH%5G1RZPA)|0aK)XwC5VTR$WTkRZ5pM}*uQS4VPPPth- z-E^ZH7pfmtON$HB8tsz7+w*lW!9{r1#d3ULYzQNbaikLqDaPDZ|J7SMC1X>Kg@B`x zl-;I5mmYo_?bf=3wjx!~q86KP)I97m5D+=b+Eotohb-N;ji9g>GDv3K$3FDcBoy_{ z@i+Fk20GsiwB`vPVuGnR+e9m~(NGl^*!0l#GYrO(gDd91Lj@>0VP70sw7P&g>ueT}3pEi%_ktfR5E z#s#<7FWnHUOJPicT0o}8*4}Ov=MHU73XgQwU=m=r8Ed{ZPzH}EMK8_vUQMv?A&x=n z*Kj&IBg*hxN;j~nRblaIEsm1MJPX`c32%Z9TinbO=eR8**d)IZH!iQ?vnZ3SGaQ#} z^QX)pwiqjs1p@aBuz=9pbD@)~k*Op$ZKE6KrO+^|5E9U4+sld-%SKUQ?$OjL3Ly&J zxGsl7c^S~x^0Sl+q@(2>GBWb3%)%}6Na$nAreU(#ki@0wAyFvRC@hm z+*vCrgX=uONYi54NW=1<$7wHz#k7+~5!6WtwkE_Sx^hFi6lOiFu#G+JAHYc=R6n>6 zVk>#BfC9Y})xww(KU9+WPm-gP{ywtTtZQK|u)QKFX6I5Ev5=WUWw4w&5s>f{4D;Y} zUkHH+4i26-L}=4q7!kw^7Z#jWPBJ<_t1T?Nh?f(b<2`&d2toXb_s?iOlCFTac-hlD zj(vmA<+;7a&V%M&WqoJ+(XAg=*0*<7o40l=LC@jIjcPokvg+3ETty%&#CIFNsbF@W zG&?CteahyBZkskN1p00`VUjUPF_+fgwA4_jRHGXty&|ZRUUw z$qSk<*X5BdoHFc`#qtkPsI(?SA9fxCsAW}WaVZ$Pfri4M%!ljzqadw`eCWsS1JZL1 zd>~X9?Ff13ZV%$tYKT(cw*hb%-@+m|B=25_vko#1b+La8b){2ReZjM(LA+zVP3eZq ziIF-SUr7rYzKDn5}=8x7T=N)k-N~^KhXjQi6GKyv_t#9&0&gKaj)L9M)apQ48 z;ck+s#*B8$e(Rt$ib$Z=p|2VvIvKR9fE|ni%jPKqfRceS89gWrxvAiAojM-{XH%#Q zbQ;HaH`2_5Q9@zxA1j9nFu1@UGzjLbF(zL8Yo1-%FB$9CR6k-pD>6%`a8}B|O>ImY zm2$K(c+i_HQkr^Rku^D5@%F)_nQ0W*MNh{GGE2m}z%c<{V5t`VpyiD|lA(Ovq<(G) zvuYcmNm8D>=$R`FTp}NFIbx3J)>-cq<3C18vVU=Y7W1GaxE!KZq-B`Pi^3A-)&#$t zl%F45H(H6qLstED!8JH(F7b5oFVWiM*kq}H)|3eq*>%MrJ4n}#)3h)WLl2xCi11!IV~49xim=CU*{$a z$y8$3>-AY^w%@~$wtczo1_R<)$IF2+7VOi+X?8P=H~#>U%59cp25x?cnmd-H~*b$$ra7j5Y!qc zGs7$kvd$S+Eu_Q+L71K6S)>Upa%li#LE)n%D)zi4$I*_jcMH92^J*lq#akVeN;B#Z zSOhLyjx6b~^?1LTYdy0z!)C>uv+9%rh;_Of$n&^MFyjpuZ8q-HMP`k*`mX6^WedzF zo;kSeVa7Jz=FXE4HXwy z@+)I;?j+3tcbbjKB?e^_CzY<|H~V2hg4I<#v%JM|6U-h**GPH3?pkJ8I)lZZ-<83iee_EYJ;Sk9EULQDN(CWdRi3j{JR zSZ2gb;?-9jxBct9jc->4U}B}T)AV9|KA{CE_Qv{g(zb=P_|3ptw?4B+dKP({Ru*%} zvvav_p9RPFBQSaOb;QLiQJnIyWF3=9Bn5pzh8J@GsMq~*C$*;L+nGJbC;l>v)5tJ8 zdjxCx(R9s-*T4lyu;!7Q4C7OzEfmr)Y{?0JE2fbYCtZ(gDS4XB+TK0P+l0|GI)j!K zMfye%ne@&ez}cGk{X#Yq(3<=U@2Cy=_Xz@gyh`>v`}>2wj$4K5-IiPC_9iJ&gJ+V+ z(Xs(K;!-(_l|51Jpk)1j)V+UfWml5lM@h4*5iz!GXV;E{_38~r!h0=VviYN>mZ)ZH z*lf1cR(G?9WUEK+*0vtW$8K)(*YL5s$<=D4*LL40|*ljXIxiRh@J1eeba)&1ejVQj_6kYUZgy=QL{^4ASqr$@*wZO|eC1wM*DvC+yQav#5YU@xq=;j_ zeba-jV9L?c7N?mK2_`X z?}?Dng&mzjr4B~z)4AUm)emNK%Ocnoyzkq%2!MK zv=I)6{+*<82V@5N!d29qL^=JHl8IH%^2VxeSl4FtO=`BKfp&w~UMTDk#pnEyufTyH z;`|$p`M2gTEi8ZYo8Oe)U?tQ7&yYf8(Qg%IWZ0W!K~0?B-gE1tn+FOi85hIG1&@FJ z+U2WuOxt_d3zU&c33F((W}EPCVu{ji@>%%@F6wY;lL0aeNP_oP?{vt_p0?%5kR=VX z1b7ghV|!j!c* zW~xv^D7JoZ<&NWeIK`tS+3%?$ z7Q?Z}6N_Jv>tvIeQ+F*h!qo+|=o7en+zkgsYZqCjYJ4}k~s?tzjMF}3-t#rcQmPRo(9W3 zq6^5Di2dC(GYqpCl#xe zXfdZxdAd(OX(Gweapn>7uF}4wr|S*`TuE57mIC6*GZP{K74a!CL6rfnQkC5*Zqm@U z?*e3yoC!ohJ=g)^=5mWrf-Z~#Fyj{LAgQuckba{4_z;v^&LJi7s{1wv&h4y+O113H z7%k6)o0p?#AP#y^U{uz!oM+M%=R%UPx8H?_QNHmp(nHSQ+F^t52kQC^LUfT$?pJsfP&syOYqBh%0i&}YMOqRlh#=M z*UVO*I*DXvVl3;EHD%itA?v$aY^Ja!D2sfDYljPRNvo%CmF2yEj-{)Yk*K+-ZAZ+k zMf2HKv+zvbK}MEi2dewb*|AAe?Ce$^R-Vb`N>TPfv58?W9`&*)_*Q1DS{3|az||W( z(JVagsA;XNdMMwl+7+M*i(ZNqET22SdgLL4K-+NhUH znafU5#uJlO0GCHa9CDRJwptnWeeX-*X`;2Vf{c}@CQO)aiU{P=Qxj;d+;L?NK2|>^ z*f#N2#IHnt1ZJtjUostVbvL?KdyM}*n1P}94+`AujKECCN`xhi;WkHUh)}_XPI8V?3%5`c6+pwd(>Ark%~A6o^@xX~ zuGt2lSFd?*v_@=m%w{V@acqS}1=+9A9WW$}&F?{xf{fvt%L?kmG|V60j4y?OCkxXR zUTB*14VuE4RJ^0UnygM>+8z{z*gK+?aZP_XYmlJfQzLEu#+##-re^-1VFD!Umsos;&t`w);Brpe} zBV^zg>+k2I&RpE_ESZ@N5C^P1=QV32^lQkVnPezx#shwaedMPl36r&jiaXAR#G2nQ zdjV>6B0i@*%uK|PUe!G$DAl;mzzW(mf!J})qPkoRznPUbuBGO#G{G!}kIhVTxaLw5 zUz_1mh|}Rzqm|qbPc;7O;CI<1JyC-;C!9hB`40}$C3nVxj z%<9O1FVSw}+wYE`vXtQz#4zR02>Z@EcN-(s93$^(lJIi(ckjw&A^JP0TrEdg)W{Y$ zT3OfYKdH$|jv(_1R09A*C3u_P$oLH|$6A34e*D+no%7kV6Il^hh)*e&d= zTezJV#X7p`<9V`%N(x}x5`OD=ieVNxu){f78=>LnYd=+jgS^`fV)ooc^cpF6ghO^V zQb0v_&V9gf4bBM=ol6CD9te^~@43_2+Ur`_F>QUY;i2)K(j7*v zBCf~2m{X=JIrn;$tTMa!w88c#jL8NPDu0xXg)HvJ!;D|;I@vy#8x;9Tg%stC_MYd`1lc5c-{;W4!G>vhAQYu0*+%h0c&P7qRj5chY=EN*F?!97 z$S`Yax372G^5kO)2B*4Ikwdi3tmuEW%hdI`zgdS0N^-4iU(wdpnzlV+ueB6YZo>P(|aN zZ#9RBV}vgiGDd?MCq57$7V608Gx3-cde6a7Nk;uRA!Tc*za}H7PJZK=N6KddFLB67W4mXWr1V#o0cc3mi@=k&I=KJ(X#;RLJoP383KW5TOyet%=3B zvLzxhg1Su~*u4w$GvMawQ)!Kk5Z6>^b}UpP^Dqs_FI|*jaml+<$)x&uS9~YiDbfOJ z)zS?giOt2&u;r#S26aIKCzBN-Yh$>o$vW9{wo?a5_Cxwc0QQBkx7uq&tntx1I09L_HL5m2p`q)ADPxer>fz_3EUr(?IGYbG`PNVo1Wb+6o!<;iQUN4`Y( zg(n+xNl>XTpzK--_%~OXVwtl1>g33C#`8((PqaNS<6aQdS4@OWPNpj-8wY{!Nu(WDSwQ9wc zEF`Pgin=B-=hJ70SYKO#Kj{@dUNen%LM^c+vmf8nxX6(Jo-k`rNH8Vi?`I*49nFXn z1^Pmn*frfsIbwd%N|k5`>_Z@V2r+~BTA0_6R@P@pG%^|oI_o4!TOkeFK#wy>z9Q`B z^Xkk*JwssAgH$P&ux$U^94dhc$4Mw`+#?FP1t*nA$2_203{Wpoxd=c|pHhED63IYT zK{WCA6uQNO_Wq6&#Z%0m3hWa{+!9{>z)*M%Kh@dlrYSVC&!;#*i*KNrN}bkK5-C5y z!+f-TBuyFf^EwP+KLnMIJA+7X5^b&MKZY1|3j@3PclW;?Q&w6q-5wz@MDZc27m zy!-k5W4eb}A$seb-Nh#`K*l}Zu~KI81iklj-q`nC)9D%aIS4Ze6+hY3cqijP3rJJ0 zZO$y^3@Zf@G*XVRu36$#%2lRc)nFQAntG`w7crc6+Z!FN6KxXLA}8cokxY+vH3s}7 zQ6G4{+8v5Is9UNR%5Rb_3e zaGPzcC{Hz1FqV==HH*50LgHOJKXlR{GBvDFauYP7%3BPGtO$W^t;%)AL8LRhha!gX zw>8U7x+r9m)%vo`P0Sct8iBU*LWS6t(sb#B7g~0@aKQb>u%wA{*E`tbK%gml@U$z5 z(#Y1iYQ|1sl1)J(%TRmDtXRz#Rb){_)AeLm~hQqxV>&WwuS3Lz3x5l8F{pdfz@HbbZdErOWqa1YMtljU~DPtw|2eGIaUy%ARgE`4vqK} zTuDr*X`jAo ztJ4?#gt4YIH!Xx9RyeI7An7k#x|~Kx+Z{N#)lusi;OeI&yvjkZj_He1m(t*u5 z&QF-#VX*rMg+)-Z%^7^IE)#Sb0ox1*c`)U|c;j`Q1~J#9bwx7~>#Oi^mm{?dzl7B~ z2B-TxF-8kJ_%xAVny5y1cMWR~+pw@b*Do=b?e89G4u#waljP#8cd)k5wJiV7s<| zbYf^o|62d?$e$e=`eWs;?fLP}|9cJh2h2eV5RQgh+1=4rlNqzRaMfw*y|zP+{VqK# zbIDhR&@QOOIigXRdfc*)=5!Qu+z}yhZx4^)8YhvWfFPUHL{bzHCpo_Z>U%CV7lrH*bg$C>01>glr0=j4?d z^)=lSNDZKe-7$-^^Q~9Ef8*`vh!)a0SQ{UvSJj41_rb*?;Z_IM%c6_o%r=WU^(mvD#1l!FM`04gyijnX0!(e75%kY|S8KX#Dp^t$-qa+b3~xi?^90!Pwop%0w^oqF7jEhx~&1_2gX3I z@!-e!CC=0y?Q4*{uGqX$)y5G|JrxB*PN;UiiAQ=rX{pXF0NLcj zUmOp{pwChs5sn=&02Pm%^gtdgrZ|CdhUr3VP_LXsNJ4im$hgnI-s5IOlvzS}x+AmS zt|4bYk$N6rXAz)~DrC|)IYXYubGK3}lCtzrEIGK_#*r~L6{4jL4h3QWCpMhos%Si8 z-Gd3&H@0E;Jr15J+&5V1vVTMk53p+(8DSTt1E6WlDT$>!WGU48tyU5t#$R5!-%^I2 zgJK@BHB_T>l(tIXWV$=Nu|+)q6R}=iX|RP^LMK&9V86e%Uv;mZGZc^ z!21c9#&SOGCCv_C6~+`a6F)!|o)I~n9p`kX+iCI@K4!d;q8B+-AHyyHB)7-KrzwQq z3^xW=H==0Muk3@H!KuM!d=+sAq*l^r5f6AwH*IRQ#CoT^aE`lQ6ndwzxvgcY+A9kg z^2d=g+$6V&UX%i$Isazc90J(2K!zJ53-M$S;h5&q?iREN83w2HEYwBGiD=Izob*H%hI4?jl_;-gqe&KG$U+{R%XhIV0l!^W8+ z!4#uGYoasWi?fXugJ!aUp49-Xjy8z&8AuQT9j99M8_%6-Ja?9JH_U>Xkgyeo_&4W( zG-7x&Nz#sRycM9^z~KS`iV+;*-SemtrM0aF1flE2l-#&;NFU>NF0I_t1a4DM%A>tR zbjnQ{NmmFl$fB@p%O3XD5l31@hrYDMi)hi%rtBs4jUS+^sn^|M%{f6qV@^T2E_8+z zH`rI#vU1AI1#L{8WtKjxtCd1tWLS*xTzt+R%wTQrp0q>5?2^Pj$a80(+cyZF>#Cku zj@jK&UKuw?N%2J#n1m2E!Opl{swz9RQIKgZBe_}Ca&mKbe0wC+2P1m=X2MjNXNE_R zcnOHc*#IsT6iNov#`OcnfiX_qnWyOY_7O{O+pg2uJzZH%&-JO@WuGH(#n}?eg^1^dWVmQ-7c}i!z6@6txkCOUFndh&X7i$G zT%P;x)wz||XQy7ke{$i= z=1_S71QcB6YP-er*YG?~VW`{PE%p=Bn;zpXMLn{p=c+1L^<;jMCulPrcO95R1-bWR zk3Ht@$=e%;UZRqw9T0+DFU?(CUJy1xom_UWbRM)$$Pc$5bO6g4?Yl@~GFRsCPLM~> zk9l<~t*i(aWkgP`F0JLz@R`6g@j<4{RHcVr+JULmwY13Sa&r3(K{kJ|zeVUzJIW-; zva&&a)T&6~D0dc@7eY6;VgRBx1$eQ(q?s;vB!P=ej9AWI!q3Anhs9h`xSV!`Bd|7R zFU%3(fzMmB(*+$`<7va=D^etVma>|k(LE!F39@)L%a|m8$|qGXzQMEI^6>#N0?Ocr zR<4YISZJ|(1MWyM1T0~ymO^zqyPT`EqHuM4mCtX_T)MctQta(()3JP4b>y#=w{o)c zpfTCnVisPsGojl!E%wH3l!L;JAopm*R-(mWVdwYzPxNc&RObwW@R@%5lAXP;W!YI&44>3ii%G08(1^5&7W~~ z+-y`rurzzu$}S7?Qn^XHeK9H>Kjzt?BNmR1a*X{Hi65n=lOgp^JoOa3Ad4rPc)FB) zW2?=!n=ujCw4O>RE>QK z5P9|ndh2(Ao-iS%EMsg``{fg2c9!TFe#B9kPIkCW3v zMv|y2wJ6zn{ztdDMVTfFh@AVnHr#&l=P9FCjyAGO50_neDr$B*bqbc+b9yA z<2A`18^PJg+&T=s*3YB04(pMw{PpC>iRvMu78Gr>wZfQ$rw# z@H08K51lxi9eFMVYcd4#-3q9Vh&_6k6H)-s?#L?^{*Hq_#BN1g7dIx~E+%1k^&f?c zbBheV8P@WgsT$|!n9)Zz`ifg907-V$LS!uqBh?+T+BT?7pHx1f%$}pR{o`w!8c^MS zR5#UE9Vgc2u3cJD^J9~WW7Q}z!?@=Nh$@)qz@7}bASop>W))h7wStaGcQFTf>O_bR zkUS{(Rd5-XhE3B?1c0vSDTWI{xS8o(MX|S08*dQ2V?}mSWzWs zB9(H?8K*B5G`BMIItuOZRGNM(U)563ZPul%FGhOhFiO|V>(&m8vfh~e2dKd|(*3l~73x6G_ob&VAo2J6YIYKk)dpMGQAlvoQU5-ub_m3K-4uBOH!;B zQM3$BK{XnSRWXUDj;}IX-Q`YVLa?2hc=^Th0~QOKnwgCvHiveQYnQe4d4XBUgu;Gc zAw)kg=t2^ihGgjr7yq~@-4}*H8YDWv!#g( zgH)X>bejZOaV%L0vTlweh=g$qkaczmK~&Z*&J59Kvztn zi$;$*V&?(_t=5G^JIySF0FljbPV9!?nB(--h@6QI+aHEaNXf}QqvOgvrfB1jp1$^h zN>mjCRR}}5;rD0-Nn~%;$3Dd$LE>(hvXV?@RS}$3mP_!gb;B2-tVN~kR60Tfs>xxv z+}=}x*1L!A#i}*^d53(5vk~s0POOKi(+OjStCXkO7UOJ@EP`6cIk20`s(MARa5((% zw`V)_MVPq`Z9G@1Pn4)A&eai9`vho174IBWn>X!HA75!45flf_MWytE8X~hjN&963 z>7Y6)_2}sAk$!7=du8!z5D^Eb*;XiZOZqQ$(wjfDmR+4R*!L^2SD39NG%u&$RiKk9 zA~5N4h*AL3>e_#*c&7_)orvb?SsV@wv%gH#I{1M#Cld)U*lBwMT{T=q(wfp_Fr66l zKe<81@sdISDp}cG$#Y;dkUof^Qys=4HO;LF4v&u*RU|T~_V$AOuek%k4zIt`cyq&Q z*oc&DJ#xZE<*wxqSW}~U5-uA6P%QyH++>}_P#%r5usM^(ZzONAFx%WZQ6jArT8Y$C zCxn907tX}AuY}e4f#1?r zGMtg9g^av$vdAQTA5lgEx#|=3jmhovd24xh!{hGX?A(~xhMr>*ACQ5d^|WS#n8-cm zJA)j+q21`|Nuiq~JOW&?2Ph~tPg~V|Fh>Lv6To)(yz-ujg5H&j%ySZeG6w#}jOK^M z5Qx#DQKLOO6&nP^E3+gDdQrr&6;%V4Xt?#f@y@k|GqaTu&dEUL87*jVr(E#HBt3QG z!Kl{4rM$GtE114|PoYMLEY-O&`O5UvwrSfg&B}Gr&2Hl+0bRVQ(aH31YJww1YJ)&`c4O)7-Fnn-sG0+&@=M9fDxBaHz-PbvP3KPIIxT~oq6dh*kc#P| zlM|*dm>&`+wb_Z+SqoMRxA=7{*Den7eb$&j%<=;|%&4z!Cb)so_fGEleS3(dQuv;b zABAcM>f8F_64%xwzCTbGNfxsRA;snD9dx(OeS+{xJC#FTv7_G%N+sZ!N-J-&SeqbF zVwMDJaM+ls0MMARz+0? zGukM-7|OVE6&1DIYVcc<62i+q+eVZ1L*Gi;u0L10Zh6Un+C^vXjuu zI{$E=?Ii-TJ{Y%MCh{S1_76W@biDeJU~Bqd}v7j z{-1Sufc{d&19Wr$JNJl`Jl?teUx}+X@oYyHgx^)HeZ+JN4P)%yO<;CoE8A&w&Ct%8 zyeIUv*%jApwg7y+g|f?XA}hLlso5d5wojzVH@)_(*A3A^_H_$-*lM27uxny>W!TE4 zm4B))EkhO#jfV`rYI~JR2RChUEw``id8RXK0sEBFDQs2>rNYuDPru!;HUDYW{I&8m zI177Aa$D8wC%OqlYphkKT(%Nbah70S+G$c?t!S*AT#W5X)>1vHzzZkDWmTTsrOhI@ z*u;PdZc77Zm6uBn?=|?Qno=uvMC8?Pz8bB0!C->n(SKmH`oI1sLqqyE|MXw@*3i%| zm$WKR=$oDO)!XBpzi~(`wYNG(a*a+dHd+*aO8kg8RS|~jj{NSmD z-C@gx$Sd+Z@I*ULYnN;LJ3g3)hvh&;u7!5@=(TGX%VJWX&65YG_A)ikj-;ibjv6@a zfj64v&R?GIV02LFHA1g-Pj=Vz{Ct;td~tj5$2%Q>u|y6y=*c{1PU6$6Yge{7U$kFo zDlQB^V0Tq{%?(F$O!>BhXL=PlE-JTvE4y!5E8uXMnqkdSvUKoJnKIcCYb}+DRD|`w zx>o@+`+TI1<^=B2KG30!N@k76Nrj5S6HhJby?fLJSY%PUgmd*a;uu&pZKWvy!XdGc zhmhoM&*hfg{WZQeu!?#<3U`%~O4A)om;$gMYfA0h@`w@xD#YCX1uA4b3(lSI52%0v z{sI+{Yd~3?EWbcm^=3ff2b2~fwuHg^sjGI~RRwSEnn>s4U7OCfobC5wS*NI7cArZ05>K*xz7!28D3=5x1LkDiXf*H2mOA}Hy_A?KjPbJDP3r$^c+KX>yB5Uk*{WS zI*RHyyBtC`R1+2Eo;~P9AG-Wr(Yb&7PPO3edz-G*ds%l?JuZuXWsj<}K07^8$Zr`- zhwjy+*Z#(-o_)u(NfF7J9#DB@Kni_9Qq&M^-L-OY?0~!p`QVnf!mh+}Wei;*{LidN z*3br(aR2Al-kPqbx9mvYgKkH|sHg2sJxRxe8fv7lyRl(OQ`v*bitjQR7-oqy?WD*l zw9SHFyMalq9c~Hdx3owIBDuH2OtyAMZs6_Ho{^48`bA}jhqV`3??q4h2MdRLQ3q|@ zKT;TE17zb+fFJ4Cp@?teNWarOaiiqj4FBG}RaIN-rB$_m*qt0yfb^+j(x(Tcha=?j z%EDE5g|w%OR|@;9JwJb1x)w<*uP-fL_p}R(m)H*+<}ApSCKP8Mk)01R0TY(A?HfuXW` z{cmHF??w{%ZrQ;uomXrZjTLt37YG;{Doo?AHV8v`YRqC$MqEw|hU*PGns&lGv4Xau zA|;tHn6>D#Y&J;IO&yxOF;VbecpLONaWxmdyD)!kW$xUig_Co|)obUL=a&{1uHgBF z+H~@bW)bz2_e(CvE>55%Wwf!6lNlR_~wlb*))(T2^nQK`oR?&r-)v70SMz|1l? z$(3qwQgLr~37vjv*FEU%X3%kqrS6g-5T=51ZQ*r%i@dE$I=VTKisucgUJMxBgh7a` z3C)uwn$7vf8MzN%)NIo!*RkNGSkZu6&FgGCtde%8$%O-&K&Og?MFT{Wv?0;nGOCw3 z?{Kf%QpGGn{0HTHW#RHwu5u~yBRx$FVOzAS%hw;#L@Zjw6C&lliJhgi^hTtm)1@@2vq9U*$-nRV=(o?sL2K;VrqA zT8V^BRa~Kv5IRK@AvrT~^5uz%lP{i{IQhcFNruVKCSJ5)xDqCdb~JG2q;q>UkhRz+ zRaKz@ksHbG;abg;B5?x@LWjwYJz&nLt{qroEfo@=_Kn*L{F^tQKV}AtTNLaPYwt+% z)37@*#WL)(At_t$Y6^X?$Py*_4zZu;_)aQ|F4(AOBtC+KXKo+0Ui5{tE``9NIoWDn z-QQ*Tv8^o#4v)BvQ)k)nWp5VETZ@Rpk=;ZvY5KL!5ky2&u`R-E#N7%HGRz7;P0TONjM28zn8~5XAQZz(3Dau0h5(4_7n-}$_8W0hD=e^ znM?yQyjDYP_!v+hzWTtS&v>%AT$KYE4hWE|eaQ4GDprA#qFu((Ztz7O81SBWBR;91 z2Sm#}C4#bxa@YZi@oSynsLcjTYmCIE%u%;^(kqr&zib?;G}XvwXZbQi$@d`*B3}|F zk~5y$dY3%Ss-L5Tgq$IhRuElil#*X0VsL2bqe-h#i1Ij=+(6y8O`!M&|)wPzNzzxQ2DDVj+Em)?@UR< zTP)3=b8Yzf&Np?6yx(Kar`=a_=J3nI4%E`I-w|1d8n2F=$kr_PD>YeCmb#EHO4lU# z1+MSrUVHhoB@hu2DCyhjKr5o$j?2l!m@dXn9<8$IP&Spkf-_xPF~B$rx**gbSfudx zz)Pw1N~sl{KtUXNfM+{vHiC3FNg zI-R~W6*^)!yxKeH%NJj(;()a%QEcSR$i5FTMmX}<|jQbv6#T-N(?^#6s-IsrJ{hE@BMP9YYUx zJacpL*sK@qjBo|EfyA(678jJkj>3GVpMhDgTacR6>y&$7R!F9C4(_|Vw~I;Tky(9g zdU7|<4eHiBbJKn$r;U7beo$8QBhK4%^sWj;b7^2!T~f~uQZTIp+gzw+wP9RAD?f&8 z7m&?JX0$Vmg*u$BTAJv5{lj=!!P<`+J!l+=#U-~rHs0LqJjhhud~;B(7ho#wx7GNk zd0|l2OD@G0u|jq7&@?aAvRZ$aSVE-KI@KTGS8!tP+_*YOCK$E=irw@uhEaes-La*3Xr*iP!HMTY&uWEsm_ zB%15+da@R{O?fjpw^*DcoTRNF8%EO6c7UUXHn=S9At@AUhPPa;RS=glXuk?K z5|L6$QmeE4%I~&OW%t1!jw1`SKO)dj;aG3z*rG2eG+G;nXJ>80#1Fb{9G#uDos)Py z?Dl--z5e~oDa<^qr(0N)&!mM)duF!fdmmh6_IyhwwQ(ypI(=f4W@9_V$Lj?*_V{v` zk9l{5{^*A!D?8Rc)0&)kzN}133;&5CGqc`kPWRWUS6Z~3PaAr9;4P~iogRH5YH+eq zp7Ln}0{42KpPU#y_41?pvw_o{$GOGkJ~R6Q)@W4+vN$2Zk>luDamr6irDhJtwG^>I zlaY)u+c?BtFT=ge_F7mK7thaMzKSrpa_#Cx?n`D2B4zQ~GLd>$Rxpg0sY`R$-&lC7 zc-OaZpoaIfaVfpF5aGodmHAzw6cf_sUh5F=72AN3D1L;Ka5izAWTM5A#k!ddOCAFPl3gm;RxSyUR(CCW>BMNN zNQr{{HJ~Cp#g?yKU08B{HOc5TO`P@qab2gm^`+h>4E+40kM9_^v~g_v*(P&55zq$6 z9NT8*)0YuBwox8M)Dm>9jcP-pzDXu&O7qTR30u3%fH=ZaQ@({>N+w`5sD)j4@KkWO z38YaokOdi#8QOYXgUv4U^Y!_m3iMOSs%P6XL6=&!xUiHNcXT# zp6sP)d{KBR;6{0u5w;{2J0<9Pfz7S;K#^6841wtN%P_E7d=vqeR>iM^)$^EsXDf3ZBp9mfXlAxW)0~sjPi`z9N|=fM!Elr!;+j6p!W-m3%+# z^qU*xA@RNlC{XaFXVpqILPL1Hdn<#0Jt$Ymn7r36e z(f(|{?TrMl0hk?P%OnO#WU9d{KgFit{;bOu&#mR8cS8)-x_?#?1l($H|IC=bxK97< z%{xh#zqyW`u+}JjBhK{^eu#4|I_X|1hDL9u(YS$k7(t!WtN*>RvhdxNqDi0wNoj(N z5?zvLj&#AS{2Ua8@(TCNoPN8nG!CtVVQSubQ#bX@aCS_=tlp_a9gB&UVrbY>Ba&vyylm# zm{LgRv(J`FLl||sgO&>z4BM4h#%?uFt$6O9e#VyaOOoFeo+``C&k>(sT4yIu_Y_qg z(|*TMtGYK-nsb5o`*K+glSP%ZQ}w?l(a>K8p%|NlDWm^AmVfj)O|+><{k{ISw6Jn* z=}JIaekz|Nq)L%Qy1RGqAUPQ3OIDjeB(p&~Uu4?oeV`309m_K}1!^?Ll_=H;obqi9GVta}?xl1y>N2jVk-4W*RF0J78QO{=(#-CaL>dX)-r=)ON8}9Nd`7 zF%x}oRv_TTjmy{)LVi*z$eA917EKL}8{svmQ^gox%qi)VVlU)8-rWnW17e>1#?3o~ zC22H^`&)|95CJ@L)@I}8_XgBA`JyV+iKP2h%1$NaLYfTL&Q5cRT$aMt+L_6z(_yo? zv4(%@jNN3f5p6WbqxM|5dGmX3S3JS$h^rHs%}@PPJjnX|DI6GSa-P$ZJ3iIM=o;Tq z-dOL^Or}7d!D#)TE%}p)Rn?tMDb7$6=y7nxTaGC z!qX>SZ7x4h#2cpaF^hoc19+cfh}f|mLrvnR-CSq4G<-REWp?KsVor>8tjr!PtB(bx zsX%4y)FQr#BDK!kDjA-e3GbV_4}he(i;eSKWHVYit}K{Dq9AdsE^iwbkiDT zL&8t5v^KrQ@+`}&7Obh75=Rc+%I<}IlwVwzW4oh55w;+bx2jF$8Y!6BO}(AE&lDew7~UXr7>gpglEV-`sEqpoVp+QE96r z*PRkdT|%W(YJ$@hR!aq9+j@z%>Ja5}Zkq_G%I1+0q~*r7oD1fv*P{)OB*C+gIv=%WNH+da^b?uju2GHJyPuh(cNuyLqoSIl8Pn|*j=Vm1X=TLpz?`~SG$$+t&!4Mgw~iibIk>U#ox0T^R_+UmFNu$7 zxQ{`EtpB?h0O-vCYrzfK3EqX)wRF#=$lft~!3%CK=v3F;)gql+sUaO`QL)Wxxx-qy zpRa-8M%}bQD9Y*ND1@natO-i>qgz0K1$`EtiEguHjSBocyX71m$uSKC#$3 zsK~Oc36MuHN*_H{IcGV_3P{=6f^WK2`o|tM|M~*XbMJ2ZDIV$Ou${^_Zpo7tCB(nz zjIq1@xzQ_+UZycsHrQT=iSOB|3udwVH6-UxZLs_Q1wT2u?0|M=EXE*lgLuZ*c$JK0 z^k)%yKHxnzma*K!KswNyzg4LFUpK#0$Og@X(1}FRDd|NKPkrX>z^ELL_6bhY6Xvn% zjsSf*W?Jc)RBBU7)t&g5>BMIS?ix8XOEB)oWUL#WD>DgpM{fYD&XQesMQ-zTCD?l4 z`#2*1N{rGq3XhhOEx9W9E5_$EMYzllFeUFVUb(PX5ShGcE7r?vuj3+%b)29C?-jDB zU_Gu&K|@z-p93p}S&KDb_o-^5A_&1opH&&!)^1L@+p?kczS}Y)s#259h%jSlhr*Zd zd2zTL>c~dXtQe$xW|8ZqU@it}5 z>XnI!*s2=DU;?n5m0|DM7pP;Yi@v#bC(mu>#+nv*W(M6+kZXb;q{N!nAD>uC`(D1{ z4}0<1GH!$x{mD00BSAg2ui;n-Q5-Wy%puiL;?=jDT!oZ>f-Vb^O%fxg&I=Nsr)#(P z9fLq>NZU>;l!l#EIL(P^@9CgADb{!}O=>Y7BJMN{+61~lWws5pQLRCZ_HO{Ca$kYo z=GL2?9D2^|S{|y{#^lD^xtkNVIuG#eW8M|riTMQ*@vRI_m-AyYlx-q%5vz2%-93dZ z9V14X8IVgYtc+uCBckDvBKG?B_BMLhozTN-^@Yjhr>_rS@tvqswL9s_x3;yp-MyV? z*Fu$qZ-J;$Vr;EYwt^s0+XYvJl8SXmg~oMhDzExX;7)#{kG0lRPMOKX@0>(YJR%4M zkn)86RplrVW>WW1MjS3&T9{w4dhBDF;gyDk(qS=M{b3yJuv$IyB-dng4mduu!8BTC zC-ZU~KjXMsy~q?rFf;X*QIYDgwR)lHR~l}@D%;Q#g=CD1ybM6aDr-jOwAKBn-V(Qx zOy~`nz2?-5^e5kCi4F9d#Ek?Y!GC}EUVmdf*R^&()YVirmz)XMeRxwv|%7hb6tYihWK ztSg7pWTbLBkrb=f@nW?Ov(4ne?5krCF`Rw{TUf6t#z@`|)G46pxqMhJjdgJOOMU3Y zxN3!U#IAP0t`7Cfpt#3)Bd~?y`hmMBHh{LKsN_vS>wWE7c zXaL^ig{PlK;_a|=tF4d&utXntYHy4gR) z8nLbVq%~ocU(wa#+ncxVV5nX@AZ#2rR_an@c6c&@B|)hd*A2(&Yrp5rR&7M9To0k!OFLu0ak~9U@bGB&-UiZXo{Un-ELyvMRLQ^l) ziLJ=*C(r(NWTl|fp&)fFNy!MM)3f)J@l@!9yP{KL^ zhm7^EzYy4Of4AaiW*F&T365KUKnHYtmrJh?qqv^UnN-AP?cc9lwz9sf8Q$vj{NICx zHa9l?8VD7r5o>@Ocn&zN&&sN=fE!;O@c5YMj{2$;*k}x-5W)22h~wX=!PjnM^gBkY zx=YC|?w!vYrvVgne)0O1jA@IYi1(6MLq9>p$5Ne*JHxEa<#22AAdL5q!Y@W^N%uS^ zskfcDfwCOD^2vs?Zy4*2c8dF3_ubp<%2y>h6CIjg49-PbUve|?<*H$#i6D6qnt zEc?uCq{%gtD+zoQ6o+=U*JHE%X0DiN85<*Jbx2m1*%Ty@Fp%!KS*cAlVQ6z9I5}mb z-k6+zdo@GK)he$kYViaRjp##5IqoU&p~qoE$b9sc^$L$w;G%A=+Bz|eHzJ&5dUuW>f_TIj7rl`^f&<3Yut7T1asBe{sg0=Lf=dJf^`G}SM_DcJgb!Gl_-}GoG z;o_C6*H(=1>~-+wD)gRZXyqCB7%%I?{k8xRE^wxZ0nMk z--7``2u}%hWgS(I%rYyL(>Q)tr7yN1vRyY@dxapoPlyJWZOFh-MN!YWUZ-M_XlU*; zS1j$hG#B5n4cg?7l@EaIhC^0503wL9c^0#sdvx@4Rq}jqt#$uM5pc7^qZP%6`1OS= zy>=V-+B$|(gF1CzStWuYwfURJmo~(t1kiVHQ@4fBwVKaA->{%x{B?7X{DKxNiVc%& zgJg@!hb>Ku$7PJdTwC#cZLKlT=*@=HrG*PCIBjU}X=U+hJmGCxO`7<>1MDRt3=&q z2;0bWyLp4zT$f0FZ%u(9icJ~<>y>?6Yq|0scK4h~d+X70HKJF}5EI$mPf;*kI+PW? zHs^~kNke62U^N+Fn%V7*mXh~c{?6Xo*p#JO&kB7@ zt79$v6x=(vKvZ@lg1u^usN+(Vk_&Wb_~9pz?4g4gMY1W zxRf>pE9|)KG2ZGjXKR6yIr_er@3Fk4T#32^uIn;wJV<`5>Erl=opo=I^B%f*2kVgM z%)C;~;<|ztw&3)sEKtE;Qc}1_A{RYzCTWqH(SycQkqTWOLpUY6$|o91uvh3#se_`x zN8cNbS~Pf3`lwv(CnmTIk8$1HMy{=Pj#$h>aQH(SU*N5Kzq6IA=xLxwGl4%UHo+z_ zbyshXQO*9ry*(J3h+(PUHu!Oyf)8NQz|3S6TSL)o+40(iSR$e8Z9I-yC1n61o-_bu zqR53+Ubjjr{ka5Sf2u;m_NMy%QHeOC?J%hJq=uzDV$v%xWB^T<|1u1qL{grO># zpW{GF@@H1HxkPQ0i`rX>k+Qfsq+yEAl=({dq?uQ4#%oz1V&)47|LK`_Q*v2jIgE}Y zdryPvfB9`Hrw1%{y{cy@rBdaKDSUIDF~#s_-u7u3;%~Iz8^uIOax0RVmvp=!MGOXG zUU0TM9%d<C^tSd=*djN{QDOF245q%4{w&YER2opHKCTMMAZZGzc%^#h;&?irKxF!iDJL>^a4n zWP#(>@+ho1VU=5|gy9%xHrp>zTsQLBxCfh9Jt7q&tO3S9eH&l^>?!iv-1*n=piK5U zbbsG)KCKg+W?0 z4PFWPt%DwL(t9E6IBd=&bDB5?5_Eyn8D7d5=ql~V+p&9*QW+`K}!KmX8 zR*4X{yT{dWtV}TbrZj~$9hHvN##u%s{YCx-QEGJ;AB=5JMp;YA``SV9RF2}bw?^Ch z&I8v~*&UJ&M%$~NsQwn`L=RMI&To)uEH%4Jiv^{&23 zh`d+eE^(#v;Bw13P+I%ciQr;hRES*`yE?;iun>?8a3HxIVY_&4Qt>slzMR?IMvtIG zzU!O%GaUJW4ElM;`=#>}Hw;ilXLW4yd51)jC5ed>ql{X$b$#qt{~C?gE?mNA4i0;L ze)00v;yaQJ5vC&IL7W~GPl+cSG?y_+V3a}aQt&&^ z^`bspSI5C*8TGU2NY?KaXBK=ZiJv$5g0aW|0#dAMb@2Rt`@uyGWEPPoAH`u}pTGfR zb{Pj6ne6sbM)TJhjE1-%BKDQ9n^t>4w_&BS)^gkd-FNn49m89l=|QMa4?bN*vc3O4 zfK;h1g|AneiGsd<%u}UO#St?NE*?IIS4VSi^YEln5j0$x@_?JwzJlpgbEzqd{cTxt zwB(cL+&N4*ezDl;mrhR={vNaGX?~j46rn4NZ_ESTcq*g{;DYi-!Np6*I8u}!-D$UeTc%1lxxWG_i zR1XqVspI5S@T#ZzaFFQeq+R_u^UhydTwZ{&*j*|4*S7%6_v!{;@hmHxg=zrwU|L2` zU8=GtFpl@JrmrwAUXC>#dAwM#LA*otwojXGU9WQ7S48ACTPGtzYjt=1NP-6;TCn43 z&gcDprS4Gbexz1HvN*>makquiH8ZN4P=&+_8E|f<2E%k~b+TBUDpsezBp{PEC6r*8 zn=2L7f%DYqo>cP*{%Ju5VnZ8R%~WxFy0|-8+?^`!PX8>}^J5=5Hp*?y-FNYr&j!H+ zEG;S&|J|tp-zEeN-=^OljCWrSG1eTX%MQ%DckAZ}@ZY#!>_O9&E2DS05!ZbaQJ(tg zBY11D-|_W3n`?Iz(vjf!?lFTg^w>Bz+0}SXR<+)92JNb=%g^-`fqax}L2bOX=&2Y! z4ao6zHKj!aB07%fbHwp#^HIUHr@z^Zziwx$>v5ctToYI|OO={+43zgXW&0E*xqkRwUEVLC>nH!9Htu;2ecZ>V#s5QF5&hzem*{;zCYl#PU z@R06C!L&N&PO7fLl>`x~ud^d3MjTQNA~p!=f+x9W(M>&RGq8SDGw%;2LY!9d_B=mZSh`NI$v0 znO{z3FWT#liW4(s_d_7+y7BfbsEc8&W+5zjq|#c&5}GL9xYvr`{9Z1f34$mB3{x6R zx2Pz_jS&qe7e>lLfT-vlZLa4|-kavUuzW}3_0ow^4-{uuN(j^F0X-osR8fuU`bUYQ zK0RJ*!b$4WX9A(Kk9ur+V0azyO@+?^GtskUm1J1DFWR|CUTa zi%_DsK6c-?*OOqgVcG0zMyNaYNNpf|J4byhd(|SSAjwuqlxJs0+9Ns6((K4@jGXWQ zd<0;c9hs|s`U~mP+U&?JK2#z?;YnKtW>SZ`wkard0mR!$m{+8od{eOyp#ZVd&2h>W z8C8%X+ys0KZC~5*Jt>Nm^IaJ=#8Ht)>fr1wQQfrf+#|}$P!i21C$QLIwm1>x%*t8i zHk)XE-B6A)K}#)webMVjPNQGy-!IP?OBvd-r>!(PQRojrXbH!}D08EvR~=B($yDPPkO>DZ}J zSb}9X>KY?+aii3T&L+eTPcvPQ?VH;imad(+u2dEd@~SRO7#44%3%ux@+Bi^Mkt^4> zU)Lhz^foJRc6M}fTjzRig`a^|oP23u{^5)qadlOp4g`6+OhtCM)dLWgwyO$|5KdXG zo$g@6lthagXP1cON|iO&_aFx}EDz2uU%GgHfurWOT?nifYzyAKjvB3r@kyLBPt0gQ znz2BeD7f*uvd4Jx1(w&%=cc#Tn`O0CRkwfe{75{!B0SG&cZ-nd=}sOw^%v!B&BZAe zARwczsaI>LRlrR>R4`SmAcF2s zU|Yb?@5X5qM;vcpbK;!uPHWKKufiu@xOgd|IMNE+ES-bpgLPa0TN~kylJ539`F!Jc zXQ#8z?!mZ0_uu)vMXew-#E77@_0J z#OK~pwNVQy26H*om>AlH_PR&@Qi9sc@y2vzlM?+$Sf%jH3`5LwEmBe?TiF}(`7Lvb zl9&EBC<~R>21^Gck-e}3lb;`Kt{>d7)H@yRr6k2Ct4}3_1ScQZbXW#B)GkztU}i{C zs~Vg~ROpuu^>x{IV?V#ko=>u!2z#l^Jd|Lhns5$|dvAVPT-2N_ePC1AH^Gl+DAjFV zVi{}%CDIV12JT4H+xP*oM46t~&z!A%gh=*TL0)Jzn@yW&DsB>_iwB4X)LFZ=rAYGc zKDhs$0*Z8tcTzF)>m}-685FTvWv29+np_1p$m-V zwwcVOl&M-`>X;H!)e^A|^){xDDKT9wVJ?pB0cWX#knv{CUK>ItE7qkRer-p0HOd|8 zfkp!FERGsWJ=1}1y9zVTbo(gR=Y-yqy{{99^pgCPBu}@B?6Z&#{}yfR3LKxFHAj6! zx!lS;0+>e$VT+VaVjFBhA8Mab(p-e2-C~9NV25+tenoB&dN@*2W!LD`jD-~{&FUaM zuSCA?RUK|zy12aZX7R4W1f|UFx(5pR#sLf^5orPfO|wFk7RlZ9W0sM z21oOF*T9ftWRCKX0(g9Pe&Om0>M#g`R>+rpTL+-Fj!hUMEvzYK2(~3^1$#YQP6OdZ zR5=7^%d$a~krCM1ENtW8*VseZp`8?~uue$54oIROT#pDtba==#@BPz@94ri4Ck<(` z0emGphQY&Iueoet?BPsorL0b-IK77yPsnWLWMhgHAWIyMy)L z3kvk5j^F&AO?{#Fu#|kTyDv+{IybZ{ryy7@wC>FT-@?Gg2^Tq&B-0Ez^fNF2s|lSH zPnToQ?ccsf5CjX;;mR`0ziq{|LS|Z^eOrfy5ezRYopd%1&Gn5mMhL!g^B@@-tdVI8 zH$L@3x=*grkb^`%No(DuLV*tUb z8$>j8_iZ3Khmb=Y#(6HtdbTT1Yfu#>P;`5zr7gs`c$gVPF5t9i&_%A?lmXGSScG z_Vp5-{^H!ZOAE^xV8!dLQY?*g1LJ@+UGLbRu`jX5PpltZatytA%rKk3+TbE`J`JFI zXhUDXM}M*Fb1U<&N10Gm;^a;bhMiy~Wmq4ez6J%?=GXq}&n+#?y>WH%;*~_$1LzNn z*Q3suwDS>@{^}RroV%1qNjIQYk>8))IpGV!1VcMmZ4pd=WlM7xmlty5eO%Qo5c5@V zz-Njwi9~TC>=~sLT(ZA07G3T)ks7qRV-8G115tj(gbHIy^7W{=E@9&XpY3!fe=|u$ zG0#^~v{Ym;GOsL}_ek_E8)ecKP(MPhAcrn2Ei5P6&1RdKyl>QBXl{A=;%kYmYI31O zVc$S$mXth+05Vss%OJaoh4SDV7iR6)`VHXmBOM<2aRcZ=g2K3gg0{CE7{%nc1c9 z;)5zn6lW9@kTzuM$<@yOwj$3b#3r^+b_^L$?r~h|b~1q9?8;^pAW?zOTrsx1lTtlc z(zndAfiE=DpR>xcj4}MGmcetPnc3R$I|r`Fr}pZlw=OTgW(`~8VGdf~CBVo72>Cd; zmAS!DEThR%aw$>LD_5u?%*#80T^JP3#3lRMlXaGou$@0v*IK|Y+I0?3XeYD!#i)5Y zM|n`sOG40>AUKU_HPaG+*>IAcvXB(C?K#bMlL%ZriLaGKo!#-mIm_m==qWR97M>oT zCLkp@W;G^;NB^C%tveHA|HJ6ekpBIrTW@^p@u6Q{-e0?U?O=1OdsEisn}ibYaAfHX z?8^(R*+epC724V*LW|aMc3nYZclFm<&2@)|SqQ8u{3Q{x4hXo?;OGPE*>?9XN1pcY z5#DCMGdz}=euk5^yLUNwr;zNO)qA&Z6JmI{bFel(JS;C(_68f57tdeAay0CJ8(7~u zYbRABwx~vv4Xl&=yK`@c_nb#AwcV2va)Uf-1^ZZMjEcrms2sLidwGdMP`E?st#ifjGg+SdEFUFDCWT#$YqWSVnZ?|s z#dBo-Ue&aP^VQ zE;^xq33I=u&I))o%wgtL1OYPxWl^uQH6<-t-W&Ii+@N|N)&AV>J+Pwy0~2Xl-ipd7 zx;1*=qkI4f?h#vio#S%vf42A>E!j`#%Gn)&w9%(4C{ z_Nlk+idV}-6|9%>YKaysfB`&ak$}NejgP^ShITKXn9tIOBp)IZPULeu?MVpHD_Nt# z%ijLDIL}eQOO-3n%xYX|(PsEYQgtNmWGX$DDrv%TBgm=UIHcG!lUEV~4(6b)P@t+C zTXdho1Ki~Gk^$~8lbwOx-MxEnPfbOCoUiC9Iio_)-bz7#q!FL66Tm$+7+IU>j!N>7 z=a4~}=TfVA$J(Jarp_35_bvbl5#YD;4d8swh({PXB)T8T@LXcF3gnuU23}>gn=ma& zM=TiemQzX{yP}Tb*A;Uq1Ki?uW_Gu{0dMzAiU1T#NHbHDiz5256=Zcyh$|~0NANsB zeF4aBYnS0SLbKovd;4lJal7crzR~e&g~=+`Xbh+h!8`7Q#1oa*E6iVesw{mPWl0QH zP!9mt`a3*!Hfi!VcZ|_*YW28VgH^*z{(#lMud+>uN>yv$G?uU;02?RTY_r2OL;wn6 zYqK}dA$~lnt|=p99;h?dor{U%aw;CbyQ4K^l_vY#6$b#Fz4Jgc4Qmwik$*_g!8Ji2 zHN(2^8;nR>ja4|jP&JpENU7lrvq%mH7?)mXH%W-+W*&(7vfxD;6(D-$#&qWWiyCbR=_f58bCrK`ok+cPO{84cFSCs0tq zE7&sCj~$!th}M&ABxN)knbw#sp;W97`)PYue3z1w{tFh$q$CG~5TRW_z{Oc*rXKAi z>#%OQ&n&$NhfW(I$t`b-8dN&56e_cmziUVO)V-nK8WXB4^MSIxeaEmp*6?yB+%E^B zi<+wUf>J9fwteMntrq~a0lsf1eFhHCfN>p|FApOMSQ^Mua@fU@&15*Gf)-l_p>iPi z^lS>BPsmuY%yYM8ewJ6tE1=qEgRtxQidsJZ)@o^^4(;ZQDL2yUR?o_5Ho0!9|GFo@ zx6mr*c1R92$xlrrbw-ut={EKOy9aiz+P7g2ZmhbtSK%sc^PQ-WZR@5k4GNc^bSbU4 z8ST1iLWoX8A6z$E#hJNCQb)=PCFo{VeOo=_j=@%8*%27SDzs#zeNPy3`b3B||@UbSjtXH(xtE&pcFMSbH=1JX_s#}Ce z;0VI{DlQuLw)Z<6^2L%L9BVmX`uc3|ELgBFGE9|hmSc|7u5m}Ny9KJb60`(&rENmu zz%(MIY0~pz9OWlwSDUFz2_kXhvomL3zjoyf&X~`gUs!V0Hqv9Q5pQsSXmsGWbRlc6 zINxQA%Eo0NXvjVh?N^(hUp&9y9M)Th^+ZK6E1;mzT`Twesnkn-uu^ojM|hJqp) zOy9JuMyhM0R(ndgfx&YXX(QW&>6VC09uqx&4lv}TrS9F$y+-$Fdv$lq(BIhHK*5mH z1UBIk9kWIU%WqviwPbB+da*nDQbBLYss1J%EH9~5ND~x|1waF91@;Q#^mISzX{yV|b9O`)tg<(@ zDO#Qe0_Es0WVHa*yC=xrmzSY3nf&Yp`^mu7AWxn~Rc%pFB=>vup z`!%LZPmMTEjFl?@g4x9IDtuwZ@yVBk{_$DS&w_KF^x5DOfsH-bGm=4xR%=hP^p8a+=S2V@}drZ?x zQm1VHwO%Q<|J)yO+9Us^%t>QbaZ;e3ywX@k&Ff#mIqu0lT!Oj-QGB?H#Dujq}2ZW z`JT_z_ZLp}X9De;tT1fs42v%e7@J&^><`Ui?AaGVbx;^bXCoTa;#Ez>#FV@``|PQO z(_HrzDHktYT6k^l5~*_+=7S>ZEGqjy=K*TkjP?S8XQd2PlpPj2kQh>oEXIY^#QEBF@l0JH-g~&(J>Zmk=c&C1*&ogJsZuL$GntdE`WaNB;_dj}T zU%*jy)~z!oR+eOWFLl1XgoCtfqaGm1N}0pJH6R^R+j6=f*+VW>q!cMM*w{-W^;A{i z9At~z#uD1Lqy9Wqbi+!e$<|d#;$|mWsw9LsX8Fy=D2H_oP}OZ0I7V`d1hWtWw940p zP>KSb-qTpk%5Bkmy>|n1@QgeNQ#&C%jl^ND{5!nyCJVFs(Z)Mmeaj-&ZKB&dN5u=q9z^`Q%eb=bS=j%<*H#pt&#>Xe8CYd4y(rDH&KQ{oMzhZ+*a#LGU7OvD2%6!KNz^B6DbqCTe!@d>>dC@@m`%j!42m@`f{zd1$jG34ekbCBF>se&v|z8A6LN|;247goI zf5!os*;k7rvp8YIAao>&TTCMMnV!*iwUqWrcsyI8AE^?{_`n8LQKo;)eu_b&;eg|e zkk2^zQX8fcm@cU%Q(9#8)SMUe#vzd}H{`Z4pkCXs+xQwL?Decr7ip|8cnPVQ(?t1* z&HN6MA&Gb`VX6w@&nKTW5LL?X6(r|#K?thB)R|c$3ftEa`1T=ooD2vbpU`$SmfW#n zV?Ap6N$O5`%4Ge^JDK)Aya)U?qZ{=)^%z>pJr8JHc#t<>$?&`k60z;RX)duph@(up zG7tO*^P4mUqvT7HE3|0i+QGve0@Oxv6!x~QotVDtUg%)+H8)U_k0~gRab!_PJ9< z6CnYwon5i`D`cH3-zz;(P@p)m+ReSk9kc#t1TJ z$CXm$s&AC+xrsCgy*>`m_u5@^(`)3dZPE_zb!TMyp>{U9x&HTsw`b;-mge5lRFpq> z(CL)Xs$y55o>A)uJ42z^?3}$8Aj#drP(MQ(^OvuJk#9|dwTuVhXl}w%Y!PzQY2W!~ z<8FuBt~a*Yx4SY>oO^9$d>L<|_WG~iGl>!ieD>7%b;sVhmF1Pjw;ua;xLLpe%U_kq#H9dAJ0JPNW4PF6gjE_cckr#|u_Oi6Hje2L7@O%*n3>+>* zd$>*EXJtTnN^+=D((<)))&XM3osMOmROd!_uf67XMD2GpzR}Qe6g#lH8gmPH^=QCE%HA#u9~*-6 z1dIkGR<>(*ZHuh@PMLEH-!X!)MBa@Up9<_n`J4@u?un9z8FVWkT=un!C-vtwEYy%K zSG=>E+^@?D>2XyEl~{8SDImXG$tn{JPT5rmQA?`{dn1C}J7#i)hMGC3 zKG*Sr)iI}C!{hR*4~f7YbP%xHHfmfhz#U@FPlbhwCytO^{2=e)bC)kNBsdcusPW<9 z1VW`BHPL&@NrI@kqWH#~Y=DVjPWMUIUK#K5a{|71GLe7WLPOqX?#gIPPmPHz#WK7i zS-^#8%Zhb792nYY(8nC8-fo6$?_d~T>+ER(uCAH*+1IDx;nc%Qzp8Xc<&+SMDP(=9 zya+`Sqjz8z(O(r1E)McU@twxE2-$RA(?k?;+4v#}>i5{>DR}C|6VVABMBQ)g60Y_Z zXO6JcrCCY*pQ_H2iuL;rVKW=cOA^ORE6b`!yardI=5u$RBmnnM3=dnE)zK;%b8cNg zfGID)JifIQx1`%xt%(#+Y_vG`65TmzO`aLGxGd?-X z4GD!ikj=VKD$Bvq#~0m|13C90Z)1E=1nFUy5S0QN8e|5yFlc_ORXaQk8d6q03nlrT z?YPDzh_Jjj!AY{r5bl_+(Wcn!?bEh4YQLaAW)#F5+U}ovH{<8@dqw-S`_S}%e1VTI zU=wm*Pp>?ko@v)BEPF$lz9LB!wvH`D4iz+Ko(za%@IBoM6t@E!^kkE2uT^JXO9yxM zcOSG++c)d*fztO1ly_o!$S2&f5P0STJ_OVMmpT3ZM}Kl?NdGqe%I3)9Lw|0$?(|Dk z+M5;;VtjLBW9rra5=H&;(9oa!OBXMlyL|5Q>*t4thJI=2zZv>3_&fCYOB2V9zOQz(EmB~Z~UJhJ^Y0ao_YB2<0n6R_}GWf@axl|9}WG&`yUMrJ^jgNLyx`s z(WgV7J$(9up`j-~8G7R3!=a(~AAUCUgys8e=;`+#KK$g#ho1^59}GSA@Y9_6Ly|rj z8hS>*s+nJ$&()s zJ@e74AN)kQKY8`xlSA)+{OU(ffA-|V4F<5;#7BSjudGwcN`22cJIEms>f{KJn2pxgYk_ zopKM=>iz@OtuFTDKC8OH&rh5CA-(*ER`>h0x`*iHuUg#>=A4fJwUX6YqLNBwy zA8PamP`R=VedEcV6u|hLf(eW=TNT;_#uK0RLi_0xB^c57AACIYS<2=p`u@`o9~+eI z`+eDdP|0Rv_%yY>nzGqge@ty3rfh#AhFaO4c?JpaX|Q3=`q4-5KVl@9)+=Rr2IOWW zdvYU^oQ$6N%ayv3T~2Zz?bYhexu5>aA5>U8<^Fi@{hB~Xb${{PBL4o|VwFL4iw&Rt zi@lJDX+J)!L-LFC(sO@Uf%`}F(sRFBgIl>J5T5yqy}2c9J~})m_iumHQ@7>*&1d@R zmLPiu(NqdaK_apD5rV8LQh~&T z_@9aD;U_Th`w*thc8?9gdmjxkO?~vt2bBqo%;bZ$`64P#naPI`;2TLM_M+wwm05M= zsgasrRc5v7^C+`~rrD441pLL-h93?+{^~Oy{L7&qK79PckKX@8P5*G{vBw|#7o_zRB> z{pXhWuReSD_9GJ?ANiAB=TH9VpXNFr|CK9V=TH98f9-WXs)L^nedE(V{P>9vpZ?2d zr+@WV&wTP@*P%Wg`o)Pq{P2mPZ~Wm;rXQR5!>=&)>rwCY^k)-8WyRl^_!KC<@%PT+ zG<&9+>`+WkpFTbD^9Sx{@AQ)sfz8i;^|9QKM-4!H`=?OtPlo>K!>>W|pAI3lU;WR9 ze(|%Rp(lPa^!Q^Rf19TdK7)v#`0&=lAAR<4=+mD(eEhSgfB&_cVtAOCL;e@ONpEBnJT`=9z+@zSq+@9+NLe}3YxynHY>bo6iicPjJn;V=LA@Bf{D z^t-3NKl$m--~JDN@8Q4uf6qSreXIXZeQoOe*Z=+E@n^sGorT|-8(R3KZ>IwP)8G2x zy}$pHfAHhK{x{$Ky@!AEpZtCA&m z_bBk=fAM?01?YncoL^9ZQ|BC~zx-oBx~Bqv>u;*S-~DeNI#U1C*G69Y`uG0vWB>gV zzw`1FfAI0)-~TWd_&Y!R-9Pi$E1$mmw?94m^j|DqwF3WqNH}@y+l=Ese>eoPf8qaQ z?`@#tI<7Op21rQ^qga$<$9Ak(O^8Z2h=*VPNf1F21V9ln2v7hh$|e}P(cJ*rY;;52 z4FWJ_iFTA3If)t3SZnF{>`3EyX1vbE$!>Nt&N#Ba=x|3SUKk6pEXADU(#f-6^D zcx+|m0zN=g;KRBzXyP;S;g$Q4_&)it7Qg%*O1TijZ0YY%26U=>VsDH!E-tQb*uDGS z4I5&cz$mdzjl?7N#+8fz@?T!K^u;fJ;H8&Vo?iiy&tC-m-;cfVx_@#1{nxJBzrV3M z#|ulRPrvxeqmN#!%JG&>`|rR1O%40^uix;YFMam^`NA9SdZF>|CxdwGEzduC`t)}% zJ^JW{mrm`v{ipYQ@84Z_@$4;s@%7kS5>5BtzlAy0e!E3e(m{-^G_c_j^roqzrX+c`}c3SYBYK7O%2x#Y-)VphEE{J)5lMr z{@m4%KKjx>{N~ez?_PT0KRkc&7hgKg98LG!bAQ90J(A<^8?Hx=4}D2;eB&2>;q;|1 zd_i*j_@(ENd+}!$x zTW;CZxcLu%<=e4e?SEnS(vwZd@%*E|`l}Z%J^AGG7r%LH`RyxnpS$jh|KgT!{C=$A zx-)-oo3-JE`~Kdx>{@&f{f0rW<9o4&hBNHNu`hoQa>Vd(;_(Xh_MqTt*b=`OyB1kCJ?^J(_}ViUSFS^j=l4dEzi~_A9lt#Btq;Wd z|GM()H{84Oxo7_OS7u(m`&aJ%b%W5Bhs^dbmQlq|LqIE#SD*`3^!kg3@?5lmfUa$GMw0aqsj1BFCfFU_pUts(r1w2 zk#9b0Gi-UF=|jD-UX$VQ=1nHU*A~8U>hmj~HyM8Go6oxp2S4$#Uew|GO)Mcq>1+S~ z_|)f7hv%MW2_8zIQf}Y3KJdb(zZqHg;5BF8`lq&pum1HzkKJ(Zb5$pOzG2}e{4ooWXpN5=R?1ohh zIk;S?@4G8?f8d?EzaPabS$;%^YC4>`k%lnDK8^ro53O2J!=edF4NSH1Y8(pVIin1XMr+4&=FHjc7hb;47=k3dZ}LHe zp_^w4f`#Ww;ywF~Bv<-dyUx8d*hJzz3ymKinoMqV>0_M7c~%*`+n*QzGAtJEcg^FT zmBqyZj&D|}AAfHYj%PTDq<8UZ`!L_E1%c*yNIR_ ztrTH=)E*Iy4=oRM;>E@gjSsB}k$5NrFf8Fet0_MOq85Tkyk`pt(|L%P@`u@-E4Mu^wIAJPQ???MU-FTP?>c+!LP%oZ_ zf>#qyb3wiIv>4Qj|6#^Oj1FEw&N{GdTgM;&FypadCIa6#Kh!Ii_J?}$KWsc-H+(hj zyaUD^zrJ2o{t1Jof6&$eEY=Yd7(4Jhga4R*z^K7L48y8{=NbG*M6LBg<7>iW(9oO z7pr4DkoeV11gjYWR-5jxHmOgpGId{Vg1*``9437Kw@+Wr_;LSC!X4FkaFHCpMD3hj z;42TT^u-8H^;j;`^wQ*nt;)XumizRtv2;ndEbHNJM5tnsz8VTs42SN^((sV`X3 zMg1u7BMSV80#`zT`<}%lhB`~AKSK|H+2257!7zR=42PJF%Tk*kAK4aSK3r410VIr% zZuRiuBbz$H_~`bHXuREe(eQZv_*hju=To}*BAUKlJXfGOFWYm?8Q8vDdYLDh%@ZaP zf4of<*eh`*@!nR5Fgf68{0F%AArf!rzu4^H$Jd)juW%;iZH2%)equlI;#Zl!W6y%0 z-t6PJmzxyo$A2Ii@AeivzDj(!ivaM9U4r{Ws^aVHBarkiK3vtmd_3(W_0sDK{(ZvR zN}s(ewJZAypYhQ({HpkSZmfY5U6*(1FL6^-xB{>7wQKDzzG_un<7?N?5r0NT_i(8k zQPysTQ9oQ2kH+ssr;c%2j;$b?9)G=GXn*q}ZBXFb7w_*sW;_<#UCDmASj}=jFP_Wp zb>p$}UN;_#@Acxj{{Cv>xe8w|Js0BZ#k)8LJp6wYAEAK0{D?lUfez>&q#HL4AonYT zfL#N4-Y4OzKc-pkiPc%1$EV+q)mej= z_|;b0S6feCZPongRo2FzK3;zXe6@A%)mF330)$o*jiLe6x9;zUMrTvnTJXPIjgc;z zuY7ecxS_{!IwVFrAPE`qPDvev!wwfaliE32$rudK2_y|T(W^vWvB&BUkPs`3if zk)t&>^pKj;LDGLu(*Ky0_1~qe zO%ngS#QWj6#6KhP9TNVsgoh;jI|#3f{Q|=GtlWce;}>F&uNQkREIVDXxDCgy^}?`X zx%h?^34a=xLCgIT;;%Zg58>-po7@^Y>MSufHDkz3;i_ zK=asJzs2x(ZeaLoX_xP_U0`r$JZ3Bi$JmbhOwIi;+uFwa;gvIt7uv2{c^2VDX^U%C zUO@P&BZmP>!y2z?8l>%FnpfHg$wK&H_@7(5+_)mN0=K*zd;4u2Zvfp^R=)Rg?2Ui^ zXV**kxtC)<{a5wFetN*UTGD_2<=ET)>;|#yBcM;31FU0y8zw%k)h$DRQ-e(YAFJ)bjvNkjk{!8B={7rA% z;CMBDtqV6izJ9%nM`1S1Id|Rg?C*YUeQf9>gIgYtt&{LUg!e_lM0$Np<7>nF7$rXo z{|DAC?}-RM}I6QS|;WS|V#D-&!hv9~J?2L_Xc-9NYDUGLJ{A~CK z)-EXGe)908MZ&*E!rzzhPfPf3Bs?$Sk22iwX@)OtmGE&1_j>UUNO(cwkJQBb>HmYI z`GlmoDB@^;kP#Y z1LD7P>E{ssscU}oe$wz?6XeH^N_ZUMSPC!^zm?$_U?Tix38U@^H%b^ZK^Vp`{6H&& z&2N33@M`U{{VSp&E_ z%Gc%jxWt^nbKRvFp7_}(IBMl(iK%_qG=BOk3ZIFwtPecS=l;zsOP@_m40rw^pVzW3 zv31Y#iS`MfaS6*4`Wxb*(cyXB%CqjNG5Qs`nU~KWR9*J2JPT+$Prc`c4Y8a5%_B`4 zVmtn?@Tu`gbM1!Mw%>VV_l8(&Yy8jg{LK}lZ2iqgdKv%N2R6v*qX!5l_5k6a#Q_Jo z@Z9?)i9aZ5l0@ItLc_13F5q}jK%XEwsqw)$pZn!GDbKe_{MBa|PtGyV#)f?eU)9Lx z2FbOlKaOyG%O*Vcy%o=OXExxd0Dl|M6f2kP^Xjk7{w}!Ddup26=M~lE@rK7Ypc0KJ z-8?rj9QzXEW9xwh`uR`12hWDCx8fQ51Ho$jdWQA6p^@RY%5x@$@VW=C#`D?@SK+y7 z1H*9%?_-#AC-kEjpN;s3a?kMDxUT`vb&vDexR0FNxKB!tkpfp#7nF>$z_aq)AB;Pm|^V?N0Ej&=VH&)~Xac;3|YTa5pr zq>M?**bc@ROcX2BfKDnm^BadiZ z{CZt+7-}eLbnjk1AN?k#WPSfZ@u@H)@_5|DwcyQJ$@Qp3#(_XZYEBC4Oa&5b%5q@-VjQ^Ne8a zKP4jaShX%NsG%%6`N-gz*tsnqIau$hY4j<{Bab?D*?Va(PRy=cMCs=FJi{xy7{7AimHY6# z_;(NEdFfBSgXc=mOMG6qaAnx~_`IHQq#E*4r!JV@5x14Uljjri+{))GVEXFv zo{jPZzKC&83C4E(C(+i@SH)ud|GiD`#tnowR@w7#*>V4&ffIv=cokpo@c8YY8Xp)v zG$ww&`$ph9a(r-PcubtI9vK^iTQWErj}PGP!uZ(8kZI`-YTacg|Gn8{5o@xDvA zr730S;oWsQ4o6WHzAwPV5M0Mii7PS5On*G$!DgvAPoF{bS`SA*yylQThf?{4)Dr*X ziwoIIcYHc`ity5~nq0I1-NjMVE@xooO!W3Mr6)HA)xgAML@Y+YWOvu8wH<=IjS)9tDO=eT2lc<-}ocM&b5_gE8lw`LJYgrH6 zjw><@GesD;EuL+g)|xjROqEJY3Ea0fUz#lTv(E8TooyW{upfLk(m!$>PNXWiSu{2- zUdCmhsr*toR}Q31di&1MGuKggPv@1xxGGdw2oUM}D~HtDjHh@fX_FS(JH@oh=@AN< zP7}~!TcSc2Z!A#VUr#FI@fzhx6lU8C-H@zOU3o32ACCK`!v+An*=&i-?`Q;}kSZ*J z8<8%X2i-w`u(}qBCY;4Jv`b)Zq5~eUKz^_*pfxI#3b?>@9Hr0Am*$GdEPV_u=QX0- zq$G5KpRDX`5j{1VnNO$a#0_13&ILQsT(pf}Op-Iy-NRcfA zp^b19H_IGAEKNsy%KRh;NOUS2fMrg?HDElctyle3?G!!rD8sh*!s7+rs3!7`%4p~w;Wz70-b-GA=))zj(VJWq8DLLeqYg9g zqRte&o8fNjg1d>8VE7&s%ZvEGV~A46HC)QM6SuF}gh$;DtPSS$xiBs$KAMlC&4PK3wCM={Q# z7QDAnuRiGR0UB-K^%9*fPvKfksUa!Wwph-+kAi3lS96B35ET*&cYp_wDp?BLH@eLu zo_=z^)15Fs72(U7#m!`M(=(M;1}A0Q!xxMz;#;`XHcOwrJ@iUQr_2HzZMS>RVi~l8 zH(L|4w0qAIV&ry`{l&#(gvM1F^_Q}DV}jjKzE;L?_@c- zSZ?jy*4*B?E$9q7yI3u4awgomed|(-;J`T1W?Jd?-#A6ag<2!=CB4D}&W9m|4kU3g z{KWevW{%x*ygQzdmLf<3HC)6O=7)E5$%XGICCE;s|Vz=7KygeO0=XsckL(_e%D9hSr%HxwOhCb542ATep1AqZJp+NvCQty zF1X|qx@XkWT~nK?9`q1dDFNMVi_kS5Rv=+fIs`EWo{`o{wRUcuT54g(Xd#~{isR@- z-jNa9dxP7?F`#5wsO)p`N1bwcusp z0fWThzB=&K12-Ig3l)^8>KeX2Oos)$%!BkE%A~{Cc+W(-_Fuwjlo&@@kc`UXri5`z z?08e%bYmvn*sAGpUD()6DXCxwgImq$*EG0#4g<5JsU>BadX>`eGAZv`6_yq|Y|;&1 zCf&PDx_4hD-JK@gotH`1XVUepo=*A-7za&e5?ArJFKO5*t0j?9n9)Z(kyoeZhT{y9 zf;*fn5LpLld>LtI%2CA|H>X)Oq4n2g-2BSMSd9PQAd{xI)J&QvN!zmj_Xja>=4N3l znS~ibW_>bC#7CVdWJ_8=T&6}C&F3d2#8jFB-|G*#ZZfs;&`AH0p#krHE`LttN2^9t z4!b}&sj`y<+_V)&x|x<2C&PUGsg?}rtIV}T6*5wn>G+OTk;_A1fhy+NgDbQE*|szi zwuqV7Qc#3$R}@Xz7^{M!4dCyooTzd3Itc6CndKz;AXv<%pyhi5KR=*MVFy7&2l}CG z!R4X&m+!=n(-A8#}~z0{-S>IB* zy{p;y*S_M~gDGCetlZQyIxSyH>x8^qXG&gJ3JRF>b7r2&3e`Z8|AA)Qyd5*b>{&E(QuAKMR4@{=RK{$OJzlf9iY>J+;l5UO zDD!ElyodAt6fOr)ulvP;>$3J zIEHk`RS!%g3;^U_RN?4beio_z;}b4N*N^t@bllP5Sx%PHp1}mG9UK)`HJJ#})M(;S z&2@A1XD+C)mkVkrJ(=3mQ&=)xsj$?7-nR$WCMY$e(?`2|ExV^I`=ktyle2Ayuj=yV zKD64lHQgE(9u%!FkOl?zL)+sc)*mt!P<5Y8&5SrRZ&gF14i27i$m%MpSXGUe0L_8m zpTJhcVaScvugzE#0YUZ0Seisr+SvB1q69y3b1cUHFP;0}U_5$js01Itx`0l{I=8iD zPd+zt7^d^FI|oL`u#DTYZP!MpvvPH<+@2~g6)+nH#pIXJ*ff`%YGScIwlqDT^Wsyp zIozY1n{20^=WDmP`xABof z@qy7%Ts1p95J;%Ee`L&r#)dR7a98gk8yX(CYh1&(9~m@sAb_F4{Thv1+~298k;4P9 zf$-zu-f@%Zjw6F6G=>Y2y!^1@!(?*g&YWthmTd@0I5vbfK|hy-z2*F9_U?JCIM=3ReI(_;B3cADjvB+24-NHEXd^Iw4&^3G zxTd`p5-Tf^hKlKvwVzpU`FuE4DrXO;V74k1kPIe!(?FIwHK~S+eXt$Zqy?E2En|xl zDp)Jiq29ajy$4p)0C%n&I6y9b_W<8vbW}qmk`SpLO}e$KrE4QEx>0EH=~MEmum%G^t%@3F3>H9PV?giI)nkmgh2AP%hR|b0z*2IEzzrAXc4H;%k3!03_Mu z{L~cDXN@iXQr!`(J(eQ1#nKl0Bn_rkROV-BNGl6&(?th)v6M}V{tHT^(L^?kZ3P(} z(eYujl*>+;H>nUZVe*LN0rwxEwvxhBmUXpR84j=!q*A#Y_W9yu3X@T`RVkawEEz)%yI*)PzbEdj6U8C{tFXjti%+B8JL*Sjmh+K4csw0a&#;bhY#c} zv_f~!G0KY5;4eVIo$WToQDCF4K z;oiQ1gEi^-sqf$bMBC}~3APT3J&e0N*`fEMWN9`I`7AG0TV5nT`G9D%hhxmgP8iN& z2}U@?f=OQn3>k@Fj>>K!z7d45mj$uVWG}k~0`jY=*|Gh-qqUK%kVpGyy(Z|-fyHqb z-4feDyL)vrWa`%kw?mDO38vdbF@y3X3JR9E2Ez5;WFz8cGR@F$~v?ymxS&NPUpi8mI%6bus4|w zY(SuI)c|=_+_Xk#6M+j{Lgtt*l1{geY!~)@}_6r4;^W6=s0g+ z>l=Wo+CKt7P@ao2q>0rj4kk%nGH=R6fp4a4$m!`#{J^|`4{ec4*_x~` zk3B?IB{E+^v$NXftaMKDPCaPk6_~)VDBPi6Eo+&tFnGu}Y9hU`=wY80$0G*HvgxrX zcS*VdTg;~E6BL#TVG_Ezzz_k7`8nRTr1S~O!|GIwi>5-StxklfXd3C0)u|*hnvSBR zIvL|kDn(4Cog|CWm}9TBqoHhfkFS9y5R1F&MID6&e4AVzj4ge8;v=-}aK?viW4LM) zo88hFT#8su;P6t!{ffW=DowVMZUZA=FVG}+V(A7nHZ{yB)UbO)#kqHE=){4+p@GqX zJB|#DjaQGMA^XOUA?bn96GsPe)$!3lKTOZGEfkDC=Oy)mnrVD+d}u%f6+Th;pTzbp zH=Kl17B8a>DuDjc-lI@;M}~*qg#}iQ!9qWqDEe2sPdF4M$~D0H+|FjMdhN zGED)qe}<_!iE9=`np&UTm20}E-nNMitJ+JE07Ecm6;dNmW`KrkY+L63KV!Y1d;ne0 z*-O}n%MUWEHyO#I1fY#!)WGK3yf|$iQf$mlt<}eAvc)n347{nyd^STKmI0Lrpsd@oU`Q-w zq3y7GXWKxj?V1n!tZLhC7_2-ykFA}${}cQr*h=ehD{yvpuCfHx4dsBr?Jh0b1U=Yn zaByJQaFRi0fLR0#Ct$JzmAlq;+h(ppP^b#Ooyw;svG-Maq$(@CJCn9sq@k}I>H|;%kZ*S|nQ?2joXub7#^F22=Cyd1t^Ba^Lava(LB39Xq z+uP*b)?Ap+#m*6Dp%A%D!tr>-M4-UHBb)>VaWjY2Y&sL-0NLGhngz&wL`K8+3oP2q z>i{(th1USOP$ZrPxG`+A5YWz5fQTqghz&`o2=ZMKRN`r@1?unxYaZfGbMlm-9PXlr zuw_aLGnw&0P)M=p8@g-WZI2&fTJ-XyCA(1J@|cZ31$JH`M&kD3=7f>2rbE>9ZPkX! zB4_|yva9!R_fWc1UYnkm9hbX$Jz0;!#wl^+41hU&fl(*VMm%Yxjzt#hP;Smo*#mXq zq_G<0CaaAG)chuy0yjJ7GaATe3qTOh?j9=~K%E(4%>-E3rX39?+}^&vfw8d@JZ-~| z20(XDpPKdiK{;mNx2YT!nyQS0uo*&gfkhI-J=36)#@1(;D=&veto=`s10bda`4DQO zyQc3gt3%+aky|ZgHWb`$S@Z+ zB4tt>VEcOdBwEI`P^yxiISl>+Kl+TP?8a))d{ZzR>=Y>EDR__Z z=qL3OSdM3M)6Fpm8I**UgIqi`0~0G;K!-%t5u?-K{1UlTf9Q`Cd~9a)1;0Qi6!lx8 z-R$pWKFe{D3?WS2lB@YpKTEF=bA*K2k_BWOEDn@PNi2_|Ka9}aed5r_=)j4AVQd~B zFngs!1!v$cnz;#8A^Ni|2my+iNZHy>+QklFEDEjEjuBB2!(425LCfQ1!{1tuBZVRM z0;UU5z(6xFG|)HhY~Y6IDG zBU|RDX0Ri5iQACDvb1H64E1wjLh@**nq8u%40S6x1vXQdO3j*XC5@$nRnkvLEs!S$ zOcDA?kx)p&`ZN~c#1qbXVLY15axfBo&@w!r%X_t^V_AvJJviJabp!T}Pkk06hBFFa zb}7x-Hflv2@WC~?u<{A6v8*N9k6_?Tl}~UAX_V`58A~W#2NbA{$OF8}W0GZT zA)1+sTRVG_IcUyR2nO+-Il>W-8}9J-JE-=UE3W?4=zk2Rtof$zPTGmi$^~HJzg5;RJp4Mo?7{^kFlII(mZHiM6N4>U`L5 zjHZG>LE|(h@^R-P|5Cb!E7m%Ht$cvV1Jp+IifF zfGQ3*uU=9XeB7)vTiGDpcT@%)H+Tw~^K%)VW9FpS$SFHCLEQ}Eg4G(+Tb&fAG8vkI ztrZxOtusx%+@}jNI+vXA5IgSW3(YN^RDRI})&dikTy4~Ev6)@05J><~$)WEDk_0SCuqZiEo`Are z$TY)tsu~=KBI(_r1qB1zw2H%3;I~*&Rc>yPV=_%3LD}`OWv!Z=jIxRvh z0h1gIRASG;M8hv=1B~v{dsrN-KwbaDoCV($ND!a$NSIZrN#+ zDW~gi8IV2ICbiM=w}dl5&~6Ba?`b4}@hz3dA#mE3`IG6umRo}OmR|htH?czQ@m@@f zxjhP=8?X~0jg$2`c!q$|Lj}qzvY3PMkP~WS@}hy=gn=dKXLCqWSlP@Q_|ftklC`t| zfTOEpJD_;5cQg)NBe4bht-2E%xf1}sA|yHirm#D+;+<{V(0P!uW8=-6Wk1(@-xiDU ze^6+`^SW?9*X{jB+Oq%l%k5j^x9bUQ7&1ofv=plfIB0&P%*q}{VK{ikEgrMQN)~G; zlTgFNM?gQ%4x$dm2w67nIMBWsM4hCQ4p~vrE~0`ERx6yemo*oxUg<77S%zRQV%vx* zrx<@<5eDvDp&cu|TvjkvPFPBGUFH~$$^#>_+u}GJg|zFLiu!xf%*hHKQUihPW;C*a zVh}E#B+L#oEFUqYd1G)MPCRmzB?jy5B#UkwI@r_21LbDhnC==I7(KDSx4(Dv_OSp# zoG|2{BjZ?U#^1h?LqnPz2~PA6jt1D{#kAoTFJ_@oAI>hA9aP-+g-QB;SbyHhFMX9# zz7OAIZ3iE14kPi+9wNgk9k zsnT>=>{|F%C_*1D>#=ieJi$?OoP;yyLzrE9hmu>ea2KNla2`hf%7Js7mnSkASmkDL zp2q@^gK0*EgRQ6xfXN8zqI7b2Jci1OI%F!1KO7X9xVbryKd!#Vy8&mFtvakVt9Q(_ z!|`q|_Xib7`aI|)Rw>vjx;f7dEqIxt5}(c;g1hHa`CxW2nC0RXnr8s}9L*Y9FCZsT z@c{I~0)66WHZRUGAQnx3WEYek=y)@c&gbIu(kXl5=)dvZr;7Rc+3cQ)LOwf%^#*uI z$;Nvky=9^xN8jByu2fAF$}>5nk7P3a&3=pKl8@+#6Ig35<>P4-LO}6j#v=*LWCeB0q705>_u`w2PJ9 zn&Z2sU+H+p{nb2L!xQeNEn7Re&sth{5u#hi32E8xo&@@yE?6jgclV59_?7n3wr4h} zf-p3iHS7k)z+hGjZEsgJKpRYu$xx<)yO9lF%=FlBE+Q7#+k)O9G0H}4zVfkEyb=hl z$cP+BqCd!WOz4-gP=YCUF=9-%NhemPC=0oK2E$n<4zZ~j$)0ADr)6!k0i2da6dKxi z-QX+g7)<&V8s`@R?quUhbgi#Hw8i69raJ$l83W`vSr5$`FyvUdoJ<^rQZtFT8Tb-0 zJ;NWJl3Q-RX>+r&hoV1W>i}eYrc|863(h~7BmV&g_$}PtX^>O#;t3oa^v8NX3ua%o zjsk=>M@zX%_CPX0E+&^_)ebzam4rbZwp`R+D4=mLa*P+}QtwONqVMJamEmsHYcfSc z_M@p>W$;k8%wA1-U};DB(cN>XJl%(Y$r?weOXVf@4g_*jIjG+@!z@_*5CyxJs4K1jHereww#2Hb1g!## zOUX%<)?Tvur&B`RR}u7Wl3=28)@Nalzv=&lz@5<0dUIAG0!Af?N#V&rP1fgcC-S~B zy|H;aqo=g1sJ2aGeWOjcXJ(*~g z&8V>&kiO!4K7*+Yv{xF5o2o{lrueCCyQ%>??aT*iv4Y7NYXR93cGimrDv+XXelhr; z7=iA8U})s%ZH^MMeTDwGu!*Hua#_vv!!Oab`(aMP4$yH)(y!a{cv)-%|?w|CsSGyG77o3pPi~VqnZeSX;sfXU0_f*#h)%Eae43gP2WtEY#*W zfd?d+5#)nXUbQV~QXonuQ^xWYw)^md0uKio*GjVZtOR5lq_74LR4iM%f)!G3e#5~% zERuk2~$x)<1^P&C_D0R?4h8l__$pt^|Uy0zh8%O>kKtyY3x0jF2B)@>DaWe0PsMF_p7{=#nKKB^y&&O3&-{)?q9>x z8H|n$V;)W-!x0vDUL}b_8Ynd5fY5jx&TK$5i+~_18z>F@IU0Zj5jbp9tSv+7Upz(L zot3RRJ zO~NjzCxlg;*~ZDoclYdxAIqa=wv#G(%9C^(18QiK^yf|`56$P3X*kp?HwOTRCTVV2 z)Ye#3`vTE6KR@r1Ch|a_Iu69rnt5%evXm9_5t+3_O6!2)?~OkvUPhi6eYwi zwQLJaNAsy#SDF}E!WkM}l_V-v8YF0 zE3ms~ivCy(`W$vS7Wt3_meShh5@isW8+}ltT|r zs`LM!XR8)upcS`ezdnd*KrfvcFU8BV+$zXfCKt;x^RsitS1*_0Q}OalmhOsyjF^PG z<6IrsoywHKHgyW1vrE?Df$G1$;cVCA^;5MxH@XQSil5mDT!*w{Ukz-A87CtR9@sl{o z($&_%wLok_z=T*=bA)bsfEJ+Hg-|*1id#a!_A*tB0#4)j8B?q~Q~4z9tZZB`lASY! zlWthrJYtz?v+MN)jTwUV>?&12o4`y`ej-Ma~Um=}4TaeO3+LE_S zl$;w_oZktU*m9up0U|c)Z5*>~CYQ%#fOA%x$0mt8f3KqR609lNhuXP=U`Jrd!<-#r zk)14=2DshZAc5(Ri7$IPyLK8`jb&LK(HLJ{W|OlvfWc7=3XJgk#^lw)?MHFx3IESd zliS}IEIZ}*)jm3qm*otuGh;F>$lYD`jA!QeIj{15Wj-uh2 z9A{zkODE#x)Ks=j3!_JTcCIWo&CBT@te2XuBM#f~joBAUMTkJD9+*>1KwLkCU-&FG z6HLOPI)Mlg5v_ecL>fB>nID~(3#ZoIoI2@Xp3vomTf5{wQh(u+jluVkBjfxtI5aeH zd#|iz!birDLuM4NJ^?R7Axt9y05c>5{P{E1+j+Pc`Qw)r)HUvX@3geNzwl8VH9iGOGP}7`yVK+ zP164DLH`cCjvd+0;`(>$>(JPcl)epcrSuZG9&7Tc{B#>rZQa$P)sH7TL2r?Yz5V?H zVu#{_&SW4adpnxByP<#oXfJrTe;3wIi)>v}=uNsfqxIh3*VhJ5CQPB#Mkc_?&f*da zIrA!I@eGpeq?9(tKrc2(tA4W)N!VbH4IE*RmboC&hCZK=k^sO0 z*MNjE-|`V3KyBw9?zY@#vpH# zg%;^l8fSYT`%r7)t2nzx;A}y(|EUO9Se|LW78coEw?JPhI7k4yR8R|Ufuy74yi#b; zW2&L4%^yA!L^sJ7Q=$y+Y&qQ4z1~Y-#91 z<(dp4aCBmtuZiQ9S$MLuAHfc;`E@HTwBwW*_N>y+}J^hHMQMx^Q;cxh?b({w9d zqw-luY_oBivelRsoX!!C|2%9I1r!+3J`lTc>z$&2lv1%6|39Ch0`jI%0U4VqE*zXM zoNUXUKMoZ{#>Z@Y1~ILoYTF@SHrVgHrDL&!`zkOB;5az^ya*$TF2F1zi#N7!WzCQF zjt*n*OSiz{7+*|p>pD@!T7{n3WO_IB>vu_t>tU!ElZ|*E4nbkM11oh~d{7l<&d|VO z(vQMxL_{Y5n-Z>SI5-b`jafrw0ad*i*Ij@X$c-*Z@}@aP-O?Gq$x(%~yah z)CP9jMd(FPhX@K6lgy^5IZ*>Jl|S@w~L_TS3QawnBev)B#BF2r1|@kwmL#f(K( z(5RurcjH2&EL?oSzs(-SiF=Uu#J6>>vXe`8QXM=p{LT|ch6mvseA~dTATIC2y@v)& zkatFzV1Ms8_VY=C{bOS$G&+DYJ=?mBxlKMwROe1V0rmpQCvo5Z*IJ_zuh`E(Gc@CKkjN;)ps4fVbYs20|xFg zU<{NK)<=&dKqO8CN?q+9w7cL||6PY5IO3?*35XR9^zH|37&AIx0x)A^DfJK>&6xND z+q!x>yKXf#X4iwv;_7J6*16h){dD!1*)=hMA=a$yK^p2@ zjTC~Wqe)zLX;}`~rby0`WNLx~nS`h#WVCplr9*O41vIuwCAl3Iy&|b76d~i*r0_-;Ee<-(#9_0M#Y}7zK78i)HRWiVrHC=)PjAQw9pL- z$;3hQQ5fzq6PJzlq3(z?32F#zo+zN1wUa4{kX;R&#ofRbZ-S>;+^?dX2oxngtID}V zC0T@10u>nMy`>8=*pyUk;XF#KtqDxcy(&iHBNT~z(Smj9BJx29Lodt8NVLd$MO4b4 z5=4lMBNe11OreQ@`3laYgw$9?);N>Las_ikpYl$bxou8pSZR7Dk@EP~vt>K1d11k( z8&6cWZj}P445jtpVBf*P!>!;Lr!RvC{rzGVX~`>;2kLA`hHW)NJj0NgKq+kuDx$m# z2eKX9h8HU=CMryQg4gcg;w7{sMV#p%X1*YqDK}Tk%q(kWrpj?!9nwhAR1nQhK|@Y6 z0tj{G;gH3aLaa$6gTt_jbYY8kJ8L*87cZa8VU5BPFYNS$ACia)QCLga2b4@065$Y4 zDhf0TGlT+N$^mg4XrN4%%TXX)t%W#fX~FIei(UxIC@2cfkwM$csLkY}+psi*p*!g| zh*Ux7+_^f0&Yf2R;TBV)dN|y28353BJbJi}A+3+KKFwWTnw>1>UAu-AP`$E#@tWx} z07MtH2!wr0iWhTzv_V#DRdh28q8L{?>5ePnq;Ne634P!3OPUay%dsK`5KEg-R7}7jkoZ75L8?T#A<{i{zer3J4jVUeSf#@*b0{Jy+*V7uPE(cYYDk4q0g%1b zYM<+=gv|zUFANg^>>DCNS*8=(i03&e&Ng5XHUp>_cA$Mqa=DYx&w!ib+AvecYD3%< zg+)7@p^{Y(3qwqm(03~3t=n6;W3WzFilXg_Hey`~u#G23%W@oSM13%wiB^TRdQq^V z3YEVc4N6{CQ=@XSoAXOIN0lKo@}MneX%=?4DZ5Y?kCTR?$K_cq+4&_z624I!TeqwI zn6P}Z;S_97e9OcPT8tGlJOPb{xbzSgoea~~ukRjiz=hk6an22U2VOlo82Q4+uY(v> zVE~@M?g}j?!VkEcq-t9cP%iO;N$zh;SXRVoTem+2EnhMXuewKsvUOezvDd7ft;3ZO zJFJsZyu@|NdRW^5CW^DuV=vEq;A8E~QHFM-7ugwixuFx_#skVk><200LO0p*pq#6_ z*?e|^NK}mx=cmCj#^}x~6U^lpJ`jh2fvuozm$SVdnYBmjhZY{r@Qb90nx91XVxe+V z1IUt+ri|83#VPrO^ph&$uMuJ4jKG$OZ(38mf&@)***@x{Cj1HA4U@-82|bCvZ-{FA zCKXw!2!jH8%CYB?;tO&XTT)i8-;~~cfw`f$*^?VtR zjS0-C3T8kE*MW5HCb|mbY#!knNqD}(mKa@O5q?@@X~iLG)>fP`W;ZTgXfIB_m-BTT zOEhyIi@A=gGVmMB2aOe2xFVP7rl{4mE5_u+Ph^O8sQ+2CF#(mx?zlyvrcjz_Xk7@E z1Z=LvdOREi;kdJmquhA{q`BHo#O=x(*vJk2eYnKEaD-dIqReH?*rKdjW^%Ue;vC0) zsT7G3%wfNAHGtwAnK=pTceC~WGK6#VgE(uLJk~VX6f`a1e;)t$!cQ`j8Mfl7gX)}M zFPhOs!XuAr8vtOk4`M25>GQ!z(pa6?A>^r(u+hA zrx-nlbJ>Ymrk`elJRm2g`M{=yAhCBZPL&DDrt_te;)Dq|1_oteC*Z&s)Od$r3ACI* z4J(nz(4vw^$uo&RaD|J3JXn~!drVf7)Aow61T6qb)o+4Zg!79CFji&gb%QjrI2cqS ze?U10iTk@uBfB;R!Pd&26V zIu0F4&;iL~D^AxYZAYa`Mrf}F6U-b<+YDg|D>;{j-U>qm)(AlHmhDOvC_h;K+8kd< zVdzyt|2)37n7t61NDA(dnQ76Y&}A<1^1BmhuWJFvyZQsbtu z56UMcKhnzzPEVJXCA~{)=<$JLD&{mSp$k8@lp4cb*bHN%k&+=--R)FH$uk1RmZ z{x5Mo#}b(ih`mfFA6b?NudXu7IA35BR)1ha2Otp4du~HsEUXX?&|FfB()QtacV5&ylo9(p&rlC3op&4Y&S@sBKDekh?amEM&-%DOXyCy4sueE2|vQ(@=Ap<-o1H%z5BGz1aZqPDZ zSbtdq@-ldRa96E}qhcscoU-d1{fU^g2^Xw|`a&pNP-vE}!={5BsaA_%-jI+;jHZ|7 zw9DLxa>jUp&{eI707El~z*}I~L&=hU7p@!`$JtG0?CA8q!xI| zQ3LKYjRNIr<|?)d@4p(BF|hmzO~_RaQB*m?8@Bt|_GUMpGu_zEP(sF&4(s>k=%+4M z9}A8on83+dXltB6c_N9EDQa$R^TnDpH84n0GZBmA^#MCLZfLIVP-as=G8qwjtlPF` zufK)T&(+ve%bR9Q;^qU2yu@UBX4(YuB@JND6avS?JtqzhTERlM4G?xYWgCxFu10pi zVpp>ihA9S2Ry73)N4v{QBRjS_S>$*{hLNy^F<`j%ts{0qlqT#rfNENn=N4n(9-{@O zXHIt631k`~!VMaJy=}!;t;A~>8!}eqO*P?6QFKCM2E;1$50eJ3!HcC_8&x0pwC7)( zLeh75Ov5`oL1j$})JkHG*JDm0tvRY}8UXv^N%?rR1N%+Q!SyCbDAzEKtL!WUWOpAi zP4<=HmKH5UCpxY?{W1~4U|(_BeOeiPZbpb?yY?=r0)$_lSc+aM%% z-WQV~cZ-NFl9oR+S+^NXteMSq_*0<>Tl&I;U~G$U{ApW=)RLc986Um=?*j?ScHbFe z`SYr#5mtN_veS!~(^@shDkylwW;$CBCrveTNMydtOtP zA}G`(_}$bXY8J5yW4?4H^t=*;>(a8mmB3ex9Sags3*!gFSD<`#!&cMIW2`Ho!|QE2 zr{uU+aRx@lysAD|{vorKBTcdLPeYnp*64C}*9561bgQc->(@}#;ePqH{6qzUJh-XV ztTWqrR?yMf*;+Ny5CdpD}#C9}Q#m!44eaNJ;Q#Dmnn%8KF z2;w2(DIaG|udD(VZB3lEWKuCm+9_NOw`|ucbt=wPLu5$l>QU^6!RWODva?z%K{c#; z7nq(_m8LrK}m|R+BE7+^GpHMFO&$`9-ItO=UYfoNuaTd*Txsl{(CH);Ac0U!AQn zzI%_Dz>ImT8fMrPaMx)ardYK-suW*gR!`NZv5pedRnsCATBE8_so`e71N=adtAkcG zGSZ?Bc}wf4oMat6>sl=c+uy3XE$bCk$0cU<-h*Sy6KSEqYvi0&x^_()TG>u3*A)=S zXXDpIqE!i0O`aOwu$W%)sIdwOszwHjQ1!SFjyMn&!K)i>EX*n{h*nW2WRbN;V|ftE zxGZv!OZYPrUTc}qNPP;JE!(rZA|njHSuEgy6GlP1ug2ze`66>dKVP9Zw|cIKIQ4V! zzTDNbMOL5vY;di(daekOB$tspC1@;Ga}#Yxv;%l2*|l?5OJ~rzv$@q;DWiSW)jr&6 zLAdxis#U`C+xo@KKuPP!e8aOfE8@eEsCC)x0rlBg3 zCRtAGN5%m9-dX6))&lxo7%Xa4f>ot|RkvYj7Wta`s{S1rEtx)oQq5Phu0#nOs_nG2 z)k$gk1A1nikM-<8EZ+XCAYofgRCLf1=JCo^Q(iOtf3!GdILbj5ns#G^*s*P=_7mB!g3YR{6&6u! zZ7KXKRH%^&Hif~X4lxX4QrJ#Z=F4;3z65qs9X_Ga#2TLvy~-5B79&X1NErLo5~Ea^ zMXO^mkpNdkDY727RwF>DD>v5AtY!pLOzIiB^hzb*lnjp5h+a zj6Bn+G(lAuldDv?=L&yhpO(I5_@?j;U?=!d5r8&b$2K(OG&kXRj0dXW{=TXa&o(~1 zEm{E#U_YcCHF}yt2`_l8w%fwZ`P_sRNZG1{eC-i8D#C3Nm%vsNQpa-m8gix6^jF~} zIama#VCHECd+dg?6gP@5`=~F=UbE1thC8`BTp+l+vx|E5EzPZXF?hS`3yGS{X#r4tppH#L-nj${dkuZrn1p zaucW84@PC-rd`X$bGQV?V`9QIYE77CzA#svX4Uamru90!?!S8w(PPj1Vk_hbus}unl`$WI*VAo46xU8@XKTtd z&0|{|U+i%-nASLmSn}jf&3nza%7EbvAhwg*?LFS0Z)9FbJDaw6*=0r_OUHyZJBgR5 zN3F|Gx}0nwS6;4aU{}vBSGPplX$j8qKibsP{4zr)dTJe2(YBZ^8;W77%D6Ax)rgI? zD`A0{`9L+%963O5h}NnZBZY*@7hU}z%UH&=fPvj**WgWBlyN1UHS8*E=gamHSB0>( zfYaqn=07a{s>1~lwe8h19pyt!j}n1swys+S)W7vcjm|6JG35-?|9XWZuY%p7rC|84jaxmnfG=9ZfkA{adV?RFotrBF(I%qIMW}jPw!%Ie_S!JCM*qD6 zSr6ONKZ>k>ZTbYT`)8+50H^=|h?L9eteu{@2a1+%{Y6K$N0)plq*D)ktY_R|=azl@ zy5etP>8@3O+p4B&b|ysW#AY<|Hg``>VXFj8Fq2c*g)=V!Z0olXupr<|I!}YmB&X*#65g#zxxoZ9lw{31TTf12?##o zC7gDuLyFO@>?(jp*3pbT61V~F%BG`kN5A^dW?RY8+U_21*wIMsopAcW6+QLL$Wyos zAx)&dcvt@=uvEcpuK5)c_3)~P0gR=t*TTSK81xIhw=q3*kZ(84sBv zk{y;ndnipCG^Bb>I-DdTI4#I3JgzK2GM}Y5aLZbLS%{JQ!6*kep>W8OOXWAy{3Z}A z+gm#%I=7f1VcVTJDH!WI8B{OX0b{20Uu!dpP8j}%~&?$b8 zO&WGBR9C$g(K?-SOH_QbOH|H2s09cDL`%$mFb!JtCSA`7O@j7Yp56uxzlBRIW+~D^ zSa1-a1VwCu7S83nr<*?6Ea8?Fbm;nfJ^gv6=d7x_e@A*uM9(uT?ez#m*9cWVH1mG= z5;>GAj zKs)LJ!krU$wBs5HJksg*{{482kM**`Ygj+-Z>(tY)S z87;&EwyQ3Nq}m-(0Jho5!FOW~&ao7MsWXCb`M`D*ezP6bD*2wM3X=)htyfFtGCx#o zWVF41@Xq$J{eAsWjM#dhxlX<{y@0v3Zk0f9(!7_CyXpd}AvCtlT0HDu;FFv$z^8t0 zx{%ETa5jJ&k#Qqb#Dhk?xrt!bNrQj%2Y`Kt4!7gpk$N~8E0ktY5b6NZ2LccfyzPgM z47K-yNbLi6-ChS)9q#PhRu3I;XFLAaqmf;t_wlLiE5K)LCO1`SA1zkU<=WXN5Adv8 zJ*;Xuva`0+kVr-2^BHm+e)+PcsZ_eEH%HgSWa8(^x^Qx6mc0?7-qav?Epv+z8t?Fn zWrlO4(iNpduiVb?^{Zkr{{M>^-p+7+css*U-kIB${m;9Atc2~o2a`*@Apw_nr{yY` zjT>=4UpYQMhwr8A-SfOKp%lkWOS~aXoJLP`jDkxZx$nDeqj6ZZK=}3sse!wC58*O| z?s#dw5Z}WKrLkhg?;0+5mn*4KWqz);%n}Nq)W(g4Y&KKojo%wLnrqdXBu^GQfVE`a zr^ai3cneb@yAVMeE((F@>_)h5Gnb#W@jF~a@va62<0s$|1KYwXC!`wiomRr#JCj*L zw6zH~zIVQiYn~uR%e=Fy&EDV^$N-&POyRya+&HC|Mvb;Qdz%bX$pATj+HpzK}&Na9261VnE%N5O zjm#w8y5dQ|E@dZ+;0q-0ZiV_my=LU_czk3GmoSVCjtuv(rR+6VnPRzJxM&I2T#+Gh zsReG(tfT8l-vkfNrcUD8_<0aYmY-#>{?L3QUq=$M{&K;cFLb+UmMc;KfV#2<<;fE9Q-o?#-m+Lpqg-STps1IdJ7 z#S5iE2FfnNjTkN01TE^2^&hLnWQ zLO4SiM<^+^A~JH3EZhW^rmM;_uP74q%7c}`X{C9v7TQ&6Be{9?4m^eqj~+NN1|ppp z8@zqEcL)@euXDJ^1rAbCU|ryV4S(bC_{ntbk}QO*Rf8<#MeB4<1?r8lqYP7|EhSli zHkEDHVRk;sB5-!M-0T!-(W9wcMYP3EvX))MPnDNORTlP^;P$5@z@2J1S&p;iWH`Ma z%F2+L?UUwf_??f7U4c3hC3BM6z<_TO9)*Chrl#$4clCgU5XV(_(C z$sQ_C6FHf;N_!d@_WR(7X^JFs1!IHn9vFe&B|^3O8X%6qPjJ6rnoJ0$Z5er^LjVI1 z8o%?*Ot(yeX&e2%VzmL@b;+m$a; zsv$^XQJxdL_ZFAkX{5=Tn$%BU?NEsckEFj-syA$SFD+n1CO*@a3w z$hB|TaeZcUEcOoB?z5g5b$umk2vG z?ikyLcb^3igT<&#SD?%lW#XC()i7L(K7+d$D#_I5_9S9A<2HE9y6BLbGrIx9Bn9Gx z7kZLoy)nL+&mqeoq^`km=avD_q}3%D_@JbLK%$25Eln7U3%I6ICHhvMsI=o5VCyTe zPEiRJvhWG--QvEMWwD_mWHK+>SPm0-N>W9`2hP7(X&PT#qcm6>m;sz z(_dT1=H|`q;oHVtfpn_;PsC#Uf4a!2#Ad%!Wr`<)y}kU--!5 zH{2G(Z{2@>dwe{5R~*;PQ0nl4(YB6T+d8_sJGbq)^_P*NfyplSTfy&<#(XUH;YTih zE*5*FF~Q)apN%zs_#?3=r+@XuTl@dw|E)WZq z@(85PY_>$(-dX-0e#-;D3@A^Z{W6Bh$~mM=+`9ej!?*tV*FOB=b9-a47kB;i-!x^er4rQs&wk3ztoe>V~{;})i2&KSXi!tg>sQ#_w;J^QbvNFszXD-W%^ z?FjM~XE6;;b7sQiZRghKZWx@>N@a?LL}eM%r}GQT3#_t(c-wG}Snhj(7xgXkg6|v( zUq-k%wTv)sA76%UV@j+P&#gOhWa+`rehV|avk$-h?_W0U*YO8m8Ggj^hPGeV*E-wK zg2x|^Wluf$NGw};X#JVkL&%YunkycBFJW{fTn0AcBb=eU`*-GqYY5`p1-h_$Nu(0nS@7c=gOugY{Z997v?m~ zvCL`ha$5xrjy7pS%LhU|%%_&i*{l){V&?qJ@)Xo9DC)`>*>d;UPrmsn)S!Rw#TRdU z=5Kc|Iu-;au;;nssm?tQUA6Zj3nP|-F9R%$2o1+#Pk=ujYJBl5>`wFf3YZL~PLc<} z9Z%VeMCu7N*EK)0Fq2E88Ni4j*5rBA&DJs_*h8wIx@> zZ)B)_tlL&)aO$DPFMN}^neF3^U--Qza%FNLu3H2GxKsFC<1@!uDfB(`N+gc(?{X=N z-Un4#svs?bMiy+&Kane--j(9ne=8hAimM4udxyIj{LUG`uv$(sP-5fnt`Uy(? z>hHo1l4iphhFQi9*CZJFO`4YFEZ8Zd{TzBH`e$|)j;&2$*-E)M2S0Nw+vx1W?4$UdJG8R$;@dYj1;6Gqd3mX` z;}5Tcq(65TSecF4N}l@oy5;_S3QfMW44lrV&gWC-4IzT_bE#4aH<{1PoG;Ho(v;6n zqPv0fmy73_cZyamQ0Ehm;TnYHQ%fclNrW;cDQrn3SOVCw(F-c)7tR+UvrN{uv!DFQ zzkR@>93p3$G+<`5eFnA!TB0atC&5_|zLbQvhv%W;fWPj3GLHuZG6&M)^mIPkI?JIn z!||ksf~H{}YJBI9N2LMottl_(rgSWxD#C_?#$PZ4aUNqDhEm&Y#S*)WyJgO2^WcCt znaYA`LkafB)KbW$L6b`Y8A$6lJ_hV66wzzC!RE$iVhCHhbW z<~EFGWcOa8GEGrC|KSfWKm5wiue`Y7KQ2Eq8oLJU$^Yx2FYfvsux))Jzj(vNSfbk( z5tUqL$CKIFIS5>ct#d2yPe3g)Lhg?yAH3tqV!keF^JR!Sri4H;vSYbSxsKbdQ~70W z%#v~g1s_%uFd>-LYTUHEW%=gipIyH9!{=fjJO80r3>xOTSmW7qS3mds&;Q}n@^nZH zC%q~;C_U|9LEJjr4s(SRp4=vqr5uPV0GlxNBaswro#wODVjpSvsn2{$%lOdBsfT~; z=X%KFKi;(C;ft-^FRuT+-qfdJSA%r?Px9^jEs*crbwgi&@h9#%{jO_b8xYU`{C3M{ zQx7%%VJK0=f%3iOnr{1Ka{*!Pm!-jrFu+RkJ8`Aq@};{8TswlB9pW~d1EZb z|4S!1NxO0FNm}-^zXl6NKlQia;{4`XD_;;lJUT$r#lYBDXxy(9i}`Xp4dOKS>06q& zOTy$w%SM^Qi#6{JjSSx&lwpw#%5cbl+mVY?Gc@$UNZez2@*WMu-(6L9OQsQ;LNkS8nV4WjaRNDc*^=2~qDM1}m z7R9Y~#iG+??k%F%C%alQbZ7XuR30gzU{2>CSZf28<@M1SyF&I&E%%zT6P&ZJTNTmf;ljZ-~)H{4Pe==e?;LZrz(Hd zxicCi&FaS~EDNLTb*xpffx{@Dj`ThEV15%85tC#`0WGZeMd%BtV)r`-KVj44jxwIT3p=z-oAHA zTx+Y5nlQK}afKa>eFqRMllKDLWhmGpB44QURZwQ~K1q(gL6js*u8etlCCj_S0Wz8H zX^J=LvMPcT6{IuCpm;@7?%pFwx$iES#)~A@)Mc!XXUjkYZ9=JDkhPehk&(mF^d#P~ z<1EQ=LLur4Kt2MT{fZ3{EmnX@oRg;3d>StVW&PrgYnQFjREmxAgY>?5WZ*#uKep|7 zckk$E@4MnybCRJhg(0pS(2|XjbD(!ziojy0Hln=2o{!~8uf8G?Py@qS0Gn!QIgT`v z-0>6Mjtq}uG)eVvcOzRhadUh+Tga9;(WAKY1Y>2k8563MC3 zk;d5Va@RMBFJLF4^LZI3_(24?OLdx)BrI0H->k)$tfFe3_VSd>ZTIpWi6wNcR9PS;}*T08(NS`|eH(3;S*F*tyK}{@sq9 zmAe6nKfG7~d(8Om@I1v!^5ShB>Dh^iLQ!$R#oH#Q&1NrE@p#^Tvb`qcd7xa68|QW# z=&~);TXA3o%LSK3M4dgA57eP!^v%vCL5u|Fl-M6WJ~}ioY*CcPo0u?@Q#3E`d;(t? z%MPV8E;rnHi50 zCr+G*I1%R&O83=NB>d)CkKIhqA`Q}}70Ivtv?6u|oU~>PBYw-GQ5wC^P$HHbPYUhS zSf-D3DUHZ*uO`J)zrI@|SlrUDf=xh4tDxS|^a;Awl~nQUQGCQMSS{7so13;#O7_1% zC0m^ONZ>_XlCYCyr{Qs3TU;-8StuXGRTy)HbW9B5$l)1Eg5$2$U`%ptdj8@rm=tqq z#&?e_YqD?K5$VE;IyGtcVw$x}XbXU+4&ejzP+G60vV8w6c_U38FjcA|)G{ql#fF_j z-AcH|z74o-5in6rHC)k-mj&Dy7HQBw;1q$SUTF)>_N$Y;OLkWRDmY*Nko_ zzvMB?yZrkN|NfqT|H!{T^6$+Xe*MV5pC<(Z8-;xGC%!)8-#1ZqVq8M^C=O=+Q|g=& zyq(=5Kai>zipjT=IXmkSMuWP5`%$kT-?<};iIC#bO$4=9fU;q;J9JG=r??|A+Q=S_ z{K)>z>JZ_l+qlAlpjUqo};pVRG_lY?O$lY0sK$^ z7-7yk{6HSR4b9>dEFoB8TnMWIKc%f-SUL~ec3Z0Dj8(5k)|x`@u7#aOLO3>%E1Pl1 zi_Y6TK4@Ump~tKToF$wP)==P&pNig$r*HwzCxnB5<#h;Df33$nj?B$pcED5Sktc>m zgWAb7n$K?2kQr9xIrikA*d5q^edmiW^zZ7I7%DK?|C9goZze@gOjHHuBq2|{aj7^8 z=s!>3gMBE8lEeVE6E}TeWmW&O|(m=N87iYo5 z;AgJuboYlMjCB%wWnJaDy>KudkfpIqhNP6nf?2i$cBa4vHfZ}YDM%)Q-9U!9z_6_V z?*Jdll((Oml|ZgiAG2jT6HhsO#01<`{xXkNqcY@%WQD5!M+*xfH>|%2e~hO_t7R=CQG-Q!)U`g4&LX z=rO?DIU%kPKTl+H&kCRs5y73XgH2J;OuAhc&%n_R*1(<2my)7h_xh)t)_b(f#k|U- zUNDqkiW*)+I$>&ftY>d#@pmvYNhxx&sBa&K>94y-UCc&$z~DQ+K@a~EEB+qX?{K;ln{Dx+|3NESDg=+I*W@>dk$t@sUkTNNQT0KmQGzET)x^vB<*lE^{ zz=Bcyop_^9Hcw4M&RmC)c>|menwL4=4?!)SxmsM872NGIGowyCLm~d*rpTU^&8L=wE7}U-@yyc`1?N*n{ z41pEqJ@Pf%bj%-Fw8VNRXCLu*aNJD0oS|JtxjeQP?98rLhB?i)Nz3A4X{BVnO&aAg z=DGoBu$TngbyzR6s!rASewtta(JS-vu6RO2CjmV4E3RE;riudj;Jq#ACgU3tL0s|{ zV(Fja_{9X)NKHr-$(jP@+mM+SIpc;KDh)3)PShl+E@sW_xPO%u(rhRD7&Vw#&|rd& zG??tvHW_}DP+G{MKO43`zCk>cR2WN{9$1r0(|vGm+FzH1(&S94-|Wqo*_*rBo8M$_ z{yuy2kJ+2O?9CsuH$P@?BD4`DZ&qKhDK=o?VoT9kg0>Qor-p{xzs4Qz=ZPn8O`!T; zP>t)~=`Rwft}nm(pWHpUkQm2*S_zuR&y*f7A$_Kjw;07IM5OUD(1fw*$glrjOGe|R zp$X02(Vzd1%1D^*-zF1{7lM9>yPN4n|3>o9v+P&PI}->vKLpvP_Sefc0@1FO#hM?Y zDWRbLza`Q9V8TpotT6LKRgNK~bdqC!Xg;jj`p5^QmumfABfX3hS0-$m8TvIbaqn*| zuISmNTLhMSr9J-F3oBgHWM$DrE89J7zQN$m4(50;mP8R%`F|*S{BW-(spE$kUDV+r zUKKj5fgs&hCGEdLzL@nFx`|DHsHd*u8ovEa+>ZuXn(@3Vi* z_Od@_KW0Az;MYq66ZJXU?Em|_Uwol||EwnqqW`RHL4*y#pJ%)OW(~I~+~T+f$643h zyZQ$=k}E!*T}a;S2d`mSP3T((uVws;dp%1Ja_%{{vEnQp$ij)VuCtV!7N+o3#&PtJ zBSbDH3>W%JHJ@8KA**4D_9h0%bOMX+oz^za$e3?_CxCkw*dSq_p1zk+w1!M`?#q1pWI4WegoE+ngsm}M0f%7iVxvp!~MGiIc zlP5akWe;C;4qEu9m=-;=&c+@do`nNe1fo-VRyP-OTeuE8r^n_tAdZ}r`pos>F7fMvicEcff5fS_WZ}#B0Yfj|btrv|) z`FL0Ian@$ZnuCy0So56F=lh(*-woTNCG#}gsjrDCrD4-gG+L95wA_==E)0-)uJ#$; z;+w{8fL+_>(m&|7{T=7k_quOaYx)dCGXc`Yz_Bj;z2L;e^5(`)JKK1<-rn45$ezt@ z9kAVpFUJzC ze;htrHp5B}glWzxAzJU9yvt9ph~nHF6d1vczhVa=)24S7pWdQtr#CXFir~yb!cCTf zvv0`%g;sdKcAon}V4Qn@qn3MPpEJv=T6}q(V8Ec!YhbFCy}O)EeXM`m-1&A-lWn!N zEp3I3m6^vGl@}WUMl`GoOU&NUi7dt-U3gbKq{l=cp(8M0(atYGmS1of&IJ77TQ48l zisp1atigmY(ExscZwE(|L&wP zd8Ht6HS0EIsHwpy%Dy|nyB_mN;Dt}qMMp%b5+X+HXxAcCXvl`U)VDuc!eT>ze46gc z(D>cS+eIxrrIMwBDV44k(YDLlrZM&nBQtn}7b6GW#(N(y5_A3o0cXAG6Fy>#Bc}6V z9DGBLA^1UrmRGm$>?$^x-Vfv=%k^enYhUIJve%PdZ$HqGGW#=Lsyc+Ydi#icX5>=2 zI98=m`(QY#I~IrNJEy0@ptFy&1c6u#7D8tk*x)d&F)juZYhGi2|=%RDNXUFBjaXCBh5%Y(7gFCMS zzBk<4bq2r9?Z)o6%EMdObFa8hS70{>L87{I*5^#dLP|qj%i%WL%3p9n4x#uqp^_p9 z`|?#6Y5Qhk_RBl3Pe?3L3MB`fQy$$wdq(aFbr6FYjNZN_DX)Xz&+kjilY20)<=hlE zb0;*IeP*2QAV>B-^e(|zB2V~slRkIDC!|GiIZ*FWww%2?qcKbR&@H3x0v*aAj{RW9 zX(Hvu9(O0c{E{x?XA`o*5OEB_#o6LEPLQwojdxxjIPZ91DkWK)gVQn|gHua9>!+p= zru)W;Xr#~$aBpqjRP2o5PL$@r)T7|pg&I^q79U3fAED6DcTlAl{mW9F6WP05S_ZDt zci{Fi95YhE6GyAA&Y|>=H@#6&}PqJFagdKe+pXK0;Vme;O5&9IP4nO z!>*3Uu#*<1i8~jbN&u}ZM5>89tWs8tzvfi0evKn8kqa-ZpgtU-u>n1xT9RYXJtT=} z4&G{Spw(|cux1EM>VfJ};OgA+uh_MWtb;3hZAtb?%FThg-aqrc^A{_n?uAZzgW!Ds zTc#g}HCwQgY*;Ve0CS1T%%dcD;p@P@D>)$Tj5;mlAM%g+b$*loCBLk=NO6dvjiYy%tDVfu zPemIT*0NaXuw1Ddg+X9k3x-v2Lm@UMM><310@tgf`XzLyyLs&7)DQg!T zwSs%^Qln0@g{h%d>G!*$NpMCaIgBMULi3IH5o`h+Nm*psx)|dYl8ziX{WRjt1XDKqAQzKFfxu9s^9fFq zKofrAXbf}P5dO|l1uIlIss!%SY~!pe&Nz$X<{Xo_BzP#<#C6vEbzD-R=tZKawP=kP z(b%7dMlH_Yp>CIWasD<&8KhRkD5+yK$&>c6W7_(?$$~;*en!q7nmgU1vV^~)^6*Gm zRs_QIfIZFZT-X4_KZ6Zi1U9gYiH!w3AKDOHy1G=9o2_s_Tnc=u+$0Ln%*iMCE?j=8 z?Z|gw<@|-K083AW^GW~dLqwCastk9Hp~H0%t_MXF|Xx`!>;;-4=Hf?C1|-K^8gc_CfS zyPm9~0bItVq~FF^R*M7B8b<8;0_HBU*<3Vly;K-EA^7PzlUXiQ3ipaWY?abZcSO42 zu%~SozY6)aUX877Jxm2`)KuH6+cjZ*=tj=u$F1-j-k?Nu$bxQbNy~|JVDd~l7y~_Vygfn#u@Pf;q zU)JY8s=atEZbjntd?>F|iOnPqNORo!W^})TipwG+>Z# zArO!P2G7_Ssp`O5eInsrb?Xdj4pT@!TGuj0Stf9(aX&N(O4as8cqxvI=>m`X8h)*g z!$WpfE%z?(AN7fKT14=G0Jx`6J8qa1$Q>Rj+A5V$6G3eiq<1Ogf^uTS1t7%xcEae3 z+bzY#HhqopIhaL!^CG+PLP4B+wi~VlwI^1!#yazsBGZ(zAzY1hL-99dL| zk!7C!LE(tFg6sCRNyO+G5H`%`!u>7m(Z#Zn#=IZL_@tko<+M)q$`}tb1wBGLeaVob zx6@nkpBZ~t_VZ(p_)581wBv_gOLHEDH`k`52K`EC~MGGe;)?&|1hw)^k?J*G?gh{Ttn{ONlLWGr=BcFoI8y&RLw zD8}s2`7ReItkbcu!5`*W9#Bg8cy`4DA@8{J=9gWjVQ*JJG#mTS5O>QCQf?}Kq0Tc4 z*yHpraYKR*EXl(;HyAgK446B`I-%YJ;oT_|!tlJ|@gG zJCVpJr`|cda2DZ9oNHQl0gxRSV)$Igs=GqeoI83eIlFTyR+?IE5jW5|v<6 z3~$VQfIgUZk}ljT9K54O{A3Ibb9m(DF>Uy|x`t>_KdA497W2;ADZ?%8C|N9#GW;lU zP&ZLnyNFO?p|3NE*XUMVzjPWpnJQoDg)l4Yt#w;7RmhH92zW(fr-7Q6M3RuV1keo6 zAXt>in4}Hc(@u`e-p7L}=O>bcd?{h&*g#)tV0^6x)f2R}CtAw%bHZXkLi~nUpeF5W zv2Ys}4JnID>qvraPQ^y3lk?o0EB550KZ7too(VZmH{AYg%i)gO4kdgqW$5|SXX zoH|ja4}>z!MX5$*SAqyeiE{4lMPha>~aSagGoG zfVS_%VQq8s@x64d{XAw zH}ANDp+-?Of(%y+ATII^F_&$uar21?i+q?fXj4?LavbNlqPghY?6TUFqA2MB4fMmg zZ3ERTTV9E|L+1=y2*0M1u{EovCPRVIg>L3qb*|XzH%vZR&P4R$<~KZ+XgEV(w61^L zuEXKr%QFX|rqBqjsmJwLTOOcdB}t&z3c^Bgi#;dJRIg63ohY|mNIJS1&=U#V-0)_J zo>A~1dL9bT%XwftHwXlB(3U1!Ka!$GN?URfVs7IsTkoC@2bi;fc%=w)lzI*lu^7A< zZmJ_!{{4St(&7I~6jJ^BFApUh{-jW5Jprm5GK5@fNc_xP)*&YMK_&y+mjR$7nL;Wx;%yTe;ueYX~14S9@VJ!tN z^mQ(^menOpgW!|XcYm3hwFPNYMLO94Tulo#8| zBw+yK)Z1D$kMB4AFB!8){fwRTCVTW?h9Q|+^xd8(Kn^*h5;x7988ia{BMG(7UMGV- zl7c~Uxb{`RmwIiL_qmP)70O6c^ zac}N%Xb-WSMM@8`lqF$rj2VQjYitSGxv#C9m%mQ`?%u-e!u;IK+~1XY&m8CF=J)xW zDI~R$arS(#op>(WX}7krV2|3d?Ong8=c&&97Lf1Fhx4t!*_mZuKFC*|++psmJZYpC zMU^?bh8s`be4xDMgGPs)o!!Ep5zDez;xu1*Xtf_UdTxr(^kv-DUMzE-uQ&oRp`WiT zOq}4%5EE9ODdLKG0nwJr11w;k?dXvR_Wlp`+O_6$5`iXsgx%N`2E8t{B8UIeH zm_CN0sinElX$@g7?Ej};Cluu+Q-?YqisJ5oSoGlD!F0WU?~m7duqh%ChHNE{XO{gD z91iZEJ4F2sMR84ZYCX84P8rODnff2E@12L&>qcRU2woVV*V8<{lzu|tomb5*rNK=q z=%Ps~qz}W*``gcu24YQyXCAZO zI3|EEmWel7gR)Gsr5|RCzBBzRk4gI^eACByEn5zOBy2Imn)Bk~3eUL1I5+Lg7fp{C zHn0nW$F2GB{F5-e+k5-$E9(Q3i7zk(zh~S79$fflkqG^7n3|BT+J-NeAzp2b4RP_j zrzjdGZ9EQ3niu*;PkLH|EUrAd-M!qoJlrJ2pJ%Hqc2}lgxH>i61Oh=SL>({TcSGem zaRJm4w}UTxfrVY2P!qQ!7C<{?C22m^TDJQdS=reGVv<@SO=E9k(Ey@^V-zHU;!_K> z-O>ovP%C|pPe49OHwopFCab;mIkt7)Yb+4R88~4W?P}$;B7+|il$bFqHC8heBUV%Y zn~684ghbarf8_5!FN-(mT2H&Pgo?03u#0>&shzRc_$vQX<14XE{7*%<>;Jdm^?&?R9!%ihzy5DWF6Fif`8tbo zQ45><6J8|Qg^g8?r5AcO_gLnec2)KddXAM)E?khw%}%~*T)=TV$5&Kn?+3FcW1a2) zNr5W3oYTr{m#+IAB60$Y7z>C71OqX7LRWc*7b(&Dyhe*F4x+c4*2J6Fspg?U!x3J#ux63P%s$ktgb~*2`+aQ~r zoz1GvrU^*)C~ZPj@nKNxqwS*y(4^1Hecnj4>l!RxGkWq5FMhGh@$^mUQgv)Xaz z(9-q!q_^)jGql-z%H5oP}${W$?aS83m#!l|GgH?^5v#$S$2c zE_UuQx88g$e>tNZt?_kf^X0~hU8$84d4PPUL2yCb)dFIh&!0D*6hNBWt!5+EzV~Rl z0J-^cdv%3JtQ+=wZ@snga%*+@chlkP=F6Ry#Dem7!Z)|^=W}858o{ga_(6W7zYibe z*XO*f39_H#A~28{LQb;U+>0#BM2OxeKZ3A!x#p+-c@h8KVRKxV~B8daZ^da zt?{y2L@AXr21yKr#NU|D0YNxd?u_%(-r===-SDy|190ts__jOuG&E>+-(Sz=@2}_c z_c#2#na}re$T{pdB1ZU77zfIZkP}(MVciMO(UUmc%GL+&tvZ9nON^g8__uI&g1LgV zgD;+y#mD(aB#A<|r{qUCGL)0WR7&$}sN9^Jb8g44@((>d1w~gZZLv{nvS?^s$v*Iq zqnx){wjvYncLrQ@Y@)MTGX}q@C$67$mcOax3r~Cp3aI$78AhmYsOssST(?%eJneXv z(KTaJl4p~h;gSBu=hKgprI}qYmD$6hs@jYc8S4(o0cWf^M_deh+U!RO`e*0Uf9#j*h{XVb-o)l>lizb{@61=x(2&v=!NLyN5q=y>lw zc$nW^p3m<-F^ONRz(}b%N~xs%i-?bu0>;Yo`0v(I3;Ep^@E$dRms*6rPV|5$R|bye zLY~OV2^&s%UT3m11+^o+VfU;|(AcOkhFB=RBfHM$L9@O)M~7?ZH?@Q4by)u|HLA{! z{h3!ij##z4#(MheYMo^-d>O7C|H`VrXDOz|KmXEd-aB6~Vx6>vj_sExTJJXdy!cU@ zi}ijXP1+yNs5SpbJvVy^k z#e9Jx{(JZGJ6o$(ncvMgw}#4FjWvs%7TD3CIt;re7@|3of;pzL+%oje3GAj##+Jr1 z9zKRTqy&k(JkpX_FNQ%3*G>X;xn`7N3*mY|@H(M95H?Z3E?0@dc9Av)@+e#w76IQu zkAfWq`W)sd$X#~=misi)>S&t;RnEL3S7AqIrH3vY`QcX8rpU-UAp9;G8)|B_q3~3) z(XHCKauXFWqd@FfoW4{~-C1(TBH?C35$WH2}|Da&Q8BYmdvLCzMcn&ocPUU6pFCymGv zm$_{3rRS!mfzLJoCu1wqY?;lR2S30>*j(bxjOw5K?W%H8Qx81^Ab?4hxyv4rxDxnJ%mb$$Eu-!#-GI$qA5h;*mJH%6!AKVl{q#u;Psi{=@O^ROM9n7P!pHvOBh$uUan^wn|nm2 zSl#5&Q48h0%0pQ%n(M7S4j+0#9=mvn^5ICMDD=yS_|LaDH`>eCFmA0izi(|XHx}|2 zoP~ClVGS3teVMPundi3gGDQ0@K5#@_gvQM1G?#oD`Bb09Ll9WHTr-V`=Yo89ZZ3b4 zXY&v9M|t*e9?cSe9_4e7`GX|JpM|gT`L8JPC|_8}(Fo)V6nT=*^W||qM_obSIs@?5 zDk08IJPzMyJ7*_MQ<&SjMe58mm76^}=@3bzQG8Zl`|YjgdpeVBzHG0pZpaqd^8ExN z!|L8;`}BOfGvIQbBMI`^dYxm8j*p0qdHAS7RZ(okJ9R(E=tQGz0avzxjmI2r(KHdP z3yN5*BfagcrTGe*Yxo*zn4QH*ySN;5Pjo+V)(_ipX-pOyA4gXZZbfIFiP2WqD=W*C zm;`rqLc0v)If-2EQQ^yz-F$AUXI(3*;@Wc-8#bx!dh<7P`bpVh4es#XUGSCyOG2p# z3Pqj0x#bcV{e+eUF{K5yUOb#s3JP|qpz;jU2Uw8#!Ew>Vkg=8cpR&}6s-4e97bxHXMH#KxNgC{bmdK(*54#hCS0j5rLA03P^y41+5p>Wi2N6?eRJ-C1*$ksGbqY2U>L zs+TtEDkZe($@jNom+DJr*L4Zc;h>s_^Js4CoVZFCqFnWxMT5?-x|LKKZb6o&BdgLr zoS&Rs)&qK1t79x1x8l2B9Sn=xyom5<@_i_O1 z{tM-k?%31@acmi(@OipO_L8s^NjIgE;j>DHkCdd*#yNkz8)?%fC6G^I5lR>mJP8A( za+041J14!vy3m{M*ahA6zK^>qsfXpDHwQAj;WEeh*DIAuhwL!qy6r1~l_V5l?tqGg zcsM08g0X~;7D@gA?iXU#EhHe5Y-`RX+^<*&bpB9eK&S=`SZz*B;Zy|Sr{}nN#7Mv@ zYo>a=y7D|x>b#dR<`xuro5 zGp4kxmL^|$QqoPo(H1wb#1wVODPS^WA9@#;SDm`wWs77*QHHCWd!yX(3ysYzm|3kg z!Yb!NnNs|0HNv7*f{jqu)}`uV)UgN`r(C~_gW{s$sI!3RIvy4`0gC)n_(kB5=?zcETB>7} zvK%?f57o6MNq@i?@KRgA-DgJRQMKaST3S3Ha~Lh}slN~D078nj5TX0Z6dTYt2U#V5 ziTf0VQ$x-5*UH6u+SKxxUKRlgR!aM0!9P<&8j?a77zPc)SJ4UU)(6ZW!t+)iuJ8HM zG_8AgKaYjQ?88k_>gJxWQq#J8_fkB;Q2%h9mr8A8JG3R$QrxhkfI)k4o2Pj2;>DPR zeTB_0wIYc6-tZoIGjS#rC|?H^fvukb<1nELST{jU;Dx+YbzvALmaT*~2&Q6^dP%A# zR7?edhq7G@HIl7l{@qqPW)IgMMrdU8eCaZp=g>;b6hu@$6}uAD=6kUzL2|xJe3i_3 z%?5YFKLb$Zj?z-%i_L8<7<+mV)AAQ>8JCuFtkoG>Z-}G6AiL$ z2!pphP2%RF0*(e2n@4M(V+Z+IFc4FUTZOB`Zua%elxg+1)qTSSl!Xlz!`c275$`Vf z7T)`@r#Q?sK*5AD9Mg3=1_<1~&AJtwDeGt;)x;#y3^1{*RID*f93UVuyQz%LNeBiT z!JKrDEJ$&niTY)IE-=I@gTn$8H~WK5DR8sf*~qE_tYp+Udz&{>3ci~ReHBPoQ;Y$b ztH|#pNMBh_OCfhb8U*|3^>PaX1*^pvyCrj$>UEbqwfix!=U78#?w8C>Dv-o2lpzC0 z2sEuuZtgr7|2~1{@cl86n!$Q*kTJBFmg3QpNM@Lo3w~#Wg_LnR73e+b;}4Ar=og?Pz>^7401%piHmzRYU+?6W{`~^ z0X*!ZwYhtMbfzxu#;^I{?IJa-h;>>e!iTcIS6mo;%P2_k3%X*npkY#`phY%(orGHL|z(o?n!)PrJ`+?>>T`u@k&wAJjGBkuQ314 z{ldwtW=*PNgKB+@4rW+Q&;ctYm#lq;IhFRWBvT?KjvZ;W$1oQjt#~jj>qGul8K|IP9GozCAykpAXe@ec2j+r_vAIHMhwXrV_(Uk;)~WhF6SNHO zNC}j+zl#kEBD;I{$#ee?D~Qog*pKTXBF>3%Q;asl@K}3|*h(DS%Q(95O$d4ChZDYU zf~JChsHVpr2qmVHD#n2(AZm>=i2*7D1Vk18=2?M5mTg^Osd-T}p|wsw?zrn~eZ?(3 zA;Z!TOg>9Pr>ldJvC}42T~$LgXPKod5D>cxK}3l@z!sJ*%)d`NU%bx>Lul)C$rIDA z6g7jCu?sXYaxm_;mAI)}nUFxX?7xfeAYqojA-{Yj79{W=;k5eSND5)Rj5!*wXr{>O>qTgo+Ri9mZt)Bo3BQ zkgxatFSjcFZ?G!m-#`18lH~r2vQ;UcUv&Gk-GA{PA%RdA7{(tb%7|FFJ>9 z9+gCHjb1O|xq8GbiCVZ_fA23I;{TzS44`4T(ueuk2YN5z9Sf(7Bjo~ZPS+A_qP}?l z>^hon@wN{_6sL4#D_a00x|zrJMYguOw6i#iD1m{5XTE4J<;ZBrlx9siFsJM2;4@M8 zM;e0FQCv@sx*ydr#sLH5Pqh8^y5AJ>|K$r#a|$!c>+h3UijP9olamQLsPtJveoj){ zoVlgaotWUIqChV4^$jo9@JW9rtXg-HZdrg=_a(SM^y0<|2@Uc{uPw@9B%w#$kVSc& zp-UrBp-bD6qh&9eDlyO8wmRz_9-N+sQv#wc2IoA6V105NJK5pYDK{CDvfP`L(0l2x zS4d42TIbD2KbfP^nsr}w8NJF{RZl_m`V)qj;sQyZJWFZ4?1$-U>D5SWG|BeHX7uX`x?n=6~a3;Y&XH)^580yhKgO+~Nryv&jf%d!8a4 z-otgjL(RTn!85&$=WPmehO-Y@!9)-4oOk{*^Hihg949kKFZ=H7@_m=b60goBI-2Tl z1`Vcg*12Qzy!*;5f!ZCt7(xsnd|kjRn{2*pbN#;Z4==Geog-*S>LiaWVoYo&fEf>f zAY=KMZR2LFb|Hrcw%2{hRy<{Qjo~1U5B7{l^#PBd~FF&WIe;j-)%BWYIu<7in=@AW;TuURu&l5h2uK)%mku_tjSm+1)RH6YaW$ zaOmDGw$MzNxSwJUS#}rnz!`A@3nie1S485=AU2Reb+2iKaFAA!{#jN&vzxCnZj8)J0f(8rk}fX6(HhMCgPkj43MDhie<&raNURDX_LTfsk+zo)J5N7 zm@IN_MT$aP;+J(~Cj@SEt`CpRpajmFYi1N0^TQO#L%AYXF{?siO=3c=R8x7eVhv~I znB`pC2m{K1_#$S!+_22qB8BX*hL!V6Nj{);n-pfUiu?81#m%xNN&Vr2uO5$M2G;h# z2`?^R@2#D64&nZ$1Bsp7-F~sBMc!AxoNvC^+gf4EpVGc-uC1=*KiZ`GS>~>9Lu@tY zyRct`#_CqgOj5pEdoJk7Qz@}2X`xHi!bRgFb;2g3dU3jiNhQI<1qIx1lcR0qZ8!hv z@ZwK>V{-%3vgGa#ciz^zAMivr8ISswJqVODss!|HK)kS9nHHmBS;?A>wgM}7>8d@Z z?|1>`XCCB&1H(~{_0YkuAVHj+p z5PPM$7_q=GZ{%WxzlF+$aAE_ybhIPD%T>E`^lSp<>s5e^F~lNO+c=R#?^30(z(?l6SV3UtoJF{}vV=F(QxKWo6mR zm^1UMJT1XlEy_#D-=&7J`#3R2$w_3npFY(p(5U>TZ-4<^D(<50fb2?gSwym|@4Bi3yY#@q4^fwmqu2baArQ3{~Orfu6_^uVH=O)Mc zur_k2w)i!LYho72pT(ggG7(Hpmk$^_ z+cHD^;0wF*av#u-#l4Y9SCq1dchqo=y#z1Wwpc=>hwbc|=WhnyPJIfBxqK$pFBVk4 zhC7b5bMgl2mP=`-5k_wrRm5d?nS&ARQvdPIz|J&3SN5V-`{niqCbfZGh8l)6-pHW- z(NO_3NbZUfZ*31rXA2=ZjKrIP9rYtB>pJ)2Dpctl@4hi!%Bg>xwZGm{0V~Ok@(!x{ zjFcCR*ptUw6k4@HCIi z!N>5gpb|MWELs7P(Vm;cF>WY)aY-C1=9zUK7fX778GU_GuZk@18(D05-M^0cnDgQ{ zq(}UFY*g|v-e~p}1pSkPT%LZT9S-L0W;XAm99n=9w@uz~sjGF&W<35BgYKz#LJ$SKKk3XICVDj35CKG4RYxUi%t8A+BFhBAn8gaPpiI&`v3q4BsxMhlqOI#pou z!mka%#WFq(qD1DvuUf2&g?V*jIn(OJUgHoz$Qekl zA&O;y8kASJv$yZI-P1DrDoxCrn7e;k(Ve&MZq24&t9t+Vd0nj|c^jV)EGCr-kqhJ1ffsv_ zPX7g0!)RFZsHXgkhR0O(Q6CB+b>IExYa8o(OU>=I=2B~|77p6AnYp-MM`S9MDu6i! z4D!2g-bF6Y4L#a0PaWZMdWF^I2?wkbY+#gt(F^C!7{Hpf;1m0Fm|M1BoX*P8V&Fte za+XlDbVrM?k?3|$emmp%M%{~y;l~^%i{L~KMkA_+C|28~`>r@^o^@qm;}>)wg4<22 zfq(GHA65pNGF{~02Wdmta#+Xw^kYytE#_lQmX-=A=z_ye9WKm&hfB|m`vR@d; zuQN(C_A3)^fB)9`w!dFYw@76+G`hbe-Ne$_wN`bc*f4Hy4yTQj{`V$vtsQZ4pov`i z3$66WmsLLavg$nc3r4(Pq1_klJwKz_zJk2au(u=X=|&<<`zlYsE(+ zb_zA+Qp!SWGqma0Qkxc3BVnSNF{Ch?%cv{ z7*z_6Uha5pfez(42Q*$|dZ|%48hGrTh zKIoz*+zO0bfPeCy7}a`ybdpO@`)lrs*LXMKVh5{2ld+tgju7~q*<-Kt#+xo1!)?3Y zp6Rx|d`E*rhQ-pV+^s@~KSoC3~AoUXK8ycQ%~xnP2RaFHUUt@bY!sAg8q+2;us z_EOW2o=&l@s+O%e*mTr*X9sJmS(#sPRrA!Z=(R<-(k4tIzx7P8HkUKI{v_s77@9OOENNCNBTwB@4_F_< zx8kZWX_`K_9>DU<3hB&@`70b)F|dHgt5aI%*Q7_p^GGcLCl<03FW==~Y*BEAihFF0 zp+rW|gi;2x0y`o(93#hWAS^)6NQDRr6g*hYm=g5dPCeCd8ekJ^xiw5h-+^6UX(4-hox?*ME%a<=nc6BBS}Z}WMAR8m!!!iL(RIe7FcN0R ztrErp6$WerWAaKUe)G)9yu7x#({dGz83SEll!C3T8-eodl59=QGfdj>kv_*^9ov}J z|1ovwN;T-uNEx9yl87LLediV{j28G$uo|;(q}?K9Pz7$7sK$0lcWm{2B4R8xIuG5W z2wUEI*Ov`VweE!u`f;}DbRQPrE=uVkvW2o*7ZnCgmd7lGy2Gyd-9fNOwG^#Z*~fkR zTm(%kLp1IrUk&P~R+FAMn~Y0Y+;=7|^p^p$0xk;J_t30u@ZGo3`8gzmS|8K0W)|T9Rpub z)#D&FhLw^fgfa7lyT+GdtSb9AhDqw9_$*VgN~Yzxgfb$QMe)9*D?+-Ekz_@UpM>@b zJ{p_?A&mi|85i?sAL~;_9LGn+s+r(gme$J9wN-@fs$OM}Fu`vK@Jg3U;kr&bw*fV; z)lcgk69QJ2K2{>GE57@67)isaqFQ5YU7x0`xW9!V*LYqpj@$JElMHc4NDcdJ+0qA& zF=dm45A1nb+pEiVU}27V1fTeA`P3d{Bmyjoppe;Z&xkqCoF(O*C8=>pRp;KCCL(d~GRfEvqns(%PP7<3+aKwBd00mWapuavU%~t*q{B zJ%72eT+1JhP-&;V=X|LV6^OQ4))P~3kqzSNMrja-(I9iE`1*!1NVDB$s2&*$ZR}ad z0u0dvau`JE>OQnsQVG=Z$AOb~zTJG~2YxaClMyh?gd*DzM!XX(xUA1muqWY-f*GzP77NsJU$3g zxGlaO9h^Ply0^A>mN&N7mThoUxLX@8yYOxkW;m7=lx*2TZ*6=8M3X%?fp!Veq!u4txZL!F)>} z*2?{WtD8*0uo7bO^oKwA;lOE5W0o}xhj^RYE6sK@mfG2BEw5r$js7VmS%^S~JX{_8 zhFV!)Z>_90+o@X+mGG3S&qvl=5#u@g#pbJZMYM~p+2E8p&4;f@8AgExzsM9&AH!-| zd-KJMHTZw6wLG#qs?N^$!D%R>p@jDLTM4bL?bdgz;2HBbY}Kz$UjbU#ZgTP{h{xvp zaww+W4zTI514HnRmrBQE~T88`JnY+!fc1A}Wcv|WYBAd2WoLB9;cbHB(jwbjpwdMYlua#`Bo%A+h0gH8+nf3q6D3a;3rajmPyI^^Oz`YK z{^AS$``71sR;m(Ws?Bx#V7B|e|5Hw#&Frvubc9DZ5A6{h6b~RYz*sEdf^tfj37+QT z?RWF+*7H$H@VFtw8Q8z-ome~qj|X*l!yQWRAd~qTd)n2(|ypO%N}P>vh3-E z`Cpp`sB(#a2^n$)t9uWZU@b{3yV-QF6IbL4Z-}$Mj%FOgimbDOyJPh${ z9q&r Class initialization + + + + IF (scr:=LockPubScreen('Workbench'))=NIL THEN Raise("scr") + + IF (win:=OpenWindowTagList(NIL, + [WA_LEFT, 0, + WA_TOP, 0, + WA_WIDTH, scr.width, + WA_HEIGHT, scr.height, + WA_FLAGS, WFLG_BORDERLESS OR WFLG_BACKDROP OR WFLG_NOCAREREFRESH, +-> WA_CUSTOMSCREEN, scr, + 0,0]))=NIL THEN Raise("win") + + + bb.setattrs([BB_POSX, 10, + BB_POSY, 10, + BB_WIDTH, 100, + BB_HEIGHT, 100, + BB_RPORT, scr.rastport, + BB_MAXX, scr.width-1, + BB_MAXY, scr.height-1, + BB_USEREL, TRUE, + BB_DRAW, {mydraw}, + 0,0]) + + + + + bb.draw() -> The first draw on the window. + + LOOP + + REPEAT + Delay(3) + IF Mouse()=2 THEN Raise("HALT") + UNTIL (Mouse()=1 AND bb.check(MouseX(win), MouseY(win))) + + WHILE (Mouse()=1) + bb.setattrs([BB_POSX, MouseX(win), BB_POSY, MouseY(win), 0,0]) + bb.draw() + ENDWHILE + + ENDLOOP + + bb.draw(FALSE) + +/* + bb.setattrs([BB_MAXX, 100, + BB_MAXY, 100, + BB_WIDTH, 80, + BB_HEIGHT, 10, + BB_POSX, 50, + BB_POSY, 0, + NIL, NIL]) +*/ + +EXCEPT DO + END bb + + IF win THEN CloseWindow(win) + IF scr THEN UnlockPubScreen (NIL, scr) + + IF exception<>"HALT" THEN explain_exception() +ENDPROC + +PROC mydraw(data:PTR TO bebox_data, mode) + SetDrMd(data.rp, 2) + + IF mode THEN IF (data.oldx=data.x) AND (data.oldy = data.y) THEN RETURN + + IF data.oldx<>-1 + Move(data.rp, data.oldx, data.oldy) + SetAPen(data.rp, data.oldcol) + + Draw(data.rp, data.oldx + data.oldw, data.oldy) + Draw(data.rp, data.oldx + data.oldw, data.oldy + data.oldh) + Draw(data.rp, data.oldx, data.oldy + data.oldh) + Draw(data.rp, data.oldx, data.oldy) + + Draw(data.rp, data.oldx + data.oldw, data.oldy + data.oldh) + Move(data.rp, data.oldx + data.oldw, data.oldy) + Draw(data.rp, data.oldx, data.oldy + data.oldh) + data.oldx:=-1 + ENDIF + + IF mode + Move(data.rp, data.x, data.y) + SetAPen(data.rp, data.col) + Draw(data.rp, data.x + data.w, data.y) + Draw(data.rp, data.x + data.w, data.y + data.h) + Draw(data.rp, data.x, data.y + data.h) + Draw(data.rp, data.x, data.y) + + Draw(data.rp, data.x + data.w, data.y + data.h) + Move(data.rp, data.x + data.w, data.y) + Draw(data.rp, data.x, data.y + data.h) + + ENDIF + + SetDrMd(data.rp, 0) + +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Change_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/Change_Example.e new file mode 100644 index 0000000..8c60eb4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Change_Example.e @@ -0,0 +1,56 @@ +/* +** StringNode Example-5 +** +** add(), search(), clear() AND change() methods. +** +** (C)Copyright 1996/97 Amiga Foundation Classes +** +** See: http://www.intercom.it/~fsoft/afc.html +** +** FOR more info about AFC AND more modules +*/ + +MODULE 'afc/StringNode', -> Our MAGIC MODULE + 'afc/explain_exception' + +PROC main() HANDLE + DEF n:PTR TO stringnode -> This is our OBJECT instance + + NEW n.stringnode() -> OBJECT initialization + + n.add('Zorro') -> Here we add some items... + n.add('Batman') + n.add('Superman') + n.add('Gold Drake') + n.add('Mandrake') + n.add('MOMMY') + + shwall(n) -> Here we see them + + n.search('momm') -> The search is CASE insensitive AND match the first one ;) + WriteF('Current:\s\n', n.obj()) -> Here we are! + + n.change('My Mommy') -> Wow! Now MOMMY is My Mommy!!! + shwall(n) + + n.clear() -> Empty StringNode! + shwall(n) + +EXCEPT DO + explain_exception() + END n -> Remember ALWAYS TO end an OBJECT + CleanUp(0) +ENDPROC + +PROC shwall(n:PTR TO stringnode) + WriteF('------- \d ----------\n', n.numitems()) + + IF n.first() -> Here we go TO the first node item + REPEAT + WriteF('Node:\s\n', n.obj()) -> Node STRING... + UNTIL n.succ() = FALSE -> LOOP UNTIL the end + ELSE + WriteF('No Nodes in LIST...\n') + ENDIF +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example1.e new file mode 100644 index 0000000..505f6c8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example1.e @@ -0,0 +1,69 @@ +/* + + $VER: Displayer Example 1 - (C)Amiga Foundation Classes + + Written By: Andrea Galimberti + + This code is Public Domain + +*/ + + +MODULE 'AFC/displayer','afc/explain_exception', + 'graphics/modeid' + + +PROC main() HANDLE + DEF myview=NIL:PTR TO displayer + DEF vp1, vp2 + DEF rp1=NIL, rp2=NIL + + NEW myview.displayer() -> create the OBJECT + + myview.add([VPORT_TOP,0, -> add viewports + VPORT_LEFT,0, + VPORT_WIDTH,640, + VPORT_HEIGHT,128, + VPORT_DEPTH,3, + VPORT_MODE,HIRES_KEY, + NIL]) + + myview.add([VPORT_TOP,140, + VPORT_LEFT,0, + VPORT_WIDTH,320, + VPORT_HEIGHT,100, + VPORT_DEPTH,3, + VPORT_MODE,LORES_KEY, + NIL]) + + myview.setup(DEFAULT_MONITOR_ID) -> build system structures + + myview.show() -> show NEW view (automatically stores the old view) + + rp1:=myview.rastport(0) -> get PTR TO rastport AND viewport system + rp2:=myview.rastport(1) -> structures OF the two viewports. + vp1:=myview.viewport(0) -> Indices refer TO the order in which the two + vp2:=myview.viewport(1) -> viewports have been added. + + SetRast(rp1,3) + SetRast(rp2,4) + + SetRGB4(vp1,2,15,15,15) + SetAPen(rp1,2) + Move(rp1,10,10) + Text(rp1,'First (Hires) ViewPort',22) + SetRGB4(vp2,2,0,0,15) + SetAPen(rp2,2) + Move(rp2,10,10) + Text(rp2,'Second (Lowres) ViewPort',24) + + REPEAT + Delay(5) + UNTIL Mouse() + myview.showOldView() -> restore old view + +EXCEPT DO + END myview + explain_exception() +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example2.e b/amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example2.e new file mode 100644 index 0000000..01b227c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Displayer_Example2.e @@ -0,0 +1,147 @@ + +/* + $VER: Displayer_Example 2 - (C)Copyright Amiga Foundation Classes + + Written By: Andrea Galimberti + + This IS a complete example that exploits the following modules belonging + TO the Amiga Foundation Classes: Displayer, Mousepointer (AND so Hardsprite). + + See how the mouse pointer automatically rescales its movements TO fit + the changing resolution; the pointer sprite IS bounded TO the + dimensions OF the viewports it moves into. + + You can scroll the topmost bitmap because it's bigger than the viewport + it's displayed in. +*/ + +MODULE 'graphics/modeid', + 'intuition/intuition', + 'AFC/displayer', + 'AFC/mousepointer', + 'AFC/explain_exception' + + +PROC main() HANDLE + DEF myview=NIL:PTR TO displayer + DEF vp1=NIL, vp2=NIL + DEF rp1=NIL, rp2=NIL + DEF win=NIL:PTR TO window, poi:PTR TO INT + DEF topo:PTR TO mousepointer, vp + DEF rx=0 + + NEW topo.mousepointer(2) + + topo.image(11,[$0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $1F7C,$1F7C, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080]:INT) + + topo.hotspot(18,6) -> the mouse starts from the topmost viewport, so + -> its hotspot it's SET in high resolution: the + -> auto() method OF mousepointer rescales it TO adapt TO + -> the changing resolution. + + NEW myview.displayer() + + myview.add([VPORT_TOP,0, + VPORT_LEFT,0, + VPORT_WIDTH,640, + VPORT_HEIGHT,100, + VPORT_DEPTH,3, + VPORT_MODE,HIRES_KEY, + VPORT_BMWIDTH,800, -> bitmap IS wider than viewport + VPORT_SPRITES,TRUE, + NIL]) + + myview.add([VPORT_TOP,110, + VPORT_LEFT,0, + VPORT_WIDTH,320, + VPORT_HEIGHT,50, + VPORT_DEPTH,3, + VPORT_MODE,LORES_KEY, + VPORT_SPRITES,TRUE, + NIL]) + + myview.add([VPORT_TOP,170, + VPORT_LEFT,0, + VPORT_WIDTH,640, + VPORT_HEIGHT,80, + VPORT_DEPTH,3, + VPORT_MODE,HIRES_KEY, + VPORT_SPRITES,TRUE, + NIL]) + + myview.setup(DEFAULT_MONITOR_ID) -> choose your monitor database + +-> this window IS opened only TO clear the standard mouse sprite + win:=OpenWindowTagList(NIL,[WA_LEFT,0, + WA_TOP,0, + WA_WIDTH,320, + WA_HEIGHT,128, + WA_TITLE,'Wow', + WA_FLAGS,WFLG_DRAGBAR OR WFLG_CLOSEGADGET OR WFLG_ACTIVATE OR WFLG_SIMPLE_REFRESH, + WA_IDCMP,IDCMP_CLOSEWINDOW OR IDCMP_ACTIVEWINDOW, + NIL,NIL]) + IF win=NIL THEN Raise("win") + poi:=[0,0]:INT + SetPointer(win,poi,1,1,0,0) + +-> here begins the show + Forbid() -> forbid task switching + myview.show() + + rp1:=myview.rastport(0) + rp2:=myview.rastport(1) + vp1:=myview.viewport(0) + vp2:=myview.viewport(1) + + SetRast(rp1,3) + SetRast(rp2,4) + SetRast(myview.rastport(2),2) + + SetRGB4(vp1,2,15,15,15) + SetAPen(rp1,2) + Move(rp1,10,10) + Text(rp1,'First (Hires) ViewPort',22) + SetRGB4(vp2,2,0,0,15) + SetAPen(rp2,2) + Move(rp2,10,10) + Text(rp2,'Second (Lowres) ViewPort',24) + + vp:=vp1 + topo.changeImage(vp1) -> install NEW image + topo.move(vp1,100,50) -> start from topmost viewport + REPEAT + topo.auto(myview) -> auto move + IF topo.vp()=0 -> IF topmost viewport + IF topo.x()>=640 -> IF mouse hits the boundaries THEN scroll + rx:=rx+1 + IF rx>80 THEN rx:=80 + myview.scroll(0,rx,0) + ENDIF + IF topo.x()<=0 + rx:=rx-1 + IF rx<0 THEN rx:=0 + myview.scroll(0,rx,0) + ENDIF + ENDIF + UNTIL Mouse() + + Permit() -> permit task switching + myview.showOldView() -> restore old view + +EXCEPT DO + END topo + END myview + IF win THEN CloseWindow(win) + explain_exception() +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/AFC.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/AFC.guide new file mode 100644 index 0000000..9a58568 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/AFC.guide @@ -0,0 +1,381 @@ +@database AFC_WhitePaper + +@$VER: Amiga Foundation Classes White Paper V1.50 + +@node main "Amiga Foundation Classes" + +Amiga Foundation Classes + +A FreeWare and Public Domain library of Object Classes devoted to the +software development on the Amiga and on future Amiga compatible machines. + +! Note: new / modified lines are signed with a "!" as the first char of the +! line. + + +1. Index + + 2.0 - Introduction + @{" 2.1 - What are the Amiga Foundation Classes " LINK "Intro_1"} + @{" 2.2 - What are the Amiga Foundation Classes for " LINK "Intro_2"} +! @{" 2.3 - Who will use the Amiga Foundation Classes " LINK "Intro_3"} + @{" 2.4 - Future of the Amiga Foundation Classes " LINK "Intro_4"} + @{" 2.5 - Interfacing with new Amiga OS Compatibles " LINK "Intro_5"} + + 3.0 - Implementation + @{" 3.1 - How to write a Class for the Amiga Foundation Classes " LINK "Impl_1"} +! @{" 3.1.1 - Class name " LINK "Impl_1_1"} +! @{" 3.1.2 - Methods' names " LINK "Impl_1_2"} +! @{" 3.1.3 - Object Inheritance " LINK "Impl_1_3"} +! @{" 3.1.4 - Object Initialization and Object Destruction " LINK "Impl_1_4"} + @{" 3.1.5 - Libraries and lowest OS version " LINK "Impl_1_5"} + @{" 3.1.6 - Tags " LINK "Impl_1_6"} + + @{" 3.2 - Definition of error codes " LINK "Impl_2"} + @{" 3.2.1 - When to report an error code " LINK "Impl_2_1"} +! @{" 3.2.2 - How to report an error code " LINK "Impl_2_2"} + @{" 3.2.3 - Classification of error codes " LINK "Impl_2_3"} + + 4.0 - Porting of Classes + @{" 4.1 - Porting features " LINK "Port_1"} + @{" 4.2 - Porting limits " LINK "Port_2"} + + 5.0 - Distribution + @{" 5.1 - Compiled Classes " LINK "Distr_1"} + @{" 5.2 - Classes' source code " LINK "Distr_2"} +! @{" 5.3 - Availability " LINK "Distr_3"} +! @{" 5.4 - Info and WEB sites " LINK "Distr_4"} + +@endnode + +@node "Intro_1" "What are the Amiga Foundation Classes" +2.1 - What are the Amiga Foundation Classes + +"Amiga Foundation Classes" (AFC from now on) is the name of a library of +Object Classes designed to manage the several features of Amiga. Each +Class will constitute an interface between the programmer and a particular +aspect of the Amiga Operating System, trying to make the design and the +coding of a program for the Amiga OS computers easier. The AFC have been +also designed to assure a quicker porting of the Amiga programs on the +future Amiga-Compatible Operating Systems. See @{" section 2.4 " LINK "Intro_4"} for more info. +@endnode + +@node "Intro_2" "What are the Amiga Foundation Classes for" +2.2 - What are the Amiga Foundation Classes for + +We have designed the AFC for different reasons: first of all the necessity +of fully exploiting the object oriented programming (OOP), that allows to +"recycle" code using it in other Classes or in other programs. The +recompilation of the AFC on future computers with an Amiga-Compatible OS +will allow a quicker porting of software products. See @{" section 2.4 " LINK "Intro_4"} for more +info. +@endnode + +@node "Intro_3" "Who will use the Amiga Foundation Classes" +2.3 - Who will use the Amiga Foundation Classes + +The AFC will be available to all programmers using a language supporting +the OOP. The AFC can be used freely in FreeWare, ShareWare, PD or +Commercial programs without paying any royalty. + +! If you use the AFC, please, quote somewhere in the "About..." requester +! and also in the documentation that your program uses the Amiga Foundation +! Classes and provide also the official URL: +! +! http://www.intercom.it/~fsoft/afc.html +! +! Note that you are just _invited_ to do so, no obbligation is given in +! any way. + +@endnode + +@node "Intro_4" "Future of the Amiga Foundation Classes" +2.4 - Future of the Amiga Foundation Classes + +The AFC have been designed to warrant a reliable base of Objects to be used +in the future Amiga-Compatible machines: by recompiling the AFC source +code will be possible to obtain an excellent library of Classes with which +one can easily build applications for the new computers. The advantage of +using Classes of objects over the Operating System calls is due to the fact +that such Classes work as an "interface" between the OS and the programmer: +people that programmed on the Amiga using the AFC will bring their code on +the new machines by simply recompiling the sources and using the AFC +version implemented on the new computer on which they are working. Thank +to the AFC, programmers will save a lot of time (otherwise spent in +learning the new OS) and will keep on using the same Classes with the same +sintax and the same behaviour. This implies, at least in our intentions, +that the software will be developed better and in a shorter time. The risk +that every new Operating System has to face, when it first comes to life, +is the lack of professional software. Thank to the AFC it will be possible +to provide in brief time professional products for these new OS. +@endnode + +@node "Intro_5" "Interfacing with new Amiga OS Compatibles" +2.5 - Interfacing with new Amiga OS Compatibles + +It's our intention to freely supply developers of Amiga-Compatible OS with +the source code of the AFC, be they Phase5, VisCorp, Be Inc., AROS, p-OS, +PIOS, etc. Indeed, we are persuaded that the future of a new machine, +possibly not depending on Microsoft, is to be found in the possibility of +having in a short time software products of a professional quality. Thus +the AFC sources will be provided to every OS developer that will ask for +them. Then the particular implementation will be examined by the +supervisors of AFC that will give their approval and allow the +distribution. See section 5.0 for more infos. +@endnode + +@node "Impl_1" "How to write a Class for the Amiga Foundation Classes" +3.1 - How to write a Class for the Amiga Foundation Classes + + @{" Class Name " LINK "Impl_1_1"} + @{" Methods' Names " LINK "Impl_1_2"} + @{" Object Inheritance " LINK "Impl_1_3"} + @{" Object Initialization and Destruction " LINK "Impl_1_4"} + @{" Libraries And lowest OS Versions " LINK "Impl_1_5"} + @{" Tags " LINK "Impl_1_6"} +@endnode + +@node "Impl_1_1" "Class name" +3.1.1 - Class name + + - The Class must have a unique and understandable name. + - The class name must be lowercase. + - The class name must be in English. + - The class name must NOT be the name of an Amiga system structure. + +! Please, note that the "_obj" naming convention has been discarted. +! Use just unique names that don't collide against Amiga system structures +! names + + + - If in doubt, you can always add to the name of the class the suffix + "_obj". +@endnode + +@node "Impl_1_2" "Methods' names" +3.1.2 - Methods' names + + - The name of a method must be as shortest and clear as possible. E.g., + in a class designed to manage a list of nodes the method that adds a + node must NOT be called "addnode", but simply "add". +! - The name of a method must start in lowercase. + +! From V1.50 of AFC white paper, you can create names with UPPERCASE chars +! to easy method naming: +! +! ie. "addviewtocopperlist" now can become: +! "addViewToCopperList" or similar. +! +! please, note that the first chars *MUST* be lowercase anyway. +! +! This way of naming is more close to Sun's Java language, another +! place where we are planning to port AFC to. + + + - The name of a method must be in English. +@endnode + +@node "Impl_1_3" "Object Inheritance" +3.1.3 - Object Inheritance + +The Object Inheritance tipical of the OOP must be used as little as you +can. This because the Object Inheritance is implemented differently in the +various languages. The AFC sources must be understandable to allow for an +easier porting and readability. Thus it is FORBIDDEN the use of particular +syntax rules characteristic of a particular language. E.g., are not +allowed structures of the "friend" type or the Multiple Inheritance of the +C++ language. + +! It's advisable to substitute the Object Inheritance with the creation of a +! copy of the Class to be "reused" in the new Class. E.g., if you have to +! inherit the Class "bitmapper" in the Class "picture" (notice the name +! lowercase and in English) it's advisable to copy the "bitmapper" Class in +! the "picture" Class. +@endnode + +@node "Impl_1_4" "Object Initialization and Object Destruction" +3.1.4 - Object Initialization and Object Destruction + +The initialization and destruction of a Class must be always performed by +means of two particular Methods: the Initialization method and the +Destruction one. + +The Initialization method must have the same name as the Class. E.g., the +Initialization method of the "picture" Class must be called "picture()" +(with parameters between the brackets, if needed). + +The Destruction method of a class must be named "end()" and must NOT +require any parameter. + +! In the C++ version of AFC classes the destruction method can also +! be called with the standard C++ notation of the "~" char. +! So the Destruction method of the "picture" class in the example +! could also be: ~picture() with NO parameters, anyway. + +These two methods must be called EXPLICITLY by the program that exploits +the Class: you must not rely only on the Initialization and Destruction +routines contained in the language you use. + +! If a Class uses another one, then it has to call in its own Initialization +! method the Initialization method of the other Class. E.g., the "picture" +! Class that contains the "bitmapper" Class has to call, within the +! "picture()" method, the "bitmapper" method associated with the +! "bitmapper" Class. +@endnode + +@node "Impl_1_5" "Libraries and lowest OS version" +3.1.5 - Libraries and lowest OS version + +Classes have to rely almost exclusively on the standard AmigaOS libraries. + +E.g., a "picture" Class that uses the "iff.library" won't be included in +AFC because you can load an image also using the "iffparse.library" and +then write the ByteRun-decoding routine. + +Besides, the use of third party libraries damages the AFC, because these +libraries might not be implemented on new Operating Systems. + +The lowest OS version supported by AFC is 2.04. We can also take into +account the compatibility with OS1.3, but it's not a fundamental feature. + +If a Class requires a newer OS version to work correctly, then this must be +documented. +@endnode + +@node "Impl_1_6" "Tags" +3.1.6 - Tags + +When possible the behaviour of the Class must be changed using tags, a +characteristic of the AmigaOS. The standard methods involving tags must be +called: + + - "setattrs(tags)" to set the tags. + - "getattr(tag)" to get a single return value (with the corresponding + tag as parameter). + - "getattrs(tags)" if you want to receive different values with the same + call. +@endnode + +@node "Impl_2" "Definition of error codes" +3.2 - Definition of error codes + + @{" When to report an error code " LINK "Impl_2_1"} + @{" How to report an error code " LINK "Impl_2_2"} + @{" Classification of error codes " LINK "impl_2_3"} +@endnode + +@node "Impl_2_1" "When to report an error code" +3.2.1 - When to report an error code + +The AFC must promptly react at all possible errors: they must be "idiot +proof". If the user makes a mistake in calling a method, or he calls it +before having initialized the Class, and so on, the Class must be able to +trap and report the error (possibly trying to continue). Thus it's +important to classify and report to the user the largest number of errors, +trying to be understandable (when possible) to make the debug session +easier. +@endnode + +@node "Impl_2_2" "How to report an error code" +3.2.2 - How to report an error code + +! To report an error it's preferable to use the (software) "Exceptions", when +! they are supported by the language; if they are not supported it's +! the called methdo can return the value of the exception as the return code. +! Anyway, it is _your_ task to provide a simple and good way to let the user +! handle exceptions and errors. + +@endnode + +@node "Impl_2_3" "Classification of error codes" +3.2.3 - Classification of error codes + +The error code of a Class is contained in a 32Bit variable (long). The +High word (2 bytes) contains the "identification number" of the Class: +this identification number is unique and it's assigned by AFC to the Class +when it is first created. This value must be stored in the source code of +the Class in a constant named as the Class itself (written UPPERCASE) with +the "_BASE" suffix. E.g., the picture Class has the identification value +named "PICTURE_BASE". The Low word (2 bytes) contains the error code: in +each Class it starts from $0000 and goes up to $FFFF (supposing that a +Class can return 65535 different error messages!). The $0000 error it's +always "No Memory". The table that associates to every error code its +description must be included in the documentation. +@endnode + +@node "Port_1" "Porting features" +4.1 - Porting features + +The AFC can (and must) be ported on the largest number of languages as +possible. The porting must take into account all the characteristics +listed in sections 2 and 3. It's forbidden to modify a Class during the +porting, but the Class has to be "adapted" if some operations are not +translatable into the language used (e.g., returning multiple values with a +single method call). +@endnode + +@node "Port_2" "Porting limits" +4.2 - Porting limits + +A Class ported by a programmer CANNOT be distributed before approval by the +AFC supervisors. This to assure the correct working of the Class after the +porting. We of AFC won't exclude any language, but the programmers that +won't accept these conditions won't receive any other Class to convert and +their Classes will be marked on the AFC WEB pages as "Not Supported". +@endnode + +@node "Distr_1" "Compiled Classes" +5.1 - Compiled Classes + +The compiled classes (e.g., the ".obj" files of C++ or the ".m" files of +AmigaE) may be freely distributed and have to be inserted in a directory +called "AFC" (obviously). + +In the ".lha" archive must be present, together with the compiled code, the +documentation in AmigaGuide format and some example sources. +@endnode + +@node "Distr_2" "Classes' source code" +5.2 - Classes' source code + +The source of the Classes is NOT public domain an so it's NOT distributed +along with the compiled code. Nevertheless, it will be always available to +programmers that ask us to do the porting of a particular Class. The +supervisors of AFC will always have all the sources and are free to decide +whether to give the source of the required Class to a particular programmer +or not. +@endnode + +@node "Distr_3" "Availability" +5.3 - Availability + +The compiled versions of AFC can be found at these sites: + + FTP: + ftp.intercom.it/pub/afc - Official site of Amiga Foundation Classes + +! HTTP: +! www.intercom.it/~fsoft/afc.html - Official WEB site of AFC + + +! The E version of the AFC classes will be also shipped with the language itself. +! But some of them will result to be unuseful without the registered version of +! the compiler. :-) + +@endnode + +@node "Distr_4" "Info and WEB sites" +5.4 - Info and WEB sites + +If you want more infos (or upgrades) you can connect to: + + http://www.intercom.it/~fsoft/afc.html + + the official page of AFC. + +Or you can subscribe to the mailing list by sending a message to: + + afc-list@intercom.it + +with (in the SUBJECT): subscribe +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Bitmapper.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Bitmapper.guide new file mode 100644 index 0000000..34e9d20 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Bitmapper.guide @@ -0,0 +1,393 @@ +@database Bitmapper.guide + +@$VER: BitMapper V2.60 - By Fabio Rotondo (C)Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: bitmapper" + + + + ** BitMapper - Original By Fabio Rotondo ** + + * Part of the Amiga Foundation Classes * + + @{" Introduction " link "BitMapper_introduction"} @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} + + Requires: + + Class Base: $00040000 + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" bitmapper() " link "BitMapper_bitmapper"} Initailizes the class. + @{" allocbitmap(w,h,d, lay=F, rp=F) " link "BitMapper_allocbitmap"} Creates a bitmap. + @{" assign(bmp,w=-1,h=-1,lay=F,r=F) " link "BitMapper_assign"} Copies a bitmap. + @{" bitmap() " link "BitMapper_bitmap"} Returns a pointer to bitmap. + @{" clear() " link "BitMapper_clear"} Free all bitmap's resources. + @{" clearrastport() " link "BitMapper_clearrastport"} Frees bitmap's rastport. + @{" clearlayers() " link "BitMapper_clearlayers"} Frees bitmap's layers. + @{" cludge(mem) " link "BitMapper_cludge"} Converts a memory area into a bitmap. + @{" createlayers(w=-1, h=-1) " link "BitMapper_createlayers"} Creates bitmap layers. + @{" createrastport() " link "BitMapper_createrastport"} Creates bitmap rastport. + @{" depth() " link "BitMapper_width"} Returns bitmap's depth. + @{" dump(fname) " link "BitMapper_dump"} Dumps a bitmap into a file. + @{" freebitmap() " link "BitMapper_freebitmap"} Free the bitmap. + @{" height() " link "BitMapper_width"} Returns bitmap's height. + @{" image() " link "BitMapper_image"} Returns the Image structure of the bitmap. + @{" loadraw() " link "BitMapper_loadraw"} Loads up a raw data bitmap. + @{" rastport() " link "BitMapper_rastport"} Scans a Directory. + @{" version() " link "BitMapper_version"} Returns bitmapper version. + @{" width() " link "BitMapper_width"} Returns bitmap's width. + + @{" Error Table " LINK bitmapper_ErrorTable} +@endnode + +@node "BitMapper_Introduction" "Introduction" + + BitMapper is an E object I have created to easyly manage bitmaps. + + Main features are: + + * Different OS2.0 and OS3.0 allocbitmap() method. + + * Methods to handle bitmap's rastport and layers. + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + +@endnode + +@node bitmapper_ErrorTable "BitMapper / Error Table " + +VALUE | DESCRIPTION +----------------+---------------------------------- +$0000 | No Memory. +$0001 | Could not open layer library +$0002 | Could not create the layer +$0003 | Could not create behind layer +$0004 | File not found +$0005 | Could not create file +@endnode + +@node "BitMapper_bitmapper" "Amiga Foundation Classes: bitmapper/bitmapper()" + NAME: bitmapper() + + DESCRIPTION: Use this method to initailize the object. + + INPUT: NONE. + + RESULTS: NONE. + + SEE ALSO: +@endnode + +@node "BitMapper_clear" "Amiga Foundation Classes: bitmapper/clear()" + NAME: clear() + + DESCRIPTION: This method frees all memory allocated by the class. + + INPUT: NONE. + + RESULTS: NONE. + + RAISE: + + SEE ALSO: @{" allocbitmap() " LINK bitmapper_alloc} + @{" freebitmap() " LINK bitmapper_freebitmap} +@endnode + +@node "BitMapper_allocbitmap" "Amiga Foundation Classes: bitmapper/allocbitmap()" + NAME: allocbitmap(width, height, depth, layers=FALSE, rastport=FALSE) + + DESCRIPTION: This method allocates a bitmap and a rastport for it. + It also frees all datas previously allocated on the same + object. + + INPUT: width - Bitmap width (in pixels) + height - Bitmap height (in pixels) + depth - Bitmap depth (1...8) + layers - (Optional) if TRUE, a layer structure + will be created. Default is FALSE. + rastport - (Optional) if TRUE, a rastport will be + created. Default is FALSE. + + RESULTS: + + SEE ALSO: @{" freebitmap() " LINK bitmapper_freebitmap} + @{" createlayers() " LINK bitmapper_createlayers} + @{" createrastport() " LINK bitmapper_createrastport} +@endnode + +@node "BitMapper_createlayers" "Amiga Foundation Classes: bitmapper/createlayers()" + NAME: createlayers(w=-1, h=-1) + + DESCRIPTION: This method creates a layers structure for the bitmap. + + INPUT: w, h - (Optional) Layer's width and height. If these + params are omitted, layers' size will be the same + of the bitmap. + + RESULTS: TRUE - creation successfull. + FALSE - creation failed. (Maybe no bitmap allocated) + + SEE ALSO: @{" clearlayers() " LINK bitmapper_clearlayers} + @{" createrastport() " LINK bitmapper_createrastport} +@endnode + +@node "BitMapper_createrastport" "Amiga Foundation Classes: bitmapper/createrastport()" + NAME: createrastport() + + DESCRIPTION: This method creates a rastport for the bitmap present in the + class. + + INPUT: NONE + + RESULTS: TRUE - creation successfull. + FALSE - creation failed. (Maybe no bitmap allocated) + + SEE ALSO: @{" clearrastport() " LINK bitmapper_clearrastport} + @{" createlayers() " LINK bitmapper_createlayers} +@endnode + +@node "BitMapper_clearrastport" "Amiga Foundation Classes: bitmapper/clearrastport()" + NAME: clearrastport() + + DESCRIPTION: This method will free bitmap's rastport. + + INPUT: NONE. + + RESULTS: rastport is freed from the memory. + + SEE ALSO: @{" createrastport() " LINK bitmapper_createrastport} + +@endnode + +@node "BitMapper_clearlayers" "Amiga Foundation Classes: bitmapper/clearlayers()" + NAME: clearlayers() + + DESCRIPTION: This method frees bitmap's layers. + + INPUT: NONE. + + RESULTS: Layer's memory is freed. + + NOTE: By freeing the layers you'll free also the rastport!!! + + SEE ALSO: @{" createlayers() " LINK bitmapper_createlayers} + @{" createrastport() " LINK bitmapper_createrastport} +@endnode + +@node "BitMapper_freebitmap" "Amiga Foundation Classes: bitmapper/freebitmap" + NAME: freebitmap() + + DESCRIPTION: This method frees the bitmap and, eventually, also + the rastport and layers. + + INPUT: NONE. + + RESULTS: NONE. + + SEE ALSO: @{" allocbitmap() " LINK bitmapper_alloc} + @{" freelayers() " LINK bitmapper_freelayers} + @{" freerastport() " LINK bitmapper_freerastport} +@endnode + +@node "BitMapper_assign" "Amiga Foundation Classes: bitmapper/assign" + NAME: assign(bitmap:PTR TO bitmap, w=-1, h=-1, layers=FALSE, rport=FALSE) + + DESCRIPTION: Use this method to "change" on the fly the bitmap + with a new one. Note that all datas of the previous + bitmap will be lost. + + INPUT: bitmap - (PTR TO bitmap) a new bitmap to handle. + w,h - (Optional) Bitmap's width and height + to copy. You can set width and height to + a different (usally minor) size of the original + bitmap, to copy just a part of it. + + layers - (Optional) if TRUE a layer structure will be + created. + + rastport - (Optional) if TRUE a rastport structure will be + created. + + RESULTS: NONE. + + NOTES: this method calls @{" allocbitmap() " LINK bitmapper_allocbitmap}. + + this method may use the blitter. + + SEE ALSO: @{" allocbitmap() " LINK bitmapper_allocbitmap}. +@endnode + +@node "BitMapper_rastport" "Amiga Foundation Classes: bitmapper/rastport" + NAME: rastport() + + DESCRIPTION: This method returns the 8Bit bitmap's rastport. + + INPUT: NONE. + + RESULTS: a ptr to a rastport. It may be NIL. + + SEE ALSO: @{" createrastport() " LINK bitmapper_createrastport} + @{" allocbitmap() " LINK bitmapper_alloc} + + +@endnode + +@node "BitMapper_bitmap" "Amiga Foundation Classes: bitmapper/bitmap()" + NAME: bitmap() + + DESCRIPTION: This method returns a PTR TO bitmap + + INPUT: NONE. + + RESULTS: a PTR TO bitmap. It may be NIL. + + SEE ALSO: @{" allocbitmap() " LINK bitmapper_allocbitmap} +@endnode + +@node "BitMapper_version" "Amiga Foundation Classes: bitmapper/version()" + NAME: version() + + DESCRIPTION: This method returns class version and revision. + + INPUT: NONE. + + RESULTS: This method returns TWO values, Version and Revision. + + SEE ALSO: +@endnode + +@node "BitMapper_cludge" "Amiga Foundation Classes: bitmapper/cludge()" + NAME: cludge(mem:PTR TO LONG) + + DESCRIPTION: This method converts a memory area into a bitmap + + INPUT: mem - Memory address. + + RESULTS: This method returns THREE values: width, height and depth + of the cludged bitmap. + + NOTE: The bitmap MUST be created using @{" dump() " LINK bitmapper_dump} method! + + SEE ALSO: @{" dump() " LINK "BitMapper_dump"} + @{" loadraw() " LINK "BitMapper_loadraw"} +@endnode + +@node "BitMapper_loadraw" "Amiga Foundation Classes: bitmapper/loadraw()" + NAME: loadraw(fname:PTR TO CHAR) + + DESCRIPTION: This method loads up a file containing a previously dump()ed + bitmap. + + INPUT: fname - File name to load. + + RESULTS: This method returns THREE values: width, height and depth + of the loaded raw data. + + NOTE: The bitmap MUST be created using @{" dump() " LINK bitmapper_dump} method! + + SEE ALSO: @{" dump() " LINK "BitMapper_dump"} + @{" cludge() " LINK "BitMapper_cludge"} +@endnode + +@node "BitMapper_dump" "Amiga Foundation Classes: bitmapper/dump()" + NAME: dump(fname:PTR TO CHAR) + + DESCRIPTION: This method dumps a bitmap inbt a raw data format file. + + INPUT: fname - File name where to dump the bitmap. + + RESULTS: NONE + + SEE ALSO: @{" loadraw() " LINK "BitMapper_loadraw"} +@endnode + +@node "BitMapper_width" "Amiga Foundation Classes: bitmapper/width()" + NAME: width() + + DESCRIPTION: This method returns bitmap's width. + + INPUT: NONE. + + RESULTS: Bitmap's width. + + SEE ALSO: @{" height() " LINK "BitMapper_height"} + @{" depth() " LINK "BitMapper_depth"} +@endnode + +@node "BitMapper_height" "Amiga Foundation Classes: bitmapper/height()" + NAME: height() + + DESCRIPTION: This method returns bitmap's height. + + INPUT: NONE. + + RESULTS: Bitmap's height. + + SEE ALSO: @{" width() " LINK "BitMapper_width"} + @{" depth() " LINK "BitMapper_depth"} +@endnode + +@node "BitMapper_depth" "Amiga Foundation Classes: bitmapper/depth()" + NAME: depth() + + DESCRIPTION: This method returns bitmap's depth. + + INPUT: NONE. + + RESULTS: Bitmap's depth. + + SEE ALSO: @{" height() " LINK "BitMapper_height"} + @{" width() " LINK "BitMapper_width"} +@endnode + +@node "bitmapper_image" "Amiga Foundation Classes: Bitmapper/image()" + + NAME: image() + + DESCRIPTION: Sometimes, it is usefull to obtain picture Image structure, the one + used by Ituition gadgets. Using this method, you can obtain this + Image structure. + + INPUT: NONE + + RESULTS: a pointer to a valid Image structure. + + NOTE: This method is *slow* the first time you call it, because it has + to create the Image structure and picture. Then, it will be + fastlighting, until you don't load another picture in the class. + + SEE ALSO: + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/DirList.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/DirList.guide new file mode 100644 index 0000000..c26e676 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/DirList.guide @@ -0,0 +1,235 @@ +@database DirList.guide + +@$VER: DirList_oo V3.00 - By Fabio Rotondo (C)Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node "Main" "Amiga Foundation Classes Module: DirList" + + + + ** DirList_OO - Original By Fabio Rotondo ** + + * Part of Amiga Foundation Classes * + + @{" Introduction " link "DirList_introduction" } @{" Author's Infos " link "author" } @{" Amiga Foundation Classes " LINK "afc.guide/main"} + + + Requires: @{" NodeMaster " LINK "NodeMaster.guide/main"}, @{" StringNode " LINK "StringNode.guide/main"} + + Base: $0003 + + + NOTE: DirList inherits completely @{" StringNode " LINK "stringnode.guide/main"} so, please, refer + to this class for further documentation. + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" DirList() " link "DirList_DirList" } Initailizes the object + @{" dirname() " link "DirList_dirname" } Returns current dir name + @{" read(dirs, files, match) " link "DirList_read" } Scans a Directory + @{" setattrs(tags) " link "DirList_setmode" } Set objects behaviours + @{" setdir(path) " link "DirList_setdir" } Set Directory to read + @{" version() " link "DirList_version"} Returns class version and revision + + @{" Tags Table " link "DirList_Tags" } Possible DirList's Tags + + @{" Errors Table " LINK "DirList_ErrorTable"} Error Table +@endnode + +@node "DirList_Introduction" "Introduction" + + DirList Object is something I created for my own needs. + + Now it is grown to a powerful and stable object, so I decided to share it +with all the rest of Amiga Foundation Classes community. + + Main features are: + + * Accept AmigaDOS Pattern Matching. + + * Very fast scanning algorithms. + + * Easy to use. + + * Relys on StringNode Object. (See StringNode_oo) + + +NEW V2.10 Features: + + * Added a new method called tagset(): + With this method you will be able to change some DirList + behaviours via tags (at the moment, just two different tags + are implemented, but many others will do as time goes by) + + * Now dirname() returns also the "/" when needed. + + * Example program now working ;) + + * New examples added. + +NEW V3.00 Features: + + * Restructured code. + + * Part of the Amiga Foundation Classes +@endnode + +@node author "Author(s) Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) +@endnode + +@node DirList_Tags "Amiga Foundation Classes Modules: DirList/Tag Table" + + + TAG NAME | VALUES (DEFAULT)| DESCRIPTION ++-------------------+-----------------+----------------------------------- + TAGDIR_MARKDIR |TRUE/FALSE(TRUE) | If TRUE, DirList will add the + | | leading "(DIR) " prefix to dir names. + | | +TAGDIR_COMPLETEPATH |TRUE/FALSE(FALSE)| If TRUE, DirList will add complete path + | | to the dirs and files read. + | | + +Please, see also @{" StringNode/Tags Table" LINK "StringNode.guide/StringNode_TagsTable"} +@endnode + +@node DirList_ErrorTable "Amiga Foundation Classes Modules: DirList / Error Table " +ERROR VALUE | DESCRIPTION +--------------------+------------------------------------------------------ + $0000 | No memory. + $0001 | Initialization failed. + $0002 | Could not lock desired dir (ie. dir not found) + $0003 | You are trying to use a class which failed to init. + $0004 | You are trying to read "nothing" (ie: you haven't set a valid dir) + $0005 | Examine() call failed. + +Please, see also @{" StringNode/Error Table" LINK "StringNode.guide/StringNode_ErrorTable"} + +@endnode + +@node "DirList_DirList" "Amiga Foundation Classes Modules: DirList/dirlist()" + NAME: dirlist() + + DESCRIPTION: Use this command to initailize the object. + + INPUT: NONE. + + RESULTS: NONE. + + SEE ALSO: @{" StringNode/stringnode() " LINK "StringNode.guide/StringNode_stringnode"} +@endnode + +@node "DirList_setdir" "Amiga Foundation Classes Modules: DirList/setdir()" + NAME: setdir(path:PTR TO CHAR) + + DESCRIPTION: Use this command to select directory to scan. + + INPUT: path - PTR TO CHAR. Directory name, FULL PATH! + + RESULTS: NONE. + + SEE ALSO: @{" dirname() " LINK "DirList_dirname"} + @{" read() " LINK "DirList_read"} +@endnode + +@node DirList_dirname "Amiga Foundation Classes Modules: DirList/dirname()" + NAME: dirname() + + DESCRIPTION: This command returns the current dir name. + + INPUT: NONE. + + RESULTS: name - A PTR TO CHAR containing current dir name. + + SEE ALSO: @{" setdir() " LINK "DirList_setdir"} +@endnode + +@node DirList_read "Amiga Foundation Classes Modules: DirList/read()" + NAME: read(dirs=TRUE, files=TRUE, match=NIL:PTR TO CHAR) + + DESCRIPTION: This command scans selected dir. + + INPUT: dirs - (TRUE) If this flag is set to TRUE, DirList + will memorize any directory it will encounter + while scanning. + + files - (TRUE) Same as dirs flag, only with files. + + match - (NIL) This is a _VALID_ search pattern. This + pattern will be CASE INSENSITIVE and it is a + _STANDARD_ AmigaDOS pattern matching. (By the + way, DirList *USES* AmigaDOS pattern matching, + so it is FAST and you already should know how + to use it!) + + Ex. "#?sequ#?" is a valid pattern matching + string. + + RESULTS: NONE + + SEE ALSO: @{" setdir() " LINK "DirList_setdir"} +@endnode + +@node "DirList_setattrs" "Amiga Foundation Classes Modules: DirList/setattrs()" + NAME: setmode(tags:PTR TO LONG) + + DESCRIPTION: Use this command to change some of object's behaviours. + This method will grow as time goes by. It is implemented + in a very comfy way: taglists. + + INPUT: tags - PTR TO LONG. Tags and their value. + See @{" Tags Table " LINK "DirList_Tags"} + + RESULTS: NONE. + + NOTE: REMEMBER to ALWAYS end taglist with 0,0, otherwise + strange things WILL happen. + + You can pass to this method also StringNode's tags. + They will be handled correctly. + + SEE ALSO: @{" dirname() " LINK "DirList_dirname"} + @{" read() " LINK "DirList_read"} + + @{" StringNode/setattrs " LINK "StringNode.guide/StringNode_setattrs"} +@endnode + +@node "DirList_version" "Amiga Foundation Classes Modules: DirList/version()" + NAME: version() + + DESCRIPTION: This method returns class version and revision. + + INPUT: NONE + + RESULTS: this method return TWO values: version and revision. + + SEE ALSO: + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Displayer.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Displayer.guide new file mode 100644 index 0000000..eefd202 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Displayer.guide @@ -0,0 +1,610 @@ +@database Displayer.guide + +@$VER: Displayer V1.01 - by Andrea Galimberti - (C) Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node main "AFC module: Displayer / Main" + + + ** Displayer V1.01 - Original By Andrea Galimberti ** + + Part of Amiga Foundation Classes + + + + + @{" Introduction " LINK obj_intro} @{" Author(s) Info " LINK author} + + + Requires: @{" Bitmapper " LINK "Bitmapper.guide/Main"}, @{" NodeMaster " LINK "nodemaster.guide/Main"} + + Base: $8000 + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + displayer methods: + + @{" displayer() " LINK displayer} Initialises the object + @{" add() " LINK view_add} Adds a ViewPort + @{" del() " LINK view_del} Removes a ViewPort + @{" setup() " LINK view_setup} Builds your display + @{" show() " LINK view_show} Shows the View + @{" showOldView() " LINK view_showold} Restores the old View + @{" address() " LINK view_address} Address of View structure + @{" viewport() " LINK view_vp} Address of a viewport + @{" rastport() " LINK view_rastport} Rastport of a viewport + @{" bitmap() " LINK view_bitmap} Bitmap of a viewport + @{" vpobj() " LINK view_vpobj} Pointer to a viewport_obj + @{" width() " LINK view_width} Width of a viewport + @{" height() " LINK view_height} Height of a viewport + @{" depth() " LINK view_depth} Depth of a viewport + @{" mode() " LINK view_mode} Display mode of a viewport + @{" scroll() " LINK view_scroll} Scrolls a BitMap + @{" swap() " LINK view_swap} Swaps BitMaps in a double buffered ViewPort + @{" vWait() " LINK view_vwait} Waits for the VBlank + @{" version() " LINK view_version} Gets version number + + viewport_obj methods: + + @{" viewport_obj() " LINK viewport_obj} Initialises the object + @{" address() " LINK vp_address} Address of ViewPort + @{" rastport() " LINK vp_rastport} RastPort of ViewPort + @{" bitmap() " LINK vp_bitmap} BitMap of ViewPort + @{" width() " LINK vp_width} Width of ViewPort + @{" height() " LINK vp_height} Height of ViewPort + @{" depth() " LINK vp_depth} Depth of ViewPort + @{" mode() " LINK vp_mode} Display mode of ViewPort + + @{" ERROR TABLE " LINK Error_Table} + +@endnode + +@node author "Author(s) Info" + + Original By: Andrea Galimberti + + E Version By: Andrea Galimberti + + + +@endnode + +@node obj_intro "Displayer / Introduction" + + Displayer. + + This module allows you to easily build, in a completely system-friendly +way, a display made of a view containing some viewports. Any viewport can +have its own resolution and depth, must have a bitmap associated with it, +and you can draw in such a bitmap just as you usually do in a simple +screen: by addressing it through its rastport. + There are two objects contained in the module: the displayer and the +viewport_obj. To create a display you first intialise (NEW +myview.displayer()) your displayer object, and then add to it how many +viewport you like using the add() method: when you are finished you call +the setup() and show() methods to admire your display. + If you want to, you can also access any single viewport_obj contained in +the displayer with a call to vpobj(number). + In addition the module allows double-buffered viewports and scrolling of +the bitmaps displayed through the viewports. + +@endnode + +@node Error_Table "Displayer / Error Table" + +Val (Hex) | Description +-----------+------------------------------------------------------ + $0000 | No memory + $0001 | Cannot allocate ViewExtra structure + $0002 | OpenMonitor() failed + $0003 | Cannot allocate ViewPortExtra structure + $0004 | GetDisplayInfoData() failed + $0005 | FindDisplayInfo() failed + $0006 | Cannot allocate ColorMap structure + $0007 | VideoControl() failed to attach structures + $0008 | Illegal ViewPort parameters (maybe NIL?) + $0009 | Failed to create ViewPort (MakeVPort()) + $000A | Failed to merge copper instructions + $000B | Illegal display parameters (maybe NIL?) + +@endnode + +@node displayer "AFC Module: displayer / displayer()" + + NAME: displayer() + + DESCRIPTION: initialises your displayer object. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node view_add "AFC module: displayer / add()" + + NAME: add(tags:PTR TO LONG) + + DESCRIPTION: adds a viewport_obj to the list contained in your displayer. + When you have finished adding viewports you build the + system structures associated to the display by calling the + @{"setup()" LINK view_setup} method. This command doesn't check if the viewports + overlap. + + INPUTS: A NIL terminated taglist. The command understands the + following tags: + + VPORT_TOP: y coordinate of the viewport top-left corner + + VPORT_LEFT: x coordinate of the viewport top-left corner + + VPORT_WIDTH: viewport width + + VPORT_HEIGHT: viewport height + + VPORT_DEPTH: viewport depth + + VPORT_MODE: viewport display mode (see the modeid.m system + module for a list of all available modes) + + VPORT_SPRITES: TRUE if you want to use sprites on the + viewport (default is FALSE) + + VPORT_BITMAP: pointer to an already initialized + @{"bitmap_obj" LINK "bitmap_obj.guide/Main"}. If this tag is present, no + bitmap_obj will be allocated for the + viewport. The bitmap passed is displayed + when the viewport is opened. It's your duty + to free the memory associated to such a + bitmap_obj. The dimensions of the bitmap are + assumed to be equal to the viewport ones, if + not differently specified with the following + tags. + + + If you want to display through the ViewPort a BitMap with + dimensions different from the ViewPort ones (e.g., to + @{"scroll" LINK view_scroll} it) you use: + + VPORT_BMWIDTH: bitmap width + + VPORT_BMHEIGHT: bitmap height + + VPORT_BMDEPTH: bitmap depth + + VPORT_DBUFFER: specifies that the ViewPort is double + buffered, that is to say two BitMaps with + equal features are allocated for the same + ViewPort: you can draw in the hidden one and + then @{"swap" LINK view_swap} the two. + + + RESULTS: NONE + + SEE ALSO: @{" setup() " LINK view_setup} + +@endnode + +@node view_del "AFC module: displayer / del()" + + NAME: del(num) + + DESCRIPTION: removes ViewPort number num from the View. Never call + this method while the View is displayed: this function + immediately deallocates all memory associated to the + ViewPort to be deleted. + You have to call the @{"setup()" LINK view_setup} method to see the results + of your changes. + + INPUTS: number of ViewPort to be killed: this ranges from 0 to + (number of viewports)-1 + + RESULTS: FALSE if num is outside the valid range, + otherwise TRUE. + + SEE ALSO: @{" add() " LINK view_add} + +@endnode + +@node view_setup "AFC module: displayer / setup()" + + NAME: setup(modeid) + + DESCRIPTION: allocates the memory and the system structures needed to + render your display. This method scans the viewports you + linked with the @{"add()" LINK view_add} method. + Never call this function while the view is displayed: it + will deallocate all memory associated to the view to + rebuild system structures from scratch. + + INPUTS: the monitor id, e.g., DEFAULT_MONITOR_ID, (see the + modeid.m system module for a full list of all modes + available) + + RESULTS: raises a lot of exceptions if something goes wrong (see the + @{"Error Table" LINK Error_Table} for more info). + + SEE ALSO: @{" add() " LINK view_add} + +@endnode + +@node view_show "AFC module: displayer / show()" + + NAME: show() + + DESCRIPTION: shows the display created with setup(). Automatically + remembers the previous display: you have to restore it with + a call to showOldView() before exiting the program. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" showOldView() " LINK view_showold} + @{" setup() " LINK view_setup} + +@endnode + +@node view_showold "AFC module: displayer / showOldView()" + + NAME: showOldView() + + DESCRIPTION: restores the previous display. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" show() " LINK view_show} + +@endnode + +@node view_vwait "AFC module: displayer / vWait()" + + NAME: vWait() + + DESCRIPTION: waits for the vertical blanking period. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node view_scroll "AFC module: displayer / scroll()" + + NAME: scroll(number,x,y) + + DESCRIPTION: scrolls the BitMap currently displayed through ViewPort + at position "number" in the list by positioning the pixel + (x,y) at the top left-hand corner of the ViewPort. If you + want to synchronize the scrolling with the video beam you + have to call the @{"vWait" LINK view_vwait} method to wait for the vertical + blanking period. + + INPUTS: number of ViewPort + x position of BitMap + y position of BitMap + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node view_swap "AFC module: displayer / swap()" + + NAME: swap(number) + + DESCRIPTION: exchanges the two BitMaps of a double buffered ViewPort + (the ViewPort at position "number" in the list). If you + want to synchronize the swapping with the video beam you + have to call the @{"vWait" LINK view_vwait} method to wait for the vertical + blanking period. + + INPUTS: number of ViewPort + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node view_address "AFC module: displayer / address()" + + NAME: address() + + DESCRIPTION: returns the address of the View structure allocated by the + system (see your Includes/graphics/view.h) + + INPUTS: NONE + + RESULTS: address of View structure + + SEE ALSO: + +@endnode + +@node view_rastport "AFC module: displayer / rastport()" + + NAME: rastport(number, alt=0) + + DESCRIPTION: returns the address of the RastPort structure belonging to + the chosen ViewPort. (See @{"viewport()" LINK view_vp} for more info.) + A ViewPort has a RastPort associated to the BitMap that is + currently displayed through it. + If alt<>0 it returns the address of the RastPort of the + alternate BitMap (only if the ViewPort is double buffered, + otherwise NIL). The alternate BitMap is the one that is + hidden when the View shows up the first time. + + INPUTS: number of ViewPort + alt: if <>0 selects the alternate BitMap + + RESULTS: address of RastPort + + SEE ALSO: viewport_obj: @{" rastport() " LINK vp_rastport} + +@endnode + +@node view_vp "AFC module: displayer / viewport()" + + NAME: viewport(number) + + DESCRIPTION: returns the address of the selected ViewPort structure + allocated by the system. The argument "number" goes from 0 + to the number of ViewPorts you linked to your View with the + @{"add()" LINK view_add} command: the order is the same in + which the ViewPorts have been linked. + + INPUTS: number of ViewPort + + RESULTS: address of ViewPort + + SEE ALSO: viewport_obj: @{" address() " LINK vp_address} + +@endnode + +@node view_vpobj "AFC module: displayer / vpobj()" + + NAME: vpobj(number) + + DESCRIPTION: returns the address of the viewport_obj object at position + "number" in the list linked to the displayer with the + @{"add" LINK view_add} command. With the returned pointer you + can call all the viewport_obj methods. + + INPUTS: number of ViewPort + + RESULTS: address of viewport_obj object + + SEE ALSO: + +@endnode + +@node view_bitmap "AFC module: displayer / bitmap()" + + NAME: bitmap(number, alt=0) + + DESCRIPTION: returns the address of the BitMap structure currently + displayed through the chosen ViewPort. (See @{"viewport()" LINK view_vp} + for more info.) + A BitMap is automatically allocated for each ViewPort when + @{"setup()" LINK view_setup} is called. + If alt<>0 it returns the address of the alternate BitMap + (only if the ViewPort is double buffered, otherwise NIL). + The alternate BitMap is the one that is hidden when the + View shows up the first time. + + INPUTS: number of ViewPort + alt: if <>0 selects the alternate BitMap + + RESULTS: address of BitMap + + SEE ALSO: viewport_obj: @{" bitmap() " LINK vp_bitmap} + @{" bitmap_obj / bitmap() " LINK "bitmap_obj.guide/bitmap_bitmap"} + +@endnode + +@node view_width "AFC module: displayer / width()" + + NAME: width(number) + + DESCRIPTION: returns the width of the ViewPort at position "number" in + the list. + + INPUTS: number of ViewPort + + RESULTS: width of ViewPort + + SEE ALSO: viewport_obj: @{" width() " LINK vp_width} + +@endnode + +@node view_height "AFC module: displayer / height()" + + NAME: height(number) + + DESCRIPTION: retuns the height of the ViewPort at position "number" in + the list. + + INPUTS: number of ViewPort + + RESULTS: height of ViewPort + + SEE ALSO: viewport_obj: @{" height() " LINK vp_height} + +@endnode + +@node view_depth "AFC module: displayer / depth()" + + NAME: depth(number) + + DESCRIPTION: retuns the depth of the ViewPort at position "number" in + the list. + + INPUTS: number of ViewPort + + RESULTS: depth of ViewPort + + SEE ALSO: viewport_obj: @{" depth() " LINK vp_depth} + +@endnode + +@node view_mode "AFC module: displayer / mode()" + + NAME: mode(number) + + DESCRIPTION: returns the display mode of the ViewPort at position + "number" in the list. + + INPUTS: number of ViewPort + + RESULTS: display mode (resolution) of ViewPort + + SEE ALSO: viewport_obj: @{" mode() " LINK vp_mode} + +@endnode + +@node view_version "AFC module: displayer / version()" + + NAME: version() + + DESCRIPTION: gets version number of Displayer module + + INPUTS: NONE + + RESULTS: displayer version, displayer revision + + SEE ALSO: + +@endnode + +@node viewport_obj "viewport_obj / viewport_obj()" + + NAME: viewport_obj() + + DESCRIPTION: initialises a viewport_obj object + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node vp_rastport "viewport_obj / rastport()" + + NAME: rastport(alt=0) + + DESCRIPTION: returns the address of the RastPort of the BitMap currently + displayed through the ViewPort. + If alt<>0 it returns the address of the RastPort of the + alternate BitMap (only if the ViewPort is double buffered, + otherwise NIL). The alternate BitMap is the one that is + hidden when the View shows up the first time. + + INPUTS: alt: if <>0 it selects the alternate BitMap + + RESULTS: address of RastPort + + SEE ALSO: displayer: @{" rastport() " LINK view_rastport} + +@endnode + +@node vp_address "viewport_obj / address()" + + NAME: address() + + DESCRIPTION: returns the address of the ViewPort structure allocated by + the system + + INPUTS: NONE + + RESULTS: address of ViewPort + + SEE ALSO: displayer: @{" viewport() " LINK view_vp} + +@endnode + +@node vp_bitmap "viewport_obj / bitmap()" + + NAME: bitmap(alt=0) + + DESCRIPTION: returns the address of the BitMap structure currently + displayed through the ViewPort + If alt<>0 it returns the address of the alternate BitMap + (only if the ViewPort is double buffered, otherwise NIL). + The alternate BitMap is the one that is hidden when the + View shows up the first time. + + INPUTS: alt: if <>0 it selects the alternate BitMap + + RESULTS: address of BitMap + + SEE ALSO: displayer: @{" bitmap() " LINK view_bitmap} + +@endnode + +@node vp_width "viewport_obj / width()" + + NAME: width() + + DESCRIPTION: returns the width of the ViewPort + + INPUTS: NONE + + RESULTS: width of ViewPort + + SEE ALSO: displayer: @{" width() " LINK view_width} + +@endnode + +@node vp_height "viewport_obj / height()" + + NAME: height() + + DESCRIPTION: returns the height of the ViewPort + + INPUTS: NONE + + RESULTS: height of ViewPort + + SEE ALSO: displayer: @{" height() " LINK view_height} + +@endnode + +@node vp_depth "viewport_obj / depth()" + + NAME: depth() + + DESCRIPTION: returns the depth of the ViewPort + + INPUTS: NONE + + RESULTS: depth of ViewPort + + SEE ALSO: displayer: @{" depth() " LINK view_depth} + +@endnode + +@node vp_mode "viewport_obj / mode()" + + NAME: mode() + + DESCRIPTION: returns the display mode of the ViewPort + + INPUTS: NONE + + RESULTS: display mode of ViewPort + + SEE ALSO: displayer: @{" mode() " LINK view_mode} + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Hardsprite.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Hardsprite.guide new file mode 100644 index 0000000..eeaaa33 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Hardsprite.guide @@ -0,0 +1,169 @@ +@database Hardsprite.guide + +@$VER: Hardsprite V1.00 - by Andrea Galimberti - (C) Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node main "AFC Module: hardsprite / Main" + + + ** Hardsprite V1.00 - Original By Andrea Galimberti ** + + Part of Amiga Foundation Classes + + + + + @{" Introduction " LINK obj_intro} @{" Author(s) Info " LINK author} + + + Requires: + + Base: $8001 + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + @{" hardsprite() " LINK hardsprite} Initialises the Object + @{" image() " LINK sprite_image} Stores the sprite image + @{" changeImage() " LINK sprite_changeimage} Changes the sprite image + @{" move() " LINK sprite_move} Moves the sprite + @{" version() " LINK sprite_version} Gets object version + + @{" ERROR TABLE " LINK Error_Table} + +@endnode + +@node author "Author(s) Info" + + Original By: Andrea Galimberti + + E Version By: Andrea Galimberti + + +@endnode + +@node obj_intro "Hardsprite / Introduction" + + Hardsprite. + + + This object allows to easily access and manipulate the so called Simple +Sprites, that is to say Hardware Sprites. You can use each of the 8 +sprites and move it to a location relative to a viewport or to the whole +view (be it the Intuition one or a custom one you created by hand). +Obviously, you can change the image of the sprites (but it cannot be more +than 16 pixels wide, 4 colours). + +@endnode + +@node Error_Table "Hardsprite / Error Table" + +Val (Hex) | Description +-----------+------------------------------------------------------ + $0000 | No Memory + +@endnode + +@node hardsprite "AFC module: hardsprite / hardsprite()" + + NAME: hardsprite(number=-1) + + DESCRIPTION: Builds a hardsprite object + + INPUTS: number of hardware sprite to use (from 0 to 7). If the + requested sprite is not available this function will return + FALSE. The default value of -1 means that it will be + allocated the first sprite available. + + RESULTS: TRUE if all went ok. + FALSE if the reqired sprite is already in use and so it + couldn't be allocated. + + SEE ALSO: + +@endnode + +@node sprite_image "AFC module: hardsprite / image()" + + NAME: image(height, list:PTR TO INT) + + DESCRIPTION: this method stores the image to be used with the sprite. + Whenever this method is called, it will discard the + previous image. + + INPUTS: height (in lines) of the image, + a typed list (it MUST be typed to INT) in the following + form: + + [ $0000, $0000, + $0000, $0000, + ... ]:INT + + ^ ^ + | | + | second bitplane (16 bits wide) + | + first bitplane (16 bits wide) + + This way you can select one of 4 colours for each pixel of + the sprite's image. + + RESULTS: returns FALSE if: sprite non allocated (with hardsprite()), + height<=0, + pointer to list =NIL. + Raise "No Memory" if it cannot allocate the (CHIP) memory + for the image. + + SEE ALSO: + +@endnode + +@node sprite_changeimage "AFC module: hardsprite / changeImage()" + + NAME: changeImage(viewport) + + DESCRIPTION: changes the sprite image to the stored one. + + INPUTS: pointer to a viewport structure. If this pointer is <>NIL + then the change will affect only the chosen viewport; if + pointer=NIL then the change is relative to the current + view. + + RESULTS: FALSE if viewport<0 or sprite not allocated. + Otherwise TRUE. + + SEE ALSO: @{" image() " LINK sprite_image} + +@endnode + +@node sprite_move "AFC module: hardsprite / move()" + + NAME: move(viewport, x, y) + + DESCRIPTION: moves the sprite to the selected location (x,y) on a + viewport. + + INPUTS: viewport: pointer to a viewport structure; if this pointer + is NIL then the coordinates are relative to the current + view. + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node sprite_version "AFC module: hardsprite / version()" + + NAME: version() + + DESCRIPTION: gets version number of the Sprite module + + INPUTS: NONE + + RESULTS: hardsprite version, hardsprite revision + + SEE ALSO: + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/IffParser.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/IffParser.guide new file mode 100644 index 0000000..a071f8f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/IffParser.guide @@ -0,0 +1,471 @@ +@database IffParser.guide + +@$VER: IFFParser V1.20 - By Fabio Rotondo (C)Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node "Main" "IFFParser Guide" + + ** IFFParser - Written By Fabio Rotondo ** + + * Part of the Amiga Foundation Classes * + + + @{" Introduction " link "Introduction"} @{" Author's Info " link "Author"} @{" Amiga Foundation Classes " link "AFC.guide/Main"} + + @{" SAS/C and StormC Notes " LINK "IFFParser_CNotes"} @{" C-Only Functions " LINK "IFFParser_COnly"} + + Requires: Nothing. + + Class Base: $00080000 + + COMMANDS BRIEF DESCRIPTION + -------------------------------------------------------------------------- - + @{" iffparser() " link "IFFParser_iffparser"} Inits the iffparser object. + @{" addr() " link "IFFParser_addr"} Returns current data position in mem. + @{" close() " link "IFFParser_close"} Closes currently IFF session. + @{" closechunk() " link "IFFParser_closechunk"} Closes last created chunk. + @{" createchunk(type, id, size) " link "IFFParser_createchunk"} Inits a new chunk to write. + @{" error() " link "IFFParser_error"} Returns last error raised. + @{" exit(type, id) " link "IFFParser_exit"} Defines when scan() must stop. + @{" first(type, id) " link "IFFParser_first"} Prepares data examination. + @{" getheader(string, filename) " link "IFFParser_getheader"} Returns header of a file. + @{" load(filename) " link "IFFParser_load"} Inits an IFF Load session. + @{" save(filename) " link "IFFParser_save"} Inits an IFF SAVE session. + @{" scan() " link "IFFParser_scan"} Begins scanning an IFF file. + @{" setscan(type, id) " link "IFFParser_setscan"} Defines type of chunk to scan for. + @{" succ() " link "IFFParser_succ"} Gets next memory data location. + @{" size() " link "IFFParser_size"} Returns current data size. + @{" writechunk(datas, datalen) " link "IFFParser_writechunk"} Writes some datas to a chunk. + @{" version() " link "IFFParser_version"} Returns IFFParser class version and revision. + + + @{" Error Table " link "IFFParser_ErrorTable"} +@endnode + +@node "IFFParser_CNotes" "SAS/C and StormC Notes" + + SAS/C and StormC Notes + + We provide ".o" files for both SAS/C and StormC compilers. + + + NOTE: + The StormC compiler we are using is a _demo_ version, so we cannot create + optimized version of the class. + + We have asked to Haage & Partner a FREE version of StormC, but we receive + no answer at all. We are still waiting. + We are not going to buy it because we usually write code using AmigaE and + furthermore, we have already bought SAS/C compiler. + + StormC supports exceptions, while SAS/C doesn't. So we have been forced to + find a "work around" for SAS/C compiler. + + We have introduced the error() method which will return the last error + encountered during program execution. + + So keep in mind this: when an error occurs, StormC version will raise an + exception, while SAS/C version will return an error code or NULL and you + will have to check error() status. + + +@endnode + +@node "IFFParser_COnly" "IFFParser C-Only Functions" + + C-Only Functions + + We have created this function: + + NAME: id(idname) + + SYNOPSIS: ULONG id(STRPTR idname) + + DESCRIPTION: This function is a short cut to allow you to easily create "chunks" name. + As you may now, chunks name are ULONG values. Usually you have to use + the MAKE_ID() macro, but the id() function is faster. + + INPUT: idname - a string, for example "ILBM", "BODY".... + + RETURNS: the corrisponding ULONG value. + + + We hope you'll find it useful + +@endnode + +@node "Introduction" "Introduction " + + + IFFParser is an Object to easily read/write IFF files. + + It is not so powerful as IFFParse.library: it misses some features, but I +have written it to match all my needs, and it does. I hope you will enjoy +using. Look at the examples for working programs. + + +@endnode + +@node "Author" "Author's Info" + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + C++ Version By: Massimo Tantignone (tanti@intercom.it) + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + + +@endnode + +@node "IFFParser_ErrorTable" "Amiga Foundation Classes Module: IFFParser / Error Table" + VALUE | DESCRIPTION +-----------------+-------------------------------------------------------- + $0000 | No Memory. + $0001 | Could not open iffparse.library. + $0002 | Could not AllocIFF(). + $0003 | Could not create filename with Open(fname, MODE_NEWFILE). + $0004 | Could not OpenIFF(). + $0005 | IFFParser object not initialized with load() or save(). + $0006 | Could not Push current chunk. + $0007 | WriteChunkBytes() failed. + $0008 | Could not Pop current chunk. + $0009 | Could not Open() file for reading. + $000A | Could not do a CollectionChunk() call. + $000B | Could not assign StopOnExit. +@endnode + +@node "IFFParser_iffparser" "Amiga Foundation Classes Module: IFFParser / iffparser() " + + NAME: iffparser() + + SYNOPSIS: iffparser(void) + + DESCRIPTION: This method will initialize the iffparser object. + + INPUT: NONE. + + RESULTS: NONE. + + SEE ALSO: +@endnode + +@node "IFFParser_close" "Amiga Foundation Classes Module: IFFParser / close() " + + NAME: close() + + SYNOPSIS: void close(void) + + DESCRIPTION: This method will close curent IFF session. + + INPUT: NONE. + + RESULTS: NONE. + + SEE ALSO: @{" load() " link "IFFParser_load"} + @{" save() " link "IFFParser_save"} +@endnode + +@node "IFFParser_save" "Amiga Foundation Classes Module: IFFParser / save(filename) " + + NAME: save(filename:PTR TO CHAR) + + SYNOPSIS: LONG save(STRPTR fname) + + DESCRIPTION: Use This method to create a new IFF file and to begin + a IFF save session. + + INPUT: filename - Name of the file to open / load. + + RESULTS: NONE. + + + SEE ALSO: @{" createchunk() " link "IFFParser_createchunk"} + @{" writechunk() " link "IFFParser_writechunk"} + @{" closechunk() " link "IFFParser_closechunk"} + @{" close() " link "IFFParser_close"} +@endnode + +@node "IFFParser_createchunk" "Amiga Foundation Classes Module: IFFParser / createchunk(type, id, size) " + + NAME: createchunk(type, id, size=IFFSIZE_UNKNOWN) + + SYNOPSIS: LONG createchunk(ULONG type, ULONG id, ULONG size = IFFSIZE_UNKNOWN) + + DESCRIPTION: This method will create a new chunk where to write in. + + INPUT: type - (LONG) type of the chunk. (ex. "ILBM") + id - (LONG) id of the chunk. (ex. "FORM") + + RESULTS: NONE. + + + SEE ALSO: @{" closechunk() " link "IFFParser_closechunk"} + @{" writechunk() " link "IFFParser_writechunk"} + @{" save() " link "IFFParser_save"} +@endnode + +@node "IFFParser_writechunk" "Amiga Foundation Classes Module: IFFParser / writechunk(datas, datalen) " + + NAME: writechunk(data, datalen) + + SYNOPSIS: LONG writechunk(STRPTR data, ULONG datalen) + + DESCRIPTION: Use This method to write some data into a chunk. + + INPUT: data - (PTR TO LONG) memory location of your datas. + datalen - (LONG) length in bytes of your data. + + RESULTS: NONE. + + + SEE ALSO: @{" save() " link "IFFParser_save"} + @{" createchunk() " link "IFFParser_createchunk"} + @{" closechunk() " link "IFFParser_closechunk"} +@endnode + +@node "IFFParser_closechunk" "Amiga Foundation Classes Module: IFFParser / closechunk() " + + NAME: closechunk() + + SYNOPSIS: LONG closechunk(void) + + DESCRIPTION: This method will close current chunk. + + INPUT: NONE. + + RESULTS: NONE. + + + SEE ALSO: @{" createchunk() " link "IFFParser_createchunk"} + @{" writechunk() " link "IFFParser_writechunk"} + @{" save() " link "IFFParser_save"} +@endnode + +@node "IFFParser_load" "Amiga Foundation Classes Module: IFFParser / load(filename) " + + NAME: load(filename:PTR TO CHAR) + + SYNOPSIS: LONG load(STRPTR filename) + + DESCRIPTION: Use This method to open an already existing IFF file and + to begin a IFF load session. + + INPUT: filename - Name of the file to open / load. + + RESULTS: NONE. + + + SEE ALSO: @{" setscan() " link "IFFParser_setscan"} + @{" scan() " link "IFFParser_scan"} + @{" close() " link "IFFParser_close"} +@endnode + +@node "IFFParser_setscan" "Amiga Foundation Classes Module: IFFParser / setscan(type, id) " + + NAME: setscan(type, id) + + SYNOPSIS: LONG setscan(ULONG type, ULONG id) + + DESCRIPTION: Use This method to set chunk that will be loaded by + scan(). + + INPUT: type - (LONG) type of chunk. (ex. "ILBM") + id - (LONG) id of chunk. (ex. "FORM") + + RESULTS: NONE. + + + NOTES: You can do more than a single setscan() before scan()ing the + IFF file. This is the biggie ;) + In this way you can load up in memory all you need in a single + file access. + + SEE ALSO: @{" scan() " link "IFFParser_scan"} + @{" load() " link "IFFParser_load"} +@endnode + +@node "IFFParser_first" "Amiga Foundation Classes Module: IFFParser / first(type, id) " + + NAME: first(type, id) + + SYNOPSIS: APTR first(ULONG type, ULONG id) + + DESCRIPTION: Use This method to position IFFParser object to the FIRST + memory data location of a specific kind. + + INPUT: type - (LONG) type of the chunk. (ex. "ILBM") + id - (LONG) id of the chunk. (ex. "FORM") + + RESULTS: a PTR TO LONG memory location of the data (may be NIL) + + + SEE ALSO: @{" load() " link "IFFParser_load"} + @{" scan() " link "IFFParser_scan"} + @{" setscan() " link "IFFParser_setscan"} + @{" succ() " link "IFFParser_succ"} +@endnode + +@node "IFFParser_addr" "Amiga Foundation Classes Module: IFFParser / addr() " + + NAME: addr() + + SYNOPSIS: APTR addr(void) + + DESCRIPTION: This method will return current memory data address. + + INPUT: NONE. + + RESULTS: a PTR TO LONG specifying memory data address (may be NIL) + + SEE ALSO: @{" size() " link "IFFParser_size"} + @{" first() " link "IFFParser_first"} + @{" succ() " link "IFFParser_succ"} +@endnode + +@node "IFFParser_size" "Amiga Foundation Classes Module: IFFParser / size() " + + NAME: size() + + SYNOPSIS: LONG size(void) + + DESCRIPTION: Use This method to get size of current memory data. + + INPUT: NONE. + + RESULTS: size - (LONG) size of the memory data. (May be NIL) + + + SEE ALSO: @{" first() " link "IFFParser_first"} + @{" succ() " link "IFFParser_succ"} +@endnode + +@node "IFFParser_succ" "Amiga Foundation Classes Module: IFFParser / succ() " + + NAME: succ() + + SYNOPSIS: APTR succ(void) + + DESCRIPTION: Use This method to position to the next memory data. + + INPUT: NONE. + + RESULTS: a PTR TO LONG to the new location of memory data. (May be NIL) + + + SEE ALSO: @{" load() " link "IFFParser_load"} + @{" first() " link "IFFParser_first"} +@endnode + +@node "IFFParser_scan" "Amiga Foundation Classes Module: IFFParser / scan() " + + NAME: scan() + + SYNOPSIS: LONG scan(void) + + DESCRIPTION: Use This method to begin scanning an IFF file. + + INPUT: NONE. + + RESULTS: NONE. + + + SEE ALSO: @{" setscan() " link "IFFParser_setscan"} + @{" load() " link "IFFParser_load"} +@endnode + +@node "IFFParser_getheader" "Amiga Foundation Classes Module: IFFParser / getheader(string, filename) " + + NAME: getheader(string:PTR TO CHAR, filename:PTR TO CHAR) + + SYNOPSIS: LONG getheader(STRPTR s, STRPTR filename) + + DESCRIPTION: Use This method to determinate the kind of a file. + + INPUT: string - A _VALID_ Estring already initialized. + filename - Name of the file to examine. + + RESULTS: string - your _VALID_ Estring will be filled with the + file header (ex. "ILBM") + + NOTE: This method returns a STRING not a LONG! + + + SEE ALSO: +@endnode + +@node "IFFParser_exit" "Amiga Foundation Classes Module: IFFParser / exit(type, id) " + + NAME: exit(type, id) + + SYNOPSIS: LONG exit(ULONG type, ULONG id) + + DESCRIPTION: Use This method to determinate WHEN scan() should stop. + + INPUT: type - (LONG) type of the chunk. (ex. "ILBM") + id - (LONG) id of the chunk. (ex. "FORM") + + RESULTS: NONE. + + + SEE ALSO: @{" load() " link "IFFParser_load"} + @{" scan() " link "IFFParser_scan"} + @{" setscan()" link "IFFParser_setscan"} +@endnode + +@node "IFFParser_version" "Amiga Foundation Classes Module: IFFParser / version() " + + NAME: version() + + SYNOPSIS: LONG version(BOOL rev = FALSE) + + DESCRIPTION: This method returns version and revision of the class. + + INPUT: NONE. + + RESULTS: this method will return TWO values: version and revision. + + PORTING NOTES: The C++ class version behaves differently, since C++ cannot + return two values at the same time. + + So, if you call just version(), you'll get the VERSION value, + while calling version(TRUE), you'll get the REVISION value. + This is just a quick and dirty workaround... + + SEE ALSO: +@endnode + +@node "IFFParser_error" "Amiga Foundation Classes Module: IFFParser / error() " + + NAME: error() + + SYNOPSIS: ULONG error(void) + + DESCRIPTION: This method returns the last error raised. + + INPUT: NONE. + + RESULTS: this method will return the last error code raised. + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Localer.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Localer.guide new file mode 100644 index 0000000..2d8961a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Localer.guide @@ -0,0 +1,188 @@ +@database Localer.guide + +@$VER: Localer V1.10 - Original by Fabio Rotondo + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node main "Amiga Foundation Classes Modules: Localer/Main" + + + ** Localer - Original By Fabio Rotondo ** + + Part of Amiga Foundation Classes + + @{" Introduction " LINK localer_intro} @{" Author(s) Info " LINK author} @{" Amiga Foundation Classes " LINK "afc.guide/main"} @{" History " LINK "Localer_History"} + + Requires: NOTHING + + Base: $0000D000 + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + @{" localer() " LINK Localer_localer} Class constructor + @{" clear() " LINK Localer_clear} Clears all resources + @{" get(num, default=NIL) " LINK Localer_get} Gets a message string + @{" language() " LINK Localer_language} Returns the current language + @{" load(cat, v=0, built=NIL) " LINK Localer_load} Loads a catalog file +@endnode + +@node localer_intro "Amiga Foundation Classes Modules: Localer/ Intro" + + INTRO + + Localer is a very simple class, which works as an interface between locale.library + and the program you are writing. + Using this class, you can easily add localization properties to your program + without worrying about the AmigaOS your program will roun on. + Infact, if the AmigaOS isn't able to handle locale.library, Localer will simply + return default strings as program strings. + +@endnode + +@node author "Author's Info" + + + Original By: Fabio Rotondo + + E Version By: Fabio Rotondo (fsoft@intercom.it) + + C++ Version By: Inyaki Galdeano (i.amanita.s@mx3.redestb.es) + +@endnode + +@node Localer_History "Amiga Foundation Classes: Localer / History" + + HISTORY + + V1.00 - Initial release + + V1.10 - Added language() method + +@endnode + +@node localer_localer "Localer / Localer()" + + NAME: localer() + + SYNOPSIS: localer() + + DESCRIPTION: This is the class constructor. + + INPUTS: NONE + + RESULTS: NONE + + NOTES: This method will _never_ fail. It has been created to handle + correctly all OSes, starting from AmigaOS V1.2+, so, if it isn't + able to open locale.library, it simply ignores it. + + SEE ALSO: + +@endnode + +@node localer_load "Localer / Load()" + + NAME: load(catalogname, version=0, builtin=NIL) + + SYNOPSIS: struct Catalog * load(STRPTR catalogname, long version = 0, STRPTR builtin = NULL) + + DESCRIPTION: This method loads a locale's catalog. + + INPUTS: catalogname - The name of the catalog file to load. + Usually, it is the program name with the + suffix ".catalog" + + version - Catalog version. Default is 0, which means + "any catalog you'll find..." + + builtin - Built in language. (Eg. "english") + + RESULTS: The method returs a pointer to a valid catalog handle or NIL. + + SEE ALSO: @{" get() " LINK localer_get} + @{" clear() " LINK localer_clear} + +@endnode + +@node Localer_get "Localer / get() " + + NAME: get(message_number, defstring=NIL) + + SYNOPSIS: STRPTR get(int message_number, STRPTR defstr = NULL) + + DESCRIPTION: This method gets a message string from an opened catalog and + returns it. + + INPUTS: message_number - Number of the message string in the catalog. + + defstring - Message string to return if any error occurs. + (Default is NIL) + + RESULTS: a message string or NIL. + + SEE ALSO: @{" load() " LINK Localer_load} + +@endnode + +@node localer_clear "Localer / clear() " + + NAME: clear() + + SYNOPSIS: void clear() + + DESCRIPTION: This method clears a catalog file from the memory. + After this method is invoked, you'll never be able to + access messages strings contained inside your catalog, + unless you open it again. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" load() " LINK Localer_load} + +@endnode + +@node localer_language "Localer / language() " + + NAME: language() + + SYNOPSIS: STRPTR language() + + DESCRIPTION: This method returns the name of the current language used by the + user. + + INPUTS: NONE + + RESULTS: a PTR TO CHAR (STRPTR) containing the name of the current language. + + NOTE: The name of the language is always ended with ".language" extension. + So, for ex., "italiano" is "italiano.language" + + SEE ALSO: + +@endnode + +@node localer_version "Localer / version() " + + NAME: version() + + SYNOPSIS: long version(rev=FALSE) + + DESCRIPTION: This method returns class version and revision. + + INPUTS: NONE + + RESULTS: Class version and revision. + + NOTE: This method returns TWO values. + + The C++ method has been translated in this way: + invoking version() without any parameter, will return + the class VERSION; calling it with TRUE as parameter + will return class REVISION. + + SEE ALSO: + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Mousepointer.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Mousepointer.guide new file mode 100644 index 0000000..d8c5089 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Mousepointer.guide @@ -0,0 +1,289 @@ +@database Mousepointer.guide + +@$VER: Mousepointer V1.00 - by Andrea Galimberti - (C) Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node main "AFC Module: mousepointer / Main" + + + ** Mousepointer V1.00 - Original By Andrea Galiberti ** + + Part of Amiga Foundation Classes + + + + + @{" Introduction " LINK obj_intro} @{" Author(s) Info " LINK author} + + + Requires: @{" Hardsprite " LINK "hardsprite.guide/Main"}, @{" Displayer " LINK "displayer.guide/Main"}, @{" nodemaster " LINK "Nodemaster.guide/Main"} + + Base: $8002 + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + @{" mousepointer() " LINK mousepointer} Initialises the mousepointer object + @{" image() " LINK mouse_image} Stores the mouse image + @{" changeImage() " LINK mouse_changeimage} Changes the mouse image + @{" hotspot() " LINK mouse_hotspot} Sets the hotspot + @{" move() " LINK mouse_move} Moves the mouse + @{" x() " LINK mouse_x} Returns x coordinate + @{" y() " LINK mouse_y} Returns y coordinate + @{" update() " LINK mouse_update} Updates mouse position + @{" auto() " LINK mouse_auto} Auto updates mouse position + @{" vp() " LINK mouse_vp} Returns mouse viewport + @{" version() " LINK mouse_version} Gets mousepointer version + + @{" ERROR TABLE " LINK Error_Table} + +@endnode + +@node author "Author(s) Info" + + Original By: Andrea Galimberti + + E Version By: Andrea Galimberti + +@endnode + +@node obj_intro "Mousepointer / Introduction" + + Mousepointer. + + + This MODULE exploits the Hardsprite MODULE TO move a pointer around a +viewport. You can move the pointer sprite by hand, or allow the module do +it for you by reading the mouse hardware registers (update() method). The +mouse sprite can be automatically clipped to a chosen viewport. If you use +this module in conjunction with the Displayer module, you can have your +mouse sprite automatically pass from one viewport to another taking care of +the changing resolution of the different viewports (auto() method). Of +course the mouse sprite image can be changed at your will. + +@endnode + +@node Error_Table "Mousepointer / Error Table" + +Val (Hex) | Description +-----------+------------------------------------------------------ + none | + +@endnode + +@node mousepointer "AFC module: mousepointer / mousepointer()" + + NAME: mousepointer(number=-1) + + DESCRIPTION: Initialises a mousepointer object. + + INPUTS: number of the (hardware) sprite (from 0 to 7) to be used to + represent the pointer on the screen. The default value of + -1 means that it will be allocated the first sprite + available. + + RESULTS: FALSE if the requested sprite is already in use and so it + couldn't be allocated. + TRUE otherwise. + + SEE ALSO: @{" hardsprite / hardsprite() " LINK "hardsprite.guide/hardsprite"} + +@endnode + +@node mouse_image "AFC module: mousepointer / image()" + + NAME: image(height, list:PTR TO INT) + + DESCRIPTION: this method stores the image to be used with the mouse + sprite. Whenever this method is called, it will discard + the previous image. + + INPUTS: height (in lines) of the image, + a typed list (it MUST be typed to INT) in the following + form: + + [ $0000, $0000, + $0000, $0000, + ... ]:INT + + ^ ^ + | | + | second bitplane (16 bits wide) + | + first bitplane (16 bits wide) + + This way you can select one of 4 colours for each pixel of + the sprite's image. + + RESULTS: returns FALSE if: sprite non allocated (with mousepointer()), + height<=0, + pointer to list =NIL. + The hardsprite will raise "No Memory" if it cannot allocate + the (CHIP) memory for the image. + + SEE ALSO: @{" hardsprite / image() " LINK "hardsprite.guide/sprite_image"} + +@endnode + +@node mouse_changeimage "AFC module: mousepointer / changeImage()" + + NAME: changeImage(viewport) + + DESCRIPTION: changes the mouse sprite image to the stored one. + + INPUTS: pointer to a viewport structure. If this pointer is <>NIL + then the change will affect only the chosen viewport; if + pointer=NIL then the change is relative to the current + view. + + RESULTS: FALSE if viewport<0 or mouse not allocated. + Otherwise TRUE. + + SEE ALSO: @{" image() " LINK mouse_image} + @{" hardsprite / changeImage() " LINK "hardsprite.guide/sprite_changeimage"} +@endnode + +@node mouse_hotspot "AFC module: mousepointer / hotspot()" + + NAME: hotspot(x,y) + + DESCRIPTION: sets the mouse hotspot + + INPUTS: x and y coordinates of the mouse hotspot: these coordinates + are relative to the top-left hand corner of the mouse + image. (Negative values are allowed.) + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node mouse_update "AFC module: mousepointer / update()" + + NAME: update(viewport, hclip=TRUE, vclip=TRUE) + + DESCRIPTION: when called, this method moves the pointer hotspot to the + new mouse coordinates relative to the top-left hand corner + of the chosen viewport. + + INPUTS: viewport: pointer to a viewport structure; if this pointer + is NIL then the pointer movements are relative to the + current view. + + hclip: TRUE= pointer hotspot cannot exceed the horizontal + dimensions of the viewport (this flag is switched + automatically to FALSE if viewport=NIL, because in this + case there aren't any bounds to check for). + + vclip: same as hclip, but for the vertical direction. + + RESULTS: NONE + + SEE ALSO: @{" auto() " LINK mouse_auto} + +@endnode + +@node mouse_move "AFC module: mousepointer / move()" + + NAME: move(viewport, x,y) + + DESCRIPTION: moves the mouse image to the desired location on a + viewport (either Intuition or hand made), taking care of + the hotspot position. + + INPUTS: viewport: pointer to a viewport structure, + x and y coordinates of the site where to move the mouse + hotspot. + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node mouse_x "AFC module: mousepointer / x()" + + NAME: x() + + DESCRIPTION: returns the x coordinate of the mouse hotspot + + INPUTS: NONE + + RESULTS: x coordinate of mouse hotspot + + SEE ALSO: @{" y() " LINK mouse_y} + +@endnode + +@node mouse_y "AFC module: mousepointer / y()" + + NAME: y() + + DESCRIPTION: returns the y coordinate of the mouse hotspot. + + INPUTS: NONE + + RESULTS: y coordinate of mouse hotspot + + SEE ALSO: @{" x() " LINK mouse_x} + +@endnode + +@node mouse_auto "AFC module: mousepointer / auto()" + + NAME: auto(vo:PTR TO displayer, hclip=TRUE) + + DESCRIPTION: when called, moves the pointer hotspot to the new + coordinates, taking care of changing viewport if necessary + and automatically switching to the new resolution. One + thing you must be aware of: when you position the mouse + sprite in the first viewport you have also to set the + correct mouse hotspot for that resolution; the auto() + method then takes care of rescaling the hotspot coordinates + when the resolution changes. + + INPUTS: vo: pointer to a displayer (see the BuildView module + documentation); this pointer contains all the information + concerning dimensions and resolutions of all the viewports + displayed in the current view. + + hclip: TRUE= pointer hotspot cannot exceed the horizontal + dimensions of the current viewport. + + RESULTS: NONE + + SEE ALSO: @{" update() " LINK mouse_update} + +@endnode + +@node mouse_vp "AFC module: mousepointer / vp()" + + NAME: vp() + + DESCRIPTION: returns the number (starting from 0) of the viewport the + mouse sprite is in. This value is meaningful only if you + are using the auto() method to move the mouse. + + INPUTS: NONE + + RESULTS: number of viewport the mouse is in + + SEE ALSO: @{" auto() " LINK mouse_auto} + +@endnode + +@node mouse_version "AFC module: mousepointer / version()" + + NAME: version() + + DESCRIPTION: returns the version number of the Mouse module. + + INPUTS: NONE + + RESULTS: version, revision of mousepointer + + SEE ALSO: + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/NodeMaster.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/NodeMaster.guide new file mode 100644 index 0000000..8788b83 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/NodeMaster.guide @@ -0,0 +1,855 @@ +@database NodeMaster.guide + +@$VER: NodeMaster V3.40 - (C)Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node "Main" "Amiga-E Module: NodeMaster" + + + + ** NodeMaster - Original By Fabio Rotondo ** + + ** This Object is part of the Amiga Foundation Classes ** + + ** DOCUMENTATION GUIDE ** + + @{" Introduction " link "NodeMaster_introduction" 0} @{" Author Info " LINK "author"} @{" History " link "NodeMaster_history" 0} @{" Amiga Foundation Classes " LINK "afc.guide/main"} + + Requires: Nothing. + + Base: $0001 + + COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" nodemaster() " link "NodeMaster_NodeMaster" 0} Initializes the NodeMaster object + @{" add(object, mode=NM_ADD_TAIL) " link "NodeMaster_add" 0} Add obejct to the list + @{" addr() " link "NodeMaster_addr" 0} Get the pointer to the Exec list + @{" change(object) " link "NodeMaster_change" 0} Change current node object + @{" changenum(newnum) " link "NodeMaster_changenum" 0} Change current node ordinal number + @{" changepos(node) " link "NodeMaster_changepos" 0} Change current node position + @{" clear() " link "NodeMaster_clear" 0} Clear ALL list + @{" clearstack() " link "NodeMaster_clearstack" 0} Clears all push()ed items + @{" del() " link "NodeMaster_del" 0} Delete the current node + @{" empty() " link "NodeMaster_empty" 0} Check if there are nodes in list + @{" error() " link "NodeMaster_error" 0} Returns last error code + @{" first() " link "NodeMaster_first" 0} Jump to the first node + @{" get() " link "NodeMaster_get" 0} Get the pointer to the current node + @{" insert(object) " link "NodeMaster_insert" 0} Insert an object AFTER the current one + @{" isfirst() " link "NodeMaster_isfirst" 0} Checks if the current item is the first + @{" islast() " link "NodeMaster_isfirst" 0} Checks if the current item is the last + @{" item(numitem) " link "NodeMaster_item" 0} Jump to the specific item + @{" last() " link "NodeMaster_last" 0} Jump to the last node + @{" obj() " link "NodeMaster_obj" 0} Get the PTR of the current object + @{" numitems() " link "NodeMaster_numitems" 0} Return number of nodes in memory + @{" numpos() " link "NodeMaster_numpos" 0} Returns current ordinal position + @{" pop(pos=TRUE) " link "NodeMaster_pop" 0} Get a node from the stack + @{" prev() " link "NodeMaster_prev" 0} Go to the previous node + @{" push() " link "NodeMaster_push" 0} Push a node on the stack + @{" sort(sortroutine, info=NIL) " link "NodeMaster_sort" 0} Sort a list of items + @{" succ() " link "NodeMaster_succ" 0} Go to the next node + @{" version() " link "NodeMaster_version" 0} Returns class version AND revision + + @{" Error Table " LINK "NodeMaster_ErrorTable"} + +@endnode + +@node author "Author(s) Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + C++ Version By: Massimo Tantignone (tanti@intercom.it) + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + --------------------------------------------------------------------------- + + Massimo Tantignone + + ITALY + + e-mail: tanti@intercom.it + + Web: http://www.intercom.it/~amigaws +@endnode + +@node "NodeMaster_history" "History" + +Legend: NEW - New feature + ADV - Advanced feature + FIX - Bug fix + +V3.40 - NEW: Added error() method. + - NEW: Added isfirst() method. + - NEW: Added islast() method. + +V3.30 - FIX: Fixed a minor bug in the clear() method. + - ADV: Clear routine optimized. + - ADV: Better docs. + - NEW: Added islast() method. + - NEW: Added isfirst() method. + - NEW: Added version() method. + - ADV: List constructors are INSIDE NodeMaster source for better porting. + +V3.20 - ADV: Optimized code. + - ADV: Now nodemaster() calls clearstack() instead of freeing stack's memory by itself. + - ADV: Now clear() calls clearstack() instead of freeing stack's memory by itself. + - ADV: clearstack() is faster. + - ADV: add() now is faster (and shorter!) + - ADV: removed all internal self.empty() calls and replaced with the (faster) + IsListEmpty() macro. + - ADV: Now item() patches positions <0 + +V3.10 - ADV: clear() modified: now the LIST IS correctly initialized. + - FIX: now frees the LIST pointer correctly. + + +V3.00 - ADV: General Optimizations + - ADV: Now first(), prev(), succ(), last(), change(), item(), insert(), add() + return the item address (instead of TRUE) and FALSE when there are + no more items. + - ADV: Now stacked push() and pop() have 8 stack levels!! + - ADV: Now pop() has an optional parameter (pos=TRUE): set it to FALSE if + you want just to free a stacked push() + - NEW: method clearstack() to free all push()ed positions. + - FIX: empty() used to crash when used after a del() with no items. + - NEW: sort() method. Incredibly fast and general-purpose sort algo + written by Andrea Galimberti. + - ADV: optimized prev() and succ() methods. Now about 20% faster. + - ADV: changepos() modified: now checks agaings no items, and return the + data inside the item or NIL. + - ADV: del() modified: now returns the pointer to the data inside the + next active node. + - FIX: pos() has been renamed numpos() + - FIX: now SN_ADD_TAIL, SN_ADD_HERE, SN_ADD_HEAD are called: + NM_ADD_TAIL, NM_ADD_HERE, NM_ADD_HEAD (short: change the SN_ + with NM_) + - ADV: change() method is now smarter and returns PTR TO obj data or + FALSE. + - ADV: better docs and examples. +@endnode + +@node "NodeMaster_introduction" "Introduction" + +INTRODUCTION + +NodeMaster is a generic object handling module which will allow you to easily +create lists of whatever you want. Its generic structure is ideal for +polimorphism and inheritance in other objects. This object just take care of +creating Exec Lists and Nodes of something you pass to it (we will call it +"object") and then it has great power in Lists manipulation. You can easily +add/del nodes from the list, go to a specific item by its ordinal number and so +on... + +I have worked out this module structuring it on Amiga Exec's Nodes. This means +that everything you will add/remove to a NodeMaster will be done on a System +List Node. + +This code is very Exec List-based, so you can do whatever you want. + +Main features are: + + * Push/Pop commands to save/restore a special node position. + + * Insert command to add a object AFTER another (usually it is added as Last + node) + + * Search command to scan trought the list looking for a string. + + * Item command to go to a specific item by its ordinal number. + +NEW V2.0 Version features: + + * New method pos() which returns the actual ordinal node position! + + * Enhanced item() method: now it does not scans from first() item to + selected, but just +/- delta objects from the starting point. + + * Internal sniff-snuff ;) + + * NO MORE ENFORCER'S HITS! ;) + + * Returns Raise() errors instead of return codes!! + + * More examples! + +NEW V2.10 Version features: + + * New changenum() method to force NodeMaster to change the + internal ordinal number of current node. + + * More code sniff-snuff ;) + +NEW V3.00 Version features: + + * General improvements in speed. + + * NEW! Low-Level tree-algo sort (FAST!!) + + * Now push() and pop() has 8 levels of stack!!! + + * Now NodeMaster is part of the @{" Amiga Foundation Classes " LINK "afc.guide/main"} + +@endnode + +@node "author" "Author's Infos " + + Original Object by: Fabio Rotondo (fsoft@intercom.it) + + E Module by: Fabio Rotondo (fsoft@intercom.it) +@endnode + +@node "example" "Example Program" + + With NodeMaster two examples are provided: + + The first one is a _GREAT_ example, which opens as many EasyGUIs as + you want (memory limiting...) and handle events from all of them ;) + + The second is just a demo of pos() and item() command based upon strings. + + PLEASE, refer to StringNode.lha archive for a demo of NodeMaster and + StringNode objects (this one inherits all methods of NodeMaster ;) + + + Thank You! +@endnode + +@node NodeMaster_ErrorTable "NodeMaster / Error Table" +ERROR VALUE | DESCRIPTION +----------------+------------------------------------- + $0000 | No Memory + +@endnode + +@node "NodeMaster_NodeMaster" "Amiga Foundation Classes Module: NodeMaster/NodeMaster()" + + NAME: NodeMaster() + + SYNOPSIS: nodemaster(void) + + DESCRIPTION: Use this command to inizialize a NodeMaster object. + + INPUT: NONE. + + RESULTS: NONE. + + SEE ALSO: +@endnode + +@node "NodeMaster_add" "Amiga Foundation Classes Module: NodeMaster/add()" + + NAME: add(object:PTR TO LONG, mode=SN_ADD_TAIL) + + SYNOPSIS: APTR add(APTR s, ULONG mode = NM_ADD_TAIL) + + DESCRIPTION: Use this command to add an object to the list. + + INPUT: object - PTR TO LONG. This is the object to add. + mode - (OPTIONAL) This flag is very useful to + choose _where_ a new node will be added. + Default is as last one, but you can + add it as the first line or in the middle + of the list (same as insert() command). + + Possible values are: + + NM_ADD_HEAD - Use this one to add the node + as the first in list. + + NM_ADD_HERE - Use this one to add the node + AFTER the current one. + (Same as insert() method) + + NM_ADD_TAIL - (Default) Use this one to add + the node as the last in list. + + + RESULTS: PTR TO obj - PTR TO add()ed obj: everything went fine. + + Raise() - An exception in case of problems. + + NOTE: Starting from V3.00, NodeMaster will return the PTR TO obj + you have just add()ed, if successfull. + + Note also that constants SN_ADD_* are now called NM_ADD_*. + + Please, be careful and *NOT* use NM_ADD_HERE if you do not + know for sure that your list is not empty: empty list can + cause problems. If you want to do things in a safe way + use the insert() method, instead of add(). + + SEE ALSO: @{" insert() " link NodeMaster_insert} + @{" del() " link "NodeMaster_del" 0} + @{" name() " link "NodeMaster_name" 0} + @{" item() " link "NodeMaster_item" 0} +@endnode + +@node "NodeMaster_get" "Amiga Foundation Classes Module: NodeMaster/get()" + + NAME: get() + + SYNOPSIS: Node *get(void) + + DESCRIPTION: Use this command to get a pointer to the current Exec List + node. + + INPUT: NONE. + + RESULTS: A PTR TO ln (An Exec List Node) + + SEE ALSO: @{" addr() " link "NodeMaster_addr" 0} +@endnode + +@node "NodeMaster_addr" "Amiga Foundation Classes Module: NodeMaster/addr() " + + NAME: addr() + + SYNOPSIS: List *addr(void) + + DESCRIPTION: Use this command to get the addr of the Exec List. + + INPUT: NONE. + + RESULTS: A PTR TO lh (an Exec List Header). + + NOTE: This command is useful expecially with ListView gadgets + which requires a PTR TO an Exec List Header. All you have + to do is: + Gt_SetGadgetAttrsA(listgad, win, req, + [GTLV_LABELS, NodeMasterobj.addr(), 0,0]) + + And the ListView will show your new list. + Please refer to RMKM and autodocs for more infos regarding + Gadtools and ListViews. + + SEE ALSO: @{" get() " link "NodeMaster_get" 0} +@endnode + +@node "NodeMaster_push" "Amiga Foundation Classes Module: NodeMaster/push()" + + NAME: push() + + SYNOPSIS: BOOL push(void); + + DESCRIPTION: Use this command to memorize the current node position. + + INPUT: NONE. + + RESULTS: TRUE - push()ing successful. + + FALSE - push()ing failed (out of stack space, or no items) + + NOTE: * From V2.00 it does not restore the internal ordinal number. + See @{" item() " LINK "NodeMaster_item" 0} for a better + explanation. + + * Starting from V3.00 now push() and pop() have 8 stack levels. + + SEE ALSO: @{" pop() " link "NodeMaster_pop" 0} + @{" first() " link "NodeMaster_first" 0} + @{" last() " link "NodeMaster_last" 0} + @{" changepos() " link "NodeMaster_changepos" 0} + @{" changenum() " link "NodeMaster_changenum" 0} +@endnode + +@node "NodeMaster_pop" "Amiga Foundation Classes Module: NodeMaster/pop()" + + NAME: pop(pos=TRUE) + + SYNOPSIS: APTR pop(BOOL autopos = TRUE) + + DESCRIPTION: Use this command to restore current node to the one + previously Push()ed. + + INPUT: pos - (default TRUE) this is a boolean flag. + + TRUE, restores the previously push()ed + node in list. + + FALSE, just removes the push()ed node from + the stack. + + RESULTS: PTR TO obj - if pop() succeded and pos=TRUE. + + FALSE - not pop()ed or pos=FALSE. + + NOTE: * If no node was Push()ed the current node won't change. + + * From V2.00 it does not restore the internal ordinal number. + See @{" item() " LINK "NodeMaster_item" 0} for a better + explanation. + + * Starting from V3.00, push() and pop() have 8 stack levels. + + SEE ALSO: @{" push() " link "NodeMaster_push" 0} + @{" changepos() " link "NodeMaster_changepos" 0} + @{" changenum() " link "NodeMaster_changenum" 0} +@endnode + +@node "NodeMaster_obj" "Amiga Foundation Classes Module: NodeMaster/obj()" + + NAME: obj() + + SYNOPSIS: APTR obj(void); + + DESCRIPTION: Use this command to get the current node's PTR TO object. + + INPUT: NONE. + + RESULTS: PTR TO obj data to the current node object. + + SEE ALSO: @{" add() " link "NodeMaster_add" 0} +@endnode + +@node "NodeMaster_del" "Amiga Foundation Classes Module: NodeMaster/del()" + + NAME: del() + + SYNOPSIS: APTR del(void) + + DESCRIPTION: Use this command to delete the current node. + After deletion the CURRENT NODE will be the next one. + If the node you deleted was the last one, then the next + will be the previous one. + + INPUT: NONE. + + RESULTS: PTR TO next obj data. Starting from V3.00 del() method + returns the pointer to the next actual obj data, or NIL + if it was the last object avaible in list (ie. list empty) + + SEE ALSO: @{" clear() " link "NodeMaster_clear" 0} + @{" add() " link "NodeMaster_add" 0} + +@endnode + +@node NodeMaster_clearstack "Amiga Foundation Classes Module: NodeMaster/clearstack()" + + NAME: clearstack() + + SYNOPSIS: void clearstack(void) + + DESCRIPTION: Use this method to clear all push()ed nodes in stack. + + INPUT: NONE. + + RESULTS: push() stack will be cleared. + + SEE ALSO: @{" push() " link "NodeMaster_push" 0} + @{" pop() " link "NodeMaster_pop" 0} +@endnode + +@node "NodeMaster_numitems" "Amiga Foundation Classes Module: NodeMaster/numitems" + + NAME: numitems() + + SYNOPSIS: ULONG numitems(void) + + DESCRIPTION: Use this command to know how many items are added to the + list. + + INPUT: NONE. + + RESULTS: items - LONG. Number of items. + + SEE ALSO: @{" add() " link "NodeMaster_add" 0} + @{" del() " link "NodeMaster_del" 0} +@endnode + +@node NodeMaster_empty "Amiga Foundation Classes Module: NodeMaster/empty()" + + NAME: empty() + + SYNOPSIS: BOOL empty(void) + + DESCRIPTION: Use this command to check whether the list is empty or not. + + INPUT: NONE. + + RESULTS: TRUE - List is empty + FALSE - At least one item is present. + + SEE ALSO: +@endnode + +@node "NodeMaster_first" "Amiga Foundation Classes Module: NodeMaster/first()" + + NAME: first() + + SYNOPSIS: APTR first(void) + + DESCRIPTION: Use this command to jump to the first object in the list. + + INPUT: NONE. + + RESULTS: PTR TO first obj - Position correct. + FALSE - Cannot go to the first (maybe list empty). + + NOTE: Before V3.00 first() used to return TRUE when positioning + correctly to the first item, now it returns directly the + obj data, so you don't have to call the "obj()" method. + + SEE ALSO: @{" last() " link "NodeMaster_last" 0} + @{" del() " link "NodeMaster_del" 0} + @{" obj() " link "NodeMaster_obj" 0} + @{" search() " link "NodeMaster_search" 0} +@endnode + +@node "NodeMaster_last" "Amiga Foundation Classes Module: NodeMaster/last()" + + NAME: last() + + SYNOPSIS: APTR last(void) + + DESCRIPTION: Use this command to position current node to the last one. + + INPUT: NONE. + + RESULTS: PTR TO obj data - Operation successfull. + + FALSE - No items. + + NOTE: V3.00 - Now last() returns directly the obj data, so you + do not have to do a "obj()" anymore. + + SEE ALSO: @{" first() " link "NodeMaster_first" 0} + @{" item() " link "NodeMaster_item" 0} +@endnode + +@node "NodeMaster_succ" "Amiga Foundation Classes Module: NodeMaster/succ()" + + NAME: succ() + + SYNOPSIS: APTR succ(void) + + DESCRIPTION: Use this command to position current node to the next one in + list. + + INPUT: NONE. + + RESULTS: PTR TO obj - PTR TO obj data: positioning successful. + FALSE - No next items. + + NOTE: It is a structural problem linked TO this method. If you + add to NodeMaster some numbers (eg. 1, 2, 3, 4,...,n) + the class could give you a wrong result, when it encounters + a number "0", because it will return a "0" and you could assume + that it is a FALSE (no next items) value. + You should check using the @{" islast() " LINK "NodeMaster_islast"} method. + + SEE ALSO: @{" prev() " link "NodeMaster_prev" 0} + @{" islast() " link "NodeMaster_islast"} + @{" last() " link "NodeMaster_last"} +@endnode + +@node "NodeMaster_prev" "Amiga Foundation Classes Module: NodeMaster/prev()" + + NAME: prev() + + SYNOPSIS: APTR prev(void) + + DESCRIPTION: Use this command to go to the previous string in the list. + + INPUT: NONE. + + RESULTS: PTR TO obj - PTR TO obj data: positioning successful. + FALSE - No previous items. + + NOTE: see note in @{" succ() " LINK NodeMaster_succ} + + SEE ALSO: @{" succ() " link "NodeMaster_succ" 0} + @{" first() " link "NodeMaster_first" 0} + @{" last() " link "NodeMaster_last" 0} +@endnode + +@node "NodeMaster_insert" "Amiga Foundation Classes Module: NodeMaster/insert()" + + NAME: insert(object:PTR TO LONG) + + SYNOPSIS: APTR insert(APTR s) + + DESCRIPTION: Use this command to add an object AFTER the current node. + + INPUT: object - PTR TO CHAR. Object you want to add. + + RESULTS: PTR TO object data. + + NOTE: The current node WILL NOT change!!! + + SEE ALSO: @{" add() " link "NodeMaster_add" 0} + @{" name() " link "NodeMaster_name" 0} + @{" del() " link "NodeMaster_del" 0} + @{" item() " link "NodeMaster_item" 0} +@endnode + +@node "NodeMaster_item" "Amiga Foundation Classes Module: NodeMaster/item()" + + NAME: item(numitem) + + SYNOPSIS: APTR item(ULONG n) + + DESCRIPTION: Use this command to position current node to the ordinal + numitem node. + + INPUT: numitem - LONG. Ordinal value of node position. + + RESULTS: PTR TO obj data - Position correct. + + FALSE - List is empty. + + NOTES: V3.00 - Now this method() returns directly obj data when + called successfully, so you don't have to do an obj() anymore. + + From V2.00 this method changes a bit. Now it scans prev() or + succ() item starting from the current position. So it is + faster, but you have to be careful. + If you use the method changepos(), the internal ordinal + position is not changed. So you have to do a first() method + before calling item(). + + In any case, if you think that something in your source could + behaves differently, just do a first() method call and + everything will behaves as always. + + Also pop() and push() do not update internal ordinal position. + Do a first() also before an item() after them. + + SEE ALSO: @{" numitems() " link "NodeMaster_numitems" 0} + @{" changepos() " link "NodeMaster_changepos" 0} + @{" changenum() " link "NodeMaster_changenum" 0} +@endnode + +@node "NodeMaster_change" "Amiga Foundation Classes Module: NodeMaster/change()" + + NAME: change(data:PTR TO LONG) + + SYNOPSIS: PTR change(APTR s) + + DESCRIPTION: Use this command to change the PTR to the data field of + current object. + + INPUT: data - PTR TO LONG. New data to change the old one with. + + RESULTS: PTR TO obj data - Changin successful. + + FALSE - No change (maybe list empty) + + SEE ALSO: +@endnode + +@node NodeMaster_clear "Amiga Foundation Classes Module: NodeMaster/clear()" + + NAME: clear() + + SYNOPSIS BOOL clear(void) + + DESCRIPTION: Use this command to clear all items in the list. + + INPUT: NONE. + + RESULTS: The list will be completely empty. + + SEE ALSO: @{" del() " link NodeMaster_del} +@endnode + +@node NodeMaster_changepos "Amiga Foundation Classes Module: NodeMaster/changepos()" + + NAME: changepos(node:PTR TO ln) + + SYNOPSIS: APTR cngepos(Node *node) + + DESCRIPTION: Use this command to change current node position to another. + + INPUT: node - (PTR TO ln) new list node to change position to. + + NOTE: You *MUST* know exactly what you are doing. Passing a wrong + node as parameter could get to Software Failures and so on. + This command is designed only for "professional" user who + intend build new object inheriting this one. + + From V2.00 note also that it does not update internal ordinal + number. See @{" item() " LINK "NodeMaster_item" 0} + + RESULTS: The current node position will be changed. + + SEE ALSO: @{" first() " link "NodeMaster_first" 0} + @{" last() " link "NodeMaster_last" 0} + @{" item() " link "NodeMaster_item" 0} + +@endnode + +@node NodeMaster_numpos "Amiga Foundation Classes Module: NodeMaster/pos()" + + NAME: numpos() + + SYNOPSIS: LONG numpos(void) + + DESCRIPTION: Use this command to know the ordinal object position inside + the list. + + INPUT: NONE. + + RESULTS: The current ordinal node position is returned. + + SEE ALSO: @{" first() " link "NodeMaster_first" 0} + @{" last() " link "NodeMaster_last" 0} + @{" item() " link "NodeMaster_item" 0} +@endnode + +@node NodeMaster_changenum "Amiga Foundation Classes Module: NodeMaster/changenum()" + + NAME: changenum(newval) + + SYNOPSIS: void chaenum(ULONG newnum) + + DESCRIPTION: Use this command to change current node ordinal position + number. + + INPUT: newval - (LONG) new ordinal number to assign to the current + node. + + NOTE: You *MUST* know exactly what you are doing. Passing a wrong + value as parameter could get to Software Failures and so on. + This command is designed only for "professional" user who + intend build new object inheriting this one. + + RESULTS: The current node ordinal number will be changed. + + SEE ALSO: @{" first() " link "NodeMaster_first" 0} + @{" last() " link "NodeMaster_last" 0} + @{" item() " link "NodeMaster_item" 0} + @{" changepos() " link "NodeMaster_changepos" 0} +@endnode + +@node NodeMaster_sort "Amiga Foundation Classes Module: NodeMaster/sort()" + + NAME: sort(sortingroutine, info=NIL:PTR TO LONG) + + SYNOPSIS: APTR sort(LONG (*comp)(APTR, APTR, APTR APTR info = NULL) + + DESCRIPTION: Use this method to sort the list. + + INPUT: sortingroutine - You MUST provide a comparison routine, + which will be used to sort your list. + The comp routine should accept three + params: item1, item2 and info. + Item1 and item2 are the two items you + should compare; while info is an + optional param containing to whatever + you want. + Your comp routine MUST return a value: + + >1 - Item1 > Item2 + =0 - Item1 = Item2 + <0 - Item1 < Item2 + + Then items will be sorted accordingly + by the sort() method. + + info - (DEFAULT NIL) This is an optional param + that will be passed to your comp routine. + It can contain everything you like. + + RESULTS: PTR TO first obj data - list has been sorted. + + FALSE - sort() failed (maybe list empty) + + NOTE: After a sort(): + + + Stack will be cleared. + + Current item will be the first one. + + SEE ALSO: @{" push() " link "NodeMaster_push" 0} + @{" pop() " link "NodeMaster_pop" 0} + @{" clearstack() " link "NodeMaster_clearstack" 0} + @{" first() " link "NodeMaster_first" 0} +@endnode + +@node NodeMaster_version "Amiga Foundation Classes Module: NodeMaster/version()" + + NAME: version() + + SYNOPSIS: ULONG version(BOOL rev = FALSE) + + DESCRIPTION: Returns class version and revision. + + INPUT: NONE + + RESULTS: This method returns TWO values: class version and revision. + + PORTING NOTES: Because in C++ a function cannot return two values, we have + arranged the version/revision return values in this way: + by calling version() method with rev=FALSE you will be + returned the Class VERSION. If you set rev=TRUE, then you'll + get the Class REVISION. + + SEE ALSO: +@endnode + +@node "NodeMaster_islast" "Amiga Foundation Classes Module: NodeMaster/islast()" + + NAME: islast() + + SYNOPSIS: BOOL islast(void) + + DESCRIPTION: This method checks if the current item is the last one. + + INPUT: NONE. + + RESULTS: TRUE - The item is the last. + FALSE - The item is not the last. + + SEE ALSO: @{" isfirst() " link "NodeMaster_isfirst" 0} +@endnode + +@node "NodeMaster_isfirst" "Amiga Foundation Classes Module: NodeMaster/isfirst()" + + NAME: isfirst() + + SYNOPSIS: BOOL isfirst(void) + + DESCRIPTION: This method checks if the current item is the first one. + + INPUT: NONE. + + RESULTS: TRUE - The item is the first. + FALSE - The item is not the first. + + SEE ALSO: @{" islast() " link "NodeMaster_islast" 0} +@endnode + +@node "NodeMaster_error" "Amiga Foundation Classes Module: NodeMaster/error()" + + NAME: error() + + SYNOPSIS: ULONG error(void) + + DESCRIPTION: This method checks if the current item is the first one. + + INPUT: NONE. + + RESULTS: last error code. 0 means "no errors". + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/ReqTooller.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/ReqTooller.guide new file mode 100644 index 0000000..b76c1a7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/ReqTooller.guide @@ -0,0 +1,380 @@ +@database ReqTooller.guide + +@$VER: ReqTooller V1.01 - (C)Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: ReqTooller" + + + + ** ReqTooller - Original By Fabio Rotondo ** + + * Part of the Amiga Foundation Classes * + + @{" Introduction " link "ReqTooller_introduction"} @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} + + Requires: + + Class Base: $000A0000 + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" reqtooller(libver=0) " link "ReqTooller_reqtooller"} Initailizes the class. + @{" setattrs(tags) " link "ReqTooller_SetAttrs"} Sets class attributes. + @{" get(tag) " link "ReqTooller_Get"} Gets class attributes. + @{" req(mode, tags=0) " link "ReqTooller_Req"} Opens a requester. + @{" version() " link "ReqTooller_version"} Returns class version. + + @{" Error Table " LINK ReqTooller_ErrorTable} +@endnode + +@node "ReqTooller_Introduction" "Introduction" + + INTRODUCTION + + This class handles reqtools requesters. + It is incredibly easy to use and it is completely tags-driven. + With this class you can create professional requester without having to + worry about how to allocate and deallocate reqtools structures: it minds + all about it. + + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + +@endnode + +@node ReqTooller_ErrorTable "ReqTooller / Error Table " + +VALUE | DESCRIPTION +----------------+---------------------------------- +$0000 | No Memory + + +@endnode + +@node "ReqTooller_reqtooller" "Amiga Foundation Classes: ReqTooller / reqtooller()" + + NAME: reqtooller(libver=0) + + DESCRIPTION: This method initializes the class. + + INPUT: libver - (Optional) Pass this param if you want a specific + version of reqtools.library to open. Default is 0 + which means "any version". + + RESULTS: NONE. + + SEE ALSO: +@endnode + +@node "ReqTooller_setattrs" "Amiga Foundation Classes: ReqTooller / setattrs()" + + NAME: setattrs(tags:PTR TO LONG) + + DESCRIPTION: This method is used to set class behaviours. + + INPUT: tags - a taglist. Avaible tags are: + + COMMON TAGS: + + RT_TITLE - Requester title. + + RT_WIN - Window where to open the requester on. + Pass a *valid* window pointer expecially if + you are using a custom screen and you don't + want the requester to open on the Workbench + screen. + + RT_LOCK - Set this tag to TRUE if you want the window + (set by RT_WIN) to be locked when the + requester appears. + + RT_UCHAR - Use this tag to define the "Underscore Char". + Default char is "_". + + FILE REQUESTER TAGS: + + RT_PATH - File Requester default path. + + RT_FILENAME - File Requester default file name. + + RT_PATTERN - File Requester default pattern. + + RT_OKGAD - String (max 4 chars) for the "OK" gadget + in the File Requester. You can, for example, + set "Load" or "Save" as "OK" gadget. + + RT_FULLNAME - Set this flag to TRUE if you want the full + path returned along with the file name. + + EASY, STRING and NUMBER REQUESTERS TAGS: + + RT_TEXT - You can specify a text inside the requester using + this tag. If you are opening an Easy requester, then + you can specify some "params", like strings and + numbers to be "dinamically" linked using the RT_ARGS + tags (see below). To specify strings use the usual + "\s" chars for E programs and "%s" for C++ programs. + Example: + + ... + RT_TEXT, "Your Name is: \s\nYou are \d years old.", + RT_ARGS, [name, age], + ... + + + + RT_GADS - You can specify all the gads to appear with this + tag. The string you pass *must* contain all the + gads divided by a "|" char. The last gad is + always the "Cancel" gadget. Example: + + "Ok|Great|No way!" + + Will show three gads: "Ok", "Great" and "No way!" + + If you pass a null string, will be just shown an + "Ok" gadget. + + RT_ARGS - Here you can specify a list of arguments to + pass to the Easy Requester. + NOTE: This tags only works with EASY requester. + + RT_INVISIBLE - Set this tag to TRUE if you want the text being + hidden (shadowed). + + RT_CHOICE - Default gadget that will be selected if the user + just presses RETURN key. If you want the default + gadget to be the "Cancel" button, then pass 0 as + value. The other gads are ordinally numbered + from 1 to n, from left to right. + + STRING REQUESTER TAGS: + + RT_MAXCHARS - Max chars that can be typed by the user. + + RT_DEFSTR - Default string requester string. + + NUMBER REQUESTER TAGS: + + RT_MINVAL - Minumum value the user can insert. + + RT_MAXVAL - Maximum value the user can insert. + + RT_NUM - Default number (please, use RT_DEFVAL). + + RT_DEFVAL - Default value in the Number requester. + + FONT REQUESTER TAGS: + + RT_FONTNAME - Default font name. + + RT_FONTSIZE - Default font size. + + RT_FONTFLAGS - Flags for the font requester. See reqtools.library + documentation for further info. + + RT_FONTSTYLE - Font style requester flags. See reqtools.library + documentation for further info. + + SCREEN MODE REQUESTER TAGS: + + RT_SCRID - Default Screen ID. + + RT_SCRWIDTH - Default Screen width. + + RT_SCRHEIGHT - Default Screen height. + + RT_SCRDEPTH - Default Screen depth. + + RT_SCROSCAN - Default Screen Overscan flag (TRUE/FALSE). + + RT_SCRASCROLL - Default Screen AutoScroll flag (TRUE/FALSE). + + PALETTE REQUESTER TAGS: + + RT_COLOR - Default selected color. + + NOTE: all these tags can be set also when you invoke a @{" req() " LINK "ReqTooller_req"} method. + + RESULTS: + + SEE ALSO: @{" get() " LINK "ReqTooller_get"} + @{" req() " LINK "ReqTooller_req"} +@endnode + +@node "ReqTooller_get" "Amiga Foundation Classes: ReqTooller / get()" + + NAME: get(tagname) + + DESCRIPTION: Use this method to get avaible values from the class. + + INPUT: tagname - Tag indicating the value you want. + Avaible value are: + + COMMOND TAGS: + + RT_TITLE - Returns default title. + + + FILE REQUESTER TAGS: + + RT_PATH - Returns actual path. + + RT_FILENAME - Return actual file name. + + + MULTIFILE REQUESTER TAGS: + + RT_MULTIFIRST - First file name selected by the user. + + RT_MULTINEXT - Next file name selected by the user. + + + FONT REQUESTER TAGS: + + RT_FONTNAME - Font name choosen by the user. + + RT_FONTSIZE - Font size choosen by the user. + + RT_FONTSTYLE - Font style choosen by the user. + + RT_FONTFLAGS - Font flags choosen by the user. + + + SCREEN REQUESTER TAGS: + + RT_SCRID - Screen Display ID value. + + RT_SCRWIDTH - Screen width. + + RT_SCRHEIGHT - Screen height. + + RT_SCRDEPTH - Screen depth. + + RT_SCROSCAN - Screen overscan value. + + RT_SCRASCROLL - Screen auto scroll. + + + STRING REQUESTER TAGS: + + RT_STRING - User inserted string. + + + NUMBER REQUESTER TAGS: + + RT_NUM - User inserted value. + + + PALETTE REQUESTER TAGS: + + RT_COLOR - User selected color. + + + RESULTS: the requested value is returned. + + SEE ALSO: @{" setattrs() " LINK "ReqTooller_SetAttrs"} + @{" req() " LINK "ReqTooller_Req"} + +@endnode + +@node "ReqTooller_req" "Amiga Foundation Classes: ReqTooller / req()" + + NAME: req(type, tags=NIL:PTR TO LONG) + + DESCRIPTION: This method opens a requester. + + INPUT: type - Type of requester. Avaible values: + + RTREQ_FILE - File requester. + + RTREQ_SAVE - Save file requester. + + RTREQ_PATH - Path requester. + + RTREQ_VOLUMES - Volumes requester. + + RTREQ_MULTI - Multi file requester. + + RTREQ_FONT - Font requester. + + RTREQ_COLFONT - Color font requester. + + RTREQ_SCREEN - Screen requester. + + RTREQ_ALLSCREEN - Screen requester showing ALL avaible screens + (also HAM and EHB modes). + + RTREQ_STRING - String requester. + + RTREQ_NUMBER - Number requester. + + RTREQ_EASY - Easy Requester. + + RTREQ_PALETTE - Palette requester. + + RTREQ_MESSAGE - Message requester. This is a very special + requester. It does not have *any* gadget: + you have to mind about opening and closing it. + This is just like an Easy requester, but with + no gadgets, so all the Easy requester tags will + work. + To close this requester, open a RTREQ_MESSAGE + with no text. + Example: + + req(RTREQ_MESSAGE, [RT_TEXT, 'Hi world!',0,0]) + Delay(100) + req(RTREQ_MESSAGE, [RT_TEXT, '',0,0]) + + RESULTS: this method returns the same thing that the corresponding + reqtools' requester should return. So, for example, the EasyRequester + returns the ordinal number of the pressed gadget. + + SEE ALSO: @{" setattrs() " LINK "ReqTooller_setattrs"} + @{" get() " LINK "ReqTooller_get"} +@endnode + +@node "ReqTooller_version" "Amiga Foundation Classes: ReqTooller / version()" + + NAME: version() + + DESCRIPTION: This method returns class version AND revision. + + INPUT: NONE. + + RESULTS: This method returns *two* values: version and revision. + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/StringNode.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/StringNode.guide new file mode 100644 index 0000000..80374bd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/StringNode.guide @@ -0,0 +1,520 @@ +@database StringNode.guide + +@$VER: StringNode V3.10 - By Fabio Rotondo (C)Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node "Main" "Amiga Foundation Classes Module: StringNode" + + + + ** StringNode_OO V3.0 - Original By Fabio Rotondo ** + + Part of The Amiga Foundation Classes + + @{" Introduction " link "StringNode_introduction" } @{" Author's Infos " link "author" } @{" Amiga Foundation Classes " LINK "afc.guide/main"} + + + Requires: @{" NodeMaster_oo " LINK "NodeMaster.guide/main"} + + Base: $0002 + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" stringnode() " link "StringNode_StringNode" } Initailizes the object + @{" add(string, mode) " link "StringNode_add" } Add a new string to the list + @{" addr() " link "StringNode_addr"} Returns memory address of the list + @{" change(string) " link "StringNode_change" } Changes the current object string + @{" clear() " link "StringNode_clear"} Free all strings in list + @{" del() " link "StringNode_del"} Deletes a string from the list + @{" empty() " link "StringNode_empty"} Checks for empty list + @{" first() " link "StringNode_first"} Pos on the first string in the list + @{" insert(string) " link "StringNode_insert" } Inserts a new string AFTER the current one + @{" item(num) " link "StringNode_item"} Pos on a specific item + @{" last() " link "StringNode_last"} Pos on the last String in the list + @{" numitems() " link "StringNode_numitems"} Returns the number of strings in the list + @{" obj() " link "StringNode_obj" } Returns the current string. + @{" pop(pos=TRUE) " link "StringNode_pop"} Pops to the current stacked string + @{" pos() " link "StringNode_pos"} Returns numeric position of a string in the list + @{" prev() " link "StringNode_prev"} Pos on the previous string in the list + @{" push() " link "StringNode_push"} Pushes current string in the stack + @{" search(string, fromhere=FALSE) " link "StringNode_search" } Search for a specific string + @{" setattrs(taglist) " link "StringNode_setattrs" } Change StringNode's behaviours + @{" sort(nocase=FALSE, inverted=FALSE) " link "StringNode_sort" } Sort All Items By Name + @{" succ() " link "StringNode_succ"} Pos on the next string in the list + @{" version() " link "StringNode_version"} Returns Class version + + @{" Tags Table " LINK "StringNode_tagstable" } + + @{" Error Table " LINK "StringNode_errortable"} + +@endnode + +@node "stringnode_introduction" "StringNode Introduction" + + StringNode is a object to handle lists of strings. + + These lists are standard Exec lists and all handling functions are +inherited by the ROOTCLASS NodeMaster_oo. But StringNode has some unique +features to handle correctly strings without memory loss or something like +that. You will also have the method "addr()" to get a pointer to the List so +you can easily add a list of items to a ListView gadget! + + Main features are: + + * Very Fast String Sorting Algorithm. + + * Very Flexible String Sorting Algo: + + - case (in)sensitive + - from a...z or z...a + + * Search routines use AmigaDOS MatchNoPattern() functions! + + - You can do searches with patterns like: + + "#?.IN#?" or "~(#?.INFO)" !!! + + * Return Raise() errors! + +NEW V2.10 features: + + * Enhanced search() method: now it updates also numeric pos! + + * Enhanced sort() method: now it is 60% faster than the original! + + * Enhanced change() method: now allows less memory fragmentation. + + * Added a new (and expandible) method: setattrs(). + + NOTE: a very big THANK YOU must go to Andrea Galimberti aka Kronos + for helping me in creating a new and fast sort() method!!! + +V3.00 features: + + * Restructured code. + + * Implemented new NodeMaster sort() method + + * Optimized code + + * Now StringNode is part of Amiga Foundation Classes + +@endnode + +@node "StringNode_tagstable" "Amiga Foundation Classes Modules: StringNode/TAGS TABLE" + TAG NAME | VALUES(DEFAULT) | DESCRIPTION +-----------------+---------------------+------------------------------------- +TAGSTR_MAXCHARS | 0..32768 (128) | Max number of chars to leave unused. +@endnode + +@node "StringNode_ErrorTable" "Amiga Foundation Classes Modules: StringNode/Error Table" +ERROR CODE | DESCRIPTION +-----------------+----------------------------------------------------------- + $0000 | No Memory +@endnode + +@node author "Author(s) Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) +@endnode + +@node "stringnode_stringnode" "StringNode_oo/stringnode()" + NAME: stringnode() + + DESCRIPTION: Use this command to initialize the object. + + INPUT: NONE + + RESULTS: NONE. + + NOTE: Starting from V2.10 TAGSTR_MAXCHARS value is set to 128. + Please, refer to @{" change() " LINK "StringNode_change" } and @{" setattrs() " LINK "StringNode_setattrs" } methods. + + SEE ALSO: @{" change() " LINK "StringNode_change" } + @{" setattrs() " LINK "StringNode_setattrs" } + + @{" NodeMaster/change() " LINK "NodeMaster.guide/NodeMaster_change"} +@endnode + +@node StringNode_add "Amiga Foundation Classes Modules: StringNode/add()" + NAME: add(string:PTR TO CHAR) + + DESCRIPTION: Use this command to add a string to the list. + + INPUT: string - PTR TO CHAR, the string you wish to add. + + RESULTS: a PTR to String - No errors. + a Raise()d exception - Possible problems. + + SEE ALSO: @{" NodeMaster/add() " LINK "NodeMaster.guide/NodeMaster_add"} +@endnode + +@node StringNode_insert "Amiga Foundation Classes Modules: StringNode/insert()" + NAME: insert(string:PTR TO CHAR) + + DESCRIPTION: Use this command to add a string AFTER the current one. + + INPUT: string - PTR TO CHAR. String to insert. + + RESULTS: a PTR to String - No Errors. + a Raise()d exception - Problems. + + SEE ALSO: @{" NodeMaster/insert() " LINK "NodeMaster.guide/NodeMaster_insert"} +@endnode + +@node StringNode_obj "Amiga Foundation Classes Modules: StringNode/obj()" + NAME: obj() + + DESCRIPTION: This command returns the current node string. + + INPUT: NONE. + + RESULTS: A PTR TO CHAR to the current node string. + + SEE ALSO: @{" NodeMaster/obj() " LINK "NodeMaster.guide/NodeMaster_obj"} +@endnode + +@node "StringNode_first" "Amiga Foundation Classes Modules: StringNode/first()" + NAME: first() + + DESCRIPTION: This method pos the class to the first String in the list. + + INPUT: NONE + + RESULTS: a PTR to String - first() succeded. + + NIL - first() failed. (Maybe list is empty) + + SEE ALSO: @{" NodeMaster/first() " LINK "NodeMaster.guide/NodeMaster_first"} + +@endnode + +@node "StringNode_succ" "Amiga Foundation Classes Modules: StringNode/succ()" + NAME: succ() + + DESCRIPTION: This method pos the class to the next String in the list. + + INPUT: NONE + + RESULTS: a PTR to String - succ() succeded. + + NIL - succ() failed. (We are on the last item) + + SEE ALSO: @{" NodeMaster/succ() " LINK "NodeMaster.guide/NodeMaster_succ"} + +@endnode + +@node "StringNode_prev" "Amiga Foundation Classes Modules: StringNode/prev()" + NAME: prev() + + DESCRIPTION: This method pos the class to the previous String in the list. + + INPUT: NONE + + RESULTS: a PTR to String - prev() succeded. + + NIL - prev() failed. (We are on the first item.) + + SEE ALSO: @{" NodeMaster/prev() " LINK "NodeMaster.guide/NodeMaster_prev"} + +@endnode + +@node "StringNode_push" "Amiga Foundation Classes Modules: StringNode/push()" + NAME: push() + + DESCRIPTION: This method pushes current string on the stack. + + INPUT: NONE + + RESULTS: TRUE - push() succeded. + + FALSE - push() failed. (Stack is full) + + SEE ALSO: @{" pop() " LINK "StringNode_pop"} + + @{" NodeMaster/push() " LINK "NodeMaster.guide/NodeMaster_push"} +@endnode + +@node "StringNode_pop" "Amiga Foundation Classes Modules: StringNode/pop()" + NAME: pop(pos=TRUE) + + DESCRIPTION: This method pops a stacked String. + + INPUT: pos - (default = TRUE) if pos is set to TRUE, the StringNode + class focuses on the pop()ed string, if it is set to + FALSE, then the current stack String is just freed. + + RESULTS: a PTR to String - pop() succeded. + + NIL - pop() failed or pos=FALSE. + + SEE ALSO: @{" push() " LINK "StringNode_push"} + + @{" NodeMaster/pop() " LINK "NodeMaster.guide/NodeMaster_pop"} + +@endnode + +@node "StringNode_addr" "Amiga Foundation Classes Modules: StringNode/addr()" + NAME: addr() + + DESCRIPTION: This method returns a PTR to the list allocated by StringNode. + + INPUT: NONE + + RESULTS: a PTR to an Exec List. + + NOTE: This function CANNOT fail: you should not be able to do an addr() + if the list isn't allocated because the object should raise an + exception during initialization. + + SEE ALSO: @{" NodeMaster/addr() " LINK "NodeMaster.guide/NodeMaster_addr"} + +@endnode + +@node "StringNode_del" "Amiga Foundation Classes Modules: StringNode/del()" + NAME: del() + + DESCRIPTION: This method deletes current String in the list. + + INPUT: NONE + + RESULTS: a PTR to next avaible string or NIL if list is empty. + + NOTE: This method "moves" inside the list in a particular way: + if you are deleting a string which is NOT the last, then + StringNode will pos to the next item, if it was the last, + it tries to move to the previous String, if nothing is + avaible, then it returns NIL. + + SEE ALSO: @{" NodeMaster/del() " LINK "NodeMaster.guide/NodeMaster_del"} + +@endnode + +@node "StringNode_empty" "Amiga Foundation Classes Modules: StringNode/empty()" + NAME: empty() + + DESCRIPTION: This method checks whether the list is empty or not. + + INPUT: NONE + + RESULTS: TRUE - List is empty + FALSE - At least one item is present + + SEE ALSO: @{" NodeMaster/empty() " LINK "NodeMaster.guide/NodeMaster_empty"} + +@endnode + +@node StringNode_change "Amiga Foundation Classes Modules: StringNode/change()" + NAME: change(string:PTR TO CHAR) + + DESCRIPTION: Use this command to change the current node string. + + INPUT: string - PTR TO CHAR, the new string you wish to replace + the existing one. + + RESULTS: a PTR to String - No Errors + a Raise()d exception - Memory problems. + + NOTE: Starting from V2.10, this method behaves quite differently + than before, to allow better control towards memory + fragmentation's problems. Now, before DisposeLink() + and do a new String(), change() checks whether or not the + new string passed to it would fit inside the current memory + area and how many bytes should be left unused. If they are + less than TAGSTR_MAXCHARS (Default is 128), the string is not + Disposed() and created again. Of course, if the new string is + bigger than the original, a new string is created. + + + SEE ALSO: @{" NodeMaster/change() " LINK "NodeMaster.guide/NodeMaster_change"} + @{" setattrs() " LINK "StringNode_setattrs" } +@endnode + +@node "StringNode_clear" "Amiga Foundation Classes Modules: StringNode/clear()" + NAME: clear() + + DESCRIPTION: This method clear all Strings in the list. + + INPUT: NONE + + RESULTS: the StringNode will be freed. + + SEE ALSO: @{" NodeMaster/clear() " LINK "NodeMaster.guide/NodeMaster_clear"} + +@endnode + +@node "StringNode_numitems" "Amiga Foundation Classes Modules: StringNode/numitems()" + NAME: numitems() + + DESCRIPTION: This method returns the number of Strings inside the list. + + INPUT: NONE + + RESULTS: a LONG containing the number of Strings in the list. + + NOTE: if the list is empty, this method returns 0. + + SEE ALSO: @{" NodeMaster/numitems() " LINK "NodeMaster.guide/NodeMaster_numitems"} + +@endnode + +@node "StringNode_item" "Amiga Foundation Classes Modules: StringNode/item()" + NAME: item(num) + + DESCRIPTION: This method to pos StringNode to the specific ordinal + String in the list. + + INPUT: num - LONG. Ordinal value of String position in the list. + + RESULTS: a PTR to CHAR - item() succeded. + + NIL - item() failed. + + NOTE: If num is greater than current items in the list, StringNode + will pos on the last item. + + SEE ALSO: @{" numitems() " LINK "StringNode_numitems"} + + @{" NodeMaster/item() " LINK "NodeMaster.guide/NodeMaster_item"} +@endnode + +@node "StringNode_last" "Amiga Foundation Classes Modules: StringNode/last()" + NAME: last() + + DESCRIPTION: This method pos StringNode on the last String in the list. + + INPUT: NONE. + + RESULTS: a PTR to CHAR - last() succeded. + + NIL - list is empty. + + SEE ALSO: @{" first() " LINK "StringNode_first"} + @{" item() " LINK "StringNode_item"} + + @{" NodeMaster/last() " LINK "NodeMaster.guide/NodeMaster_last"} + +@endnode + +@node "StringNode_pos" "Amiga Foundation Classes Modules: StringNode/pos()" + NAME: pos() + + DESCRIPTION: This method returns the numberic (ordinal) position + of the String in the list. + + INPUT: NONE + + RESULTS: a LONG value containing the ordinal position of the String + in the list. + + NOTE: If the StringNode is empty, this method returns 0. + + SEE ALSO: @{" item() " LINK "StringNode_item"} + + @{" NodeMaster/numpos() " LINK "NodeMaster.guide/NodeMaster_numpos"} + +@endnode + +@node "StringNode_search" "Amiga Foundation Classes Modules: StringNode/search()" + NAME: search(string:PTR TO CHAR, fromhere=FALSE) + + DESCRIPTION: Use this command to scan the list looking for a specific + string inside the node. + + INPUT: string - PTR TO CHAR. Pattern string to search. + (Standard AmigaDOS match patterns) + + fromhere - A BOOL value. + TRUE = Scan starting from current node. + FALSE = Scan starting from the first node. + + RESULTS: a PTR to String - Searching successful. + FALSE - Nothing found. + + + NOTES: * Search is NOT case sensitive. + + * Search support AmigaDOS MatchNoCase() functions. + So you can create Pattern String such as: + + "#?.INFO" or "~(#?.info)" and so on. + + * Search will position the current node to a valid value + IF Search() fails, the current node will not change. + + SEE ALSO: +@endnode + +@node "StringNode_setattrs" "Amiga Foundation Classes Modules: StringNode/setattrs()" + NAME: setattrs(tags:PTR TO LONG) + + DESCRIPTION: Use this command to change the way stringnode works. + At the moment just ONE single tag has been implemented, + but they'll grow as soon as new needs will raise. + + INPUT: setattrs - This is a list of tags. + Please, refer to @{" TAGS TABLE " LINK "StringNode_TagsTable" } + to know what tags are implemented. + + RESULTS: NONE. + + NOTE: REMEMBER TO END THE LIST WITH TAG_END or 0!!! + + SEE ALSO: @{" change() " LINK "StringNode_change" } + @{" Tags Table " LINK "StringNode_tagstable" } +@endnode + +@node StringNode_sort "Amiga Foundation Classes Modules: StringNode/sort()" + NAME: sort(nocase=FALSE, inverted=FALSE) + + DESCRIPTION: Use this command to sort by name all items in a object. + + INPUT: nocase - (OPTIONAL) if you set this to TRUE, the sort will + be done without case sense (but it is slower...) + + inverted - (OPTIONAL) if you set this to TRUE, the sort will + be done hight to low and not low-2-high as + default. + + RESULTS: The list will be completely sorted up. + + SEE ALSO: @{" NodeMaster/sort() " LINK "NodeMaster.guide/NodeMaster_sort"} +@endnode + +@node "StringNode_version" "Amiga Foundation Classes Modules: StringNode/version()" + NAME: version() + + DESCRIPTION: This method returns StringNode version and revision values. + + INPUT: NONE + + RESULTS: this method returns TWO values, version and revision. + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Tasker.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Tasker.guide new file mode 100644 index 0000000..59f8633 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Tasker.guide @@ -0,0 +1,452 @@ +@database Tasker.guide + +@$VER: Tasker V1.02 - by Andrea Galimberti - (C) Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node main "AFC Module: tasker/Main" + + + ** Tasker V1.02 - Original By Andrea Galimberti ** + + Part of Amiga Foundation Classes + + + + + @{" Introduction " LINK task_intro} @{" Author(s) Info " LINK author} + + + Requires: + + Base: $8004 + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + @{" tasker() " LINK tasker} Initialises the object + @{" code() " LINK task_code} Selects the task code + @{" stack() " LINK task_stack} Sets the task stack dimension + @{" start() " LINK task_start} Starts a TASK + @{" stop() " LINK task_stop} Stops a task or a process + @{" process() " LINK task_process} Starts a PROCESS + @{" buildport() " LINK task_buildport} Creates a port for the TASK + @{" endport() " LINK task_endport} Kills the task message port + @{" port() " LINK task_port} Returns the task port + @{" dosport() " LINK task_dosport} Returns the process DOS port + @{" send() " LINK task_send} Sends a message to the task + @{" dossend() " LINK task_dossend} Sends a message to the process' DOS port + @{" version() " LINK task_version} Returns tasker version + + Procedures: + + @{" storea4() " LINK t_storea4} Stores the E global data pointer + @{" geta4() " LINK t_geta4} Gets the E global data pointer + @{" buildPort() " LINK t_buildport} Creates a message port + @{" endPort() " LINK t_endport} Kills a message port + @{" setupMsg() " LINK t_setupmsg} Prepares a message to be sent + @{" sendMsg() " LINK t_sendmsg} Safely sends a message to a port + + + @{" ERROR TABLE " LINK Error_Table} + +@endnode + +@node author "Author(s) Info" + + Original By: Andrea Galimberti + + E Version By: Andrea Galimberti + + +@endnode + +@node task_intro "Tasker / Introduction" + + Tasker. + + + This module allows you to transform a procedure in an independent task +that runs asynchronously to the main program. You can choose if you want +to start a task or a process, and how big the task's stack must be, and so +on... A task can also be terminated by the main program. Instructions are +also supplied to create message ports to communicate between the main +program and the tasks. + + Remember: a TASK cannot access disks and, in general, all resources +managed by the dos.library, while a PROCESS can. Tasks and processes share +with the main program only variables that have been defined as global. + +@endnode + +@node Error_Table "Tasker / Error Table" + +Val (Hex) | Description +-----------+------------------------------------------------------ + $0000 | No Memory + $0001 | Cannot get E code for the task + $0002 | Cannot start the task + $0003 | Cannot start the process + $0004 | Cannot create the message port + +@endnode + +@node t_storea4 "procedure / storea4()" + + NAME: storea4() + + DESCRIPTION: memorizes the E global data pointer. You MUST call this + procedure (only once) at the beginning of your main program + before you start any process or task. Then, in the task body, + you MUST call the @{"geta4()" LINK t_geta4} procedure before accessing any + global variable or calling a procedure. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" geta4() " LINK t_geta4} + +@endnode + +@node t_geta4 "procedure / geta4()" + + NAME: geta4() + + DESCRIPTION: gets the E global data pointer. You MUST call this + procedure in the body of your process or task before you + access any global variable or call a procedure. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" storea4() " LINK t_storea4} + +@endnode + +@node tasker "AFC module: tasker / tasker()" + + NAME: tasker(name, kill=TRUE) + + DESCRIPTION: this method creates a task object: name is the name + (possibly unique) the task will have when started. Some + values are set to their defaults: the stack allocated for + the task will be of 4000 bytes if not specified with the + @{"stack()" LINK task_stack} method. + If the kill flag is TRUE then the task (or process) will + be stopped and its port (if it has been created with + @{"buildport()" LINK task_buildport}) will be closed when the tasker object + is disposed; if the kill flag is FALSE then it's your duty + to close the port (with @{"endport()" LINK task_endport}) and @{"stop()" LINK task_stop} the task + before disposing of the object. + + INPUTS: name: name of the task. + kill: if TRUE the task and its port are killed before + disposing the object + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node task_code "AFC module: tasker / code()" + + NAME: code(procedure) + + DESCRIPTION: chooses the code that will be executed when the task is + started. + + INPUTS: procedure is the ADDRESS of the procedure you want to start + as a separate task. + + RESULTS: NONE + + SEE ALSO: @{" start() " LINK task_start} + +@endnode + +@node task_stack "AFC module: tasker / stack()" + + NAME: stack(bytes) + + DESCRIPTION: with this method you enter the dimension of the stack (in + bytes) to be allocated when the task is started. + + INPUTS: the dimension in bytes of the task's stack: this defaults + to the value of 4000 bytes. + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node task_start "AFC module: tasker / start()" + + NAME: start(priority=0) + + DESCRIPTION: starts a TASK. The task ends if stopped with the @{"stop()" LINK task_stop} + method, or if the task object is ENDed, or if the task code + terminates its job. + + INPUTS: the priority of the task: default is 0 (normal priority). + + RESULTS: raises an exception if it's not been able to create the + task. (see @{"Error Table" LINK Error_Table}) + + SEE ALSO: @{" stop() " LINK task_stop} + +@endnode + +@node task_process "AFC module: tasker / process()" + + NAME: process(priority=0) + + DESCRIPTION: starts a PROCESS: remember that a process is a task that + can access the Dos resources (e.g., drives) because it is + managed by the dos.library. The process' code and stack are + entered with the same methods used with tasks. + The process ends when it has finished its job (just as + any other program does), or when it is stopped with the + @{"stop()" LINK task_stop} method, or when the tasker associated with it is + ENDed. + + INPUTS: priority of the process: default is 0. + + RESULTS: raises an exception if it cannot create the process. + (see @{"Error Table" LINK Error_Table}) + + SEE ALSO: @{" code() " LINK task_code} + @{" stack() " LINK task_stack} + @{" stop() " LINK task_stop} + + Important: see @{" storea4() " LINK t_storea4} + @{" geta4() " LINK t_geta4} + +@endnode + +@node task_stop "AFC module: tasker / stop()" + + NAME: stop() + + DESCRIPTION: terminates the TASK: Exec will remove the task from its + list and will automatically deallocate the task's stack. + Remember that you have to free yourself all resources you + have allocated for this task. The task object is not + modified, so you can start again the same task by calling + the @{"start()" LINK task_start} method once again. + This works also with a process (only you call the + @{"process()" LINK task_process} method to restart it). + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" start() " LINK task_start} + +@endnode + +@node task_buildport "AFC module: tasker / buildport()" + + NAME: buildport(name=NIL, priority=0) + + DESCRIPTION: this method creates a message port associated with the + task. Important: the port is associated to the task that + created it, so make sure that this method is called by the + procedure that constitutes the task, not by the main + program. + If you supply a name the port will be made public, and in + such a case you can even choose the priority of your public + port. + + INPUTS: name: <>NIL if you want the port to be public + priority: only needed if the port is a public port. + + RESULTS: raises an exception if unable to create the port + (see @{"Error Table" LINK Error_Table}) + + SEE ALSO: @{" endport() " LINK task_endport} + +@endnode + +@node task_endport "AFC module: tasker / endport()" + + NAME: endport() + + DESCRIPTION: removes the task's message port created with @{"buildport()" LINK task_buildport}. + Remember to get all the messages (and to reply) before + ending the port (if you are sure that the port is empty you + needn't do this). The method cannot do it for you because + it can't know if the task that sent the message is still + present or not (replying to an unexisting task will cause a + guru). + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" buildport() " LINK task_buildport} + +@endnode + +@node task_port "AFC module: tasker / port()" + + NAME: port() + + DESCRIPTION: returns the address of the port created by @{"buildport()" LINK task_buildport}, + or NIL if the port doesn't exist. + + INPUTS: NONE + + RESULTS: the port address. + + SEE ALSO: @{" buildport() " LINK task_buildport} + +@endnode + +@node task_dosport "AFC module: tasker / dosport()" + + NAME: dosport() + + DESCRIPTION: returns the address of the port associated to the process: + this port is created by AmigaDOS when the process is + started and is reserved to exclusive use of AmigaDOS, so + you are invited to create your own port with the + @{"buildport()" LINK task_buildport} method if you need one. + + INPUTS: NONE + + RESULTS: the port address, or NIL if the task is not a process. + + SEE ALSO: @{" buildport() " LINK task_buildport} + +@endnode + +@node task_send "AFC module: tasker / send()" + + NAME: send(message) + + DESCRIPTION: sends an Exec message to the port created with the + @{"buildport()" LINK task_buildport} method. + + INPUTS: the message address. + + RESULTS: TRUE if message sent, otherwise FALSE. + + SEE ALSO: @{" buildport() " LINK task_buildport} + @{" port() " LINK task_port} + +@endnode + +@node task_dossend "AFC module: tasker / dossend()" + + NAME: dossend(message) + + DESCRIPTION: sends an Exec message to the port associated with the + process (the one created by and reserved to AmigaDOS). + + INPUTS: the message address. + + RESULTS: TRUE if message sent, otherwise FALSE. + + SEE ALSO: @{" dosport() " LINK task_dosport} + +@endnode + +@node task_version "AFC module: tasker / version()" + + NAME: version() + + DESCRIPTION: returns version and revision of tasker code. + + INPUTS: NONE + + RESULTS: version, revision + + SEE ALSO: + +@endnode + +@node t_buildPort "procedure / buildPort()" + + NAME: buildPort(name=NIL, priority=0) + + DESCRIPTION: creates a message port: this port will be associated to the + task that creates it. The port will be made public if you + supply a name for it. + + INPUTS: name: if <>NIL the port will be made public. + priority: only needed if the port is a public port. + + RESULTS: address of the port or NIL if failure. + + SEE ALSO: @{" endPort() " LINK t_endport} + +@endnode + +@node t_endport "procedure / endPort()" + + NAME: endPort(port) + + DESCRIPTION: kills a message port. Remember to get and reply to all + messages contained in the port before destroying it. + + INPUTS: port address + + RESULTS: NONE + + SEE ALSO: @{" buildPort() " LINK t_buildport} + +@endnode + +@node t_setupmsg "procedure / setupMsg()" + + NAME: setupMsg(message, sizeof, replyport=NIL) + + DESCRIPTION: after you have allocated the memory needed for your + message, you pass the message pointer to this procedure + specifying its size and the address of the port to which + the message must be replyed. The MessageNode part will be + filled; then, it's up to you to fill the extra information + you want to send within this message. Always remember to + free the memory allocated for the message before ending the + program. + Your message structure must be defined as follows: + + OBJECT mymessage + mnode:mn + . + . -> extra fields (your private datas) + . + ENDOBJECT + + INPUTS: message: pointer to message memory + sizeof: size of the message (e.g., SIZEOF mymessage) + replyport: port to which the message is to be replyed, or + NIL if an answer is not needed. + + RESULTS: the message pointer (the same you passed as first + parameter) or NIL if something went wrong. + + SEE ALSO: + +@endnode + +@node t_sendmsg "procedure / sendMsg()" + + NAME: sendMsg(message, port) + + DESCRIPTION: sends message to the port specified; if such a port is + public then the procedure checks if the port is still + present before sending anything + + INPUTS: message: pointer to the message to be sent + port: destination port + + RESULTS: TRUE if successful, otherwise FALSE + + SEE ALSO: @{" send() " LINK task_send} + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/ToolType.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/ToolType.guide new file mode 100644 index 0000000..edf66a0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/ToolType.guide @@ -0,0 +1,161 @@ +@database ToolType.guide + +@$VER: ToolType V1.00 - (C)Copyright Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: tooltype" + + + + ** ToolType - Original By Fabio Rotondo ** + + * Part of the Amiga Foundation Classes * + + @{" Introduction " link "ToolType_introduction"} @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} + + Requires: + + Class Base: $000E0000 + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" tooltype() " link "ToolType_tooltype"} Initailizes the class. + @{" file(programname) " link "ToolType_file"} Grabs an icon from a given file. + @{" get(tooltypename) " link "ToolType_get"} Gets a specific ToolType from the icon. + @{" match(tooltypename, value) " link "ToolType_match"} Compares a ToolType with the given value. + @{" version() " link "ToolType_version"} Returns tooltype version. + + @{" Error Table " LINK tooltype_ErrorTable} +@endnode + +@node "ToolType_Introduction" "Introduction" + + ToolType is a class to easyly manage icons tooltypes. + It is extremely easy to use and flexible: enjoy it! + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + +@endnode + +@node tooltype_ErrorTable "ToolType / Error Table " + +VALUE | DESCRIPTION +----------------+---------------------------------------------------- +$0000 | No Memory. +$0001 | Failed TO open "icon.library" (maybe wrong version) +$0002 | No valid WB Message +$0003 | File not found (the icon you are requiring does not exists) +$0004 | No Disk Icon (current program has no icon) +$0005 | Not a valid tool array structure + +@endnode + +@node "ToolType_tooltype" "Amiga Foundation Classes: tooltype/tooltype()" + + NAME: tooltype(grab=FALSE) + + DESCRIPTION: Use this method to initailize the object. + + INPUT: grab - If it is TRUE, tooltype will try to get + tooltypes from the icon the user clicked + to start the program. + + RESULTS: if any error, it can raise exceptions. + + SEE ALSO: +@endnode + +@node "ToolType_file" "Amiga Foundation Classes: tooltype/file()" + + NAME: file(programname:PTR TO CHAR) + + DESCRIPTION: Use this method to 'grab' tooltypes from a file. + + INPUT: file - the name of the program you wish to + read ToolTypes. + + RESULTS: if any error, it can raise exceptions. + + SEE ALSO: +@endnode + +@node "ToolType_get" "Amiga Foundation Classes: tooltype/get()" + + NAME: get(tooltypename:PTR TO CHAR) + + DESCRIPTION: Use this method to read the value of a specific + tooltype. + + INPUT: tooltypename - the name of the tooltype you want to + examine. + + RESULTS: a ptr to the returned value. + + FALSE means "ToolType" not found. + + SEE ALSO: @{" match() " LINK tooltype_match} +@endnode + +@node tooltype_match "Amiga Foundation Classes: tooltype/match()" + + NAME: match(tooltypename:PTR TO CHAR, value:PTR TO CHAR) + + DESCRIPTION: Use this method to check if a particular ToolType is + set to a specific value. + + INPUT: tooltypename - Name of the ToolType to examine. + + value - Value to match with. + + + RESULTS: TRUE - Matching successfull + + FALSE - Otherwise. + + EXAMPLE: match('CYBERGRAPHX', 'TRUE') + + SEE ALSO: @{" get() " LINK tooltype_get} +@endnode + +@node "ToolType_version" "Amiga Foundation Classes: tooltype/version()" + + NAME: version() + + DESCRIPTION: This method returns class version and revision. + + INPUT: NONE. + + RESULTS: This method returns TWO values, Version and Revision. + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Worldbuilder.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Worldbuilder.guide new file mode 100644 index 0000000..479a5ff --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/Worldbuilder.guide @@ -0,0 +1,1457 @@ +@database Worldbuilder.guide + +@$VER: Worldbuilder V1.00 - by Andrea Galimberti - (C) Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node main "AFC Module: Worldbuilder / Main" + + + ** Worldbuilder V1.00 - Original By Andrea Galimberti ** + + Part of Amiga Foundation Classes + + + @{" Introduction " LINK world_intro} Important: don't skip this as usual. + @{" Author(s) Info " LINK author} + + + Requires: @{" nodemaster " LINK "nodemaster.guide/Main"} + + Base: $8005 + + Sections: @{" Worldbuilder methods " LINK world_methods} + @{" Object_obj methods " LINK world_o_methods} + @{" Procedures " LINK world_procedures} + + + @{" ERROR TABLE " LINK Error_Table} +@endnode + +@node world_methods "AFC module: Worldbuilder methods" + + Worldbuilder methods: + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + + @{" worldbuilder() " LINK worldbuilder} Initializes a world + + @{" addobj() " LINK world_addobj} Create and add an object + @{" setobj() " LINK world_setobj} Only add an existing object + @{" getobj() " LINK world_getobj} Get a specified object + @{" delobj() " LINK world_delobj} Delete object + @{" unlinkobj() " LINK world_unlinkobj} Remove an object + @{" clearobj() " LINK world_clearobj} Clear an object + + @{" setvertex() " LINK world_setvertex} Add vertex to object + @{" getvertex() " LINK world_getvertex} Get vertex of object + @{" fastsetvert() " LINK world_fastsetvert} Fast add vertex + @{" delvertex() " LINK world_delvertex} Delete vertex from object + + @{" setline() " LINK world_setline} Add line to object + @{" getline() " LINK world_getline} Get line from object + @{" fastsetline() " LINK world_fastsetline} Fast add line + @{" delline() " LINK world_delline} Delete line from object + + @{" setsurface() " LINK world_setsurface} Add surface to object + @{" getsurface() " LINK world_getsurface} Get surface from object + @{" delsurface() " LINK world_delsurface} Delete surface from object + + @{" visible() " LINK world_visible} Switch on and off an object + @{" position() " LINK world_position} Move local axes of an object + @{" scale() " LINK world_scale} Scale an object + @{" applyobj() " LINK world_applyobj} Apply transformations to an object + + @{" projection() " LINK world_projection} 3D -> 2D conversion + @{" getpoint() " LINK world_getpoint} Get projected pixel + @{" draw() " LINK world_draw} Draw wireframe (or points) + @{" init3D() " LINK world_init3d} Initialise filled vectors + @{" drawfill() " LINK world_drawfill} Draw filled vectors + + @{" copyobj() " LINK world_copyobj} Copy two objects + @{" cloneobj() " LINK world_cloneobj} Duplicate an object + + @{" setobserver() " LINK world_setobserver} Position observer + @{" setscale() " LINK world_setscale} Scale all objects + @{" settrasl() " LINK world_settrasl} Traslate all objects + @{" setrot() " LINK world_setrot} Rotate all objects + @{" setafterscale() " LINK world_setafterscale} Scale to fit screen + @{" setaftertrasl() " LINK world_setaftertrasl} Traslate origin of axes + @{" setdisplay() " LINK world_setdisplay} Set display features + + @{" version() " LINK world_version} Version of Worldbuilder + +@endnode + +@node world_o_methods "AFC module: Object_obj methods" + + Object_obj methods: + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + + @{" object_obj() " LINK object_obj} Initializes an object + @{" clear() " LINK object_clear} Clear object + + @{" name() " LINK object_name} Return object name + + @{" setvertex() " LINK object_setvertex} Add vertex + @{" getvertex() " LINK object_getvertex} Get vertex + @{" fastsetvert() " LINK object_fastsetvert} Fast add vertex + @{" delvertex() " LINK object_delvertex} Delete vertex + + @{" setline() " LINK object_setline} Add line + @{" getline() " LINK object_getline} Get line + @{" fastsetline() " LINK object_fastsetline} Fast add line + @{" delline() " LINK object_delline} Delete line + + @{" setsurface() " LINK object_setsurface} Add surface + @{" getsurface() " LINK object_getsurface} Get surface + @{" delsurface() " LINK object_delsurface} Delete surface + + @{" position() " LINK object_position} Move local axes + @{" scale() " LINK object_scale} Scale object + @{" apply() " LINK object_apply} Apply transformations + + @{" projection() " LINK object_projection} Project single object + @{" getpoint() " LINK object_getpoint} Get projected pixel + + @{" copy() " LINK object_copy} Copy object + @{" clone() " LINK object_clone} Duplicate object + +@endnode + +@node world_procedures "AFC module: Procedures" + + Procedures: + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + + @{" fillSinTable() " LINK world_fillsintable} Initialize table of sines + @{" limitangle() " LINK world_limitangle} Bound angle (0 - 360 degrees) + @{" crossprod() " LINK world_crossprod} Vector product + @{" dotprod() " LINK world_dotprod} Scalar product + +@endnode + +@node author "Author(s) Info" + + Original By: Andrea Galimberti + + E Version By: Andrea Galimberti + +@endnode + +@node world_intro "AFC module: Worldbuilder / Introduction" + + + Worldbuilder + ------------ + + This Class contains instructions to create, manipulate and draw three +dimensional objects: they can be rotated, scaled and drawn in a wireframe +and in a filled vector mode; at any time you can add, remove or modify +vertices, lines and surfaces, the system keeping track automatically of +your changes. + + + @{" The objects " LINK world_i_objects} + @{" Lines and surfaces " LINK world_i_lines} + @{" The coordinate system " LINK world_i_coords} + +@endnode + +@node world_i_objects "AFC module: Introduction / objects" + + Two are the objects contained in this class: worldbuilder and object_obj. +The latter represents a single 3D object containing its description in +terms of position of vertices, lines and/or surfaces. The former +represents the world in which to insert the objects before they are +rendered. You have to keep in mind this: objects can be manipulated and +drawn on the screen only when they are in a worldbuilder, because it's the +worldbuilder that contains notions as rotation, traslation, scaling and +observer position. + + The methods are accordingly divided in two sets: one pertaining to the +worldbuilder and one to the object_obj. Most of the methods of the two sets +share the same name, because they do exactly the same thing: the method of +worldbuilder acts on objects already linked to that world, while the +corresponding method of object_obj acts on the single object. + But why this division can be useful? I must say that you're invited to +use only the methods of worldbuilder (because otherwise, as I said before, +objects cannot be rendered), but perhaps you may want to keep your own +database of objects and link them to a worldbuilder only when needed, and this +is where the methods of object_obj come into play. + +@endnode + +@node world_i_lines "AFC module: Introduction / lines and surfaces" + + An object_obj contains vertices, lines and surfaces. No doubt you have +to define vertices before defining anything else, but you haven't to define +lines before surfaces: these two structures are independent but, anyway, +they aren't mutually exclusive. You need lines if you render the world in +wireframe; otherwise, if you use the filled vector mode you need only +surfaces. + +@endnode + +@node world_i_coords "AFC module: Introduction / coordinate system" + + There's always a weird (for physicists) peculiarity in the coordinate +system of a computer world: unfortunately it's left-handed. The three +axes are directed as follows: + + y + ^ _ z + | /| + | / + | / + |/ + |-----------> x + 0 + +(obviuosly, negative coordinate values are allowed). + +@endnode + +@node Error_Table "AFC module: worldbuilder / Error Table" + +Val (Hex) | Description +-----------+------------------------------------------------------ + $0000 | No Memory + $0001 | AreaInfo not available in init3D() + $0002 | TempRas not available in init3D() + $0003 | Vector buffer not available in init3D() + $0004 | Extra bitplane not available in init3D() + +@endnode + +@node object_obj "AFC module: object_obj / object_obj()" + + NAME: object_obj(name) + + DESCRIPTION: creates an object_obj with name 'name'. The name + parameter is necessary because all objects in a worldbuilder + are addressed with their names. + Objects cannot be rendered independently outside a world; + the object_obj methods are supplied to manipulate single + objects e.g. for storing purposes: you can, for example, + create a database of objects and then link to an + initialized worldbuilder only the ones you actually need. + To link an already existing object to a worldbuilder you use + the @{"worldbuilder / setobj()" LINK world_setobj} method; alternatively you can + directly create and add an object to a world in one step by + calling the @{"worldbuilder / addobj()" LINK world_addobj} method. + + INPUTS: name of the object to be crated (max 30 chars). + + RESULTS: NONE + + SEE ALSO: @{" worldbuilder / addobj() " LINK world_addobj} + @{" worldbuilder / setobj() " LINK world_setobj} + +@endnode + +@node object_clear "AFC module: object_obj / clear()" + + NAME: clear() + + DESCRIPTION: clears all object's contents (except its name). + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" worldbuilder / clearobj() " LINK world_clearobj} + +@endnode + +@node object_setvertex "AFC module: object_obj / setvertex()" + + NAME: setvertex(num, x, y, z) + + DESCRIPTION: if 'num' is greater than the number of vertices of the + object, then a new vertex is added to the object at the + last position (independently of its number); so you cannot + leave holes e.g. by adding vertex 4 and then vertex 10: + in this case vertex 10 enters in position number 5. + + This underlines one thing you have to care about: + vertices have NOT a fixed number; their number it's their + position in the list (for speed reasons). Usually the + module takes care of this automatically, but you must + remember it when you delete a vertex. + + If 'num' is an already attached vertex, then this + instruction modifies the coordinates of that vertex. + + Vertex numbers start from 0 (just like array elements). + + INPUTS: num: number of the vertex + x, y, z: coordinates of the vertex. + + RESULTS: FALSE if num<0, otherwise the number of vertices currently + in object. + + SEE ALSO: @{" fastsetvert() " LINK object_fastsetvert} + @{" worldbuilder / setvertex() " LINK world_setvertex} + +@endnode + +@node object_getvertex "AFC module: object_obj / getvertex()" + + NAME: getvertex(num) + + DESCRIPTION: if num is a valid vertex number (that is to say in the + range [0 - ((number of vertices of the object)-1)]), this + call returns a pointer to a vertex_obj. + A vertex_obj contains three fields: x, y and z, + representing the three coordinates of the vertex. After + you got the pointer to a vertex_obj you can access its + coordinates by the usual way: vertex_obj.x, vertex_obj.y + and vertex_obj.z. I left this structure public because it + can be of some use for you. + + INPUTS: number of (an existing) vertex; remember: vertex numbers + start from 0 (and go to (number of vertices in object)-1). + + RESULTS: pointer to a vertex_obj + FALSE if num is an illegal number (e.g., num<0) + + SEE ALSO: @{" setvertex() " LINK object_setvertex} + @{" worldbuilder / getvertex() " LINK world_getvertex} + +@endnode + +@node object_fastsetvert "AFC module: object_obj / fastsetvert()" + + NAME: fastsetvert(vertex_list) + + DESCRIPTION: adds vertices to the object according to the content of + vertex_list. Vertex_list is a TYPED list of type + vertex_obj with the following form: + + [x1,y1,z1, x2,y2,z2, ... ]:vertex_obj + + This command is equivalent to the following code + + FOR k:=0 to (number of vertices)-1 + o.setvertex(k, x[k], y[k], z[k]) + ENDFOR + + but it's quicker. + + INPUTS: vertex_list: list of vertices to be added. + + RESULTS: NONE + + SEE ALSO: @{" setvertex() " LINK object_setvertex} + @{" worldbuilder / fastsetvert() " LINK world_fastsetvert} + +@endnode + +@node object_delvertex "AFC module: object_obj / delvertex()" + + NAME: delvertex(num) + + DESCRIPTION: removes a vertex from the object. Removes all references + to that vertex by deleting all lines and/or surfaces + attached to the vertex. + All vertex numbers will be scaled down one step to fill + in the hole leaved by the deletion. + + INPUTS: number of vertex to be killed. + + RESULTS: FALSE if num is not the number of an existing vertex (e.g., + num<0), otherwise TRUE. + + SEE ALSO: @{" setvertex() " LINK object_setvertex} + @{" worldbuilder / delvertex() " LINK world_delvertex} + +@endnode + +@node object_setline "AFC module: object_obj / setline()" + + NAME: setline(num, startv, endv, colour) + + DESCRIPTION: adds or modifies line number 'num' in object 'name': the + line starts from vertex number 'startv', ends in vertex + number 'endv' and has colour 'colour'. + If num is greater than the number of lines contained in + the object_obj, then the new line will be added as last + item; if num points to an existing line, then the new datas + will replace the old line definition. + + This underlines one thing you have to care about: + lines have NOT a fixed number; their number it's their + position in the list (for speed reasons). Usually the + module takes care of this automatically, but you must + remember it when you delete a line. + + Line numbers start from 0. + + INPUTS: num: line number, + startv: starting line vertex, + endv: ending line vertex, + colour: line colour. + + RESULTS: FALSE if num<0 or startv and/or endv outside the range of + existing vertices of the object, + otherwise the number of lines currently in object. + + SEE ALSO: @{" worldbuilder / setline() " LINK world_setline} + +@endnode + +@node object_getline "AFC module: object_obj / getline()" + + NAME: getline(num) + + DESCRIPTION: returns a description of line number 'num' in the form of a + pointer to a line_obj. An object of type line_obj contains + three fields named 'startv', 'endv' and 'colour'; after + having received the pointer you access those fields in the + usual way: line_obj.startv, line_obj.endv and + line_obj.colour. + I left the line_obj object description public because it + can be of use to you. + + INPUTS: number of line to be inquired. + + RESULTS: FALSE if num is outside the valid range of existing line + numbers (going from 0 to (number of lines)-1), + otherwise a pointer to a line_obj. + + SEE ALSO: @{" setline() " LINK object_setline} + @{" worldbuilder / getline() " LINK world_getline} + +@endnode + +@node object_fastsetline "AFC module: object_obj / fastsetline()" + + NAME: fastsetline(line_list) + + DESCRIPTION: adds the line descriptions contained in line_list to the + object. Line_list is a TYPED list of type line_obj of the + following form: + + [startv1,endv1,colour1, startv2,endv2,colour2, ...]:line_obj + + This command is equivalent to the following code + + FOR k:=0 to (number of lines)-1 + o.setline(k, startv[k], endv[k], colour[k]) + ENDFOR + + but it's quicker. + + If a startv or endv exceeds the range of existing vertex + numbers for the object, then it is automatically set to + vertex number 0. + + INPUTS: list of lines to be added. + + RESULTS: NONE + + SEE ALSO: @{" setline() " LINK object_setline} + @{" worldbuilder / fastsetline() " LINK world_fastsetline} + +@endnode + +@node object_delline "AFC module: object_obj / delline()" + + NAME: delline(num) + + DESCRIPTION: removes line number 'num' from the object. + All line numbers will be scaled down one step to fill in + the hole leaved by the deletion. + + INPUTS: number of line to be killed. + + RESULTS: FALSE if num is outside the valid range for the object. + + SEE ALSO: @{" setline() " LINK object_setline} + @{" worldbuilder / delline() " LINK world_delline} + +@endnode + +@node object_setsurface "AFC module: object_obj / setsurface()" + + NAME: setsurface(num, vertex_list, colour) + + DESCRIPTION: adds (or modifies) a surface. If num is greater than the + number of surfaces contained in the object, then the new + surface will be added at the end of the list; if num points + to an existing surface, then the contents of that surface + will be replaced by the new datas. + The vertex_list is a list of vertex NUMBERS belonging to + the surface, in the following order: you rotate the object + until the surface is visible and then enumerate the + vertices in a clockwise direction. + + I want to underline one thing you have to care about: + surfaces have NOT a fixed number; their number it's their + position in the list (for speed reasons). Usually the + module takes care of this automatically, but you must + remember it when you delete a surface. + + Surface numbers start from 0. + + If a vertex number in the list is outside the range of + existing vertices, then it is arbitrarily set to vertex + number 0. + + If you modify a surface it doesn't matter if the new + vertex_list is shorter or longer than the previous one. + + INPUTS: num: number of surface, + vertex_list: list of vertex numbers, + colour: surface colour register. + + RESULTS: FALSE if num<0, + otherwise the total number of surfaces in the object. + + SEE ALSO: @{" worldbuilder / setsurface() " LINK world_setsurface} + +@endnode + +@node object_getsurface "AFC module: object_obj / getsurface()" + + NAME: getsurface(snum, vnum) + + DESCRIPTION: returns the vertex number contained in position vnum of + surface snum. + + INPUTS: snum: number of surface to be inquired, + vnum: position of vertex in the surface's list. + + RESULTS: vertex number contained in position vnum, + FALSE if snum outside the valid range or vnum outside the + valid range for the object. + + SEE ALSO: @{" setsurface() " LINK object_setsurface} + @{" worldbuilder / getsurface() " LINK world_getsurface} + +@endnode + +@node object_delsurface "AFC module: object_obj / delsurface()" + + NAME: delsurface(num) + + DESCRIPTION: removes surface number 'num' from the object. All surface + numbers will be scaled down by one step to fill in the hole + leaved by the deletion. + + INPUTS: number of the surface to be killed. + + RESULTS: FALSE if num is outside the valid range for the object, + otherwise TRUE. + + SEE ALSO: @{" setsurface() " LINK object_setsurface} + @{" worldbuilder / delsurface() " LINK world_delsurface} + +@endnode + +@node object_projection "AFC module: object_obj / projection()" + + NAME: projection(x, y, z) + + DESCRIPTION: reduces the 3D coordinates of the object in a 2D + representation, according to the position of the observer + (specified with the x, y and z parameters). Local axes are + not supplied, so you cannot rotate objects individually; + besides, you cannot draw objects individually. To perform + rotations and drawing you have to link the object to a + worldbuilder. + + INPUTS: position of the observer. + + RESULTS: NONE + + SEE ALSO: @{" worldbuilder / projection() " LINK world_projection} + +@endnode + +@node object_getpoint "AFC module: object_obj / getpoint()" + + NAME: getpoint(vertex) + + DESCRIPTION: returns the coordinates of a projected vertex in the form + of a pointer to a screen_pixel object. Such an object is + made of two fields named 'x' and 'y' (guess what they + mean!); after having got the pointer you access the two + coordinates by the usual way: screen_pixel.x, + screen_pixel.y. + + INPUTS: number of the vertex to be inquired. + + RESULTS: pointer to a screen_pixel object, + FALSE if vertex is outside the valid range for the object. + + SEE ALSO: @{" projection() " LINK object_projection} + @{" worldbuilder / getpoint() " LINK world_getpoint} + +@endnode + +@node object_position "AFC module: object_obj / position()" + + NAME: position(x, y, z) + + DESCRIPTION: moves the origin of the object's local axes to the + position specified. This means you can always enter the + object's coordinates relative to the object's local origin + and then move the object around in the worldbuilder. + This method only sets the origin coordinates to the new + values, and the traslation is performed every time the + object is @{"project()" LINK world_projection}ed within a worldbuilder: this behaviour + obviuosly slows down the projection routine. If you want + to make the changes permanent (calculated once for ever) + you call the @{"apply()" LINK object_apply} method. + + To traslate the whole worldbuilder you can use the + @{"settrasl()" LINK world_settrasl} method. + + INPUTS: coordinates of the local origin. + + RESULTS: NONE + + SEE ALSO: @{" apply() " LINK object_apply} + @{" worldbuilder / position() " LINK world_position} +@endnode + +@node object_scale "AFC module: object_obj / scale()" + + NAME: scale(x, y, z) + + DESCRIPTION: scales the object. + This method only sets the scaling factors to the new + values, and the scaling is performed every time the object + is @{"project()" LINK world_projection}ed within a worldbuilder: this behaviour + obviuosly slows down the projection routine. If you want + to make the changes permanent (calculated once for ever) + you call the @{"apply()" LINK object_apply} method. + The scaling factors are entered as a percentage: 100 + means original dimensions, 50 means a half, and so on... + + To scale the whole worldbuilder you can use the + @{"setscale()" LINK world_setscale} method. + + INPUTS: scaling factors. + + RESULTS: NONE + + SEE ALSO: @{" apply() " LINK object_apply} + @{" worldbuilder / scale() " LINK world_scale} + +@endnode + +@node object_copy "AFC module: object_obj / copy()" + + NAME: copy(dest:PTR TO object_obj) + + DESCRIPTION: copies all the contents of an object (except its name) to + the destination object: the latter will be @{"clear()" LINK object_clear}ed + before being modified. + + INPUTS: pointer to an already initialized object_obj. + + RESULTS: FALSE if dest=NIL, otherwise TRUE. + It may raise exceptions (see the @{"Error Table" LINK Error_Table}). + + SEE ALSO: @{" clone() " LINK object_clone} + @{" worldbuilder / copyobj() " LINK world_copyobj} + +@endnode + +@node object_clone "AFC module: object_obj / clone()" + + NAME: clone(newname=NIL) + + DESCRIPTION: creates a new object_obj and copies the contents of the + current object to the new one. The newname parameter will + be the name of the newborn object_obj (if it is not + supplied the new name will be something like + 'Copy_of_oldname'). + + INPUTS: name of the object to be created. + + RESULTS: pointer to the new object_obj. + + SEE ALSO: @{" copy() " LINK object_copy} + @{" worldbuilder / cloneobj() " LINK world_cloneobj} + +@endnode + +@node object_name "AFC module: object_obj / name()" + + NAME: name() + + DESCRIPTION: returns the object's name. + + INPUTS: NONE + + RESULTS: object's name. + + SEE ALSO: + +@endnode + +@node object_apply "AFC module: object_obj / apply()" + + NAME: apply() + + DESCRIPTION: makes the changes on an object permanent (calculated once + for ever). Changes such as @{"position()" LINK object_position} or @{"scale()" LINK object_scale} of an + object_obj are affected: this increases the speed of the + @{"projection()" LINK world_projection} routine, because permanent transformations + are skipped. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" position() " LINK object_position} + @{" scale() " LINK object_scale} + @{" worldbuilder / applyobj() " LINK world_applyobj} + +@endnode + +@node worldbuilder "AFC module: worldbuilder / worldbuilder()" + + NAME: worldbuilder() + + DESCRIPTION: builds a worldbuilder object (constructor). + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node world_addobj "AFC module: worldbuilder / addobj()" + + NAME: addobj(name) + + DESCRIPTION: creates an object_obj called 'name' and adds it to the + worldbuilder. The name parameter is necessary because all + objects in a world are recognized by their names. + + INPUTS: the name of the object to be created (max 30 chars). + + RESULTS: NONE + + SEE ALSO: @{" object_obj() " LINK object_obj} + @{" setobj() " LINK world_setobj} + +@endnode + +@node world_setobj "AFC module: worldbuilder / setobj()" + + NAME: setobj(object) + + DESCRIPTION: links an existing object_obj to the worldbuilder. + + INPUTS: 'object' is the pointer to an object_obj. + + RESULTS: NONE + + SEE ALSO: @{" addobj() " LINK world_addobj} + @{" getobj() " LINK world_getobj} + +@endnode + +@node world_getobj "AFC module: worldbuilder / getobj()" + + NAME: getobj(name) + + DESCRIPTION: returns the pointer to the object_obj named 'name'. + + INPUTS: name of the object. + + RESULTS: pointer to an object_obj. + + SEE ALSO: @{" setobj() " LINK world_setobj} + @{" addobj() " LINK world_addobj} + +@endnode + +@node world_delobj "AFC module: worldbuilder / delobj()" + + NAME: delobj(name) + + DESCRIPTION: unlinks from the worldbuilder and deletes (freeing all memory + associated with it) the object 'name'. If such an object + doesn't exist, it does nothing. + + INPUTS: name of the object to be killed. + + RESULTS: NONE + + SEE ALSO: @{" addobj() " LINK world_addobj} + @{" unlinkobj() " LINK world_unlinkobj} + +@endnode + +@node world_unlinkobj "AFC module: worldbuilder / unlinkobj()" + + NAME: unlinkobj(name) + + DESCRIPTION: removes the object 'name' from the worldbuilder, without + freeing its memory. It returns a pointer to an object_obj, + that you must remember to END yourself before exiting the + program. + + INPUTS: name of the object to unlink. + + RESULTS: pointer to an object_obj, or FALSE if 'name' not found. + + SEE ALSO: @{" delobj() " LINK world_delobj} + +@endnode + +@node world_setvertex "AFC module: worldbuilder / setvertex()" + + NAME: setvertex(name, num, x, y, z) + + DESCRIPTION: same as @{"object_obj / setvertex()" LINK object_setvertex} + + INPUTS: name of the object_obj to be modified + num: vertex number + x, y, z: vertex coordinates + + RESULTS: FALSE if object not found, + otherwise the number of vertices currently in object. + + SEE ALSO: @{" fastsetvert() " LINK world_fastsetvert} + @{" object_obj / setvertex() " LINK object_setvertex} + +@endnode + +@node world_getvertex "AFC module: worldbuilder / getvertex()" + + NAME: getvertex(name, num) + + DESCRIPTION: same as @{"object_obj / getvertex()" LINK object_getvertex} + + INPUTS: name of the object to be inquired + num: number of vertex + + RESULTS: FALSE if object not found, or num outside a valid range, + pointer to vertex_obj if successful. + + SEE ALSO: @{" setvertex() " LINK world_setvertex} + @{" object_obj / getvertex() " LINK object_getvertex} + +@endnode + +@node world_fastsetvert "AFC module: worldbuilder / fastsetvert()" + + NAME: fastsetvert(name, vertex_list) + + DESCRIPTION: same as @{"object_obj / fastsetvert()" LINK object_fastsetvert} + + INPUTS: name of the object to be modified + vertex_list of vertices to be added. + + RESULTS: FALSE if object not found. + + SEE ALSO: @{" setvertex() " LINK world_setvertex} + @{" object_obj / fastsetvert() " LINK object_fastsetvert} + +@endnode + +@node world_delvertex "AFC module: worldbuilder / delvertex()" + + NAME: delvertex(name, num) + + DESCRIPTION: same as @{"object_obj / delvertex()" LINK object_delvertex} + + INPUTS: name of the object to be modified + num: number of vertex to be killed. + + RESULTS: FALSE if object not found, or num outside a valid range, + otherwise TRUE. + + SEE ALSO: @{" setvertex() " LINK world_setvertex} + @{" object_obj / delvertex() " LINK object_delvertex} + +@endnode + +@node world_setline "AFC module: worldbuilder / setline()" + + NAME: setline(name, num, startv, endv, colour) + + DESCRIPTION: same as @{"object_obj / setline()" LINK object_setline} + + INPUTS: name of the object to be modified, + num: number of line, + startv: line starting vertex, + endv: line ending vertex, + colour: line colour register. + + RESULTS: FALSE if object not found, + FALSE if num<0 or startv and/or endv outside the range of + existing vertices of the object, + otherwise the number of lines currently in the object. + + SEE ALSO: @{" fastsetline() " LINK world_fastsetline} + @{" object_obj / setline() " LINK object_setline} + +@endnode + +@node world_getline "AFC module: worldbuilder / getline()" + + NAME: getline(name, num) + + DESCRIPTION: same as @{"object_obj / getline()" LINK object_getline} + + INPUTS: name of the object, + num: line number. + + RESULTS: FALSE if object not found, or num outside the range of + existing line numbers. + + SEE ALSO: @{" setline() " LINK world_setline} + @{" object_obj / getline() " LINK object_getline} + +@endnode + +@node world_fastsetline "AFC module: worldbuilder / fastsetline()" + + NAME: fastsetline(name, line_list) + + DESCRIPTION: same as @{"object_obj / fastsetline()" LINK object_fastsetline} + + INPUTS: name of the object to be modified, + line_list: typed list of objects line_obj. + + RESULTS: FALSE if object not found, otherwise TRUE + + SEE ALSO: @{" setline() " LINK world_setline} + @{" object_obj / fastsetline() " LINK object_fastsetline} + +@endnode + +@node world_delline "AFC module: worldbuilder / delline()" + + NAME: delline(name, num) + + DESCRIPTION: same as @{"object_obj / delline()" LINK object_delline} + + INPUTS: name of the object to be modified, + num: number of line to be killed. + + RESULTS: FALSE if object not found, or num outside the valid line + numbers range for the object. + + SEE ALSO: @{" setline() " LINK world_setline} + @{" object_obj / delline() " LINK object_delline} + +@endnode + +@node world_setsurface "AFC module: worldbuilder / setsurface()" + + NAME: setsurface(name, num, vertex_list, colour) + + DESCRIPTION: same as @{"object_obj / setsurface()" LINK object_setsurface} + + INPUTS: name of the object to be modified, + num: number of surface, + vertex_list: list of vertex numbers defining the surface, + colour: surface colour register. + + RESULTS: FALSE if object not found, or num<0 + + SEE ALSO: @{" object_obj / setsurface() " LINK object_setsurface} + +@endnode + +@node world_getsurface "AFC module: worldbuilder / getsurface()" + + NAME: getsurface(name, snum, vnum) + + DESCRIPTION: same as @{"object_obj / getsurface()" LINK object_getsurface} + + INPUTS: name of the object, + snum: number of surface to be inquired, + vnum: number of vertex + + RESULTS: FALSE if object not found or snum outside the valid range + or vnum outside the valid range for the object, + otherwise the vertex number in position vnum. + + SEE ALSO: @{" setsurface() " LINK world_setsurface} + @{" object_obj / getsurface() " LINK object_getsurface} + +@endnode + +@node world_delsurface "AFC module: worldbuilder / delsurface()" + + NAME: delsurface(name, num) + + DESCRIPTION: same as @{"object_obj / delsurface()" LINK object_delsurface} + + INPUTS: name of the object to be modified, + num: number of surface to be killed. + + RESULTS: FALSE if object not found or num outside the valid surface + number range for the object, + otherwise TRUE. + + SEE ALSO: @{" setsurface() " LINK world_setsurface} + @{" object_obj / delsurface() " LINK object_delsurface} + +@endnode + +@node world_getpoint "AFC module: worldbuilder / getpoint()" + + NAME: getpoint(name, vertex) + + DESCRIPTION: same as @{"object_obj / getpoint()" LINK object_getpoint} + + INPUTS: name of the object, + vertex number to be inquired. + + RESULTS: FALSE if object not found or vertex number outside the + valid range for the object, + otherwise the pointer to a screen_pixel object. + + SEE ALSO: @{" object_obj / getpoint() " LINK object_getpoint} + +@endnode + +@node world_visible "AFC module: worldbuilder / visible()" + + NAME: visible(name [,v]) + + DESCRIPTION: an object is by default visible, that is to say it will be + drawn on the scene. If v=FALSE then the object won't + appear on the scene any more, until v is reset to TRUE. If + v is omitted then the function returns the state of the + object. + + INPUTS: name of the object to be modified, + v: TRUE if visible, FALSE if not + + RESULTS: FALSE if object not found, otherwise TRUE; if v is omitted + then the result is the state of the object. + + SEE ALSO: + +@endnode + +@node world_position "AFC module: worldbuilder / position()" + + NAME: position(name, x,y,z) + + DESCRIPTION: same as @{"object_obj / position()" LINK object_position}. + + INPUTS: name of the object ot be modified, + coordinates of the local origin. + + RESULTS: FALSE if object not found. + + SEE ALSO: @{" applyobj() " LINK world_applyobj} + @{" object_obj / position() " LINK object_position} + +@endnode + +@node world_scale "AFC module: worldbuilder / scale()" + + NAME: scale(name, x,y,z) + + DESCRIPTION: same as @{"object_obj / scale()" LINK object_scale}. + + INPUTS: name of the object to be modified, + scaling factors. + + RESULTS: FALSE if object not found. + + SEE ALSO: @{" applyobj() " LINK world_applyobj} + @{" object_obj / scale() " LINK object_scale} + +@endnode + +@node world_clearobj "AFC module: worldbuilder / clearobj()" + + NAME: clearobj(name) + + DESCRIPTION: same as @{"object_obj / clear()" LINK object_clear}. + + INPUTS: name of the object to be cleared. + + RESULTS: FALSE if object not found, otherwise TRUE. + + SEE ALSO: @{" object_obj / clear() " LINK object_clear} + +@endnode + +@node world_copyobj "AFC module: worldbuilder / copyobj()" + + NAME: copyobj(source_name, dest_name) + + DESCRIPTION: copies the contents of source_name object to dest_name + object (except names). + + INPUTS: name of two object_obj's. + + RESULTS: FALSE if either of the objects has not been found. + + SEE ALSO: @{" cloneobj() " LINK world_cloneobj} + @{" object_obj / copy() " LINK object_copy} + +@endnode + +@node world_cloneobj "AFC module: worldbuilder / cloneobj()" + + NAME: cloneobj(name, new_name=NIL) + + DESCRIPTION: creates a new object of name new_name (if supplied), + copies the contents of the object_obj 'name' in the newborn + object, and then links the latter to the worldbuilder. + + INPUTS: name of the object to be cloned, + new_name: name of the new object (if not supplied the + default is 'Copy_of_name'). + + RESULTS: FALSE if object 'name' not found. + + SEE ALSO: @{" copyobj() " LINK world_copyobj} + @{" object_obj / clone() " LINK object_clone} + +@endnode + +@node world_applyobj "AFC module: worldbuilder / applyobj()" + + NAME: applyobj(name) + + DESCRIPTION: same as @{"object_obj / apply()" LINK object_apply}. + + INPUTS: name of the object to be modified. + + RESULTS: FALSE if object not found. + + SEE ALSO: @{" position() " LINK world_position} + @{" scale() " LINK world_scale} + @{" object_obj / apply() " LINK object_apply} + +@endnode + +@node world_projection "AFC module: worldbuilder / projection()" + + NAME: projection() + + DESCRIPTION: transforms the 3D representation of the world in a 2D + representation, according with the chosen values of + rotantion angles (@{"setrot()" LINK world_setrot} method) and observer position + (@{"setobserver()" LINK world_setobserver} method). + You have to call this instruction before the drawing + routine, if you have performed some changes on the + worldbuilder. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" object_obj / projection() " LINK object_projection} + +@endnode + +@node world_draw "AFC module: worldbuilder / draw()" + + NAME: draw(rastport) + + DESCRIPTION: draws the worldbuilder in a wireframe fashion. If an object + has at least one line, then only its lines are drawn; if an + object has no lines, then its vertices are drawn. Rastport + is the address of a valid rastport in which to draw the + graphics. + The drawing is then traslated and scaled according to the + values entered with the @{"setaftertrasl()" LINK world_setaftertrasl} and + @{"setafterscale()" LINK world_setafterscale} methods. + Remember to @{"projection()" LINK world_projection} the worldbuilder before drawing + it (you needn't do this if it's not the first time and + you've made no changes). + + INPUTS: address of a rastport. + + RESULTS: NONE + + SEE ALSO: @{" drawfill() " LINK world_drawfill} + @{" projection() " LINK world_projection} + +@endnode + +@node world_drawfill "AFC module: worldbuilder / drawfill()" + + NAME: drawfill(rastport, onlylines=FALSE) + + DESCRIPTION: draws the projected worldbuilder with filled vectors. + The drawing is then traslated and scaled according to the + values entered with the @{"setaftertrasl()" LINK world_setaftertrasl} and + @{"setafterscale()" LINK world_setafterscale} methods. + Clipping is made according to the dimensions of the + screen area entered with the @{"setdisplay()" LINK world_setdisplay} method. + If the onlylines parameter is set to TRUE, then also + objects without surfaces are drawn. + + Remember to @{"projection()" LINK world_projection} the worldbuilder before drawing + it (you needn't do this if it's not the first time and + you've made no changes). + You must call the @{"init3D()" LINK world_init3d} routine at least one time + before drawing any filled graphics. + + INPUTS: address of a rastport in which to draw the graphics. + + RESULTS: NONE + + SEE ALSO: Important: @{" init3D() " LINK world_init3d} + @{" projection() " LINK world_projection} + +@endnode + +@node world_setobserver "AFC module: worldbuilder / setobserver()" + + NAME: setobserver(x, y, z) + + DESCRIPTION: sets the observer position. + + INPUTS: coordinates of the observer. + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node world_setscale "AFC module: worldbuilder / setscale()" + + NAME: setscale(x, y, z) + + DESCRIPTION: the three scale factors will be applied to the whole + worldbuilder before projecting it. They are entered as a + percentage: 100 means original dimensions, 50 means a + half, and so on... + This is a 3D operation: compare it with + @{"setafterscale()" LINK world_setafterscale} + + INPUTS: scaling factors in the three directions. + + RESULTS: NONE + + SEE ALSO: @{" setafterscale() " LINK world_setafterscale} + +@endnode + +@node world_settrasl "AFC module: worldbuilder / settrasl()" + + NAME: settrasl(tx, ty, tz) + + DESCRIPTION: traslates the whole worldbuilder by the specified amounts + before projecting it. + This is a 3D operation: compare it with + @{"setaftertrasl()" LINK world_setaftertrasl} + + The traslation is done before any rotation is performed. + + INPUTS: traslation amounts in the three directions. + + RESULTS: NONE + + SEE ALSO: @{" setaftertrasl() " LINK world_setaftertrasl} + +@endnode + +@node world_setrot "AFC module: worldbuilder / setrot()" + + NAME: setrot(x, y, z) + + DESCRIPTION: rotates the whole worldbuilder around the three axes by the + specified amounts. + + INPUTS: angles of rotation around the three axes (degrees). + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node world_setafterscale "AFC module: worldbuilder / setafterscale()" + + NAME: setafterscale(x, y) + + DESCRIPTION: scales the projected world while drawing it to adapt it to + the screen area. The scaling factors are entered as a + percentage: 100 means original dimensions, 50 means a + half, and so on... + This is a 2D operation: compare it with @{"setscale()" LINK world_setscale} + + INPUTS: scaling factors in the two directions. + + RESULTS: NONE + + SEE ALSO: @{" setscale() " LINK world_setscale} + +@endnode + +@node world_setaftertrasl "AFC module: worldbuilder / setaftertrasl()" + + NAME: setaftertrasl(x, y) + + DESCRIPTION: translates the origin of the screen coordinate system + (default: top left-hand corner, as usual). + This is a 2D operation: compare it with @{"settrasl()" LINK world_settrasl} + + INPUTS: traslation factors in the two directions. + + RESULTS: NONE + + SEE ALSO: @{" settrasl() " LINK world_settrasl} + +@endnode + +@node world_setdisplay "AFC module: worldbuilder / setdisplay()" + + NAME: setdisplay(width, height) + + DESCRIPTION: used to enter the screen area dimensions. These are used + in the allocation of the extra bitplane in the @{"init3D()" LINK world_init3d} + routine, and in the clipping of graphics in the + @{"drawfill()" LINK world_drawfill} method. + + INPUTS: width and height of the drawing area (defaults are: + width=320, height=256). + + RESULTS: NONE + + SEE ALSO: + +@endnode + +@node world_init3d "AFC module: worldbuilder / init3D()" + + NAME: init3D(bufon=TRUE, dispon=TRUE) + + DESCRIPTION: allocates the resources needed by the @{"drawfill()" LINK world_drawfill} method + to draw filled vectors: you must call this routine before + any call to drawfill() is made. + It allocates a buffer needed by the operating system to + store the vectors before they are drawn, and an extra + bitplane to allow the drawing of filled areas. If, in a + second time, you change the dimensions of the screen area, + you have to recall this routine to update the dimensions of + the extra bitplane; in the same manner, if you add lots of + surfaces to your world, you have to call this routine to + adapt the buffer dimensions to the new situation (otherwise + you can get only partial rendering). + You needn't do both the operations every time you call + the init3D method, infact the two flags mean: + + bufon =TRUE -> resize the buffer + dispon=TRUE -> resize the extra bitplane. + + The dimensions of the screen area are entered with the + @{"setdisplay()" LINK world_setdisplay} method, and they are used also for graphic + clipping purposes. + + INPUTS: flags described above. + + RESULTS: raises some exceptions if memory allocation fails (see the + @{"Error Table" LINK Error_Table}). + + SEE ALSO: @{" drawfill() " LINK world_drawfill} + +@endnode + +@node world_version "AFC module: worldbuilder / version()" + + NAME: version() + + DESCRIPTION: returns version and revision of worldbuilder module + + INPUTS: NONE + + RESULTS: version, revision + + SEE ALSO: + +@endnode + +@node world_limitangle "AFC module: procedure / limitangle()" + + NAME: limitangle(angle) + + DESCRIPTION: bounds the angle in range [0-359] degrees. + + INPUTS: angle to be wrapped. + + RESULTS: angle in the range [0-359] degrees + + SEE ALSO: + +@endnode + +@node world_crossprod "AFC module: procedure / crossprod()" + + NAME: crossprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj) + + DESCRIPTION: this is the vector product between the two vectors 'a' and + 'b'. The two arguments are defined as vertex_obj because + points in three-space and three-dimensional vectors share + the same structure (remember: points can be represented as + vectors from the origin). + The vectors have three fields: a.x, a.y and a.z; you + fill in these fields and call the routine: it returns the + three components of the resulting vector. + + INPUTS: two (pointers to) vectors. + + RESULTS: three return values, representing the three components of + the resulting vector, in the order: x, y, z. + + SEE ALSO: @{" dotprod() " LINK world_dotprod} + +@endnode + +@node world_dotprod "AFC module: procedure / dotprod()" + + NAME: dotprod(a:PTR TO vertex_obj, b:PTR TO vertex_obj) + + DESCRIPTION: this is the scalar product between the two vectors 'a' and + 'b'. See the observations about points and vectors in the + @{"crossprod()" LINK world_crossprod} procedure. + + INPUTS: two (pointers to) vectors. + + RESULTS: scalar product of the two vectors. + + SEE ALSO: @{" crossprod() " LINK world_crossprod} + +@endnode + +@node world_fillsintable "AFC module: procedure / fillSinTable()" + + NAME: fillSinTable() + + DESCRIPTION: this is used to fill in a pointer to the table of sines: + of course, sines for rotations are not calculated realtime, + but peeked from this table. The table is automatically + filled when you create the first worldbuilder object, so, in + general, you have not to do this task by hand. On the + other hand, if you don't fill the table before accessing it + you can crash your machine. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/bebox.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/bebox.guide new file mode 100644 index 0000000..206f1f0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/bebox.guide @@ -0,0 +1,305 @@ +@database bebox.guide + +@$VER: BeBox V1.10 - (C)Copyright Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: BeBox" + + + + ** BeBox - Original By Fabio Rotondo ** + + * Part of the Amiga Foundation Classes * + + @{" Introduction " link "BeBox_introduction"} @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} + + Requires: Nothing. + + Class Base: $000C0000 + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" bebox(x=0,y=0,w=0,h=0) " link "BeBox_BeBox"} Initailizes the class. + @{" check(x,y) " link "BeBox_Check"} Checks if coords hit the box. + @{" draw(mode=TRUE) " link "BeBox_Draw"} Draws the box. + @{" error() " link "BeBox_Error"} Returns last error raised. + @{" get(tag) " link "BeBox_Get"} Gets class values. + @{" setattrs(tags) " link "BeBox_SetAttrs"} Sets class attributes. + @{" version() " link "BeBox_version"} Returns BeBox version. + + @{" BeBox Structure " link "BeBox_Structure"} + + @{" Error Table " LINK BeBox_ErrorTable} +@endnode + +@node "BeBox_Introduction" "Introduction" + + BeBox is a class to handle a "sensible" area on the screen. + It is as simple as powerful: you can hook a procedure to add to the BeBox a + drawing routine, or to teach it how to move on the screen. + + It can return relative mouse coordinates and so on. + + This class is _very_ useful. You'll learn how to use it. + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + C++ Version By: Massimo Tantignone (tanti@intercom.it) + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + +@endnode + +@node BeBox_ErrorTable "BeBox / Error Table " + +VALUE | DESCRIPTION +----------------+---------------------------------- +$0000 | No Memory. +@endnode + +@node BeBox_Structure "BeBox Structure" + + BeBox Structure + + Here there is a very quick explanation of the BeBox Structure. + Please, remember that these fields are *READ ONLY*: use tags + to modify them! + + OBJECT bebox_data + oldx :INT -> Old X Pos + oldy :INT -> Old Y Pos + oldw :INT -> Old width value + oldh :INT -> Old height value + oldcol:INT -> Old color used + + x :INT -> Actual X Position + y :INT -> Actual Y Position + w :INT -> Width and Height + h :INT + relx:INT -> Last Relative Mouse Click inside the Box + rely:INT + + minx:INT -> min x,y bounds + miny:INT + maxx:INT -> max x,y bounds + maxy:INT + + rp :PTR TO rastport -> Rastport where to draw on. + + col :INT -> Color to use + + userel:CHAR -> This is a flag: TRUE means auto relative coords + user :PTR TO LONG -> Pointer to anything + ENDOBJECT + +@endnode + +@node "BeBox_bebox" "Amiga Foundation Classes: BeBox/bebox()" + + NAME: bebox(x=0, y=0, w=0, h=0) + + SYNOPSIS: bebox(ULONG x = 0, ULONG y = 0, ULONG w = 0, ULONG h = 0) + + DESCRIPTION: This is the class constructor. If you want, you can + pass the box dimensions and positions, while creating + the object. + + INPUT: x, y - (Optional) Box left and top position. + + w, h - (Optional) Box width and height. + + + RESULTS: + + SEE ALSO: +@endnode + +@node "BeBox_setattrs" "Amiga Foundation Classes: BeBox/setattrs()" + + NAME: setattrs(tags:PTR TO LONG) + + SYNOPSIS: setattrs(struct TagItem *tags) + + DESCRIPTION: This method is used to change Box attributes, such + as dimensions, positions and so on. + It is *the only way* to access to BeBox class structure. + + INPUT: tags - (PTR TO LONG) taglist. Avaible tags are: + + + SIZE: + + BB_WIDTH - Box's Width + BB_HEIGHT - Box's Height + BB_ENDX - Box's end X coord (instead of specify the Width, you + just specify box's end x position: BeBox will + compute automagically the width for you). + BB_ENDY - Box's end Y coord. + + COORDS: + + BB_POSX - Box's X Position + + BB_POSY - Box's Y Position + + BB_RELX - Box's Relative X coord. You can specify an "offset" + that will be added to the box's X coord. + BB_RELY - Box's Relative Y coord. + + BB_OLDX - Box's last x position. (-1 = erase last value) + + BB_OLDY - Box's last y position. (-1 = erase last value) + + BOUNDS: + + You can "bound" the box inside a rectangle. With the following + tags you can set the coords of that rectangle. + Please note that MAXX and MAXY refer to box's x+width. + + + BB_MINX - Box's Min X coord. + BB_MINY - Box's Min Y coord. + BB_MAXX - Box's Max X coord. + BB_MAXY - Box's Max Y coord. + + GRAPHIC: + + You can set rastport, draw color and other values. + Here come the tags... + + BB_RPORT - Box's rastport to draw on. + + BB_COL - Box's drawing color. + + BB_USEREL - This is a flag: if set to TRUE, box will compute + new coords by checking mouse coords inside the box. + + BB_DRAW - You can assign a pointer to a function right here. + The destination function *must* accept the following + parameters, in this order: + + drawingproc(data:PTR TO bebox_data, mode) + + where data is a PTR TO a @{" bebox_data " LINK bebox_structure} + structure. + + Mode is a flag: TRUE means "draw", while FALSE means + "delete obj from the screen". + + USER: + + BB_USER - Box's user tag. Place here whatever you want. + + RESULTS: + + SEE ALSO: @{" get() " LINK bebox_get} +@endnode + +@node "BeBox_get" "Amiga Foundation Classes: BeBox/get()" + + NAME: get(tagname) + + SYNOPSIS: APTR get(ULONG tag) + + DESCRIPTION: This method returns the current value of the specified + tag. Please refer to @{" setattrs() " LINK bebox_setattrs} for a + complete list of tags. + + INPUT: tagname - Tag to query the value. + + RESULTS: a LONG value containing the result + + SEE ALSO: @{" setattrs() " LINK bebox_setattrs} +@endnode + +@node "BeBox_check" "Amiga Foundation Classes: BeBox/check()" + + NAME: check(x, y) + + SYNOPSIS: BOOL check(ULONG x, ULONG y) + + DESCRIPTION: This method checks the given coords and returns + whether they are inside or outside the bebox. + + INPUT: x,y - Corrdinates to check. + + RESULTS: TRUE - The coords are inside the box. + + FALSE - Coords are outside the box. + + SEE ALSO: +@endnode + +@node "BeBox_draw" "Amiga Foundation Classes: BeBox/draw()" + + NAME: draw(mode = TRUE) + + SYNOPSIS: void draw(BOOL mode = TRUE) + + DESCRIPTION: This method invokes the drawing routine. + + INPUT: mode - (Optional) If TRUE then the box will be drawn on the + screen. If FALSE the box will be erased from the screen. + Default: TRUE. + + RESULTS: + + SEE ALSO: +@endnode + +@node "BeBox_version" "Amiga Foundation Classes: BeBox/version()" + + NAME: version() + + SYNOPSIS: ULONG version(BOOL revision = FALSE) + + DESCRIPTION: This method returns class version and revision. + + INPUT: NONE. + + RESULTS: this method returns TWO values: VERSION and REVISION. + + SEE ALSO: +@endnode + +@node "BeBox_error" "Amiga Foundation Classes: BeBox/error()" + + NAME: error() + + SYNOPSIS: ULONG error(void) + + DESCRIPTION: This method returns the last error raised. + + INPUT: NONE. + + RESULTS: the last error raised by this class. + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/explain_exception.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/explain_exception.guide new file mode 100644 index 0000000..acc92de --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/explain_exception.guide @@ -0,0 +1,78 @@ +@database explain_exception.guide + +@$VER: explain_exception V1.20 + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: explain_exception" + + + + ** Explain_Exception - Original By Fabio Rotondo ** + + * Part of the Amiga Foundation Classes * + + @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} @{" History " LINK "explain_exception_History"} + + REQUIRES: AmigaE version needs "tools/exceptions" + + + + NAME: explain_exception(v=0) + + SYNOPSIS: VOID explain_exception(LONG v=0) + + DESCRIPTION: This function helps you to debug your program. + Using this program you can "translate" the error Raise()d + by a method inside an AFC class into a message sent to the + consolle. + It is incredibly easy and handy to use. + + + INPUT: v - (Optional) Exception value. + If it is omitted, it will return the + current exception. + + + RESULTS: NONE. + + + SEE ALSO: + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + +@endnode + +@node explain_exception_history "Amiga Foundation Classes: explain_exception / HISTORY" + + HISTORY + + V1.20 - Initial Release +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/mgui.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/mgui.guide new file mode 100644 index 0000000..c0b97af --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/mgui.guide @@ -0,0 +1,576 @@ +@database mgui.guide + +@$VER: MGui V2.30 - By Fabio Rotondo (C)Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node main "Amiga Foundation Classes: mgui_oo/Main" + + + ** Mgui- Original By Fabio Rotondo ** + + Part of Amiga Foundation Classes + + + + + @{" Introduction " LINK mgui_intro} @{" Author(s) Info " LINK author} @{" Amiga Foundation Classes " LINK "afc.guide/main"} + + + Requires: @{" NodeMaster " LINK "NodeMaster.guide/Main"}, EasyGUI + + Base: $000C + + COMMANDS BRIEF DESCRIPTION + ----------------------------------------------------------------------- + @{" mgui() " LINK mgui_mgui} Init the object. + @{" addA(wtitle, gui, tags) " LINK mgui_addA} Add a new GUI. + @{" clear() " LINK mgui_clear} Close all GUIs. + @{" del() " LINK mgui_del} Delete a GUI. + @{" empty() " LINK mgui_empty} Check if mgui has no GUIs. + @{" first() " LINK mgui_first} Pos on first GUI. + @{" freeguis() " LINK mgui_INTERNAL} * INTERNAL USE ONLY * + @{" gui() " LINK mgui_gui} Actual GUI pointer. + @{" lock(mode=TRUE) " LINK mgui_lock} Lock/Unlock GUI. + @{" message() " LINK mgui_message} Parse a message. + @{" nm() " LINK mgui_nm} Returns related NodeMaster object. + @{" numgui() " LINK mgui_numgui} Number of avail GUIs. + @{" pop(pos=TRUE) " LINK mgui_pop} Pop a GUI from the stack. + @{" pos(v, m=NAME, here=FALSE) " LINK mgui_pos} Search for a GUI. + @{" push() " LINK mgui_push} Push a GUI into the stack. + @{" setattrs(tags) " LINK mgui_setattrs} Set various attributes. + @{" succ() " LINK mgui_succ} Pos on next GUI. + @{" version() " LINK mgui_version} Returns object's version and revision. + + @{" ERROR TABLE " LINK Error_Table} + +@endnode + +@node author "Author(s) Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) +@endnode + +@node mgui_intro "mgui / Introduction" + + MGUI + + Mgui is a class that helps Amiga E programmers to write multi-gui programs + very easily. + + It rely heavily on EasyGUI, so it is very hard that it will be ported to + any other language. Anyway, I decided to include it in AFC because it is + extremily useful. + + Note: you must to know how to use EasyGUI to use mgui. + + I have nothing more to add. Just try this class and enjoy yourself. + + Cheers, + + Fabio Rotondo + +@endnode + +@node Error_Table "mgui / Error Table" + +At the moment, this class does not define any error. + +@endnode + +@node mgui_mgui "mgui / mgui()" + + NAME: mgui() + + DESCRIPTION: mgui class constructor. + + INPUTS: NONE + + RESULTS: NONE + + SEE ALSO: @{" NodeMaster/nodemaster() " LINK "NodeMaster.guide/NodeMaster_nodemaster"} + +@endnode + +@node mgui_first "mgui / first()" + + NAME: first() + + DESCRIPTION: Set position to the first GUI in the mgui object. + + INPUTS: NONE + + RESULTS: a PTR to GUI - First() succeded. + + NIL - First() failed. + + SEE ALSO: @{" NodeMaster/first() " LINK "NodeMaster.guide/NodeMaster_first"} + +@endnode + +@node mgui_succ "mgui / succ()" + + NAME: succ() + + DESCRIPTION: Set position to the next GUI in the mgui object. + + INPUTS: NONE + + RESULTS: a PTR to GUI - succ() succeded. + + NIL - succ() failed. + + SEE ALSO: @{" NodeMaster/succ() " LINK "NodeMaster.guide/NodeMaster_succ"} + +@endnode + +@node mgui_empty "mgui / empty()" + + NAME: empty() + + DESCRIPTION: Checks if mgui object is empty or not. + + INPUTS: NONE + + RESULTS: TRUE - mgui object is empty. + + FALSE - at least one GUI is present. + + SEE ALSO: @{" NodeMaster/empty() " LINK "NodeMaster.guide/NodeMaster_empty"} + +@endnode + +@node mgui_gui "mgui / gui()" + + NAME: gui() + + DESCRIPTION: Get actual GUI pointer. + + INPUTS: NONE + + RESULTS: a PTR to a GUI - gui() succeded. + + NIL - gui() failed. (mgui is empty) + + SEE ALSO: @{" NodeMaster/obj() " LINK "NodeMaster.guide/NodeMaster_obj"} + +@endnode + +@node mgui_numgui "mgui / numgui()" + + NAME: numgui() + + DESCRIPTION: Get the number of GUIs opened at the moment. + + INPUTS: NONE + + RESULTS: a LONG containing the number of GUIs opened. + + SEE ALSO: @{" NodeMaster/numitems() " LINK "NodeMaster.guide/NodeMaster_numitems"} + +@endnode + +@node mgui_push "mgui / push()" + + NAME: push() + + DESCRIPTION: Push a GUI into the stack. + + INPUTS: NONE + + RESULTS: TRUE - GUI pushed into the stack. + + FALSE - push() failed. (Stack is full) + + SEE ALSO: @{" NodeMaster/push() " LINK "NodeMaster.guide/NodeMaster_push"} + +@endnode + +@node mgui_pop "mgui / pop()" + + NAME: pop(pos=TRUE) + + DESCRIPTION: Pop a GUI from the stack. + + INPUTS: pos - Should be TRUE or FALSE: + + TRUE - (default) a GUI is pop()ed from the stack + and the mgui object is positioned on it. + + FALSE - a GUI is pop()ed from the stack, but mgui + IS NOT positioned on it (ie. just clear a + push()ed GUI) + + RESULTS: a PTR to GUI - pop() succeded. + + NIL - pop() failed (stack is empty or pos=FALSE) + + SEE ALSO: @{" NodeMaster/pop() " LINK "NodeMaster.guide/NodeMaster_pop"} + +@endnode + +@node mgui_clear "mgui / clear()" + + NAME: clear() + + DESCRIPTION: Close all GUIs. + + INPUTS: NONE + + RESULTS: all GUIs are closed. + + SEE ALSO: @{" NodeMaster/clear() " LINK "NodeMaster.guide/NodeMaster_clear"} + +@endnode + +@node mgui_addA "mgui / addA()" + + NAME: addA(wtitle:PTR TO CHAR, gui, tags=NIL:PTR TO LONG) + + DESCRIPTION: Add a new GUI to mgui object using tag-list. + + INPUTS: wtitle - Title of the GUI window. + + gui - GUI description (see EasyGUI) + + tags - Tag List. You can happily mix EasyGUI tags + with Mgui tags in the same list. + + RESULTS: a PTR to a gui_obj - The GUI has been added. + + NOTES: - This method may raise exceptions coming from NodeMaster() and + EasyGUI. + + - Starting from EasyGUI V3.3a, new tags have been added to + allow better multiple GUIs handling. + Please, note that: + + -->> you MUST NOT use the EG_CLEAN tag <<-- + + Use the MGUI_FREEPROC method instead. + + - Don't use EG_INFO. Use MGUI_INFO instead. + + - This method actually returns TWO values: + + gui - a pointer to a valid gui_obj + gh - pointer to the gui handle + + SEE ALSO: @{" setattrs() " LINK Mgui_setattrs} + + EasyGUI/easyguiA() + + @{" NodeMaster/add() " LINK "NodeMaster.guide/NodeMaster_add"} + + +@endnode + +@node mgui_message "mgui / message()" + + NAME: message() + + DESCRIPTION: Waits for a new message from the user. + This is one of the coolest methods of the object: + you just do not have to do anything: everything is + handled by this method, which minds also for + inputs coming from external signals. + + INPUTS: NONE + + RESULTS: This method returns THREE values at a time: + + parsed - TRUE if signal arrived has been + correctly parsed. + + sig - Signal arrived at Wait(). + + res - result returned by guimessage(). + + SEE ALSO: EasyGUI/guimessage() + +@endnode + +@node mgui_setattrs "mgui / setattrs()" + + NAME: setattrs(tags) + + DESCRIPTION: This method is used to change some current GUI's attributes + and also to change mgui object's attributes. + This is the only way to modify mgui behaviours. + + INPUTS: There are two kind of tags, those working on the current GUI + and the others working on mgui itself. We'll list them + separately. + + GUI Tags, these are the tags acting on the current GUI: + + MGUI_MAIN - Tells mgui whether the current GUI is the main one + or not. When the main GUI is closed, all the + others GUI will be closed at the same time. + Possible values, TRUE / FALSE. + + MGUI_FREEPROC - Tells mgui what procedure(s) to call when + the current GUI'll be closed. This is very + useful, because you can create very complex + GUI with a lot of dinamycally allocated + objects and structures, that have to be freed + on GUI closing. This command needs a list + (or a structure) containing: PTR to proc and + arguments to pass to the procedure. Example: + + [MGUI_FREEPROC, [{freeobj}, obj, + {freesig}, sig, + NIL, NIL], + NIL, NIL] + + MGUI_NAME - This is not just a name, it is more like an + "handle". Name value can be of 4 bytes (4 CHARS) + just like the errors you usually Raise(). + Possible values, anything 4 bytes long. + Example: "MAIN" + + MGUI_USER - This is a field you should fill with anything you + want. It is just a PTR to something. + Possible values, everything. + Example: myobj. + + MGUI_INFO - This is the MGui replacement FOR EG_INFO. + + MGUI_LOCK - You can lock/unlock a GUI with this tag, so you + can receive user's inputs or just ignore them. + Possible values: TRUE (locks GUI), FALSE (unlock GUI) + + MGUI_FREEGUI - You can tell to Mgui class whether to free a GUI + or not. Usually, Mgui will mind GUI deallocation + after closing the GUI, so you don't have to + worry about it, but sometimes, it is better if + YOU do it by yourself. For example, in a + multi-gui list. This TAG will allow you to do + whatever you want with your GUI definition. + Possible values: TRUE (default) free the gui + definition. FALSE do not free gui definition. + NOTE: by default the gui definition WILL BE + freed. And you have to set this tag to FALSE + for every GUI you do not want to free. + + MGUI Tags, these are tags action on the mgui object as a whole: + + MGUI_ADDSIGMASK - With this tag you can add to mgui Wait() + signal some external signals you want mgui to + hear about. When the Wait() is trigged by + one of these sigs, the message isn't parsed + and the message() method will return it to + your control: you should be able to handle + this message correctly. + + MGUI_REMSIGMASK - With this tag you can remove an external + signal previously added with MGUI_ADDSIGMASK. + From now on, Wait() will not wait for it + anymore. + + MGUI_ADDEXTERNAL - This is a tag very similar to + MGUI_ADDSIGMASK, but this time, you have to + provide to mgui also a procedure to call + whenever the Wait() is trigged by the sig + you want. This is very useful, for example, + to wait for Commodity or ARexx events and + then to have mgui to handle all these stuff + for you. + The syntax is the following: + [MGUI_ADDEXTERNAL, [{procedure}, signal, + proc_params], + NIL, NIL] + + procedure - proc to call when Wait() is + trigged. + + signal - External signal to check. + + proc_params - Paramteres to pass to the + procedure. If you want to + pass more than one single + value, enclose them inside + []. Example: + [param1, param2, param3] + + MGUI_REMEXTERNAL - This tag removes a signal set with + MGUI_ADDEXTERNAL. From now on, Wait() will + not wait for external exents anymore. + Possible values: signal to remove. + Example: + [MGUI_REMEXTERNAL, signal, NIL, NIL] + + MGUI_LOCKALL - This tag will enable you to lock/unlock + ALL GUIs in one single shot. + Possible values: TRUE (locks GUIs), FALSE + (unlock GUIs) + + + NOTES: - Don't use EG_INFO in your program. Use MGUI_INFO instead. + + - Don't use EG_CLEAN in your program. Use MGUI_FREEPROC instead (it is + also more comfy than EG_CLEAN) + + RESULTS: NONE + + SEE ALSO: @{" message() " LINK mgui_message} + @{" action() " LINK mgui_action} + +@endnode + +@node mgui_lock "mgui / lock()" + + NAME: lock(mode=TRUE) + + DESCRIPTION: This method locks or unlocks current GUI. + + INPUTS: mode - TRUE locks the GUI (default), + + FALSE unlocks the GUI. + + RESULTS: NONE + + SEE ALSO: @{" setattrs() " LINK mgui_setattrs} + + EasyGUI/blockwin() + EasyGUI/unblockwin() +@endnode + +@node mgui_del "mgui / del()" + + NAME: del() + + DESCRIPTION: This method close current GUI. + The current GUI is closed and the proc set using + MGUI_FREEPROC tag is called to free resources. + + INPUTS: NONE + + RESULTS: PTR to next avaible GUI or NIL if it was the last GUI. + + + SEE ALSO: @{" add() " LINK mgui_add} + + @{" NodeMaster/del() " LINK "NodeMaster.guide/NodeMaster_del"} + +@endnode + +@node mgui_pos "mgui / pos() " + + NAME: pos(value, mode=MGUI_SEARCH_NAME, fromhere=FALSE) + + DESCRIPTION: This method will scan all GUIs to find the one matching the + value required. Value may vary and it is influenced by the + mode value. + + INPUTS: value - Value to search. + + mode - Search mode. Avaible modes are: + + MGUI_SEARCH_NAME - Compare value with GUI's name + field. + + MGUI_SEACH_GUIHANDLE - Compare value with GUI's + guihandle. + + MGUI_SEARCH_MAIN - Will search for the first + GUI with the main flag set. + + fromhere - Tells mgui whether to scan from the beginning + of the list of GUIs or just from the current + position. Default is FALSE: the list is scanned + from the first position. + + + RESULTS: a PTR to GUI - pos() succeded. + + NIL - pos() failed. + + NOTE: When the pos() has mode set to MGUI_SEARCH_MAIN, value is + ignored. + + SEE ALSO: + +@endnode + +@node mgui_nm "mgui / nm() " + + NAME: nm() + + DESCRIPTION: This method returns the PTR to the embedded + NodeMaster object. + + INPUTS: NONE + + RESULTS: a PTR to NodeMaster object. + + SEE ALSO: @{" NodeMaster " LINK "NodeMaster.guide/main"} +@endnode + +@node mgui_action "mgui / action() " + + NAME: action(actions) + + DESCRIPTION: This method is used to trig some actions on current GUI. + + INPUTS: actions - Action to perform on current GUI. + Current defined actions are: + + MGUI_ACTION_TOFRONT - Brings GUI window to front. + + MGUI_ACTION_TOBACK - Brings GUI window to back. + + MGUI_ACTION_ACTIVATE - Activate GUI window. + + These actions can be ORed together. Example: + + action(MGUI_ACTION_TOFRONT OR MGUI_ACTION_ACTIVATE) + + RESULTS: TRUE - Actions performed. + + FALSE - action() failed (maybe no GUI is avaible) + + + SEE ALSO: @{" setattrs() " LINK mgui_setattrs} + +@endnode + +@node mgui_version "mgui / version() " + + NAME: version() + + DESCRIPTION: This method returns current version and revision of the + mgui class currently in use. + + INPUTS: NONE + + RESULTS: This method returns TWO values: version and revision. + + SEE ALSO: + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/parser.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/parser.guide new file mode 100644 index 0000000..1c08bbc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/parser.guide @@ -0,0 +1,161 @@ +@database parser.guide + +@$VER: Parser V1.30 - By Fabio Rotondo (C)Brighting Brain Brothers + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: Parser" + + + + ** Parser - Original By Fabio Rotondo ** + + Part of the Amiga Foundation Classes + + @{" Introduction " link "Parser_introduction"} @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} @{" History " LINK "Parser_History"} + + Requires: Nothing. + + Class Base: $00090000 + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" parser(numelems=25) " link "Parser_Parser"} Initailizes the class. + @{" arg(n) " Link "Parser_Arg"} Returns n.th argument. + @{" parse(template, string) " Link "Parser_Parse"} Parses a string. + @{" version() " link "Parser_version"} Returns Parser version. + + @{" Error Table " LINK Parser_ErrorTable} +@endnode + +@node "Parser_Introduction" "Introduction" + + INTRODUCTION + + Parser is a class which relies on AmigaDOS ReadArgs() method to parse strings. + This is a very smart approach to, for example, ARexx argument parsing and can + lead to great results and incredibly flexible implementations. + + With Parser class you can use all standard AmigaDOS templates to parse a string. + + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + C++ Version By: Massimo Tantignone (tanti@intercom.it) + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + +@endnode + +@node Parser_ErrorTable "Parser / Error Table " + +VALUE | DESCRIPTION +----------------+---------------------------------- +$0000 | No Memory. +@endnode + +@node "Parser_Parser" "Amiga Foundation Classes: Parser/Parser()" + + NAME: parser(numelems=25) + + SYNOPSIS: VOID parser(ULONG numelems=25) + + DESCRIPTION: This is the class constructor. + You should pass the maximum number of elements to parse + at every call. Default value is 25 elements which should be + enought for everyday use. + + INPUT: numelems - (Optional) Number of elements to parse. + + RESULTS: + + SEE ALSO: +@endnode + +@node "Parser_Parse" "Amiga Foundation Classes: Parser/Parse()" + + NAME: parser(template:PTR TO CHAR, str:PTR TO CHAR) + + SYNOPSIS: RDArgs * parse(STRPTR template, STRPTR str) + + DESCRIPTION: This method parses a string using the provided template. + Templates are standard AmigaDOS templates, such as: + + "FILE/A,NAME/K,DELETE/S" + + INPUT: template - String parsing template. + + str - String to parse. + + RESULTS: a pointer to the resulting RDArgs structure. + Just check it against NIL (or NULL) which means "error". + + NOTE: The template string CANNOT contain white spaces. + + SEE ALSO: @{" arg() " LINK "Parser_arg"} +@endnode + +@node "Parser_arg" "Amiga Foundation Classes: Parser/arg()" + + NAME: arg(ULONG elem) + + SYNOPSIS: APTR arg(ULONG elem) + + DESCRIPTION: This method returns the argument 'elem'. + You MUST have parsed something to get reliable results. + + INPUT: elem - The (ordinal) number of the argument you wish to get. + The number starts from 0 and increments until the last + argument present in the template you provided to + @{" parse() " LINK "Parser_parse"} method. + Ex: + + "FILE/A,NAME/K,DELETE/S" + + 0 1 2 + + RESULTS: the pointer to the argument selected. + + SEE ALSO: @{" parse() " LINK "Parser_parse"} +@endnode + +@node "Parser_version" "Amiga Foundation Classes: Parser/version()" + + NAME: version() + + SYNOPSIS: ULONG version(BOOL revision = FALSE) + + DESCRIPTION: This method returns class version and revision. + + INPUT: NONE. + + RESULTS: this method returns TWO values: VERSION and REVISION. + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/rexxer.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/rexxer.guide new file mode 100644 index 0000000..81a9f92 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/rexxer.guide @@ -0,0 +1,354 @@ +@database rexxer.guide + +@$VER: Rexxer V1.10 - (C)Copyright Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: Rexxer" + + + + ** Rexxer - Original By Fabio Rotondo and Andrea Galimberti ** + + * Part of the Amiga Foundation Classes * + + @{" Introduction " link "Rexxer_introduction"} @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} @{" History " LINK "rexxer_history"} + + Requires: @{" validPortName " LINK "validPortName.guide/main"} + + Class Base: $000D0000 + + NEW COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" rexxer(portname, start) " link "Rexxer_Rexxer"} Initailizes the class. + @{" get(parserproc) " link "Rexxer_Get"} Gets an ARexx message. + @{" getanswer() " link "Rexxer_GetAnswer"} Gets an ARexx reply string from a host. + @{" name() " link "Rexxer_Name"} Returns the port name. + @{" port() " link "Rexxer_port"} Returns class port. + @{" rc() " link "Rexxer_rc"} Gets message RC. + @{" reply(mes, rc=0, resultstr=NIL) " link "Rexxer_reply"} Replies TO an ARexx message. + @{" result() " link "Rexxer_result"} Gets message result. + @{" send(hostname, command) " link "Rexxer_send"} Sends an ARexx message TO a program. + @{" sigbit() " link "Rexxer_sigbit"} Gets the signal bitmask of the class. + @{" version() " link "Rexxer_version"} Returns Rexxer version. + + + + @{" Error Table " LINK Rexxer_ErrorTable} +@endnode + +@node Rexxer_History "Amiga Foundation Classes: Rexxer / History" + + HISTORY + + v1.10 - Added the "validPortName" AFC function to allow better performances in + looking for the right ARexx Port name. + + v1.00 - First AFC release. + + Thanks to Wouter who fixed a very nasty problem in the send() method. + +@endNode + +@node "Rexxer_Introduction" "Introduction" + + INTRODUCTION + + Rexxer is a class to create and handle ARexx ports and messages. + Using this class, you'll be able to send messages to other programs, + to receive messages to external programs and to share data with them. + + This class has been designed to be extremely easy to use. + + We hope you'll like it. + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + Andrea Galimberti + + E Version By: Fabio Rotondo + Andrea Galimberti + + Addresses: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + + + + Andrea Galimberti + Via E.Villoresi 279 + Turbigo (MI) + ITALY + + Phone: (ITA) - (0)331 - 871009 (home) + +@endnode + +@node Rexxer_ErrorTable "Rexxer / Error Table " + +VALUE | DESCRIPTION +----------------+-------------------------------------------------------------------- +$0000 | No Memory. +$0001 | "Double Port": you are trying to create a port that already exists. +$0002 | Error during port creation. +$0003 | Cannot find "rexxsyslib.library" +$0004 | Error creating the message using CreateRexxMsg() call. +@endnode + +@node "Rexxer_Rexxer" "Amiga Foundation Classes: Rexxer/Rexxer()" + + NAME: rexxer(portname:PTR TO CHAR, start = 1) + + SYNOPSIS: rexxer(STRPTR portname, CHAR start = 1) + + DESCRIPTION: This is the class constructor. + During class initialization, the port of the Rexx handler + will be created, so you have to provide the port name as + a parameter. + + + INPUT: portname - Name of the port, ex. "AREXX_TEST" + NOTE: to follow Commodore's Style Guide, + you should provide a complete + UPPERCASE port name, without spaces. + + start - (Optional) The portname number. + Ex. in 'DOPUS.1' the ".1" is the number. + + NOTES: - The portname you should provide is just the basename. + + * DO NOT PROVIDE COMPLETE NAMES, SUCH AS 'DOPUS.1' * + * BUT JUST 'DOPUS' * + + - The ARexx Port name may differ from the original + basename + number you'll provide. + Use the @{" name() " LINK "Rexxer_name"} method to + know the _right_ name of your ARexx Port. + RESULTS: + + SEE ALSO: @{" name() " LINK "Rexxer_name"} + + @{" validPortName " LINK "validPortName.guide/main"} +@endnode + +@node "Rexxer_get" "Amiga Foundation Classes: Rexxer/get()" + + NAME: get(parseproc) + + SYNOPSIS: get((VOID *) parserproc (STRPTR)) + + DESCRIPTION: This method looks for queued ARexx messages and + pass them to the 'parseproc' you should provide. + The parseproc MUST return three values: + + quit - If TRUE, it means that the application should quit. + rc - RC result value + result - An (optional) result string. You can provide it ONLY + when RC is 0. + + INPUT: parseproc - Parsing procedure to be called. + + RESULTS: this method returns THREE values: + + quit + rc + result + + see above for their discussion. + + NOTES: The ARexx message received will be automatically replied with + rc and result parameters you will provide, using the + @{" reply() " LINK "Rexxer_reply"} method. + So remember: YOU SHOULD NOT REPLY TO A MESSAGE ARRIVED TO YOUR + PORT. + + SEE ALSO: @{" send() " LINK "Rexxer_send"} + @{" reply() " LINK "Rexxer_reply"} +@endnode + +@node "Rexxer_reply" "Amiga Foundation Classes: Rexxer/reply()" + + NAME: reply(mes:PTR TO rexxmsg, rc=0, resultstring = NIL) + + SYNOPSIS: void reply(struct RexxMsg * mes, LONG rc=0, STRPTR resultstr=NULL) + + DESCRIPTION: this method reply to a previosly received ARexx message. + If you use the @{" get() " LINK "Rexxer_get"} method + you should not worry about this method to reply to messages, + because they will be automatically replied. + + INPUT: mes - Original ARexx message + + rc - RC to return + + resultstring - Result String to return + + RESULTS: + + SEE ALSO: @{" get() " LINK "Rexxer_get"} +@endnode + +@node "Rexxer_send" "Amiga Foundation Classes: Rexxer/send()" + + NAME: send(hostname:PTR TO CHAR, command:PTR TO CHAR) + + SYNOPSIS: BOOL send(STRPTR hostname, STRPTR command) + + DESCRIPTION: this method sends an ARexx message to another program. + + INPUT: hostname - This is the port name of the program you wish + to contact (ex. 'DOPUS.1' for Directory Opus) + + command - The string you wish to send to the program you + are contacting. + + RESULTS: This method returns THREE values: + + success - TRUE means "Message sent successfully" + + FALSE "Something went wrong" (usually: port not found) + + rc - The RC code returned by the ARexx host contacted. + + result - The RESULT string returned by the ARexx host contacted. + + NOTE: It is safe to address the RESULT string with just a char pointer because + the RESULT string is stored internally in Rexxer class. + Of course, the RESULT string will not change until you'll create and send + a new ARexx message. + If you want to store the RESULT string for further uses, please consider + StrCopy()ing it inside a variable you own. + + SEE ALSO: @{" get() " LINK "Rexxer_get"} + @{" getanswer() " LINK "Rexxer_getanswer"} + @{" rc() " LINK "Rexxer_rc"} + @{" result() " LINK "Rexxer_result"} +@endnode + +@node "Rexxer_getanswer" "Amiga Foundation Classes: Rexxer/getanswer()" + + NAME: getanswer() + + SYNOPSIS: void getanswer( void ) + + DESCRIPTION: this method forces the Rexxer class to wait for an answer + from an hosts it has contacted. + + * This is a very LOW LEVEL function and you should never * + * use it for everyday applications, because it could hang * + * up your machine. Be carefull!!! * + + + INPUT: NONE + + RESULTS: This method returns TWO values: + + rc - The last RC arrived + + result - The last RESULT arrived + + SEE ALSO: @{" rc() " LINK "Rexxer_rc"} + @{" result() " LINK "Rexxer_result"} +@endnode + +@node "Rexxer_rc" "Amiga Foundation Classes: Rexxer/rc()" + + NAME: rc() + + SYNOPSIS: LONG rc( VOID ) + + DESCRIPTION: This method returns the last RC received by + @{" getanswer() " LINK "Rexxer_getanswer"} OR @{" send() " LINK Rexxer_send} + + INPUT: NONE + + RESULTS: a LONG value containing the last RC received. + + SEE ALSO: @{" send() " LINK "Rexxer_send"} + @{" getanswer() " LINK "Rexxer_getanswer"} + @{" result() " LINK "Rexxer_result"} +@endnode + +@node "Rexxer_result" "Amiga Foundation Classes: Rexxer/result()" + + NAME: result() + + SYNOPSIS: STRPTR result( VOID ) + + DESCRIPTION: This method returns the last result received by + @{" getanswer() " LINK "Rexxer_getanswer"} OR @{" send() " LINK Rexxer_send} + + INPUT: NONE + + RESULTS: a PTR TO CHAT (STRPTR) value containing the last result received. + + SEE ALSO: @{" send() " LINK "Rexxer_send"} + @{" getanswer() " LINK "Rexxer_getanswer"} + @{" rc() " LINK "Rexxer_rc"} +@endnode + +@node "Rexxer_name" "Amiga Foundation Classes: Rexxer/name()" + + NAME: name() + + SYNOPSIS: STRPTR name( VOID ) + + DESCRIPTION: This method returns the ARexx Port name. + + INPUT: NONE + + RESULTS: a PTR TO CHAT (STRPTR) value containing the ARexx Port Name. + + SEE ALSO: @{" validPortName() " LINK "validPortName.guide/main"} +@endnode + +@node "Rexxer_port" "Amiga Foundation Classes: Rexxer/port()" + + NAME: port() + + SYNOPSIS: MsgPort * port( VOID ) + + DESCRIPTION: This method returns a pointer TO the message port of the class. + + INPUT: NONE + + RESULTS: a MsgPort * value relative TO the Port of the class. + + SEE ALSO: +@endnode + +@node "Rexxer_sigbit" "Amiga Foundation Classes: Rexxer/sigbit()" + + NAME: sigbit() + + SYNOPSIS: ULONG sigbit( VOID ) + + DESCRIPTION: This method returns the signal bit mask FOR the Wait() + command. + + INPUT: NONE + + RESULTS: a LONG containing the signal bitmask. + + SEE ALSO: +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/super_picture.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/super_picture.guide new file mode 100644 index 0000000..c0a882f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/super_picture.guide @@ -0,0 +1,523 @@ +@database super_picture.guide + +@$VER: Super_Picture V1.50 - (C)Copyright Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node "Main" "Amiga-E MODULE: Super_Picture" + + + + ** Super_Picture - Original By Fabio Rotondo ** + + ** This Object is part of the Amiga Foundation Classes ** + + ** DOCUMENTATION GUIDE ** + + @{" Introduction " link "Super_Picture_introduction" 0} @{" Author Info " LINK "author"} @{" Amiga Foundation Classes " LINK "afc.guide/main"} @{" History " LINK "Super_Picture_History"} + + Requires: @{" IFFParser " LINK "IFFParser.guide/main"}, @{" Bitmapper " LINK "bitmapper.guide/main"} + + Base: $0007000 + + COMMANDS BRIEF DESCRIPTION + ------------------------------------------------------------------------- + @{" super_picture(pal=TRUE) " link "Super_Picture_Super_Picture" 0} Class Constructor. + @{" bitmap() " LINK "Super_Picture_bitmap"} Returns picture's bitmap. + @{" bmhd() " LINK "Super_Picture_bmhd"} Returns the BitmapHeader. + @{" bmobj() " LINK "Super_Picture_bmobj"} Returns embedded bitmapper. + @{" check(filename) " link "Super_Picture_check"} Checks if the file is a valid ILBM. + @{" clear() " link "Super_Picture_clear"} Frees all memory. + @{" cludge() " LINK "Super_Picture_cludge"} Converts a memory area into a picture. + @{" depth() " LINK "Super_Picture_depth"} Returns picture's depth. + @{" dtload(fname, layers, rport, scr) " LINK "Super_Picture_dtload"} Loads a picture using DataTypes only. + @{" dump() " LINK "Super_Picture_dump"} Dumps a picture inside a file in raw format. + @{" height() " LINK "Super_Picture_height"} Returns picture's height. + @{" image() " LINK "Super_Picture_image"} Creates and returns picture's image structure. + @{" load(fname, layers, rport, trap) " link "Super_Picture_load"} Loads up a picture. + @{" loadraw(filename) " LINK "Super_Picture_loadraw"} Loads a dumped file into memory. + @{" modeid() " LINK "Super_Picture_modeid"} Returns picture's ModeID. + @{" numcols() " LINK "Super_Picture_numcols"} Returns number of colours. + @{" palette() " LINK "Super_Picture_palette"} Returns the picture's palette. + @{" paltoscr(screen) " link "Super_picture_paltoscr"} Set the screen palette. + @{" width() " LINK "Super_Picture_width"} Returns picture's width. + @{" version() " link "Super_Picture_version" 0} Returns class version AND revision. + + @{" Error Table " LINK "Super_Picture_ErrorTable"} + +@endnode + +@node Super_Picture_History "Amiga Foundation Classes: Super_Picture / History" + + HISTORY + + V1.50 - Add: @{" dtload() " LINK Super_Picture_dtload} method + + Enh: now datatype loading supports remapping + + Enh: Added an optional parameter to the @{" load() " LINK Super_Picture_load} method. + + V1.40 - Add: image() method + + V1.30 - Add: dump() method + + V1.20 - Fix: small bug in decodebody() method + + V1.10 - Add: cludge() method + + V1.00 - Inital release + +@endnode + +@node author "Author(s) Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) +@endnode + +@node "Super_Picture_introduction" "Introduction" + + Super Picture Class - Introduction + + This is a very useful class which interfaces the programmer with OS2.0 and OS3.0 + features in loading pictures. + This class allows you to load any kind of picture (via DataTypes) without worrying + about interfacing with datatypes.library, because it does it all by itself. + + The great thing is that is the class itself which knows if DataTypes are avaible + or not and, if not, the class will just handle standard ILBM IFF files, using a + very fast ILBM decoding routine built in: no need of iff.library or any other + "non-standard Amiga" libraries. + + I hope you will enjoy this class. + + Fabio Rotondo + + + NOTE: many thanks to Alfred P. Schwarz, who elped me in writing the image() method. +@endnode + +@node Super_Picture_ErrorTable "Super_Picture / Error Table" + +ERROR VALUE | DESCRIPTION +----------------+------------------------------------- + $0000 | No Memory + $0001 | Could not open 'datatypes.library' + $0002 | Could not create datatype OBJECT + $0003 | DoMethod() call failed + $0004 | Could not save file + $0005 | Could not open file FOR saving + $0006 | BitMapHeader Chunk not found + $0007 | ColorMap chunk not found + $0008 | Body Chunk not found +@endnode + +@node "Super_Picture_Super_Picture" "Amiga Foundation Classes: Super_Picture/Super_Picture()" + NAME: super_picture(pal=TRUE) + + DESCRIPTION: This is the class constructor. + + INPUT: pal - (DEFAULT: TRUE) this is a flag and it is used to tell + the class whether you want to store also a palette along + with picture data or not. + NOTE: if you set it to TRUE, additional 256*3 bytes of memory + will be allocated during construction. + + + RESULTS: NONE. + + SEE ALSO: +@endnode + +@node "Super_Picture_clear" "Amiga Foundation Classes: Super_Picture/clear()" + + NAME: clear() + + DESCRIPTION: This method will free all allocated resources inside a + super_picture class. + + INPUT: NONE. + + RESULTS: Memory will be freed. + + NOTE: It is safe to call this method also if the class has not been + used yet. + + SEE ALSO: @{" bitmapper / clear() " LINK "bitmapper.guide/bitmapper_clear"} +@endnode + +@node "Super_Picture_load" "Amiga Foundation Classes: Super_Picture/load()" + + NAME: load(fname: PTR TO CHAR, layers=FALSE, rastport=FALSE, trap=FALSE, scr=NIL) + + DESCRIPTION: This is the biggy. This method will try to load a picture in + memory. If the user has OS3.0+, also all picture formats + supported by datatypes can be loaded. Under OS2.0+ only ILBM + IFF files will be supported. + + INPUT: fname - The file name of the picture you wish to load. + + layers - (DEFAULT: FALSE) If you want to create a layer + related to the picture you are loading, + set this to TRUE. + + rastport - (DEFAULT: FALSE) If you want to create a + rastport to the picture you are loading, + set this to TRUE. + + trap - (DEFAULT: TRUE) If the picture does not + exists (i.e. "File not found"), then the + class WILL NOT return raise any error, + but you will get the error number as + a return code (you can also ignore it, + if you want.) + If it is set to FALSE, then the class + will raise an exception. + + scr - (DEFAULT: NIL) You can provide a screen + from where the palette will be used to + remap the picture during loading. + This remap works only on DataTypes pictures + at the moment. + + RESULTS: if trap is TRUE and an error occurred, you will have as a + result the error value. + + SEE ALSO: @{" dtload() " LINK "Super_picture_dtload"} + @{" Bitmapper / allocbitmap() " LINK "bitmapper.guide/bitmapper_allocbitmap"} + @{" IFFParser / load() " LINK "iffparser.guide/iffparser_load"} +@endnode + +@node "Super_Picture_check" "Amiga Foundation Classes: Super_Picture/check()" + + NAME: check(filename : PTR TO CHAR) + + DESCRIPTION: This method checks the given file and says if it is a valid + IFF ILBM file or not. + + INPUT: filename - Name of the file to check + + RESULTS: TRUE - It is a valid IFF ILBM file + + FALSE - It is not a valid IFF ILBM file + + NOTE: Usually, you should not use this method, because the + @{" load() " LINK "Super_Picture_load"} method will do this check for you. + + SEE ALSO: @{" IFFParser / getheader() " LINK "IFFParser.guide/IFFParser_getheader"} +@endnode + +@node "Super_Picture_paltoscr" "Amiga Foundation Classes: Super_Picture/paltoscr()" + + NAME: paltoscr(scr:PTR TO screen) + + DESCRIPTION: This method set up the palette of a screen accordingly to the + picture palette. + + INPUT: scr - A *valid* screen pointer. + + RESULTS: NONE. + + SEE ALSO: +@endnode + +@node "Super_Picture_bmhd" "Amiga Foundation Classes: Super_Picture/bmhd()" + + NAME: bmhd() + + DESCRIPTION: This method returns the current BitMapHeader. + + INPUT: NONE. + + RESULTS: A pointer to a valid BitMapHeader structure. + + SEE ALSO: +@endnode + +@node "Super_Picture_bitmap" "Amiga Foundation Classes: Super_Picture/bitmap()" + + NAME: bitmap() + + DESCRIPTION: This method returns a pointer to the current bitmap structure. + + INPUT: NONE. + + RESULTS: a pointer to a Bitmap structure. It may be NIL. + + SEE ALSO: @{" bitmapper / bitmap() " LINK "bitmapper.guide/bitmapper_bitmap"} +@endnode + +@node "Super_Picture_numcols" "Amiga Foundation Classes: Super_Picture/numcols()" + + NAME: numcols() + + DESCRIPTION: This method returns the number of colours of the loaded picture. + + INPUT: NONE. + + RESULTS: number of colours of the picture. It may be 0. + + SEE ALSO: +@endnode + +@node "Super_Picture_modeid" "Amiga Foundation Classes: Super_Picture/modeid()" + + NAME: modeid() + + DESCRIPTION: This method returns the default modeid of the picture. + The ModeID is the standard monitor value for displaying the + picture. + + INPUT: NONE. + + RESULTS: a LONG value, containing the ModeID. + + SEE ALSO: +@endnode + +@node "Super_Picture_width" "Amiga Foundation Classes: Super_Picture/width()" + + NAME: width() + + DESCRIPTION: This method returns picture's width. + + INPUT: NONE. + + RESULTS: a INT containing picture's width. It may be 0. + + SEE ALSO: @{" height() " LINK "Super_Picture_height"} + @{" depth() " LINK "Super_Picture_depth"} +@endnode + +@node "Super_Picture_height" "Amiga Foundation Classes: Super_Picture/height()" + + NAME: height() + + DESCRIPTION: This method return picture's height. + + INPUT: NONE. + + RESULTS: a INT value containing the picture's height. It may be 0. + + SEE ALSO: @{" width() " LINK "Super_Picture_width"} + @{" depth() " LINK "Super_Picture_depth"} +@endnode + +@node "Super_Picture_depth" "Amiga Foundation Classes: Super_Picture/depth()" + + NAME: depth() + + DESCRIPTION: This method returns the picture's depth. + + INPUT: NONE. + + RESULTS: a BYTE value containing the picture depth. It may be 0. + + SEE ALSO: @{" width() " LINK "Super_Picture_width"} + @{" height() " LINK "Super_Picture_height"} +@endnode + +@node "Super_Picture_Super_Picture" "Amiga Foundation Classes: Super_Picture/Super_Picture()" + + NAME: rastport() + + DESCRIPTION: This method returns a pointer to the picture's rastport. + + INPUT: NONE + + RESULTS: a ptr to the picture's rastport. It may be NIL. + + SEE ALSO: @{" bitmapper / rastport() " LINK "bitmapper.guide/bitmapper_rastport"} +@endnode + +@node "Super_Picture_bmobj" "Amiga Foundation Classes: Super_Picture/bmobj()()" + + NAME: bmobj() + + DESCRIPTION: This method returns a pointer to the embedded bitmapper class. + + INPUT: NONE. + + RESULTS: a ptr to the embedded bitmapper class: USE IT AT YOUR OWN RISK! + + SEE ALSO: @{" bitmapper " LINK "bitmapper.guide/main"} +@endnode + +@node "Super_Picture_palette" "Amiga Foundation Classes: Super_Picture/palette()" + + NAME: palette() + + DESCRIPTION: This method returns picture's palette. + + INPUT: NONE. + + RESULTS: it returns a pointer to picture's palette. Please note, it behaves + differently under OS2.0 and OS3.0: + + OS2.0 - It is just a 8 bit palette + + OS3.0+ - It is a 32Bit palette. + + Please, note also that this method returns TWO values: the pointer + to the palette and palette bits involved. + + I.e. under OS2.0 it may return: $10293102, 8 + under OS3.0+ it may return: $10293102, 32 + + SEE ALSO: +@endnode + +@node "Super_Picture_version" "Amiga Foundation Classes: Super_Picture/version()" + + NAME: version() + + DESCRIPTION: This method returns class version and revision. + + INPUT: NONE. + + RESULTS: This method returns TWO values, version and revision. + + SEE ALSO: +@endnode + +@node "Super_Picture_cludge" "Amiga Foundation Classes: Super_Picture/cludge()" + + NAME: cludge(mem:PTR TO CHAR) + + DESCRIPTION: This method converts a memory area into a bitmap. + + INPUT: mem - PTR to the starting memory area. + + RESULTS: + + NOTE: this MUST be a _valid_ memory area created using the + @{" dump() " LINK "Super_Picture_dump"} method. + + SEE ALSO: @{" dump() " LINK "Super_Picture_dump"} + @{" bitmapper / cludge() " LINK "bitmapper.guide/bitmapper_cludge"} + +@endnode + +@node "Super_Picture_dump" "Amiga Foundation Classes: Super_Picture/Super_Picture()" + + NAME: dump(filename) + + DESCRIPTION: This method dumps the current picture into a file in raw format. + + INPUT: filename - Name of the file where to dump the picture. + + RESULTS: NONE. + + NOTE: Current version of this method does not save the palette. + + SEE ALSO: @{" cludge() " LINK "Super_Picture_cludge"} + @{" bitmapper / dump() " LINK "bitmapper.guide/bitmapper_dump"} +@endnode + +@node "Super_Picture_loadraw" "Amiga Foundation Classes: Super_Picture/loadraw()" + + NAME: loadraw(filename) + + DESCRIPTION: This method loads a file created with @{" dump() " LINK "Super_Picture_dump"} method + and creates a picture. + + INPUT: filename - Name of the raw data file to load. + + RESULTS: The picture will be loaded inside the object. + + NOTE: All data in the object will be lost. + + SEE ALSO: @{" clear() " LINK "Super_Picture_clear"} + @{" dump() " LINK "Super_Picture_dump"} + @{" bitmapper / loadraw() " LINK "bitmapper.guide/bitmapper_loadraw"} +@endnode + +@node "Super_Picture_image" "Amiga Foundation Classes: Super_Picture/image()" + + NAME: image() + + DESCRIPTION: Sometimes, it is usefull to obtain picture Image structure, the one + used by Ituition gadgets. Using this method, you can obtain this + Image structure. + + INPUT: NONE + + RESULTS: a pointer to a valid Image structure. + + NOTE: This method is *slow* the first time you call it, because it has + to create the Image structure and picture. Then, it will be + fastlighting, until you don't load another picture in the class. + + SEE ALSO: @{" Bitmapper / image() " LINK "Bitmapper.guide/Bitmapper_image"} + +@endnode + +@node "Super_Picture_dtload" "Amiga Foundation Classes: Super_Picture/dtload()" + + NAME: dtload(fname: PTR TO CHAR, layers=FALSE, rastport=FALSE, scr=NIL:PTR TO screen) + + DESCRIPTION: This is a lower level method than the @{" load() " LINK "Super_Picture_Load"} one. + Using this method you will load a picture using DataTypes ONLY. + This means that you can use this only on OS3.0+. + + This method is faster than the @{" load() " LINK "Super_Picture_Load"} one because + it does not perform the usual "format checking" before trying to load the + picture. + + + + This is the biggy. This method will try to dtload a picture in + memory. If the user has OS3.0+, also all picture formats + supported by datatypes can be dtloaded. Under OS2.0+ only ILBM + IFF files will be supported. + + INPUT: fname - The file name of the picture you wish to dtload. + + layers - (DEFAULT: FALSE) If you want to create a layer + related to the picture you are dtloading, + set this to TRUE. + + rastport - (DEFAULT: FALSE) If you want to create a + rastport to the picture you are dtloading, + set this to TRUE. + + scr - (DEFAULT: NIL) You can provide a pointer to + a screen as the last parameter. + If a screen pointer is passed, then the picture + will be remapped accordingly to the palette + attatched to the provided screen. + + NOTE: This method CANNOT be trapped. If an error occurred, it will raise + an error. + + RESULTS: NOTHING. + + + SEE ALSO: @{" load() " LINK "Super_Picture_Load"} + @{" Bitmapper / allocbitmap() " LINK "bitmapper.guide/bitmapper_allocbitmap"} + @{" IFFParser / dtload() " LINK "iffparser.guide/iffparser_dtload"} +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Docs/validPortName.guide b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/validPortName.guide new file mode 100644 index 0000000..4edd6fb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Docs/validPortName.guide @@ -0,0 +1,102 @@ +@database validPortName.guide + +@$VER: validPortName V1.00 - (C)Copyright Amiga Foundation Classes + +This guide file has been created using AutoGuide V1.05 - By Fabio Rotondo (fsoft@intercom.it). + +@node Main "Amiga Foundation Classes: validPortName" + + + + ** validPortName - Original By Fabio Rotondo ** + + * Part of the Amiga Foundation Classes * + + @{" Introduction " link "validPort_introduction"} @{" Author's Info " link "author"} @{" Amiga Foundation Classes " LINK "AFC.Guide/main"} @{" History " LINK "validPort_History"} + + + + NAME: validPortName(basename:PTR TO CHAR, count=1) + + SYNOPSIS: STRPTR validPortName(STRPTR basename, CHAR count=1) + + DESCRIPTION: This function helps you TO find an unique Message Port name. + The messahe port will be created in the standard format: + + basename.number + + For example: + + 'DOPUS.1', 'IMAGEFX.2' ... + + Where 'basename' is 'DOPUS' and 'IMAGEFX' and number is 1 and 2. + + + INPUT: basename - It must be a *valid* string pointer + that _MUST_ be large enough to handle the + resulting Message Port name. + + count - (Optional) Starting number value. + Default is 1. + + + + RESULTS: portname - A valid (unique) port name. + + NOTE: The portname will be copied in basename, so be sure that the + the string you pass as parameter is large enough to handle + the portname correctly. + + SEE ALSO: + +@endnode + +@node "validPort_Introduction" "Introduction" + + + INTRODUCTION + + validPortName is a function that will help you TO find an unique + Message Port name. + + It is extremely easy TO use AND, even IF it isn't really a class, + it will be included inside the standard AFC distribution because it + is used by various classes. + +@endnode + +@node "author" "Author's Info" + + Original By: Fabio Rotondo (fsoft@intercom.it) + + E Version By: Fabio Rotondo + + Address: + + Fabio Rotondo + C.so Vercelli 9 + 28100 Novara + ITALY + + e-mail: fsoft@intercom.it + Fabio.Rotondo@deagostini.it + + Phone: (ITA) - (0)321 - 459676 (home) + (ITA) - (0)2 - 38086520 (office) + (ITA) - (0)338 - 7336477 (GSM Phone) + + Fax: (ITA) - (0)2 - 38086278 + + Web: http://www.intercom.it/~fsoft (my home page) + + http://www.intercom.it/~fsoft/ablast.html (Amiga Blast Home Page) + +@endnode + +@node validport_history "Amiga Foundation Classes: validPortName / HISTORY" + + HISTORY + + V1.00 - Initial Release +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/EasyGUI_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/EasyGUI_Example.e new file mode 100644 index 0000000..9b1a9af --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/EasyGUI_Example.e @@ -0,0 +1,101 @@ +/* +** NodeMaster_EGui.e +** +** (C)1996/97 Amiga Foundation Classes +** +** This code is placed in the Public Domain. +** It is intended FOR demostration of NodeMaster only. +** +** Feel free of examine, modify AND DO whatever you want! +** +*/ + +/* +** DESCRIPTION: +** +** NodeMaster can HANDLE Exec Lists of everything. +** +** Just TO show its power, you'll see a way of creating +** multiwindows application relying on Wouter's EasyGUI AND +** my NodeMaster. This application is quite complicated AND I'll try TO +** explain it in the better way I can. ;) +*/ +OPT OSVERSION = 37 + +MODULE 'afc/nodemaster', -> This is OUR MODULE + 'afc/explain_exception', + 'tools/easygui' -> 'tools/easygui'... GUESS! + +DEF nm:PTR TO nodemaster -> This is an hinstance of our NodeMaster + +PROC main() HANDLE -> Please, note: HANDLE keyword FOR EXCEPTIONS handling + NEW nm.nodemaster() -> Here we setup our OBJECT. + + dogui() -> we MUST have at least one gui! + + REPEAT -> We will hear FOR GUI events + multiwait() -> (Of multiple windows ;) ... + UNTIL FALSE + +EXCEPT DO -> In CASE of some problems... (OR just TO quit) + explain_exception() + closeall() + END nm -> Remeber ALWAYS TO END a OBJECT!!! + CleanUp(0) -> Let's keep things clean... +ENDPROC + +PROC dogui() HANDLE -> This PROC creates a GUI on the WB screen + DEF gh=NIL:PTR TO guihandle -> a guihandle (NOTE: It is LOCAL! ;) + + gh:=guiinitA('NEW EasyGUI Window!', + [EQROWS, + [SBUTTON, {dogui}, 'Create!'], -> This button just call dogui() again! + [BAR], + [SBUTTON, {do_quit},'Quit!'] -> This will quit ALL! + ]) + + nm.add(gh) -> Here we add this GUI_handle TO our NodeMaster OBJECT + Wait(gh.sig) -> AND wait FOR this window's first signal + +EXCEPT -> In CASE of any error + remgui(gh) -> we remove THIS window from thje Windows LIST + ReThrow() -> AND rethrow() error one level up! +ENDPROC + +PROC multiwait() -> This is one of the most important PROCS! + DEF gh:PTR TO guihandle -> Another LOCAL gui_handle var! + DEF res -> Here we store Window event value... + + IF nm.first() -> Let's start from the first GUI_handler we have stored... + REPEAT + gh:=nm.obj() -> Here we set our gh TO original GUI_handler + res:=guimessage(gh) -> We get one message + IF res>=0 -> AND eventually close this GUI window + remgui(gh) + ENDIF + UNTIL nm.succ() = FALSE -> Now we JUMP TO the next one + ENDIF +ENDPROC + +PROC do_quit() IS Raise("END!") + +PROC closeall() -> This PROC just close ALL opened windows + + IF nm.first() -> We start from the first + REPEAT + cleangui(nm.obj()) -> we clear things up + UNTIL nm.succ() = FALSE -> AND get the next + ENDIF +ENDPROC + +PROC remgui(gh:PTR TO guihandle) -> This PROC remove just one desired gui + IF nm.first() -> Here we scan LIST from the first + REPEAT + IF gh = nm.obj() -> IF the current item is exactly the one we want + nm.del() -> We remove the item from the LIST + cleangui(gh) -> AND clear the interface + RETURN -> THEN exit without ending the LOOP + ENDIF + UNTIL nm.succ() = FALSE -> Here we look FOR the next item... + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/First_Del_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/First_Del_Example.e new file mode 100644 index 0000000..03cdcf9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/First_Del_Example.e @@ -0,0 +1,60 @@ +/* +** StringNode Example-2 +** +** add(), del(), first(), succ() AND last() methods. +** +** (C)Copyright 1996/97 Amiga Foundation Classes +** +** See: http://www.intercom.it/~fsoft/afc.html +** +** FOR more info about AFC AND more modules +*/ + +MODULE 'afc/StringNode', -> Our MAGIC MODULE + 'afc/Explain_Exception' + +PROC main() HANDLE + DEF n:PTR TO stringnode -> This is our OBJECT instance + + NEW n.stringnode() -> OBJECT initialization + + n.add('Zorro') -> Here we add some items... + n.add('Batman') + n.add('Superman') + n.add('Gold Drake') + n.add('Mandrake') + n.add('MOMMY') + + shwall(n) -> Here we see them + + n.first() -> This method should be checked agains FALSE... + n.del() -> It is DEAD! + shwall(n) -> Show Results + + n.succ() -> Two items later... (The first killed...) + n.del() -> Another Kill! + shwall(n) -> Show Results + + n.last() -> The last item + n.del() -> Is DEAD too! + WriteF('Last:\s\n', n.obj()) -> Now this is the last + shwall(n) + +EXCEPT DO + explain_exception() + END n -> Remember ALWAYS TO end an OBJECT + CleanUp(0) +ENDPROC + +PROC shwall(n:PTR TO stringnode) + WriteF('------- \d ----------\n', n.numitems()) + + IF n.first() -> Here we go TO the first node item + REPEAT + WriteF('Node:\s\n', n.obj()) -> Node STRING... + UNTIL n.succ() = FALSE -> LOOP UNTIL the end + ELSE + WriteF('No Nodes in LIST...\n') + ENDIF +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Hardsprite_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/Hardsprite_Example.e new file mode 100644 index 0000000..0c8284f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Hardsprite_Example.e @@ -0,0 +1,72 @@ +/* + + $VER: HardSprite Example 1 - (C)Copyright Amiga Foundation Classes + + Written By: Andrea Galimberti + + This code is Public Domain + + + +*/ + +MODULE 'AFC/hardsprite', + 'AFC/explain_exception', + 'intuition/screens' + + + +PROC main() HANDLE + DEF scr=NIL:PTR TO screen + DEF vp, spr:PTR TO hardsprite + DEF x,y,dx,dy + + NEW spr.hardsprite(2) -> allocate sprite number 2 (IF available) + + spr.image(15,[$0180,$0000, + $03C0,$0000, + $07E0,$0000, + $0FF0,$0000, + $1FF8,$0180, + $3FFC,$03C0, + $7FFE,$07E0, + $FFFF,$0FF0, + $7FFE,$07E0, + $3FFC,$03C0, + $1FF8,$0180, + $0FF0,$0000, + $07E0,$0000, + $03C0,$0000, + $0180,$0000]:INT) -> the LIST must be OF INT type + + + scr:=OpenScreenTagList(NIL,[SA_TOP,0, + SA_LEFT,0, + SA_WIDTH,320, + SA_HEIGHT,256, + SA_DEPTH,5, + SA_TITLE,'Sprite Test', + NIL,NIL] + ) + IF scr=NIL THEN Raise("scr") + vp:=scr.viewport + + x:=36; y:=0 + dx:=1; dy:=1 + + spr.changeImage(vp) + spr.move(vp,x,y) + REPEAT + x:=x+dx; y:=y+dy + IF (x=304) OR (x=0) THEN dx:=-dx + IF (y=240) OR (y=0) THEN dy:=-dy + spr.move(vp,x,y) + WaitTOF() + UNTIL Mouse() + +EXCEPT DO + END spr + IF scr THEN CloseScreen(scr) + explain_exception() +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example.e new file mode 100644 index 0000000..8a06ae0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example.e @@ -0,0 +1,85 @@ +/* +** IFFParser_oo Example 1 +** +** Here you will see how to +** write some chunks and then read them again! +** +** This code is meant for demostration only. +** +** Feel free of examine, modify or rip it! +** +** (C)Copyright 1997 Amiga Foundation Classes. +** +** PD Source Code. +** +*/ + +MODULE 'afc/IFFParser', -> Our MAGIC MODULE! + 'afc/explain_exception' + +PROC main() HANDLE -> NOTE: Exception handling! + DEF iff:PTR TO iffparser -> OBJECT instance + DEF buf[128]:STRING -> a STRING ;) + DEF s:PTR TO CHAR + + NEW iff.iffparser() -> Let's create it! + + iff.save('Ram:Test.IFF') -> First Of ALL let's save an ugly IFF file + iff.createchunk("DEMO","FORM") -> This is the FORM chunk! + + iff.createchunk("DEMO","FTXT") -> This is a FTXT (not exactly 8) chunk! + StrCopy(buf, 'DO you like my object?') -> Here we fill our STRING... + iff.writechunk(buf, StrLen(buf)+1) -> AND write it into the chunk! + iff.closechunk() -> AND THEN we close the chunk... + + iff.createchunk("DEMO","FTXT") -> Another chunk! + StrCopy(buf, 'Is not that easy TO create IFF files with this object?') + iff.writechunk(buf, StrLen(buf)+1) + iff.closechunk() + + iff.createchunk("DEMO","FTXT") -> AND the last FTXT chunk! + StrCopy(buf, 'What a kind of magic!') + iff.writechunk(buf, StrLen(buf)+1) + iff.closechunk() + + iff.createchunk("DEMO","INFO") -> Whaaaat?!?! a nek kind of chunk! + StrCopy(buf, 'Hello ALL, I\qm the INFO chunk!') + iff.writechunk(buf, StrLen(buf)+1) + iff.closechunk() + + iff.closechunk() -> Here we close DEMO FORM chunk! + iff.close() -> AND here we close IFF save file session. + + iff.getheader(buf,'Ram:Test.IFF') -> What kind of file we created? + WriteF('\s\n', buf) + + + iff.load('Ram:Test.IFF') + iff.setscan("DEMO","FTXT") -> Let's load ALL FTXT chunks! + iff.setscan("DEMO","INFO") -> Let's load ALL INFO chunks also! + iff.exit("DEMO","FORM") -> We will stop when FORM ends! + + iff.scan() -> Here comes the sun! + + IF (s:=iff.first("DEMO","INFO")) -> Here we pos TO the first INFO chunk + REPEAT + WriteF('INFO txt:\s\n', s) -> We WriteF() it + UNTIL (s:=iff.succ()) = FALSE -> AND get the next one + ENDIF + + IF (s:=iff.first("DEMO","FTXT")) -> Here we pos TO the first FTXT chunk + REPEAT + WriteF('FTXT txt:\s\n', s) -> We WriteF() it + UNTIL (s:=iff.succ()) = FALSE -> AND get the next one + ENDIF + + iff.close() -> Here we close ALL resources + + +EXCEPT DO + WriteF('Here we die!\n') + explain_exception() + END iff -> ALWAYS END the OBJECT before exiting!!!! + CleanUp(0) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example2.e b/amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example2.e new file mode 100644 index 0000000..1da741d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/IFFParser_Example2.e @@ -0,0 +1,58 @@ +/* +** IFFParser_oo Example 2 +** +** This code shows how to load/save +** a very simple IFF preferences file. +** +** (C)Copyright 1997 Amiga Foundation Classes. +** +** This code is placed in the PD +** and may be intended for explanation only. +** +*/ + +MODULE 'afc/iffparser', -> Our MAGIC MODULE! + 'afc/explain_exception' + +OBJECT testprefs -> This is our little prefs structure + x + y + w + h +ENDOBJECT + +PROC main() HANDLE + DEF iff:PTR TO iffparser -> This is our object instance + DEF t:testprefs -> Here there is our prefs var + DEF n=NIL:PTR TO testprefs -> And just a ptr to it + + NEW iff.iffparser() -> First of all we have to INIT the object + + t.x := 1 -> Here we set some dummy values inside + t.y := 2 -> Our prefs var + t.w := 3 + t.h := 4 + + iff.save('ENV:Test.prefs') -> Here we begin to write our prefs file + iff.createchunk("PREF","FORM") -> This is the FORM chunk + iff.createchunk("PREF","PRHD") -> And inside this one + iff.writechunk(t, SIZEOF testprefs) -> We will store the prefs var + iff.closechunk() -> And close it + iff.closechunk() -> Here we close the FORM chunk + iff.close() -> End of IFF save session. + + iff.load('ENV:Test.prefs') -> Now we have to try to read it again! + iff.setscan("PREF","PRHD") -> We look for PRHD inside PREF + iff.exit("PREF","FORM") -> The search will stop at the end of FORM + iff.scan() -> Scan! + IF (n:=iff.first("PREF","PRHD")) -> If there is at least one item... + WriteF('x:\d - y:\d\nw:\d - h:\d\n', n.x, n.y, n.w, n.h) -> Show it! + ENDIF + iff.close() -> End of IFF load session + +EXCEPT DO + explain_exception() -> Just to know exception name + WriteF('Cleaning Up... \n') + END iff -> ALWAYS END THE OBJECT BEFORE EXITING!!! + CleanUp(0) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Localer_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/Localer_Example1.e new file mode 100644 index 0000000..a258615 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Localer_Example1.e @@ -0,0 +1,35 @@ +/* + + Localer Example 1 - (C)Copyright Amiga Foundation Classes + + Written By: Fabio Rotondo + + Public Domain Source + +*/ + +MODULE 'afc/localer' + +PROC main() + DEF loc:PTR TO localer + + NEW loc.localer() + + WriteF('System Language:\s\n', loc.language()) + +/* + + Since we don't have any ".catalog" provided with this + example, the loading will fail AND the get() method + will RETURN DEFAULT messages + +*/ + + loc.load('test.catalog') + + + WriteF('\s - \s\n', loc.get(0, 'Test'), loc.get(1, 'Message!')) + + END loc +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/MGUI_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/MGUI_Example1.e new file mode 100644 index 0000000..ca3af47 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/MGUI_Example1.e @@ -0,0 +1,92 @@ +OPT OSVERSION=37 +OPT LARGE + +MODULE 'afc/mgui', + 'afc/explain_exception', + 'tools/easyGUI', + 'exec/ports', + 'intuition/intuition' + +DEF times=0 + +PROC main() HANDLE + DEF mg=NIL:PTR TO mgui + DEF win=NIL:PTR TO window + DEF sig + + NEW mg.mgui() + + mg.addA('MGUI Main', [ROWS, + [SBUTTON, {kill_all}, 'Kill ALL'], + [SBUTTON, {newgui}, 'NEW!'], + [SBUTTON, {hideall}, 'Hide'], + [SBUTTON, {showall}, 'Show'] + ], + [MGUI_MAIN, TRUE, + NIL, NIL] + ) + + test(mg) + test(mg) + test(mg) + + IF (win:=OpenWindowTagList(NIL, [WA_WIDTH, 200, + WA_HEIGHT, 100, + WA_TITLE, 'Click Inside!', + WA_IDCMP, IDCMP_MOUSEBUTTONS, + NIL, NIL]))=NIL THEN Raise("win") + + sig:=win.userport::mp.sigbit + sig:=Shl(1, sig) + + mg.setattrs([MGUI_ADDEXTERNAL, [{click}, sig, [win, win.userport, mg, sig, {win}]], + 0,0]) + + WHILE (mg.empty() = FALSE) + mg.message() + ENDWHILE + +EXCEPT DO + IF win THEN CloseWindow(win) + WriteF('Exiting...\n') + explain_exception() + + END mg + CleanUp(0) +ENDPROC + +PROC hideall(gui:PTR TO gui_obj) + gui.mg.setattrs([MGUI_HIDEALL, TRUE, NIL, NIL]) + gui.mg.first() + gui.mg.hide(FALSE) +ENDPROC + +PROC showall(gui:PTR TO gui_obj) IS gui.mg.setattrs([MGUI_HIDEALL, FALSE, NIL, NIL]) + +PROC newgui(gui:PTR TO gui_obj) IS test(gui.mg) + +PROC kill_all(gui:PTR TO gui_obj) IS gui.mg.clearguis() + +PROC msg() IS WriteF('Message!\n') + + +PROC test(mg:PTR TO mgui) + DEF gui:PTR TO LONG + + gui:=NEW [ROWS, + NEW [SBUTTON, {msg}, 'Msg'], + NEW [SBUTTON, 1, 'End'] + ] + + mg.addA('MGui Power!', gui) + +ENDPROC + +PROC click(t:PTR TO LONG) + DEF x:PTR TO LONG + + x:=GetMsg(t[1]) + ReplyMsg(x) + WriteF('Win Clicked: \d Times!\n', times++) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Mousepointer_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/Mousepointer_Example.e new file mode 100644 index 0000000..6ae40d8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Mousepointer_Example.e @@ -0,0 +1,59 @@ +/* + + $VER: MousePointer Example 1 - (C)Amiga Foundation Classes + + Written By: Andrea Galimberti + + This code is Public Domain + +*/ + +MODULE 'AFC/mousepointer', 'AFC/explain_exception', + 'intuition/screens' + + +PROC main() HANDLE + DEF scr=NIL:PTR TO screen + DEF vp + DEF topo:PTR TO mousepointer + + NEW topo.mousepointer(2) -> try TO get hold OF sprite number 2 + + topo.image(11,[$0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $1F7C,$1F7C, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080, + $0080,$0080]:INT) -> the LIST must be OF INT type + + topo.hotspot(9,6) -> we SET the hotspot + + scr:=OpenScreenTagList(NIL,[SA_TOP,0, + SA_LEFT,0, + SA_WIDTH,320, + SA_HEIGHT,256, + SA_DEPTH,5, + SA_TITLE,'Mouse Test', + NIL,NIL] + ) + IF scr=NIL THEN Raise("scr") + vp:=scr.viewport + + topo.changeImage(vp) -> the NEW image IS bound TO the viewport + topo.move(vp,10,10) + REPEAT + topo.update(vp) -> read mouse movements from hardware registers + WaitTOF() + UNTIL Mouse() + +EXCEPT DO + END topo + IF scr THEN CloseScreen(scr) + explain_exception() +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Parser_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/Parser_Example1.e new file mode 100644 index 0000000..4f7e9da --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Parser_Example1.e @@ -0,0 +1,29 @@ +/* + + $VER: Parser Example 1 - (C)Copyright Amiga Foundation Classes + + Written By: Fabio Rotondo + + This code is Public Domain + +*/ + +MODULE 'afc/parser', 'afc/explain_exception' + +PROC main() HANDLE + DEF par=NIL:PTR TO parser + + NEW par.parser() + + WriteF('Template: FILE/A,COLOR/K,NAME/K\n') + WriteF('STRING: NAME="Amiga Foundation Classes" COLOR="Blue" Parser.e\n') + + par.parse('FILE/A,COLOR/K,NAME/K', 'NAME="Amiga Foundation Classes" COLOR="Blue" Parser.e') + + WriteF('Results:\nArg 0 (File) - \s\nArg 1 (Color) - \s\nArg 2 (Name) - \s\n', par.arg(0), par.arg(1), par.arg(2)) + +EXCEPT DO + explain_exception() + END par +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/PatternMatch_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/PatternMatch_Example.e new file mode 100644 index 0000000..d402b24 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/PatternMatch_Example.e @@ -0,0 +1,47 @@ +/* +** DirList_Example 2 +** +** Methods: setdir(), read(), sort(), first(), obj() +** succ() +** +** This code shows an example of parsing with pattern matching +** +** This code is placed in Public Domain +** +** (C)Copyright 1996/97 Amiga Foundation Classes +** +** See: http://www.intercom.it/~fsoft/afc.html +** +** FOR more info about AFC AND modules. +** +*/ + + +MODULE 'afc/DirList', -> Our MAGIC MODULE! + 'afc/explain_exception' + +PROC main() HANDLE + DEF dl:PTR TO dirlist + + NEW dl.dirlist() -> Here we init the dirlist obj + + dl.setdir('ram:') -> This is the working dir + WriteF('Reading...\n') + dl.read(FALSE, TRUE, '#?.info')-> Read FILES only, matching #?.info + WriteF('Sorting!\n') + dl.sort() -> NOTE: This sort is CASE sensitive + + WriteF('Done!\n--------------\n') + + IF dl.first() -> Here we pos TO the first item + REPEAT + WriteF('\s\n',dl.obj()) -> Here we show the name + UNTIL dl.succ()=FALSE -> AND get the succ() + ENDIF + +EXCEPT DO + END dl + explain_exception() + CleanUp(0) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Push_Pop_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/Push_Pop_Example.e new file mode 100644 index 0000000..0d713da --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Push_Pop_Example.e @@ -0,0 +1,61 @@ +/* +** StringNode Example-3 +** +** add(), item(), push() AND pop() methods. +** +** (C)Copyright 1996/97 Amiga Foundation Classes +** +** See: http://www.intercom.it/~fsoft/afc.html +** +** FOR more info about AFC AND more modules +*/ + +MODULE 'afc/StringNode', -> Our MAGIC MODULE + 'afc/explain_exception' + +PROC main() HANDLE + DEF n:PTR TO stringnode -> This is our OBJECT instance + + NEW n.stringnode() -> OBJECT initialization + + n.add('Zorro') -> Here we add some items... + n.add('Batman') + n.add('Superman') + n.add('Gold Drake') + n.add('Mandrake') + n.add('MOMMY') + + shwall(n) -> Here we see them + + n.item(2) -> Let's pos us on item 2 + WriteF('Current:\s\n', n.obj()) + + n.push() -> Here we memorize our position + + n.item(5) -> Let's pos us on item 5 + WriteF('Current:\s\n', n.obj()) + + n.pop() -> Here we RETURN TO item 2!!! + WriteF('Current:\s\n', n.obj()) + + n.item(99) -> What??!?!?! This item DOES NOT EXISTS!!! + WriteF('Current:\s\n', n.obj()) -> Is it safe enought?? + +EXCEPT DO + explain_exception() + END n -> Remember ALWAYS TO end an OBJECT + CleanUp(0) +ENDPROC + +PROC shwall(n:PTR TO stringnode) + WriteF('------- \d ----------\n', n.numitems()) + + IF n.first() -> Here we go TO the first node item + REPEAT + WriteF('Node:\s\n', n.obj()) -> Node STRING... + UNTIL n.succ() = FALSE -> LOOP UNTIL the end + ELSE + WriteF('No Nodes in LIST...\n') + ENDIF +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/RamScan_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/RamScan_Example.e new file mode 100644 index 0000000..2ab2a86 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/RamScan_Example.e @@ -0,0 +1,52 @@ +/* + + DirList Example + + RamScan + + + (C)Copyright 1996/97 Amiga Foundation Classes + + See: http://www.intercom.it/~fsoft/afc.html + + FOR more info about AFC AND more modules + +*/ + +MODULE 'afc/dirlist', + 'afc/explain_exception' + +PROC main() HANDLE + DEF dl:PTR TO dirlist + + NEW dl.dirlist() + + + dl.setattrs([DIRTAG_COMPLETEPATH, TRUE, + DIRTAG_MARKDIR, TRUE, + 0,0 + ]) + + + + dl.setdir('ram:') + WriteF('Reading...\n') + dl.read(TRUE, TRUE) + WriteF('Sorting...') + dl.sort(TRUE) + + WriteF('Done!\n') + + IF dl.first() + REPEAT + WriteF('\s\n',dl.obj()) + UNTIL dl.succ()=FALSE + ENDIF + + WriteF('Dir Name:"\s"\n', dl.dirname()) + +EXCEPT DO + explain_exception() + END dl +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/ReqTooller_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/ReqTooller_Example1.e new file mode 100644 index 0000000..d2d94ad --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/ReqTooller_Example1.e @@ -0,0 +1,113 @@ +/* + + $VER: ReqTooller Example 1 - (C)Copyright Amiga Foundation Classes + + Written By: Fabio Rotondo + + This code is Public Domain + + +*/ + +MODULE 'afc/reqtooller', 'afc/explain_exception' + +PROC main() HANDLE + DEF rt=NIL:PTR TO reqtooller + DEF s:PTR TO CHAR + + NEW rt.reqtooller() -> First of all, we init the class. + + -> Here we set the default title and path + rt.setattrs([RT_TITLE, 'reqtooller Example', + RT_PATH, 'Ram:', + NIL, NIL]) + + + + /* + Here we open a SAVE requester + Please, note the RT_FULLNAME set to TRUE: + when we'll do a get(RT_FILENAME) the filename returned will contain + also the path. + */ + rt.req(RTREQ_SAVE, [RT_OKGAD, '_Save', RT_FULLNAME, TRUE, NIL]) + WriteF('Path:\s\n', rt.get(RT_PATH)) + WriteF('FullName:\s\n', rt.get(RT_FILENAME)) + + + -> Hey! Here there is a path requester! + -> (Here we change the OK gadget, because it would remain "Save"...) + rt.req(RTREQ_PATH, [RT_OKGAD, 'Ok', NIL, NIL]) + WriteF('NEW Path:\s\n', rt.get(RT_PATH)) + + + -> And here a Volumes requester! + rt.req(RTREQ_VOLUMES, NIL) + + + -> And what about a MultiFile requester? + rt.req(RTREQ_MULTI, NIL) + + /* + This is the right routine to scan throught all + the files selected. + Please, note that we have still the RT_FULLNAME flag set. + So the names returned will contain full path. + */ + WHILE (s:=rt.get(RT_MULTINEXT)) + WriteF('Name:\s\n', s) + ENDWHILE + + + -> Wow a font requester + rt.req(RTREQ_FONT, NIL) + + + -> And a font requester supporting color fonts :-) + rt.req(RTREQ_COLFONT, [RT_FONTNAME, 'XHelvetica.font', NIL]) + WriteF('FontName:\s\n', rt.get(RT_FONTNAME)) + + -> Look: the EasyReq returns a value, we get it! + WriteF('EasyReq result:\d\n', rt.req(RTREQ_EASY, [RT_TEXT, 'Do You Like This Requester?', + RT_GADS, 'Yes!|Hmmm...|No', + RT_CHOICE, 2, + NIL, NIL])) + + + -> A Standard Screen Requester + rt.req(RTREQ_SCREEN) + WriteF('ModeID:\h\n', rt.get(RT_SCRID)) + + -> And a ALL resolutions screen requester + rt.req(RTREQ_ALLSCREEN) + + -> A String Requester (also this requester returns a value... + WriteF('STRING Result:\d\n', rt.req(RTREQ_STRING, [RT_DEFSTR, 'Hello!', + RT_MAXCHARS, 10, + RT_TEXT, 'Insert Your Name', + RT_GADS, 'This is|I do not want', + NIL])) + + -> A number requester + rt.req(RTREQ_NUMBER, [RT_MINVAL, 10, RT_MAXVAL, 20, RT_DEFVAL, 11, NIL]) + + + -> An example of EasyRequester with arguments. + rt.req(RTREQ_EASY, [RT_TEXT, 'My name is:\s \s.', + RT_ARGS, ['Fabio', 'Rotondo'], + RT_GADS, 'Ok', + NIL]) + + -> A Message requester... + rt.req(RTREQ_MESSAGE, NIL) + + -> That will be there for 1 second. + Delay(50) + +EXCEPT DO + + explain_exception() + END rt + CleanUp(0) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Receiver.e b/amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Receiver.e new file mode 100644 index 0000000..e7be2a5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Receiver.e @@ -0,0 +1,44 @@ +/* + + $VER: Rexxer Receiver Example 1.0 + + Written By Fabio Rotondo + + (C)Copyright Amiga Foundation Classes + + NOTES: Run this program BEFORE Rexxer Sender. + + The Rexxer Receiver will handle messages + arriving from Rexxer Sender. + + Even if it is possible to run multiple instances + of this program, only the 'RECEIVE.1' port will + be addressed by Rexxer Sender, so be careful! + +*/ + +MODULE 'afc/rexxer', 'afc/explain_exception' + +PROC main() HANDLE + DEF rx=NIL:PTR TO rexxer + + NEW rx.rexxer('RECEIVE') + + REPEAT + Wait(rx.sigbit()) + UNTIL rx.get({parse}) + + WriteF('Rexxer Receiver is terminating...\n') + +EXCEPT DO + explain_exception() + END rx + CleanUp(0) +ENDPROC + +PROC parse(s, mes=NIL) + WriteF('Message arrived:\s\n', s) + + mes:=NIL +ENDPROC StrCmp('QUIT', s), 0, 'Hello World!' + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Sender.e b/amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Sender.e new file mode 100644 index 0000000..0b4df72 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Rexxer_Sender.e @@ -0,0 +1,35 @@ +/* + + $VER: Rexxer Sender Example 1.0 + + Written By Fabio Rotondo + + (C)Copyright Amiga Foundation Classes + + NOTES: Run this program AFTER you have run 'Rexxer Receiver'. + + This program will communicate using ARexx with 'RECEIVE.1'. + If the "RECEIVE.1" port is not found, the program will raise + an exception. + +*/ + +MODULE 'afc/rexxer', 'afc/explain_exception' + +PROC main() HANDLE + DEF rx=NIL:PTR TO rexxer + + + IF FindPort('RECEIVE.1')=NIL THEN Raise("recv") + NEW rx.rexxer('SENDER') + + rx.send('RECEIVE.1', 'QUIT') + + WriteF('RC:\d - Result:\s\n', rx.rc(), rx.result()) + WriteF('ARexx Sender port terminating...\n') +EXCEPT DO + explain_exception() + END rx + CleanUp(0) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Search_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/Search_Example.e new file mode 100644 index 0000000..dd38b8c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Search_Example.e @@ -0,0 +1,55 @@ +/* +** StringNode Example-4 +** +** add(), search() AND insert() methods. +** +** (C)Copyright 1996/97 Amiga Foundation Classes +** +** See: http://www.intercom.it/~fsoft/afc.html +** +** FOR more info about AFC AND more modules +*/ + +MODULE 'afc/StringNode', -> Our MAGIC MODULE + 'afc/explain_exception' + +PROC main() HANDLE + DEF n:PTR TO stringnode -> This is our OBJECT instance + + NEW n.stringnode() -> OBJECT initialization + + n.add('Zorro') -> Here we add some items... + n.add('Batman') + n.add('Superman') + n.add('Gold Drake') + n.add('Mandrake') + n.add('MOMMY') + + shwall(n) -> Here we see them + + n.search('bat#?') -> The search is CASE insensitive AND match the first one ;) + -> Note we use STANDARD AmigaDOS match pattern strings! + + WriteF('Current:\s\n', n.obj()) -> Here we are! + + n.insert('Spiderman') -> Wow! Another super-hero after Batman! + shwall(n) + +EXCEPT DO + IF exception THEN WriteF('Exception: \z\h[8]\n', exception) + END n -> Remember ALWAYS TO end an OBJECT + CleanUp(0) +ENDPROC + +PROC shwall(n:PTR TO stringnode) + WriteF('------- \d ----------\n', n.numitems()) + + IF n.first() -> Here we go TO the first node item + REPEAT + WriteF('Node:\s\n', n.obj()) -> Node STRING... + UNTIL n.succ() = FALSE -> LOOP UNTIL the end + ELSE + WriteF('No Nodes in LIST...\n') + ENDIF +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/SetAttrs_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/SetAttrs_Example.e new file mode 100644 index 0000000..501fe55 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/SetAttrs_Example.e @@ -0,0 +1,51 @@ +/* +** DirList_Example 3 +** +** Methods: setdir(), read(), sort(), first(), obj() +** succ(), dirname(), setattrs() +** +** +** This code is placed in Public Domain +** +** (C)Copyright 1996 Fabio Rotondo +** +*/ + + +MODULE 'afc/DirList', -> Our MAGIC MODULE! + 'afc/explain_exception' + +PROC main() HANDLE + DEF dl:PTR TO dirlist + + NEW dl.dirlist() + + + dl.setattrs([DIRTAG_COMPLETEPATH, TRUE, -> We want TO store the complete path + DIRTAG_MARKDIR, TRUE, -> AND we want DirList TO mark dirs + 0,0 + ]) + + + + dl.setdir('ram:') -> We'll scan RAM: + WriteF('Reading...\n') + dl.read(TRUE, TRUE) -> Here we read it + WriteF('Sorting...') + dl.sort(TRUE) -> AND here we sort it + + WriteF('Done!\n') + + IF dl.first() -> Let's show! + REPEAT + WriteF('\s\n',dl.obj()) + UNTIL dl.succ()=FALSE + ENDIF + + WriteF('DIR:\s\n', dl.dirname()) -> Actual dir name is this + +EXCEPT DO + explain_exception() + END dl +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Sort_Example.e b/amigae33a/E_v3.3a/Src/Src/Afc/Sort_Example.e new file mode 100644 index 0000000..adaa759 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Sort_Example.e @@ -0,0 +1,97 @@ +/* + NodeMaster_Sort.e - V1.00 + + Written By Andrea Galimberti + + This source demonstates how to create + sort a list of "objects". In this case + our "object" will be called "stuff" and + will contain just one field called "avg". + + Our comparison routine will take as parameters + two "Stuff" items and the info param (which will be + ignored). + + This source shows also the version() method. + + + This source is Public Domain. + + NodeMaster is part of the Amiga Foundation Classes + See: + http://www.intercom.it/~fsoft/afc.html + + for more info and more modules. +*/ + +MODULE 'afc/nodemaster', + 'afc/explain_exception' + +CONST MAX_ELEM = 50 -> Change this value TO increase/decrease no. of items TO sort + +OBJECT stuff + avg +ENDOBJECT + +/* + This is our comparison routine. + look: + + a and b are two "stuff" objects. + + Their ".avt" field just contains a number: + by sub a.avg-b.avg will have a value < or > or = to 0 + That we'll return as result. + + This is a simple example, but you can create better + and more complex ones. +*/ +PROC cpstuff(a:PTR TO stuff,b:PTR TO stuff, info) IS a.avg - b.avg + + +PROC main() HANDLE + DEF k + DEF num:PTR TO nodemaster, l:PTR TO stuff + DEF v,r + + NEW num.nodemaster() + + -> Here we fill the list with random numbers + Rnd(-RndQ($FFA354B2)) + FOR k:=0 TO MAX_ELEM-1 + NEW l + l.avg:=Rnd(1000) + num.add(l) + ENDFOR + + WriteF('Now sorting...') + + -> and here we sort it!!! + num.sort({cpstuff}) + + WriteF('Done!\n') + + -> Let's see the result + l:=num.first() + REPEAT + WriteF('\d\n',l.avg) + UNTIL (l:=num.succ())=FALSE + + + -> Good: which version of NodeMaster is this? + v,r := num.version() + + WriteF('NodeMaster V\d.\d \n', v,r) + +EXCEPT DO + explain_exception() + + IF (l:=num.first())<>FALSE + REPEAT + Dispose(l) + UNTIL (l:=num.succ())=FALSE + ENDIF + END num + CleanUp(0) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/SuperPic_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/SuperPic_Example1.e new file mode 100644 index 0000000..6026fe7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/SuperPic_Example1.e @@ -0,0 +1,81 @@ +/* + + $VER: Super Picture Example no. 1 (V1.00) - By Fabio Rotondo + + (C)Copyright Amiga Foundation Classes + + This example is Public Domain. + +*/ + +MODULE 'afc/super_picture', 'afc/explain_exception', + 'dos/rdargs', + 'intuition/screens' + +PROC main() HANDLE + DEF myargs:PTR TO LONG, rda=NIL + DEF pic=NIL:PTR TO super_picture -> The SuperPic OBJECT + DEF scr=NIL:PTR TO screen, w, h, sw, sh + + WriteF('PView V1.00 - By Fabio Rotondo.\n') + + myargs:=[0,0,0,0,0,0]:LONG + IF (rda:=ReadArgs('PICNAME/A,VERBOSE/S', myargs, NIL))=NIL THEN Raise("args") + + NEW pic.super_picture() -> Here we init the class + + pic.load(myargs[0]) -> Just a load command (Supports DataTypes!) 8-) + + w:=pic.width() -> Here we obtain pic's width and height + h:=pic.height() + + IF w<320 THEN sw:=320 ELSE sw:=w -> And here we compute screen sizes + IF h<256 THEN sh:=256 ELSE sh:=h + + -> If the user set the VERBOSE flag in the Shell parameters, we just show + -> some more info about the picture before displaying it. + IF myargs[1] + WriteF('Picture:\s\nWidth: \d\nHeight: \d\nDepth:\d\nModeID: $\h\n', + myargs[0], + w,h,pic.depth(), + pic.modeid()) + ENDIF + + -> Here we open a screen + IF (scr:=OpenScreenTagList(NIL, + [SA_WIDTH, sw, + SA_HEIGHT, sh, + SA_DEPTH, pic.depth(), + SA_DISPLAYID, pic.modeid(), + 0,0]))=NIL THEN Raise("scr") + + pic.paltoscr(scr) -> Just to set the right palette + + + -> We blit it all! + BltBitMapRastPort(pic.bitmap(), 0,0, scr.rastport, 0,0, w, h, $C0) + + + -> Waiting for a mouse click... + REPEAT + Delay(5) + UNTIL Mouse() + +EXCEPT DO + SELECT exception + CASE "args" + WriteF('Bad args!\n') + CASE "scr" + WriteF('Could not open screen!\n') + DEFAULT + explain_exception() + ENDSELECT + + IF scr THEN CloseScreen(scr) -> Close the screen + + IF rda THEN FreeArgs(rda) -> Free ReadArgs structure + + END pic -> Close the object + + CleanUp(0) -> General cleaning up... +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example1.e new file mode 100644 index 0000000..e43e04f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example1.e @@ -0,0 +1,30 @@ + +MODULE 'AFC/tasker', 'afc/explain_exception' + +-> tasks can only access global variables +DEF sharedvar + +PROC simpletask() + WHILE sharedvar<$8000000 DO sharedvar++ + Wait(NIL) -> that IS TO say: wait TO be killed +ENDPROC + + +PROC main() HANDLE + DEF myt:PTR TO tasker + + NEW myt.tasker('simpletask') -> name OF the task + + myt.code({simpletask}) -> what code TO use + WriteF('starting task...(press RETURN TO end)\n') + myt.start() -> starting task + + Inp(IF stdin THEN stdin ELSE stdout) + WriteF('The shared variable now equals \d\n', sharedvar) + +EXCEPT DO + END myt -> killing task (you can stop() it IF you don't need TO END + -> the whole OBJECT (maybe TO restart it again later)) + explain_exception() +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example2.e b/amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example2.e new file mode 100644 index 0000000..812e2cb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Tasker_Example2.e @@ -0,0 +1,94 @@ + +MODULE 'AFC/tasker', 'AFC/explain_exception', + 'exec/ports','exec/memory','exec/nodes' + + +-> a complex message +OBJECT complex + mnode:mn ->BE CAREFUL: This IS the structure, NOT the pointer + wow:LONG +ENDOBJECT + +-> the tasker structure IS DEFined global because we use it also in the +-> process' body. +DEF myp:PTR TO tasker + +PROC thread() + DEF message:PTR TO complex + +-> get the global data pointer, previously stored by the main process. +-> IMPORTANT: DO this before using global variables OR functioncalls. + geta4() + +/* + IF you DEF'd your tasker ('myp' in this CASE) as a global variable, + you can access its port by the dosport() method. IF you need TO make it a + local variable THEN, TO get the port associated TO the process, you + follow the standard way: + + DEF thisthread:PTR TO process + thisthread:=FindTask(0) + dosport:=thisthread.msgport + + Warning: the use OF this port IS reserved TO AmigaDOS, so create your + own port IF you need one. +*/ + + -> create a port associated TO the process (this method must be called + -> from the task that needs the port, not by the main program). + myp.buildport() + + WaitPort(myp.port()) + message:=GetMsg(myp.port()) + + PrintF('Hello, I''m a NEW thread. Wow IS:\d\n', message.wow) + Delay(50) + +-> make sure there IS no taskswitching after we replied the message + Forbid() + ReplyMsg(message) + myp.endport() -> remember TO close the port before ending. +ENDPROC + +PROC main() HANDLE + DEF mainp=NIL, mess=NIL:PTR TO complex + +-> Store the global data pointer: DO this BEFORE any process IS started. +-> Remember TO geta4() in the process before using any global variable OR +-> functioncall! + storea4() + + NEW myp.tasker('simpleprocess') -> name AND initialization + myp.code({thread}) -> the code TO be used + + IF (mainp:=buildPort()) -> we need a port in the main() process TO + -> communicate with thread() + + WriteF('Starting the process...\n') + myp.process() -> starting the process + + mess:=NewM(SIZEOF complex, MEMF_PUBLIC OR MEMF_CLEAR) -> alloc AND + setupMsg(mess, SIZEOF complex, mainp) -> setup the message + mess.wow:=10 -> fill in your additional fields + + WriteF('Sending the message...\n') + REPEAT -> wait FOR the process TO create its own port + Delay(5) -> before sending anything TO it. + UNTIL myp.port() + + myp.send(mess) -> send the message TO thread() + + WaitPort(mainp) -> wait FOR an answer. +-> IF process doesn't reply we can't Dispose the message memory 'cause +-> the thread may be still using it. + ELSE + WriteF('well, no port!\n') + ENDIF + +EXCEPT DO + IF mess THEN Dispose(mess) -> remember TO free the memory + IF mainp THEN endPort(mainp) + END myp + explain_exception() +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/ToolType_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/ToolType_Example1.e new file mode 100644 index 0000000..1cc7fbb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/ToolType_Example1.e @@ -0,0 +1,37 @@ +/* + + ToolType Example 1 - (C)Copyright Amiga Foundation Classes + + Written By: Fabio Rotondo + + Public Domain Source + + + NOTE: This program will happily fail, raising an exception + if you don't provide a _valid_ icon for it and don't + modify the tooltypes... see docs! + +*/ + +MODULE 'afc/tooltype', 'afc/explain_exception' + +PROC main() HANDLE + DEF ttype:PTR TO tooltype + DEF s + + WriteF('This is a little try of tooltype\n') + + NEW ttype.tooltype(TRUE) + + WriteF('Everything Is Fine\n') + s:=ttype.get('MYTRY') + IF s THEN WriteF('Get() Result:\s\n', s) + + s:=ttype.match('MYTRY','FABIO') + WriteF('Match Result:\d\n', s) + +EXCEPT DO + explain_exception() + END ttype +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example1.e b/amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example1.e new file mode 100644 index 0000000..5ef372b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example1.e @@ -0,0 +1,224 @@ +/* + worldbuilder example. + + Needs: 'bitmap_obj' AND 'explain_exception' from AFC. + + Instructions: left - right arrow: move observer x + up - down arrow: move observer y + Del - Help : move observer z + q - w : rotate around x + a - s : rotate around y + z - x : rotate around z + space : reset TO defaults + Esc : quit +*/ + +MODULE 'AFC/worldbuilder', + 'AFC/bitmapper', + 'AFC/explain_exception', + 'intuition/intuition', + 'intuition/screens', + 'graphics/view', + 'exec/ports' + + +PROC main() HANDLE + DEF scene:PTR TO worldbuilder + DEF scr=NIL:PTR TO screen, rp, vp:PTR TO viewport + DEF win=NIL:PTR TO window, port:PTR TO mp + DEF msg:PTR TO intuimessage, class, code + DEF oox,ooy,ooz, rrx,rry,rrz + DEF bm2:PTR TO bitmapper, rp2, bitmap2, ri:PTR TO rasinfo + DEF usebm=0, scrbm + + -> fillSinTable() IS done automatically by the following: + NEW scene.worldbuilder() + + -> we add three objects + scene.addobj('cube') + scene.addobj('axis') + scene.addobj('pyramid') + + -> vertices, lines AND surfaces FOR the 'cube' object_obj: + -> name x1,y1, z1, x2,y2, z2, ... + scene.fastsetvert('cube',[-50,50,-50, 50,50,-50, 50,-50,-50, -50,-50,-50, + -50,50,50, 50,50,50, 50,-50,50, -50,-50,50]:vertex_obj) + -> MUST be a typed LIST: ^^^^^^^^^^ + + -> name startv1, endv1, colour1, ... + scene.fastsetline('cube',[0, 1, 2, 1,2,2, 2,3,2, 3,0,2, + 4,5,2, 5,6,2, 6,7,2, 7,4,2, + 0,4,2, 1,5,2, 2,6,2, 3,7,2]:line_obj) + + -> name,num,vertices,colour + scene.setsurface('cube',0,[0,1,2,3],2) + scene.setsurface('cube',1,[0,4,5,1],3) + scene.setsurface('cube',2,[7,6,5,4],4) + scene.setsurface('cube',3,[3,2,6,7],5) + scene.setsurface('cube',4,[0,3,7,4],6) + scene.setsurface('cube',5,[1,5,6,2],7) + + -> definition OF the three axes + scene.fastsetvert('axis',[0,0,0, 100,0,0, 0,100,0, 0,0,100]:vertex_obj) + + scene.fastsetline('axis',[0,1,3, 0,2,4, 0,3,5]:line_obj) + + -> AND now there comes the 'pyramid' object_obj + scene.fastsetvert('pyramid',[0,60,-50, 50,60,-50, 50,60,50, + 0,60,50, 25,120,0]:vertex_obj) + + scene.fastsetline('pyramid',[0,1,6, 1,2,6, 2,3,6, 3,0,6, + 0,4,6, 1,4,6, 2,4,6, 3,4,6]:line_obj) + + scene.setsurface('pyramid',0,[0,1,2,3],3) + scene.setsurface('pyramid',1,[0,4,1],2) + scene.setsurface('pyramid',2,[3,4,0],4) + scene.setsurface('pyramid',3,[2,4,3],5) + scene.setsurface('pyramid',4,[1,4,2],6) + + + scene.setdisplay(320,256) -> display dimensions + scene.init3D() -> build system structures FOR filled vectors + + scene.setaftertrasl(160,128) -> origin OF the screen axes. + scene.setafterscale(200,200) -> scaling AFTER projection (TO fit in + -> the screen): 200 = double. + scene.setobserver(0,0,-200) -> position OF the observer + + -> we open a screen + scr:=OpenScreenTagList(NIL,[SA_TOP,0, + SA_LEFT,0, + SA_WIDTH,320, + SA_HEIGHT,256, + SA_DEPTH,3, + SA_TITLE,'Routines3D', + SA_SHOWTITLE,FALSE, + 0,0]) + IF scr=NIL THEN Raise("SCR") + vp:=scr.viewport + ri:=vp.rasinfo -> we get the rasinfo structure FOR double buffering + scrbm:=ri.bitmap + + -> a trivial palette + SetRGB4(vp,3,15,0,0) + SetRGB4(vp,4,0,15,0) + SetRGB4(vp,5,0,0,15) + SetRGB4(vp,7,12,12,0) + + -> we allocate a second bitmap FOR the double buffering + NEW bm2.bitmapper() + bm2.allocbitmap(320,256,3,TRUE) + rp2:=bm2.rastport() + bitmap2:=bm2.bitmap() + + -> the window IS needed TO get keypresses + win:=OpenWindowTagList(NIL,[WA_TOP,0, + WA_LEFT,0, + WA_WIDTH,320, + WA_HEIGHT,256, + WA_TITLE,'Routines3D', + WA_FLAGS,WFLG_ACTIVATE OR WFLG_SMART_REFRESH OR WFLG_BACKDROP OR WFLG_BORDERLESS, + WA_IDCMP,IDCMP_RAWKEY, + WA_CUSTOMSCREEN,scr, + 0,0]) + IF win=NIL THEN Raise("WIN") + rp:=win.rport + port:=win.userport + + oox:=0 ; ooy:=0 ; ooz:=-200 -> observer initial position + rrx:=0 ; rry:=0 ; rrz:=0 -> angles OF rotation + + scene.projection() -> project + scene.drawfill(rp) -> AND draw the scene + usebm:=1-usebm + + LOOP + Wait(Shl(1,port.sigbit)) + REPEAT + IF (msg:=GetMsg(port))<>NIL + class:=msg.class + code:=msg.code + ReplyMsg(msg) + SELECT class + CASE IDCMP_RAWKEY -> IF user presses a key... + SELECT code + CASE $4C -> up arrow + ooy:=ooy+1 + scene.setobserver(oox,ooy,ooz) -> change observer position + CASE $4D -> down arrow + ooy:=ooy-1 + scene.setobserver(oox,ooy,ooz) + CASE $4E -> right arrow + oox:=oox+1 + scene.setobserver(oox,ooy,ooz) + CASE $4F -> left arrow + oox:=oox-1 + scene.setobserver(oox,ooy,ooz) + CASE $46 -> del + ooz:=ooz-1 + scene.setobserver(oox,ooy,ooz) + CASE $5F -> help + ooz:=ooz+1 + scene.setobserver(oox,ooy,ooz) + CASE $10 -> q + rrx:=rrx-1 + scene.setrot(rrx,rry,rrz) -> SET NEW rotation angles + CASE $11 -> w + rrx:=rrx+1 + scene.setrot(rrx,rry,rrz) + CASE $20 -> a + rry:=rry-1 + scene.setrot(rrx,rry,rrz) + CASE $21 -> s + rry:=rry+1 + scene.setrot(rrx,rry,rrz) + CASE $31 -> z + rrz:=rrz-1 + scene.setrot(rrx,rry,rrz) + CASE $32 -> x + rrz:=rrz+1 + scene.setrot(rrx,rry,rrz) + CASE $40 -> space + oox:=0 ; ooy:=0 ; ooz:=-200 + rrx:=0 ; rry:=0 ; rrz:=0 + scene.setobserver(oox,ooy,ooz) + scene.setrot(rrx,rry,rrz) + CASE $45 -> esc + REPEAT + IF (msg:=GetMsg(port))<>NIL THEN ReplyMsg(msg) + UNTIL msg=NIL + Raise("end") -> quit + ENDSELECT + ENDSELECT + ENDIF + UNTIL msg=NIL + scene.projection() -> project the scene + + SetAPen(IF usebm=0 THEN rp ELSE rp2, 0) + RectFill(IF usebm=0 THEN rp ELSE rp2, 0,0,320,256) -> clear the screen + + scene.drawfill(IF usebm=0 THEN rp ELSE rp2) -> eventually draw + -> ^^^^^^^^: change this in 'draw' IF you want TO see wireframe objects + + IF usebm=0 -> handmade double buffering (in a screen) + ri.bitmap:=scrbm + ELSE -> swap the two bitmaps + ri.bitmap:=bitmap2 + ENDIF + WaitTOF() + ScrollVPort(vp) -> update copperlist TO NEW pointers + usebm:=1-usebm + ENDLOOP + +EXCEPT DO + IF win THEN CloseWindow(win) + IF scr + ri.bitmap:=scrbm + CloseScreen(scr) + ENDIF + END scene -> remember TO free ALL memory + END bm2 + IF exception<>"end" THEN explain_exception() + CleanUp(0) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example2.e b/amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example2.e new file mode 100644 index 0000000..f7d84be --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Afc/Worldbuilder_Example2.e @@ -0,0 +1,174 @@ + +MODULE 'AFC/worldbuilder', + 'AFC/bitmapper', + 'AFC/explain_exception', + 'intuition/intuition', + 'intuition/screens', + 'graphics/view', + 'exec/ports' + + +PROC main() HANDLE + DEF scene:PTR TO worldbuilder, scr:PTR TO screen, win:PTR TO window + DEF vp:PTR TO viewport, ri:PTR TO rasinfo, scrbm, bm2:PTR TO bitmapper + DEF rp2, bitmap2, port:PTR TO mp, usebm=0, rp + DEF rrx, rry, rrz, oox, ooy, ooz + + NEW scene.worldbuilder() + + scene.addobj('A') + scene.addobj('N') + scene.addobj('D') + scene.addobj('R') + scene.addobj('E') + scene.addobj('A2') + + + scene.fastsetvert('A',[-10,0,0, -20,0,0, -20,60,0, 20,60,0, 20,0,0, + 10,0,0, 10,30,0, -10,30,0, -10,50,0, 10,50,0, + 10,40,0, -10,40,0]:vertex_obj) + + scene.setsurface('A',0,[0,1,2,3,4,5,6,7],3) + scene.setsurface('A',1,[8,9,10,11],0) + scene.setsurface('A',2,[7,6,5,4,3,2,1,0],3) + scene.setsurface('A',3,[11,10,9,8],0) + + scene.fastsetvert('N',[-20,0,0, -20,60,0, -10,60,0, 10,10,0, 10,60,0, + 20,60,0, 20,0,0, 10,0,0, -10,50,0, -10,0,0]:vertex_obj) + + scene.setsurface('N',0,[0,1,2,3,4,5,6,7,8,9],3) + scene.setsurface('N',1,[9,8,7,6,5,4,3,2,1,0],3) + + + scene.fastsetvert('D',[-20,0,0, -20,60,0, 10,60,0, 20,50,0, 20,10,0, + 10,0,0, -10,10,0, -10,50,0, 0,50,0, 10,40,0, + 10,20,0, 0,10,0]:vertex_obj) + + scene.setsurface('D',0,[0,1,2,3,4,5],3) + scene.setsurface('D',1,[6,7,8,9,10,11],0) + scene.setsurface('D',2,[5,4,3,2,1,0],3) + scene.setsurface('D',3,[11,10,9,8,7,6],0) + + + scene.fastsetvert('R',[-20,0,0, -20,60,0, 10,60,0, 20,50,0, 20,40,0, + 10,30,0, 20,0,0, 10,0,0, 0,30,0, -10,30,0, + -10,0,0, -10,40,0, -10,50,0, 0,50,0, 0,40,0]:vertex_obj) + + scene.setsurface('R',0,[0,1,2,3,4,5,6,7,8,9,10],3) + scene.setsurface('R',1,[11,12,13,14],0) + scene.setsurface('R',2,[10,9,8,7,6,5,4,3,2,1,0],3) + scene.setsurface('R',3,[14,13,12,11],0) + + + scene.fastsetvert('E',[-20,0,0, -20,60,0, 20,60,0, 20,50,0, -10,50,0, + -10,40,0, 0,40,0, 0,30,0, -10,30,0, -10,10,0, + 20,10,0, 20,0,0]:vertex_obj) + + scene.setsurface('E',0,[0,1,2,3,4,5,6,7,8,9,10,11],3) + scene.setsurface('E',1,[11,10,9,8,7,6,5,4,3,2,1,0],3) + + scene.copyobj('A','A2') + + scene.position('A',-140,-30,0) + scene.position('N',-90,-30,0) + scene.position('D',-40,-30,0) + scene.position('R',10,-30,0) + scene.position('E',60,-30,0) + scene.position('A2',110,-30,0) + + scene.applyobj('A') + scene.applyobj('N') + scene.applyobj('D') + scene.applyobj('R') + scene.applyobj('E') + scene.applyobj('A2') + + scene.setdisplay(320,256) -> display dimensions + scene.init3D() -> build system structures FOR filled vectors + + scene.setaftertrasl(160,128) -> origin OF the screen axes. +-> scene.setafterscale(200,200) -> scaling AFTER projection (TO fit in + -> the screen): 200 = double. + scene.setobserver(0,0,-200) -> position OF the observer + + -> we open a screen + scr:=OpenScreenTagList(NIL,[SA_TOP,0, + SA_LEFT,0, + SA_WIDTH,320, + SA_HEIGHT,256, + SA_DEPTH,3, + SA_TITLE,'Routines3D', + SA_SHOWTITLE,FALSE, + 0,0]) + IF scr=NIL THEN Raise("SCR") + vp:=scr.viewport + ri:=vp.rasinfo -> we get the rasinfo structure FOR double buffering + scrbm:=ri.bitmap + + -> a trivial palette + SetRGB4(vp,3,15,0,0) + SetRGB4(vp,4,0,15,0) + SetRGB4(vp,5,0,0,15) + SetRGB4(vp,7,12,12,0) + + -> we allocate a second bitmap FOR the double buffering + NEW bm2.bitmapper() + bm2.allocbitmap(320,256,3,TRUE) + rp2:=bm2.rastport() + bitmap2:=bm2.bitmap() + + -> the window IS needed TO get keypresses + win:=OpenWindowTagList(NIL,[WA_TOP,0, + WA_LEFT,0, + WA_WIDTH,320, + WA_HEIGHT,256, + WA_TITLE,'Routines3D', + WA_FLAGS,WFLG_ACTIVATE OR WFLG_SMART_REFRESH OR WFLG_BACKDROP OR WFLG_BORDERLESS, + WA_IDCMP,IDCMP_RAWKEY, + WA_CUSTOMSCREEN,scr, + 0,0]) + IF win=NIL THEN Raise("WIN") + rp:=win.rport + port:=win.userport + + oox:=0 ; ooy:=0 ; ooz:=-200 -> observer initial position + rrx:=0 ; rry:=0 ; rrz:=0 -> angles OF rotation + + ClearScreen(rp) + scene.projection() -> project + scene.drawfill(rp) -> AND draw the scene + usebm:=1-usebm + + FOR rry:=0 TO 359 + scene.setrot(0,rry,0) + scene.projection() + SetAPen(IF usebm=0 THEN rp ELSE rp2, 0) + RectFill(IF usebm=0 THEN rp ELSE rp2, 0,30,320,200) + scene.drawfill(IF usebm=0 THEN rp ELSE rp2) + + IF usebm=0 + ri.bitmap:=scrbm + ELSE + ri.bitmap:=bitmap2 + ENDIF + WaitTOF() + ScrollVPort(vp) + usebm:=1-usebm + ENDFOR + + REPEAT + Delay(5) + UNTIL Mouse() + +EXCEPT DO + IF win THEN CloseWindow(win) + IF scr + ri.bitmap:=scrbm + CloseScreen(scr) + ENDIF + IF scene THEN END scene -> remember TO free ALL memory + IF bm2 THEN END bm2 + explain_exception() + CleanUp(0) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Args/GetArgs.e b/amigae33a/E_v3.3a/Src/Src/Args/GetArgs.e new file mode 100644 index 0000000..300682d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Args/GetArgs.e @@ -0,0 +1,5 @@ +/* get command line args. note that `arg' is a predefined E-var */ + +PROC main() + WriteF(IF arg[]=0 THEN 'No Args!\n' ELSE 'You wrote: \s\n',arg) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Args/ReadArgs.e b/amigae33a/E_v3.3a/Src/Src/Args/ReadArgs.e new file mode 100644 index 0000000..b8caae1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Args/ReadArgs.e @@ -0,0 +1,17 @@ +/* Use readargs() to get parameters instead of using the string 'arg'. + This is more convenient if more than one arg is needed. Uses kick 2.0 */ + +OPT OSVERSION=37 + +PROC main() + DEF myargs:PTR TO LONG,rdargs + myargs:=[0,0,0] + IF rdargs:=ReadArgs('UNIT/N,DISK/A,NEW/S',myargs,NIL) + WriteF('UNIT=\d\n',Long(myargs[0])) /* integer */ + WriteF('DISK=\s\n',myargs[1]) /* string */ + WriteF('NEW=\d\n',myargs[2]) /* boolean */ + FreeArgs(rdargs) + ELSE + WriteF('Bad Args!\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Args/WbArg.e b/amigae33a/E_v3.3a/Src/Src/Args/WbArg.e new file mode 100644 index 0000000..b88f6e7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Args/WbArg.e @@ -0,0 +1,15 @@ +/* reading the arguments when started from wb. + give this program a .info file, and shift-select some icons with it. */ + +MODULE 'workbench/startup' + +PROC main() + DEF wb:PTR TO wbstartup, args:PTR TO wbarg, a + IF wbmessage=NIL /* we got from cli */ + WriteF('args = "\s"\n',arg) + ELSE /* from wb */ + wb:=wbmessage + args:=wb.arglist + FOR a:=1 TO wb.numargs DO WriteF('wbarg #\d = "\s"\n',a,args[].name++) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Class/BinTree/bintree b/amigae33a/E_v3.3a/Src/Src/Class/BinTree/bintree new file mode 100644 index 0000000000000000000000000000000000000000..b87ff3fffa956a1865c6ebf1f589bf35cb0b28ee GIT binary patch literal 1672 zcmah}UuauZ82{2->ZQGmP=n+_#_1)-q)mIXA|hkL?ZQSD>`86?vxm7gbL1`>*I09B zg(7zfB4e61 zexBOH#@HkBjlU`X2`*MJcOIU5>2*31Wkr%DaZ68%Ry_ASUV(h$c*0ls<*znO~1BNzo#uO8BhdVI(NLD zaWeJotL~0@c~=b1-Q$LunI+oF-PxP3Px_Gs85&>g)co&y3>mM=c!M&tLgcBdPgcs; z)k3Bae6gb!2TfGhWHpl6rLWKPwYPlWlN?=8*7m9r=~SH!iMCu_vI46ftF?<21grHA zR?A~~-*x*8Y7jTn+LIUJlsWbdPHrf@ zzS-_SLK^TcFod%yd+6b81l|Z{&jZ82<9_r=C)!&D>&&_66TIVWVrrXB7b@HoCZt^L#jsQ_c)@#oMZSXq`r6|Hew99____ z^CvpI%?@TG1rqN3ax5KFC*PNyk4|i`V62zhkJY)2S`FxG6nA9sH-Gjndb1_(9^8}F za#(gMD~Wr&klSU z3J=Oqje6TstLETF3cNP)lG9}dU2AX59BpofZeC|0E3BJrUhiEyGI_2-`ttKvg$qtn zRINRF??O#ne!ct0nyA7DwU1uPhoG#Qn8W*r;_}q(aVJWhTVB=yyTm1Dx;wt$ G?|%VXlvq0e literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Class/BinTree/bintree.e b/amigae33a/E_v3.3a/Src/Src/Class/BinTree/bintree.e new file mode 100644 index 0000000..97bcf0e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/BinTree/bintree.e @@ -0,0 +1,60 @@ +-> binary tree implementation in E + +OBJECT bintree PRIVATE + left:PTR TO bintree + right:PTR TO bintree +ENDOBJECT -> subclasses can add data here + +PROC is_bigger(other:PTR TO bintree) OF bintree IS EMPTY +PROC is_equal(other:PTR TO bintree) OF bintree IS EMPTY + +PROC bintree(l,r) OF bintree + self.left:=l + self.right:=r +ENDPROC + +-> folds value v with proc through the tree. + +PROC traverse(proc,v) OF bintree + v:=proc(self,v) + IF self.left THEN v:=self.left.traverse(proc,v) + IF self.right THEN v:=self.right.traverse(proc,v) +ENDPROC v + +/*-------------------------------------------------------*/ + +-> integer tree + +OBJECT intbintree OF bintree + i:LONG +ENDOBJECT + +PROC intbintree(l,r,i) OF intbintree + self.bintree(l,r) -> call super constructor + self.i:=i +ENDPROC + +PROC is_bigger(other:PTR TO intbintree) OF intbintree IS self.i>other.i +PROC is_equal(other:PTR TO intbintree) OF intbintree IS self.i=other.i + +PROC total() OF intbintree IS self.traverse({sum},0) +PROC sum(t:PTR TO intbintree,v) IS t.i+v + +/*-------------------------------------------------------*/ + +-> string tree + +OBJECT strbintree OF bintree + s:PTR TO CHAR +ENDOBJECT + +PROC is_bigger(other:PTR TO strbintree) OF strbintree IS EMPTY ->??? +PROC is_equal(other:PTR TO strbintree) OF strbintree IS StrCmp(self.s,other.s) + +/*-------------------------------------------------------*/ + +PROC main() + DEF p:PTR TO intbintree,p1:PTR TO intbintree,p2:PTR TO intbintree + NEW p.intbintree(NEW p1.intbintree(NIL,NIL,2),NEW p2.intbintree(NIL,NIL,3),40) + WriteF('total=\d\n',p.total()) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.doc b/amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.doc new file mode 100644 index 0000000..dd853f0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.doc @@ -0,0 +1,175 @@ +HASH.M: flexible and fast hashing functions. + +note: if you have no clue what hashing is, you might want to read a little + explanation I gave at the end of this doc first. + +why use these hashing functions? +-------------------------------- +simple: one does not need to know anything about how hashing to make + good use of this module. +flexible: the functions do not make _any_ assumptions upon the nature + of the data, the size of it, or anything else. you may therefore + use it to hash strings, graphical data, etc. +fast: not only does this module use a high performance hashing function, + but also the most time-consuming function, hash_find() has been + written in optimised inline assembly. + +the object +---------- + +OBJECT hashtable + hashtable(tablesize) + end() + find(ptr,len) + add(link,hashvalue,ptr,len) + iterate(do_proc) + calc_hash_spread() +ENDOBJECT + +methods +------- + + hastable(tablesize) + +This constructor initialises an empty hashtable. tablesize is the size of +the hashtable, predifined are some usefull values: + + tablesize size in kb +HASH_NORMAL 211* 1 +HASH_MEDIUM 941 4 +HASH_HEAVY 3911 16 +HASH_HEAVIER 16267 64 + +(*) the tablesizes above are primes close to 2 to the power + of 8,10,12,14,16 (for performance reasons) + +The larger the table, the faster the search. +instead of these constanst, you can also use your own size, +if you wish. the size should however be between 2 and 65535, +and a prime for best performance. + +example: + +DEF t:PTR TO hashtable +NEW t.hashtable(HASH_HEAVY) + +may raise: "MEM" + + + end() + +frees table. memory is also deallocated automatically at the end of +the program. example: + +END t + + + hashlink,hashvalue:=t.find(data,len) + +Tries to find data with length len in hash table. When data is not present +in the table, hashlink will NIL. You'll need to store hashvalue only if you +wish to call add() next, and hashlink only if you wish to access the data +related to whatever you hashed next (see below). + + + add(link:PTR TO hashlink,hashvalue,data,len) + + +adds data to table. you'll need to call find() before this one, +not only to know the hashvalue this function needs, but also to be +sure data isn't already in the table. link must be a subclass of +'hashlink': + +OBJECT hashlink +ENDOBJECT /* SIZEOF=12 */ + +the hashtable uses this object to store data in the table. if you wish +to associate data with whatever you're hashing, make a subclass: + +OBJECT mylink OF hashlink + type:INT -> extra field +ENDOBJECT + +these objects are also the ones return by find if data is already present in +table. example: + +t.add(NEW linkptr,hashv,ptr,len) + +ptr and len are the same ones you passed to find(). note that add() does +not copy the 'ptr'. + + + total,num:=t.iterate(proc) + +walks through the whole hashtable, calling proc for every link. +proc must be something like: + +PROC it(link:PTR TO hashlink,depth) + +depth is how deep the link hangs in a chain, i.e. minimally 1. +returned from iterate() is the sum of all returnvalues from +calling proc, and the number of links visited. + + calc_hash_spread() + +makes use of iterate() to calculate the average number of StrCmp's +needed to find some data in this table. see hashtest.e for example use. + + +example use +----------- + +Imagine we're programming a compiler, like EC. To keep things simple, +we only do global variables. first, set up the table: + +DEF t:PTR TO hashtable, identinfo:PTR TO mylink -> see above +NEW t.hashtable(HASH_MEDIUM) + +now the following piece of code would be entered when we've read +an identifier. in 'ident' and 'len' we have the identifier, +and 'status' says wether we are currently in the scope of a DEF or not: + +-> see if ident is already there +identinfo,hashvalue:=t.find(ident,len:=EstrLen(ident)) + +IF identinfo + IF status=DEFINITION THEN Raise('double declaration!') + -> do something with identinfo.type here, for example +ELSE + IF status=USE THEN Raise('unknown variable!') + t.add(NEW identinfo,hashvalue,ident,len) + -> assign here to identinfo.type, for example +ENDIF + + +for those who don't know: what is hashing? +------------------------------------------ +Assume the task of having to store identifiers like the ones used +for variables in E, and later finding them again (this could be any +kind of data, but for now just strings). We could put all these strings +in a linked list, and when a new identifier arrives, simply walk down +the list and see if it's there. While this may seem a nice and easy +way of doing it, this becomes unacceptably slow when storing, say, +2000 identifiers: we would, on average, perform 1000 StrCmp()s just +to find one identifier! + +then comes hashing, which is a simple and fast technique to dramatically +reduce search times: + +take a table of n entries (say, n=256), and take a function which for +every ident can compute a number 0..n-1 (this is called the hashvalue, +and such a function might be: add all ascii values MOD n). when you +now put the idents in n linked list hanging from the n entries in the +table, you only have to compute the hashvalue to theorethically wipe +out 255 of each 256 possibilities. searchtime for our example becomes +2000/256/2 => 4 StrCmp, without any costly computations. +and imagine what happens if you take a larger n, say 4096, then for most +compilations, you reduce to 1 StrCmp (!). + +This is an ideal situation, since strangely enough, in reality lot's of +strings end up in the same entry. To make a good distribution of strings +over entries, this module uses several techniques, among them a better +hashing function, primes for n, and others. While in reality you may +end up doing 8 StrCmp()s instead of 4 as in the ideal case, this is +still a huge improvement over the 1000 we started with. + diff --git a/amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.e b/amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.e new file mode 100644 index 0000000..a7cd933 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/Hash/hash.e @@ -0,0 +1,117 @@ +-> hashing module + +OPT MODULE + +EXPORT CONST HASH_NORMAL = 211, + HASH_MEDIUM = 941, + HASH_HEAVY = 3911, + HASH_HEAVIER = 16267 + +EXPORT OBJECT hashtable PRIVATE + size,entries:PTR TO LONG +ENDOBJECT + +EXPORT OBJECT hashlink PRIVATE + next +PUBLIC + data, len +ENDOBJECT + +PROC hashtable(tablesize) OF hashtable -> constructor + DEF table:PTR TO LONG + self.entries:=NEW table[tablesize] + self.size:=tablesize +ENDPROC + +PROC end() OF hashtable -> destructor + DEF p:PTR TO LONG + p:=self.entries + END p[self.size] +ENDPROC + +PROC end_links(sizeof) OF hashtable -> destruct all links if desired + DEF a,p:PTR TO hashlink, o:PTR TO hashlink + FOR a:=0 TO self.size-1 + p:=self.entries[a] + WHILE o:=p; p:=p.next; FastDispose(o,sizeof); ENDWHILE + ENDFOR +ENDPROC + +/* hashes data, then tries to find entry. + returns hashlink, hashvalue */ + +PROC find(data,len) OF hashtable + DEF e,s + e:=self.entries + s:=self.size + MOVEM.L D3-D7,-(A7) + MOVE.L data,D6 -> D6=data + MOVE.L e,A1 -> A1=table + MOVE.L s,D3 -> D3=tablesize + MOVEQ #0,D1 -> D1=hashvalue + MOVEQ #0,D0 -> D0=hashlink + MOVE.L len,D4 -> D4=len + BEQ.S done + MOVE.L D4,D5 + MOVE.L D6,A2 + SUBQ.L #1,D5 +loop: + LSL.W #4,D1 + ADD.B (A2)+,D1 + DBRA D5,loop + DIVU D3,D1 + SWAP D1 + EXT.L D1 + MOVE.L A1,A2 -> now find entry + MOVE.L D1,D5 + LSL.L #2,D5 + ADD.L D5,A2 -> A2 points to spot in table +findd: + MOVE.L (A2),D5 -> pick next + BEQ.S done + MOVE.L D5,A2 + CMP.L 8(A2),D4 -> if lengths are unequal, don't bother + BNE.S findd + MOVE.L 4(A2),A0 -> get pointers to both areas + MOVE.L D6,A3 + MOVE.L D4,D5 + SUBQ.L #1,D5 +compare: -> bytewise compare + CMPM.B (A0)+,(A3)+ + BNE.S findd + DBRA D5,compare + MOVE.L A2,D0 -> found entry +done: + MOVEM.L (A7)+,D3-D7 +ENDPROC D0 + +-> add a new hashlink + +PROC add(link:PTR TO hashlink,hashvalue,data,len) OF hashtable + link.next:=self.entries[hashvalue] + link.data:=data + link.len:=len + self.entries[hashvalue]:=link +ENDPROC + +PROC iterate(do_proc) OF hashtable + DEF a,n,p:PTR TO hashlink, depth, r=0, num=0, table:PTR TO LONG + n:=self.size + table:=self.entries + FOR a:=1 TO n + p:=table[]++ + depth:=1 + WHILE p + r:=r+do_proc(p, depth++) + num++ + p:=p.next + ENDWHILE + ENDFOR +ENDPROC r,num + +PROC calc_hash_spread() OF hashtable + DEF idepth,num + idepth,num:=self.iterate({calcspread}) +ENDPROC IF num THEN !idepth/num ELSE 0.0 + +PROC calcspread(h,depth) IS depth diff --git a/amigae33a/E_v3.3a/Src/Src/Class/Hash/hashtest.e b/amigae33a/E_v3.3a/Src/Src/Class/Hash/hashtest.e new file mode 100644 index 0000000..cfcdbf3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/Hash/hashtest.e @@ -0,0 +1,58 @@ +/* test hashing functions + +identifiers are generated in amounts of 10,100,1000, which are +then hashed with tables of size 1, 211, 941, 3911 and 16267. +Displayed are the average number of StrCmp()'s needed to find +any of these identifiers. + +*/ + +MODULE 'class/hash' + +RAISE "MEM" IF String()=NIL + +PROC main() + DEF heavy:PTR TO LONG,a,b,l,num:PTR TO LONG,t=NIL:PTR TO hashtable, + c,ll,n,h,link:PTR TO hashlink,rs[10]:STRING + heavy:=[1,HASH_NORMAL,HASH_MEDIUM,HASH_HEAVY,HASH_HEAVIER] + num:=[10,100,1000] + l:=genidents(1000) + WriteF('numidents:') + FOR b:=0 TO 2 DO WriteF('\t\d\t',num[b]) + WriteF('\ntablesize:\n') + FOR a:=0 TO 4 + WriteF('[\d]\t\t',heavy[a]) + FOR b:=0 TO 2 + NEW t.hashtable(heavy[a]) + ll:=l + FOR c:=1 TO num[b] + n,h:=t.find(ll,EstrLen(ll)) + t.add(NEW link,h,ll,EstrLen(ll)) + ll:=Next(ll) + ENDFOR + WriteF('\s[8]\t',RealF(rs,t.calc_hash_spread(),4)) + END t + ENDFOR + WriteF('\n') + ENDFOR +ENDPROC + +-> generate some random identifiers + +PROC genidents(n) + DEF l=NIL,a,s[100]:STRING,x:PTR TO LONG,len,prt,b,y + x:=['bla','burp','e_','pom','ti','dom','aap','noot','mies'] + len:=ListLen(x) + FOR a:=1 TO n + StrCopy(s,'') + StrAdd(s,(y:=Rnd(26)+"A") BUT {y}+3,1) + StrAdd(s,(y:=Rnd(26)+"a") BUT {y}+3,1) + StrAdd(s,(y:=Rnd(26)+"A") BUT {y}+3,1) + prt:=Rnd(3)+1 + FOR b:=1 TO prt DO StrAdd(s,x[Rnd(len)]) + StrAdd(s,(y:=Rnd(26)+"A") BUT {y}+3,1) + StrAdd(s,(y:=Rnd(26)+"a") BUT {y}+3,1) + StrAdd(s,(y:=Rnd(26)+"A") BUT {y}+3,1) + l:=Link(StrCopy(String(EstrLen(s)),s),l) + ENDFOR +ENDPROC l diff --git a/amigae33a/E_v3.3a/Src/Src/Class/README b/amigae33a/E_v3.3a/Src/Src/Class/README new file mode 100644 index 0000000..38aa331 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/README @@ -0,0 +1,6 @@ +Gathered here are some class bits'n pieces. + +In the future, the emodules:class dir should be filled with +useful classes, but I'm sorry to say I haven't got to really +building a class-library. Hash and Stack though are quite +practical. diff --git a/amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/sc.doc b/amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/sc.doc new file mode 100644 index 0000000..6243fc1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/sc.doc @@ -0,0 +1,109 @@ +sc.m and sctext.m: scrolling windows. [see also: textview.e] + +The object `scrollwin' contained in sc.m is a general purpose window with +scrollbars that will display any items of information. `scrolltext' in the +module sctext.m inherits from scrollwin and implements a scrolling window with +text. It is very easy (and encouraged) to inherit from either of these +objects and implement your own scrolling windows (EDBG, for example, uses two +further objects that inherit from scrolltext and display memory/registers). + +members and methods of OBJECT scrollwin: + + NEW scrollwinptr.open(title,x,y,sx,sy,screen=NIL,ownidcmp=0,ownhandle=NIL) + +The constructor is called with some obvious arguments. With ownidcmp you can +for example attach menus to the window. ownhandle is a callback PROC with one +arg (the intuimessage). Will raise "scrl" if it can't get what if wants +(window etc.). + + quit:=handle() + +will handle messages to the window. May call your callback or some of the +extra_ methods below. If quit=TRUE the user clicked the close gadget. + + END scrollwinptr + +closes the window. + + refreshwindow() + +refresh the window manually if you change something about the data +represented. normally this is done by the window automatically. + +The extra_ methods are the ones you are supposed to override to implement the +display of the actual data (if you just want to use scrolltext, skip these): + + extra_init(screen) + +called from open(). Do any initialisations here if you wish. + + extra_exit() + +same for end(). + + px,py:=extra_unit() + +called by the object when it wants to know how big the items being displayed +are (i.e. (1,1) for pixels, (fontwidth,fontheight) for text etc.). The +default method returns (1,1). + + ux,uy:=extra_max() + +called by the object to ask the number of objects being displayed. this +should be somewhere between (1,1) and (32767,32767). + + extra_refresh(x,y,xsize,ysize,xoff,yoff,win:PTR TO window) + +The core. This method is called when the area of your data denoted by +(x,y,xsize,ysize) is currently visible (problably because the user scrolled it +there), and needs to be rendered. Note that these four numbers are in units +of your data, not pixels! You can use `win' to render the data, from (pixel) +offsets (xoff,yoff) in the window. + +As an example, say you're displaying a text with a font of 8x8 pixels, the +text has 100 lines and 80 columns. The user has resized the window such that +it has space for 10 lines of text and 40 columns, and scolled to the middle of +it. The call will then look like (for example): + +extra_refresh(20,45,40,10,12,4,win) + +the area to be rendered is thus (320,80) in size. Of course you can optimize +refreshing by using scrolling instead of re-rendering, you should implement +this yourself though (scrolltext does that). + + ux,uy:=where(px,py) + +finds the element denoted by those (pixel) coordinates, as you might receive +them in an intuimessage on a mouse click. The returned 2 coordinates take +care of position of the scrollers and unit size. + + settop(newtop=0,dorefresh=TRUE) + +manually sets the top of the area being displayed. do not use too often +as it might confuse the user. + + window:PTR TO window + +the only instance variable. careful when using this. + +The scrolltext object inherits from scrollwin. You should call open / handle +/ end etc. on it as usual. scrollwin redefines the extra_ methods of +scrollwin to implement text-specific scrolling. Following methods are added: + + settext(textlist,width) + +The constructor for this object. textlist should be an E list of +nil-terminated strings. width is the maximum width to display, i.e. usually +the maximum width of these strings. Call open() as the first method after +this one. + + active(cur,dorefresh=TRUE) + +Will set the current active line. This will be graphically marked by inverting the +line. If this method is never called there will be no active line display. + + uy:=getactive() + +asks what the currently active line is. + +as an example of all this, please see the extremely simple textview.e diff --git a/amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/textview.e b/amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/textview.e new file mode 100644 index 0000000..04675a8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/ScrollWin/textview.e @@ -0,0 +1,15 @@ +-> show a textfile in a nice juicy scrolling window + +MODULE 'tools/file', 'tools/exceptions', 'class/sctext' + +PROC main() HANDLE + DEF m,l,n,list,sc=NIL:PTR TO scrolltext + m,l:=readfile(arg) + list:=stringsinfile(m,l,n:=countstrings(m,l)) + NEW sc.settext(list,100) + sc.open('TextView v0.1',20,20,300,150) + WHILE sc.handle()=FALSE DO Wait(-1) +EXCEPT DO + END sc + report_exception() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Class/Stack/stack.e b/amigae33a/E_v3.3a/Src/Src/Class/Stack/stack.e new file mode 100644 index 0000000..21d3148 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/Stack/stack.e @@ -0,0 +1,35 @@ +-> Jaaaa, a true STACK in E! :-) + +OPT MODULE + +EXPORT OBJECT stack + PRIVATE d:PTR TO LONG +ENDOBJECT + +PROC stack() OF stack -> constructor + self.d:=NIL +ENDPROC + +PROC is_empty() OF stack IS self.d=NIL + +PROC push(x) OF stack + self.d:=NEW [self.d,x]:LONG +ENDPROC + +PROC pop() OF stack + DEF a:PTR TO LONG,b + IF a:=self.d + self.d:=a[]; b:=a[1] + END a[2] + ELSE + Raise("estk") + ENDIF +ENDPROC b + +PROC end() OF stack -> destructor + DEF a:PTR TO LONG,b:PTR TO LONG + a:=self.d + WHILE a + b:=a; a:=a[]; END b[2] + ENDWHILE +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Class/Stack/stackuse.e b/amigae33a/E_v3.3a/Src/Src/Class/Stack/stackuse.e new file mode 100644 index 0000000..db55c4e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Class/Stack/stackuse.e @@ -0,0 +1,13 @@ +-> lets use a STACK! + +MODULE 'class/stack' + +PROC main() HANDLE + DEF s=NIL:PTR TO stack,a + NEW s.stack() -> amaaazing! :-) + FOR a:=1 TO 10 DO s.push(a) + FOR a:=1 TO 11 DO WriteF('element = \d\n',s.pop()) +EXCEPT DO + END s + IF exception="estk" THEN WriteF('You underflowed the stack!\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Dos/Shell.e b/amigae33a/E_v3.3a/Src/Src/Dos/Shell.e new file mode 100644 index 0000000..e0f99bc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Dos/Shell.e @@ -0,0 +1,15 @@ +-> Silly Shell Example + +PROC main() + DEF inputstring[80]:STRING, con + IF con:=Open('con:10/10/400/100/MySillyShell v0.1',NEWFILE) + Write(con,'Shell by $#%! in 1991. "BYE" to stop.\n',STRLEN) + WHILE StrCmp(inputstring,'BYE')=FALSE + Execute(inputstring,0,con) + Write(con,'MyPrompt> ',STRLEN) + ReadStr(con,inputstring) + UpperStr(inputstring) + ENDWHILE + Close(con) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Dos/date.e b/amigae33a/E_v3.3a/Src/Src/Dos/date.e new file mode 100644 index 0000000..8cd058f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Dos/date.e @@ -0,0 +1,28 @@ +/* example of usage for DateStamp() and DateToStr() functions */ + +MODULE 'dos/datetime', 'dos/dos' + +DEF dt:datetime,ds:PTR TO datestamp + +/* these are filled by DateToStr() */ +DEF day[50]:ARRAY,date[50]:ARRAY,time[50]:ARRAY + +PROC main() + + /* get stamp in part of datetime structure */ + ds:=DateStamp(dt.stamp) + + WriteF('days=\d, minutes=\d, ticks=\d\n',ds.days,ds.minute,ds.tick) + + /* fill datetime structure */ + dt.format:=FORMAT_DOS + dt.flags:=DTF_SUBST + dt.strday:=day + dt.strdate:=date + dt.strtime:=time + + IF DateToStr(dt) + WriteF('day=\s, date=\s, time=\s\n',day,date,time) + ENDIF + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Dos/readtext.e b/amigae33a/E_v3.3a/Src/Src/Dos/readtext.e new file mode 100644 index 0000000..ee87558 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Dos/readtext.e @@ -0,0 +1,27 @@ +/* read a text file example. note that the program has no + hardcoded limit on the lenght of the file */ + +CONST MAXLINELEN=1000 + +PROC main() + DEF fh,buf[MAXLINELEN]:ARRAY,n=0,last=NIL,s,first=NIL + IF fh:=Open(arg,OLDFILE) + WHILE Fgets(fh,buf,MAXLINELEN) + IF (s:=String(StrLen(buf)))=NIL THEN Raise("MEM") + StrCopy(s,buf,ALL) + IF last THEN Link(last,s) ELSE first:=s + last:=s + INC n + ENDWHILE + Close(fh) + WriteF('FILE: "\s", \d lines.\n\n',arg,n) + s:=first + WHILE s + PutStr(s) + s:=Next(s) + ENDWHILE + DisposeLink(first) + ELSE + WriteF('no file: "\s"\n',arg) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Explorer/Explorer.doc b/amigae33a/E_v3.3a/Src/Src/Explorer/Explorer.doc new file mode 100644 index 0000000..f97d795 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Explorer/Explorer.doc @@ -0,0 +1,224 @@ +Short: Amazing System Browser and Debugger +Type: dev/e +Author: jason@fsel.com (Jason R. Hulance) + +Explorer 2.1j +============= +Allows you to browse around memory as E objects (which are like C structs). + +Basic Function +-------------- +You enter an address and then select the object which is (supposed to be?) +at that address. You can then see the value that each element of the +object takes, and follow pointers etc. by double-clicking on the element (a +single click changes the address to the element's address, which is an +offset from the address you specified for the object). + +A double-click may therefore change the object being browsed, so there is a +way of returning to the original object via the "Back Up" button. As you +double-click and select new objects your choices are recorded. The current +depth of this path is shown as the 'Depth:' text. The action of the "Back +Up" button is duplicated by the "Back Up" menu item on the "Selections" +menu. There is also an option to clear the current path on this menu. + +The list of objects may be created in several ways (these are found on the +"Project" menu): + + 1) "Open" Opens a previously saved config file, containing any number of + objects. By default, when Explorer starts it tries to load + objects from "explorer.config" in the current directory, and + then "s:explorer.config" if that fails. The supplied + "explorer.config" file contains all the standard Amiga OS + objects. (This file was created by using "Load Modules" on the + "Emodules:" directory and then saving the config using the next + option.) + 2) "Save" Saves the current list of objects as an Explorer config file. + 3) "Load Modules" Scan the selected module or all the modules in the + selected directory and its sub-directories. The found objects + will replace any current list of objects. This operation can + take a long time, especially if you try to load all the modules + in "Emodules:". You can interrupt it at any time by closing the + status window. + 4) "Merge Modules" Same as 3) but any objects found are added to the + current list of objects rather than replacing them. + 5) "Load Cache" Same as 3) but the current E module cache is scanned. + This is most useful when Explorer is used to help debug your + programs. + +The address and object can also be specified via ARexx, making Explorer an +extremely useful debugging tool as well as a system browser! In fact, EDBG +v3.3a+ makes use of Explorer to analyse typed variables. (A module is +supplied to show how easy it is to integrate the appropriate ARexx call +into your program.) + +Object Layout +------------- +The elements of the selected object are listed in order. If you choose to +see the value of element it will be displayed in hex in parenthesis after +the element, and if you choose to see the element address (an offset from +the object address) it will be displayed after an '@'. (Use the +"Selections" menu to decide which, if any, you want to see.) + +Where to Start +-------------- +Explorer starts off with the address of an internal hail and copyright +string. The items on the "Presets" menu give some other, interesting +starting points: + + 1) "Dos" Views the address stored in the 'dosbase' global variable as a + 'doslibrary' object. The dos.library is one of the fundamental + Amiga system libraries, and 'dosbase' is its corresponding + library base object. + 2) "Exec" Same as 1) but for the 'execbase' variable and object for the + exec.library (the most fundamental Amiga system library). + 3) "Graphics" Same as 1) but for the 'gfxbase' variable and object for the + graphics.library. + 4) "Intuition." Same as 1) but for the 'intuitionbase' variable and + object for the intuition.library. + 5) "This Process." Views the 'process' object for the running Explorer + program! + +For a typical Explorer session, you would probably start at one of these +points and then double-click on elements and use the "Back Up" button to +browse around. You never really need to set the address explicitly on the +GUI (at worst you'd do it by ARexx), but the option is there if you really +want to... + +Simple Types +------------ +The "CHAR", "INT" and "LONG" buttons view the contents of the address as if +it were a pointer to the corresponding type, and fills in the 'Hex:', +'Decimal:' and 'String:' texts with the value(s) being pointed at. + +"BSTR" is similar to "CHAR" but it first converts the address from a BCPL +pointer and then skips over the length byte. "BADDR" just converts the +address to a BCPL pointer. + +"--" and "++" treat the address as if it were pointing to an array of the +type last requested (i.e., an object or simple type). "--" moves the +address back to the previous element in the array, and "++" moves it on to +the next. The size of the last requested type is shown as the 'Size:' +text. (Note: "--" can be activated also by the "p" key and "++" by the "n" +key.) + +Display Beeps! +-------------- +The screen will flash (or you'll get a beep or whatever your Workbench is +set up to do) if you do one of the following: + + 1) Select something when the address is NIL (zero). A NIL address is not + valid (although Explorer will behave as if it were). + 2) Select an element which is a NIL pointer or a LONG that is NIL. + 3) Select an element with object or PTR TO object type, where the object + is not in the current list of objects. + 4) Backup past a depth of zero. + +Command Line Options +-------------------- +The command line template is: + + OBJECT,ADDR,ALL/S,CACHE/S,NONE/S,CONFIG/K,SCREEN/K,NOAUTOREPLY/S + + 1) OBJECT Specify an initial object to be displayed (to be useful, the + appropriate module must also be loaded using 'ALL' or 'CACHE'). + 2) ADDR Specify an initial address to be displayed (NIL is ignored!). + 3) ALL Load all objects from the modules in Emodules: and its + sub-directories (overrides 'CACHE' and 'CONFIG'). + 4) CACHE Load all objects from the modules in the current E module cache + (overrides 'CONFIG'). + 5) NONE Start with no objects (overrides 'ALL', 'CACHE' and 'CONFIG'). + 6) CONFIG Specify the config file to load. If this load fails then + Explorer will try "s:explorer.config". + 7) SCREEN Specify the public screen to open on. Normally Explorer will + open on the default public screen. + 8) NOAUTOREPLY Specifies that the "Auto Reply" option (described below) + should start as off rather than on. + +By default, Explorer will try to load the "explorer.config" in the current +directory (as if you'd used the CONFIG option -- so if will fall back to +trying "s:explorer.config"). The starting address will be that of an +internal hail and copyright string (which will be displayed as the +'String:' text). + +ARexx +----- +The "Reply" menu item on the "ARexx" menu manually replies to an ARexx +message that may have been received. You can also let Explorer +automatically reply to these messages by checking the "Auto Reply" option, +but the manual method is best since you can be sure that the pointers +remain valid while you browse (since the calling program is halted). Once +you've replied to a message the calling program is free to scribble all +over the memory at the address it just gave you... + +A module 'sendexplorer' is supplied to simplify the debugging facilities of +Explorer. It defines a single function, 'sendExplorer': + + PROC sendExplorer(addr,obj=NIL,repPort=NIL,message=NIL,quiet=FALSE) + + 'addr' is the address you wish to use. + 'obj' is the name of the object you are interested in. + 'repPort' is a message port for replies. If you don't supply this then a + temporary port is created for the duration of the function call. + (The purpose of this parameter is to allow you to re-use the + same port during your program if you call 'sendExplorer' a lot.) + 'message' is a short string to be displayed in the 'Message:' part of + Explorer. Use this to communicate some information about the + address and object (EDBG uses this to give the name, type and + scope of the variable being explored). + 'quiet' is a boolean to say whether Explorer should complain if the + object is not loaded. + +An example call is: + + sendExplorer(packet, 'dospacket') + +To browse using your own objects you'd separate them out into modules and +load these modules in your program. Compiling your program would add these +to the E module cache, which can then be used to set-up Explorer (using the +"Load Cache" menu item). Alternatively, you could "Load" or "Merge" the +appropriate module directly, or use a config file if the objects don't +change very often. + +Altering Data +------------- +By popular demand, if you hold down the shift key when you click on an +element of an object or on the 'CHAR', 'INT' or 'LONG' buttons, then a +small window pops up which allows you to edit the appropriate value. It's +not very safe to randomly edit data (especially system data), so use of +this feature is discouraged unless you really know what you're doing... + +Example Program +--------------- +To show how useful Explorer can be, there is a modified version of the +'empty' handler supplied. This uses the above call to 'sendExplorer' to +communicate the value of the packet currently being processed. Since the +handler is not a full process (it's just a task) there would normally be no +simple way of debugging it or examining the packets as they arrive (none of +the DOS functions, such as printing text, are available to simple tasks). +However, the handler can send messages to ARexx and thus to Explorer. + +To try it out: + + 1) Make sure ARexx is up (by running RexxMast, if necessary). + 2) Start up Explorer using, + run explorer all + 3) Now copy the 'empty-handler' to L:, + copy empty-handler L: + 4) Mount it using, + mount empty: from empty.mountlist + 5) Use the handler, + type empty:10 + 6) Look at Explorer. It will be displaying the first packet. Browse + around it, remembering that most elements will be BCPL strings. + 7) Select "Reply" from the ARexx menu (or press RAmiga-R) to reply to this + message. + 8) Another packet arrives and the message is sent to Explorer. + 9) Repeat 6)-8) until the 'type' command finishes and you get the Shell + prompt back. + +EDBG +---- +EDBG v3.3a+ communicates data about a variable if you hold down the shift +key and double-click on a variable that's within the current scope (EDBG +also adds it to the list of watched variables, if necessary). + diff --git a/amigae33a/E_v3.3a/Src/Src/Explorer/empty-handler.e b/amigae33a/E_v3.3a/Src/Src/Explorer/empty-handler.e new file mode 100644 index 0000000..84a4246 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Explorer/empty-handler.e @@ -0,0 +1,103 @@ +/*** + Returns the number of X's specified as filename: + "Copy Empty:100 Ram:test" will create a file "test" in Ram: + containing 100 X's +***/ + +OPT OSVERSION=37, PREPROCESS + +MODULE 'dos/dos', + 'dos/dosextens', + 'dos/filehandler', + 'exec/ports', + 'exec/nodes', + 'rexx/rxslib', + 'rexxsyslib', + 'amigalib/ports', + 'other/sendexplorer' + +ENUM ERR_NONE, ERR_LIB + +RAISE ERR_LIB IF OpenLibrary()=NIL + +PROC getpacket (p:PTR TO process) + DEF port:PTR TO mp, msg:PTR TO mn + port:=p.msgport -> The port of our process + WaitPort(port) -> Wait for a message + msg:=GetMsg(port) +ENDPROC msg.ln.name + +PROC main() HANDLE + DEF myrep=NIL:PTR TO mp + rexxsysbase:=OpenLibrary(RXSNAME, 0) + IF NIL=(myrep:=createPort(NIL,0)) THEN Raise("PORT") + handler(myrep) +EXCEPT DO + IF myrep THEN deletePort(myrep) + IF rexxsysbase THEN CloseLibrary(rexxsysbase) +ENDPROC + +PROC initialpacket(myrep) + DEF proc:PTR TO process, packet:PTR TO dospacket, ln:PTR TO ln, + dev:PTR TO devicenode + proc:=FindTask(NIL) + ln:=wbmessage + packet:=ln.name + wbmessage:=NIL + dev:=BADDR(packet.arg3) + dev.task:=proc.msgport + sendExplorer(packet, 'dospacket', myrep) + ReplyPkt(packet, DOSTRUE, 0) +ENDPROC proc, dev + +PROC handler(myrep) + DEF proc, packet:PTR TO dospacket, dev:PTR TO devicenode, + fh:PTR TO filehandle, running=TRUE, opencount=0, + readlen, c, s, filename[64]:STRING, type + proc,dev:=initialpacket(myrep) + WHILE running + packet:=getpacket(proc) + sendExplorer(packet, 'dospacket', myrep) + type:=packet.type + SELECT type + CASE ACTION_FINDINPUT + s:=BADDR(packet.arg3) + c:=0 + WHILE c":") DO INC s + IF s[]=":" THEN INC s + c:=Val(s) + INC opencount + fh:=BADDR(packet.arg1) + fh.interactive:=0 -> Non-interactive file + fh.args:=fh + fh.arg2:=c + ReplyPkt(packet, DOSTRUE, 0) + CASE ACTION_READ + fh:=packet.arg1 + s:=packet.arg2 + readlen:=Min(fh.arg2, packet.arg3) + c:=0 + WHILE c0 + ReplyPkt(packet, DOSTRUE, 0) + DEFAULT + ReplyPkt(packet, DOSFALSE, ERROR_ACTION_NOT_KNOWN) + ENDSELECT + ENDWHILE + dev.task:=FALSE +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Explorer/empty.mountlist b/amigae33a/E_v3.3a/Src/Src/Explorer/empty.mountlist new file mode 100644 index 0000000..0715db2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Explorer/empty.mountlist @@ -0,0 +1,5 @@ +EMPTY: Handler = l:empty-handler + Stacksize = 4096 + Priority = 5 + GlobVec = -1 +# diff --git a/amigae33a/E_v3.3a/Src/Src/Explorer/explorer.config b/amigae33a/E_v3.3a/Src/Src/Explorer/explorer.config new file mode 100644 index 0000000000000000000000000000000000000000..181d931fb33a589d6f60b1550f13005f360a88bf GIT binary patch literal 68154 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

!T5Hw%WDaU@0~G^M<3IfW1xz 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ʊp0h_w311_d@SzYohwU$b@(Xis5EQHlE0b64pd5 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 E04ZTu8~^|S literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/24bitColourDemo.e b/amigae33a/E_v3.3a/Src/Src/Gfx/24bitColourDemo.e new file mode 100644 index 0000000..2432de9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/24bitColourDemo.e @@ -0,0 +1,46 @@ +/* 24bit color demo. works only on AGA machines with kick3 + +A small demo demonstrating the new 24bit palette of the newer AA +Amigas. You'll need such an amiga and kick3 to run this demo, ofcourse. +The demo will draw lines in 256 tints and less on the screen, and then +lets you manipulate the colour-registers by pressing the leftMB on some +(x,y) spot on the screen. These coordinates will serve as RGB values. +To quit, press the rightMB. + +*/ + +OPT OSVERSION=39 + +CONST X=319, Y=255 + +PROC main() + DEF s,win,x,y,z + IF s:=OpenS(X+1,Y+1,8,0,'bla') + IF win:=OpenW(0,0,X+1,Y+1,0,0,'bla',s,15,0) + FOR x:=0 TO 255 DO SetColour(s,x,x,x,x) + FOR y:=0 TO Y DO Line(0,y,63,y,y AND $FF) + FOR y:=0 TO Y DO Line(64,y,127,y,y AND $FE) + FOR y:=0 TO Y DO Line(128,y,191,y,y AND $FC) + FOR y:=0 TO Y DO Line(192,y,255,y,y AND $F8) + FOR y:=0 TO Y DO Line(256,y,319,y,y AND $F0) + SetDrMd(stdrast,0) + SetTopaz(8) + TextF(0,30,' Press leftMB on some (x,y) spot') + TextF(0,40,' Press (0,0) to leave.') + TextF(0,50,' #of colours:') + TextF(0,60,' 256 128 64 32 16 ') + TextF(0,70,' #bits colour:') + TextF(0,80,' 24 21 18 15 12 ') + TextF(0,90,' AGA AGA AGA AGA ECS ') + WHILE TRUE + WaitLeftMouse(win) + y:=MouseX(win)*4/5 + z:=MouseY(win) + EXIT y+z<4 + FOR x:=0 TO 255 DO SetColour(s,x,y,x,z) + ENDWHILE + CloseW(win) + ENDIF + CloseS(s) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/TEXTUREMAP_ROAD.br.chunky b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/TEXTUREMAP_ROAD.br.chunky new file mode 100644 index 0000000000000000000000000000000000000000..9c4c8fde844b24888f1f1bdc6d71914badba0f58 GIT binary patch literal 16384 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 C@`RiK literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/c2p4.m b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/c2p4.m new file mode 100644 index 0000000000000000000000000000000000000000..a8db0f2459badbbd64f764fb830551430b38705a GIT binary patch literal 1374 zcmb7^Ur1A77{;INoNUSblMLC#qI0&xIE|GWB3;N_u|njyEOsM^jEtdPwA~mcBc^5( zl`bMAx(YA6@S>ZfFeN0q2(gF?k%+tzQV6{1qGIm!oU=db1fc`J_w3vIz3=`|LBGSI&ERJDHYsanfG+8$T&F1?WQSys}E!>Qr%F}L+i+9#}} zx2ML3$=I2YgvHUV$>$^YMz4-!hJ$rmTdnYt1h!^uiMnp-v@;~|BON}Hxx|h zR5a8;A7ZkpDLOoV3=j8krfh*P?x|%)9@0NSGiQj1aK05cO?#suSq*eGBv)6Fkdqag z5)h=vg6@ldx!T~W3_32TUxTp&Smg+!_OLo!d6$TC?WYdpr4gfUhZQHh^4kxPWJ)($dAxJv7N z!aUY#@|64{zxlP}Dh1{dm`7k9fiXgabd!E^i!g`qg1jPc$w%^qd}mJ%(ntajQPy)l S(Fo(NRr9v+m>G|*8}=U#VNIa` literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls.e b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls.e new file mode 100644 index 0000000..9fea03c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls.e @@ -0,0 +1,143 @@ +-> landscape test + +OPT OSVERSION=39 + +CONST CWIDTH=256,CHEIGHT=128,CWSHIFT=8 +CONST SCHEIGHT=CHEIGHT+20 +CONST TEMPBUFS=CWIDTH*CHEIGHT/2,BUFS=CWIDTH*CHEIGHT,BUFM=$7FFF +CONST SXOFF=50,SYOFF=80 + +MODULE '*c2p4', '*screenmodereq_db', 'tools/exceptions', 'tools/scrbuffer', + 'intuition/screens', 'graphics/rastport', 'graphics/gfx', + 'intuition/intuition' + +PROC main() HANDLE + DEF dbs,scr=NIL:PTR TO screen,bm:PTR TO bitmap,win=NIL:PTR TO window, + tbuf2,tbuf3,tbuf2b,tbuf3b,cbuf,dbuf,dbuf2,lsbuf,sigbit,sig,safe=TRUE,a,x=0,y=0, + imsg:PTR TO intuimessage,temp + IF (dbs:=openreqscreen(CWIDTH,SCHEIGHT,4,'bla'))=NIL THEN Raise() + scr:=sb_GetScreen(dbs) + IF (win:=OpenW(0,0,CWIDTH-1,SCHEIGHT-1, + IDCMP_MOUSEBUTTONS OR IDCMP_MOUSEMOVE, + WFLG_REPORTMOUSE OR WFLG_BORDERLESS OR WFLG_SIMPLE_REFRESH OR WFLG_BACKDROP OR WFLG_ACTIVATE, + '',scr,15,NIL))=NIL THEN Raise("WIN") + tbuf2:=NewM(TEMPBUFS+TEMPBUFS,2) + tbuf3:=tbuf2+TEMPBUFS + tbuf2b:=NewM(TEMPBUFS+TEMPBUFS,2) + tbuf3b:=tbuf2b+TEMPBUFS + NEW cbuf[BUFS] + NEW dbuf[BUFS] + NEW dbuf2[BUFS] + NEW lsbuf[BUFS] + FOR a:=0 TO BUFS-1 + dbuf[a]:=-1 + dbuf2[a]:=-1 + ENDFOR + FOR a:=0 TO 15 DO SetColour(scr,15-a,a*16,a*16,a*16) + mountain(cbuf) + CopyMem(cbuf,lsbuf,BUFS) + SetRast(scr.rastport,0) + IF (sigbit:=AllocSignal(-1))<>-1 + sig:=Shl(1,sigbit) + REPEAT + render(cbuf,lsbuf,CWIDTH*y+x,80,80) + x:=x+2 + y:=y+3 + IF safe=FALSE + Wait(sig) + safe:=TRUE + ENDIF + bm:=sb_NextBuffer(dbs) + ->SetColour(scr,15,f:=255-f,f,f) + c2p4(tbuf3,tbuf2,cbuf,dbuf,bm.planes,FindTask(NIL),sig,gfxbase) + temp:=dbuf; dbuf:=dbuf2; dbuf2:=temp + temp:=tbuf2; tbuf2:=tbuf2b; tbuf2b:=temp + temp:=tbuf3; tbuf3:=tbuf3b; tbuf3b:=temp + IF imsg:=GetMsg(win.userport) + x:=0-imsg.mousex + y:=0-imsg.mousey + ReplyMsg(imsg) + ENDIF + safe:=FALSE + UNTIL Mouse() + IF safe=FALSE THEN Wait(sig) + FreeSignal(sigbit) + ENDIF +EXCEPT DO + IF win THEN CloseWindow(win) + closereqscreen(dbs) + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "REQ"; WriteF('Error: Could not allocate ASL request\n') + CASE "ASL"; WriteF('Error: Could not open ASL library\n') + ENDSELECT + report_exception() +ENDPROC + +PROC mountain(buf) + DEF a,x,y + FOR a:=0 TO BUFS-1 + y:=a/CWIDTH; x:=Mod(a,CWIDTH) + buf[a]:=Bounds( + ((x-128)*(x-128))+((y-64)*(y-64))/300, + ->x*y/300, + ->!(!Fsin(x!/10.0)*3.0+3.0)+(!Fsin(y!/10.0)*3.0+3.0)!, + ->!Fsin(x!/10.0)*6.0*Fsin(y!/10.0)+5.0!, + 0,15) + ENDFOR +ENDPROC + +PROC render(destbuf,lsbuf,offs,xs,ys) + DEF a,t1,t2 + clearmem(destbuf,BUFS) + t1:=ys-1*CWIDTH-1+offs + t2:=xs-1+offs + FOR a:=1 TO xs DO line(a,t1+a AND BUFM,a+SXOFF,a/2+SYOFF,destbuf,lsbuf) + FOR a:=ys-1 TO 1 STEP -1 DO line(a,a-1*CWIDTH+t2 AND BUFM,xs*2+SXOFF-a,a/2+SYOFF,destbuf,lsbuf) +ENDPROC + +PROC clearmem(mem,size) + DEF e:REG,a:REG,b:REG,c:REG,d:REG + e:=size/16-1 + a:=b:=c:=d:=$04040404 + MOVE.L mem,A0 + ADD.L size,A0 +clloop: + MOVEM.L a/b/c/d,-(A0) + DBRA e,clloop +ENDPROC + +PROC line(num,start,sx,sy,destbuf,lsbuf) + DEF a:REG,y,t:REG,c=0:REG,xoff:REG,yoff:REG + xoff:=sx+destbuf + yoff:=sy-25-num+1 + y:=sy*CWIDTH+xoff + a:=num-1+yoff + MOVE.L start,D2 -> D2=start + MOVEA.L lsbuf,A3 -> A3=lsbuf + MOVE.L y,A2 -> A2=y + MOVE.L #CWIDTH,D1 -> D1=CWIDTH + MOVE.L #BUFM,D0 -> D0=BUFM + MOVE.L #CWIDTH+1,A1 -> A1=CWIDTH+1 +bloop: -> this loop eats almost all cpu-time. + MOVE.B 0(A3,D2.L),c + MOVE.L a,t + ADD.L c,t + LSL.L #CWSHIFT,t + ADD.L xoff,t + CMP.L A2,t + BGE.S skip + BRA.S loop +begi: + SUBA.L D1,A2 + MOVE.B c,(A2) +loop: + CMP.L A2,t + BMI.S begi +skip: + SUB.L A1,D2 + AND.L D0,D2 + SUBQ.L #1,a + CMP.L yoff,a + BPL.S bloop +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls_sculpt.e b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls_sculpt.e new file mode 100644 index 0000000..9f22d74 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/ls_sculpt.e @@ -0,0 +1,205 @@ +/* ++---------------------------------------------------------------+ +| RealTime 2.5d Landscape Sculpting ! | ++---------------------------------------------------------------+ + +usage: run it, preferably selecting lowres from the requester, +the sculpt with leftmouse, quit with rightmouse. + +sculpting is done as follows: two halfs of the screen (left-right) +influence the height of the two sides of the landscape. You'll need +to experiment a bit to get an idea what you can accomplish this way. + +for further fun: try and recompile with a different #define for +`trans()' further down the source. + +The code is pretty OS friendly (using intuition double-buffering +etc.), I hope it also works on gfx-cards (don't know about the +chunky code though). + +The sculpting bit is only a demo for the underlying engine, which +could display _any_ animated 3d landscape in realtime [it +should be fast enough on anything from an A1200+fast upwards] + +*/ + +OPT OSVERSION=39, PREPROCESS + +CONST CWIDTH=256,CHEIGHT=128,CWSHIFT=8 +CONST SCHEIGHT=CHEIGHT+20 +CONST TEMPBUFS=CWIDTH*CHEIGHT/2,BUFS=CWIDTH*CHEIGHT,BUFM=$7FFF +CONST SXOFF=50,SYOFF=80 +CONST XY3D=80 + +MODULE '*c2p4', '*screenmodereq_db', 'tools/exceptions', 'tools/scrbuffer', + 'intuition/screens', 'graphics/rastport', 'graphics/gfx', + 'intuition/intuition', 'devices/inputevent' + +DEF sideh[XY3D]:ARRAY OF LONG, both[XY3D]:ARRAY OF LONG + +PROC main() HANDLE + DEF dbs,scr=NIL:PTR TO screen,bm:PTR TO bitmap,win=NIL:PTR TO window, + tbuf2,tbuf3,tbuf2b,tbuf3b,cbuf,dbuf,dbuf2,lsbuf,sigbit,sig,safe=TRUE,a,x=0,y=0, + imsg:PTR TO intuimessage,temp,lastx=-1,lasty=-1,quit=FALSE + IF (dbs:=openreqscreen(CWIDTH,SCHEIGHT,4,'2.5d'))=NIL THEN Raise() + scr:=sb_GetScreen(dbs) + IF (win:=OpenW(0,0,CWIDTH-1,SCHEIGHT-1, + IDCMP_MOUSEBUTTONS OR IDCMP_MOUSEMOVE, + WFLG_REPORTMOUSE OR WFLG_BORDERLESS OR WFLG_SIMPLE_REFRESH OR WFLG_BACKDROP OR WFLG_ACTIVATE OR WFLG_RMBTRAP, + '',scr,15,NIL))=NIL THEN Raise("WIN") + tbuf2:=NewM(TEMPBUFS+TEMPBUFS,2) + tbuf3:=tbuf2+TEMPBUFS + tbuf2b:=NewM(TEMPBUFS+TEMPBUFS,2) + tbuf3b:=tbuf2b+TEMPBUFS + NEW cbuf[BUFS] + NEW dbuf[BUFS] + NEW dbuf2[BUFS] + NEW lsbuf[BUFS] + FOR a:=0 TO BUFS-1 + dbuf[a]:=-1 + dbuf2[a]:=-1 + ENDFOR + FOR a:=0 TO XY3D-1 + sideh[a]:=15 + both[a]:=15 + ENDFOR + ->FOR a:=0 TO 15 DO SetColour(scr,15-a,a*16,(15-a)*16,240) + FOR a:=0 TO 15 DO SetColour(scr,15-a,a*16,a*16,a*16) + FOR a:=0 TO BUFS-1 DO cbuf[a]:=15 + CopyMem(cbuf,lsbuf,BUFS) + SetRast(scr.rastport,0) + IF (sigbit:=AllocSignal(-1))<>-1 + sig:=Shl(1,sigbit) + REPEAT + render(cbuf,lsbuf,0,XY3D,XY3D) + IF safe=FALSE + Wait(sig) + safe:=TRUE + ENDIF + bm:=sb_NextBuffer(dbs) + c2p4(tbuf3,tbuf2,cbuf,dbuf,bm.planes,FindTask(NIL),sig,gfxbase) + temp:=dbuf; dbuf:=dbuf2; dbuf2:=temp + temp:=tbuf2; tbuf2:=tbuf2b; tbuf2b:=temp + temp:=tbuf3; tbuf3:=tbuf3b; tbuf3b:=temp + WHILE imsg:=GetMsg(win.userport) + x:=imsg.mousex; y:=imsg.mousey + IF imsg.qualifier AND IEQUALIFIER_RBUTTON THEN quit:=TRUE + IF (imsg.class=IDCMP_MOUSEBUTTONS) AND (imsg.code=SELECTUP) + lastx:=-1; lasty:=-1 + ENDIF + IF imsg.qualifier AND IEQUALIFIER_LEFTBUTTON + IF lastx>=0 + WHILE lastx<>x + IF lastx>x THEN lastx-- ELSE lastx++ + press(lastx,y,lsbuf) + ENDWHILE + ELSE + press(lastx:=x,lasty:=y,lsbuf) + ENDIF + ENDIF + ReplyMsg(imsg) + ENDWHILE + safe:=FALSE + UNTIL quit + IF safe=FALSE THEN Wait(sig) + FreeSignal(sigbit) + ENDIF +EXCEPT DO + IF win THEN CloseWindow(win) + closereqscreen(dbs) + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "REQ"; WriteF('Error: Could not allocate ASL request\n') + CASE "ASL"; WriteF('Error: Could not open ASL library\n') + ENDSELECT + report_exception() +ENDPROC + +PROC press(mx,my,buf) + DEF height,xc,lr + mx:=Bounds(mx,0,CWIDTH-1) + my:=Bounds(my,0,SCHEIGHT-1) + height:=my*16/SCHEIGHT + xc,lr:=Mod(mx,CWIDTH/2) + xc:=xc*XY3D*2/CWIDTH + IF lr THEN side_sculpt(XY3D-1-xc,buf,height) ELSE bot_sculpt(xc,buf,height) +ENDPROC + +#define trans(a,b) a + b / 2 +->#define trans(a,b) Eor(a,b) +->#define trans(a,b) Max(a,b) +->#define trans(a,b) Min(a,b) + +PROC bot_sculpt(off,buf,h) + DEF p,a,sh:PTR TO LONG + p:=off+buf + both[off]:=h + sh:=sideh + FOR a:=0 TO XY3D-1 + p[]:=trans(sh[]++,h) + p:=p+CWIDTH + ENDFOR +ENDPROC + +PROC side_sculpt(off,buf,h) + DEF p,a,bh:PTR TO LONG + p:=off*CWIDTH+buf + sideh[off]:=h + bh:=both + FOR a:=0 TO XY3D-1 DO p[]++:=trans(bh[]++,h) +ENDPROC + +PROC render(destbuf,lsbuf,offs,xs,ys) + DEF a,t1,t2 + clearmem(destbuf,BUFS) + t1:=ys-1*CWIDTH-1+offs + t2:=xs-1+offs + FOR a:=1 TO xs DO line(a,t1+a AND BUFM,a+SXOFF,a/2+SYOFF,destbuf,lsbuf) + FOR a:=ys-1 TO 1 STEP -1 DO line(a,a-1*CWIDTH+t2 AND BUFM,xs*2+SXOFF-a,a/2+SYOFF,destbuf,lsbuf) +ENDPROC + +PROC clearmem(mem,size) + DEF e:REG,a:REG,b:REG,c:REG,d:REG + e:=size/16-1 + a:=b:=c:=d:=$04040404 + MOVE.L mem,A0 + ADD.L size,A0 +clloop: + MOVEM.L a/b/c/d,-(A0) + DBRA e,clloop +ENDPROC + +PROC line(num,start,sx,sy,destbuf,lsbuf) + DEF a:REG,y,t:REG,c=0:REG,xoff:REG,yoff:REG + xoff:=sx+destbuf + yoff:=sy-25-num+1 + y:=sy*CWIDTH+xoff + a:=num-1+yoff + MOVE.L start,D2 -> D2=start + MOVEA.L lsbuf,A3 -> A3=lsbuf + MOVE.L y,A2 -> A2=y + MOVE.L #CWIDTH,D1 -> D1=CWIDTH + MOVE.L #BUFM,D0 -> D0=BUFM + MOVE.L #CWIDTH+1,A1 -> A1=CWIDTH+1 +bloop: -> this loop eats most cpu-time. + MOVE.B 0(A3,D2.L),c + MOVE.L a,t + ADD.L c,t + LSL.L #CWSHIFT,t + ADD.L xoff,t + CMP.L A2,t + BGE.S skip + BRA.S loop +begi: + SUBA.L D1,A2 + MOVE.B c,(A2) +loop: + CMP.L A2,t + BMI.S begi +skip: + SUB.L A1,D2 + AND.L D0,D2 + SUBQ.L #1,a + CMP.L yoff,a + BPL.S bloop +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/rr.e b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/rr.e new file mode 100644 index 0000000..c562097 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/rr.e @@ -0,0 +1,226 @@ +-> "Rude Racing" or "Wreckless Driving" or "The Need For Traffic Jams" +-> see main() below for the controls. + +OPT OSVERSION=39, PREPROCESS + +CONST CWIDTH=256,CHEIGHT=128 +CONST SCHEIGHT=CHEIGHT+20 +CONST TEMPBUFS=CWIDTH*CHEIGHT/2,BUFS=CWIDTH*CHEIGHT + +MODULE '*c2p4', '*screenmodereq_db', 'tools/exceptions', 'tools/scrbuffer', + 'intuition/screens', 'graphics/rastport', 'graphics/gfx', + 'intuition/intuition' + +/*------------------------------------------------------------------------*/ + +OBJECT rseg + bend:INT -> in degrees, often between -10 and +10, 0=straight + steepness:INT -> in degrees, often between -40 and +40, 0=flat +ENDOBJECT + +CONST SEGX=256,SEGY=64, -> in pixels + LOOKAWAY=3, + SPEED=3, + WIDTHSTEP=5, + HORIZON=21 + +DEF road:PTR TO rseg, + roadlen, -> #of segments + cp=0, -> current pos in segments*pixels + turn=0, -> in degrees + rpos=0, -> in pixels, -128..127 + sintab[271]:ARRAY OF INT, + tmap + +-> both in range -90 to 90 + +#define sin(x) sintab[(x)+90] +#define cos(x) sintab[(x)+180] + +PROC ahead() IS cp:=cp+(SEGY/SPEED) +PROC back() IS cp:=Bounds(cp-(SEGY/SPEED),0,1000000) +PROC tleft() IS turn:=Bounds(turn-3,-60,60) +PROC tright() IS turn:=Bounds(turn+3,-60,60) +PROC pleft() IS rpos:=Bounds(rpos+3,-128,127) +PROC pright() IS rpos:=Bounds(rpos-3,-128,127) +PROC center() IS (turn:=0) BUT (rpos:=0) + +PROC render(cbuf) + DEF cpos,cpospix -> in segments, pixels in cur segment + DEF cangle,width=550,middle,ypos,pixstep=100,vp,vpos,vpospix,cbend=0,ccbend,lvpos,lvpospix,cmiddle + DEF omiddle,nval=0,nposr=0,posadj,te=0,tt=0 + clearmem(cbuf,CWIDTH*HORIZON,$0E0E0E0E) + clearmem(cbuf+(CWIDTH*HORIZON),BUFS-(CWIDTH*HORIZON),$0F0F0F0F) + cpospix,cpos:=Mod(cp,SEGY); cpos:=Mod(cpos,roadlen) + cangle:=road[cpos].steepness + middle:=CWIDTH/2+(rpos*2) + ypos:=CHEIGHT-1 + vp:=cp+(LOOKAWAY*SEGY) + lvpospix,lvpos:=Mod(vp,SEGY); lvpos:=Mod(lvpos,roadlen) + WHILE width>15 + vpospix,vpos:=Mod(vp,SEGY); vpos:=Mod(vpos,roadlen) + IF lvpos<>vpos + cbend:=cbend+(road[lvpos].bend*256) + IF tt++=0 THEN cbend:=cbend*(SEGY-lvpospix-1)/SEGY + ENDIF + ccbend:=cbend+(road[vpos].bend*256*(SEGY-vpospix-1)/SEGY) + nval,omiddle:=Mod(sin(Bounds(ccbend/256,-90,90))+nval,20000/(vp-cp)) + nposr,posadj:=Mod(WIDTHSTEP*rpos+nposr,256) + middle:=middle+omiddle-posadj + cmiddle:=middle+(sin(-turn)*32/ypos) + rline(cbuf,width,cmiddle,ypos,vpos,vpospix*CWIDTH+tmap) + ypos-- + + width:=width-WIDTHSTEP + vp:=vp+(pixstep/256) + + ->fake hills + ->width:=width-WIDTHSTEP+(road[vpos].steepness/10) + ->vp:=vp+Div(Mul((pixstep/256),100),(100-road[vpos].steepness)) + + pixstep:=pixstep/20+pixstep + lvpos:=vpos + ENDWHILE +ENDPROC + +PROC rline(cbuf,width,middle,ypos,vpos,tm) + DEF x,pstep,pcur=0,end + x:=middle-(width/2) + IF (x>=CWIDTH) OR (x+width<=0) THEN RETURN + cbuf:=ypos*CWIDTH+cbuf + pstep:=256*1024/width + IF x<0 + pcur:=-x*pstep + x:=0 + ENDIF + end:=Min(CWIDTH-x,256*1024-pcur/pstep)+cbuf+x + MOVE.L tm,A0 + MOVE.L cbuf,A1 + ADDA.L x,A1 + MOVE.L end,A2 + MOVE.L pcur,D1 + MOVE.L pstep,D2 + MOVEQ #10,D3 +tmloop: + MOVE.L D1,D0 + LSR.L D3,D0 + MOVE.B 0(A0,D0.L),(A1)+ + ADD.L D2,D1 + CMPA.L A2,A1 + BMI.S tmloop +ENDPROC + +PROC init() + DEF a + road:=[0,0,0,0,0,0,0,0,0,0,0,0, + 2,0,4,0, + 6,0,8,0,10,0,12,0,15,0,15,0,15,0,15,0,12,0,10,0,8,0,6,0, + 4,0,2,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + -2,0,-4,0, + -6,0,-8,0,-10,0,-10,0,-8,0,-6,0, + -4,0,-2,0, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,10,0,15,0,20,0,30,0,20,0,15,0,10, + 0,0, + 0,0,0,15,0,20,0,-20,0,-15,0,0,0,0,0,0 + ]:rseg + roadlen:=ListLen(road)/2 -> rseg elems + FOR a:=-90 TO 180 DO sintab[a+90]:=!Fsin(a!/180.0*3.14159)*255.0! + tmap:={tmaplab} +ENDPROC + +tmaplab: INCBIN 'e:rr/TEXTUREMAP_ROAD.br.chunky' + +/*------------------------------------------------------------------------*/ + +PROC main() HANDLE + DEF dbs,scr=NIL:PTR TO screen,bm:PTR TO bitmap,win=NIL:PTR TO window, + tbuf2,tbuf3,tbuf2b,tbuf3b,cbuf,dbuf,dbuf2,sigbit,sig,safe=TRUE,a,temp, + imsg:PTR TO intuimessage,key,frames=0,dframes,fsec,ssec,smic,esec,emic + IF (dbs:=openreqscreen(CWIDTH,SCHEIGHT,4,'bla'))=NIL THEN Raise() + scr:=sb_GetScreen(dbs) + IF (win:=OpenW(0,0,CWIDTH-1,SCHEIGHT-1, + IDCMP_MOUSEBUTTONS OR IDCMP_VANILLAKEY, + WFLG_REPORTMOUSE OR WFLG_BORDERLESS OR WFLG_SIMPLE_REFRESH OR WFLG_BACKDROP OR WFLG_ACTIVATE, + '',scr,15,NIL))=NIL THEN Raise("WIN") + tbuf2:=NewM(TEMPBUFS+TEMPBUFS,2) + tbuf3:=tbuf2+TEMPBUFS + tbuf2b:=NewM(TEMPBUFS+TEMPBUFS,2) + tbuf3b:=tbuf2b+TEMPBUFS + NEW cbuf[BUFS] + NEW dbuf[BUFS] + NEW dbuf2[BUFS] + FOR a:=0 TO BUFS-1 + dbuf[a]:=-1 + dbuf2[a]:=-1 + ENDFOR + FOR a:=1 TO 13 DO SetColour(scr,15-a-1,a*19,a*19,a*14) + SetColour(scr,0,212,0,9) + SetColour(scr,14,171,203,255) + SetColour(scr,15,156,194,0) + SetRast(scr.rastport,13) + bm:=sb_NextBuffer(dbs) + SetRast(scr.rastport,13) + init() + IF (sigbit:=AllocSignal(-1))<>-1 + sig:=Shl(1,sigbit) + CurrentTime({ssec},{smic}) + REPEAT + render(cbuf) + IF safe=FALSE + Wait(sig) + safe:=TRUE + ENDIF + bm:=sb_NextBuffer(dbs) + c2p4(tbuf3,tbuf2,cbuf,dbuf,bm.planes,FindTask(NIL),sig,gfxbase) + frames++ + temp:=dbuf; dbuf:=dbuf2; dbuf2:=temp + temp:=tbuf2; tbuf2:=tbuf2b; tbuf2b:=temp + temp:=tbuf3; tbuf3:=tbuf3b; tbuf3b:=temp + IF imsg:=GetMsg(win.userport) + IF imsg.class=IDCMP_VANILLAKEY + key:=imsg.code + SELECT key + CASE "a"; ahead() + CASE "b"; back() + CASE "z"; tleft() + CASE "x"; tright() + CASE "n"; pleft() + CASE "m"; pright() + CASE "c"; center() + -> "q" quits + ENDSELECT + ENDIF + ReplyMsg(imsg) + ENDIF + safe:=FALSE + UNTIL key="q" + CurrentTime({esec},{emic}) + IF safe=FALSE THEN Wait(sig) + FreeSignal(sigbit) + ENDIF +EXCEPT DO + IF win THEN CloseWindow(win) + closereqscreen(dbs) + dframes:=esec-ssec*100+(emic-smic/10000) + fsec:=frames*10000/dframes + IF frames THEN WriteF('calculated \d pictures \d.\z\d[2] seconds, giving \d.\z\d[2] f/s\n',frames,Div(dframes,100),Mod(dframes,100),Div(fsec,100),Mod(fsec,100)) + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "REQ"; WriteF('Error: Could not allocate ASL request\n') + CASE "ASL"; WriteF('Error: Could not open ASL library\n') + ENDSELECT + report_exception() +ENDPROC + +PROC clearmem(mem,size,pat) + DEF e:REG,a:REG,b:REG,c:REG,d:REG + e:=size/16-1 + a:=b:=c:=d:=pat + MOVE.L mem,A0 + ADD.L size,A0 +clloop: + MOVEM.L a/b/c/d,-(A0) + DBRA e,clloop +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/screenmodereq_db.m b/amigae33a/E_v3.3a/Src/Src/Gfx/Chunky3d/screenmodereq_db.m new file mode 100644 index 0000000000000000000000000000000000000000..cbd9738654e08b786efa03c48ab963b1a93b4e59 GIT binary patch literal 752 zcmY*VJx|+E6g>{E>LNr_gqSMT{h(@82P2e)ih(2`MF<>0iqxT1NZ^H1ImFnB1XWde z>fE6}A_GDhSh_QH>d4lyW7jB3`g-0Y5PGe1uJ60&+2`KXjp7RKK*e)l)7EdmxXxqb zBX3)F3%?)1b!3M)C)%l^>|}dJE>)1{sSVlA_l&Q>tmDf|?`&|HS|0S*;u@=obkdvAx$kf?a zmE|Ja!?0hX<;&B;EM246qCJ56- z;TWJ(1}CyOL-%IZQhw{!3~AX-mAR`jcT|?09UynR&Yj9rJ1zU1Y*NiJ+{zEz8R)Yo z+|t!X|5o)^MS%5R=z8zGmbVSH2TSiI>GJKykr_ZKDv>|uA5_Cic%rP{CCnJc7h*mJ zd}0MAlDmE*5}`PXc0(Z!!7#qT;G@FiDcv;!armEvBABvE#nf@+oJ7u^2%7Jm=0VdJ zkP=p`Zf9W8MYR$M7RE>Z4MwQ>gJOKv{91EHv$}haoi}(W>W#gYFQQk?M#GO>8mYEw mH4)C$*-s!DRm*v0y>#tcdp6qaO|n;{ back to the root! + [ .2, .23,(-.26),.22,.0,1.6, 7 ]:trans, -> right leaf + [(-.15), .26, .28, .24,.0, .44,7 ]:trans, -> left leaf + [ .85,(-.04), .04, .85,.0,1.6, 85]:trans]) -> body + ->WaitIMessage(win) + CloseW(win) + ENDIF + CloseS(scr) + ENDIF +ENDPROC + +PROC do(t:PTR TO LONG) + DEF x=1.,y=1.,r,n,a,tr:PTR TO trans,xn,yn,sx,sy,d + REPEAT + r:=Rnd(100) + n:=0 + FOR a:=1 TO ListLen(t) + tr:=t[a-1] + EXIT (r>=n) AND (tr.prob+n>r) + n:=n+tr.prob + ENDFOR + sx:=!(xn:=!(!tr.a*x)+(!tr.c*y)+tr.ox)*60.!+(SCRX/2) + sy:=SCRY-(!(yn:=!(!tr.b*x)+(!tr.d*y)+tr.oy)*50.!) + d:=Bounds(ReadPixel(stdrast,sx,sy)+20,64,255) + Plot(sx,sy,d) + x:=xn; y:=yn + UNTIL LeftMouse(win) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/IntMandel.e b/amigae33a/E_v3.3a/Src/Src/Gfx/IntMandel.e new file mode 100644 index 0000000..71550fa --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/IntMandel.e @@ -0,0 +1,56 @@ +-> Yet Another Mandel, translated from Oberon. integer this time. + +OPT OSVERSION=37, REG=5 + +MODULE 'tools/clonescreen' + +CONST DEPTH=4,COLOURS=16 -> related :-) +CONST ITERDEPTH=25 + +PROC main() HANDLE + + DEF zr,zi,ar,ai,dr,di,sr,si,st,x,y,i, + screen=NIL,font=NIL,win=NIL,xsize,ysize,depth + + screen,font:=openclonescreen('Workbench','YAM',DEPTH) + win:=backdropwindow(screen) + depth,xsize,ysize:=getcloneinfo(screen) + + x:=256/COLOURS*2 + FOR i:=0 TO COLOURS-1 DO SetColour(screen,i,0,i*x,i*x) + + sr:=$400000/xsize -> shrink horiz + si:=$300000/ysize -> shrink vert + st:=$140000*-2 -> move side + zi:=$160000 -> move up + + FOR y:=ysize-1 TO 0 STEP -1 + IF CtrlC() THEN Raise("^C") + zi:=zi-si + zr:=st + FOR x:=0 TO xsize-1 + i:=0; ar:=zr; ai:=zi + REPEAT + dr:=Shr(ar,10); di:=Shr(ai,10) + ai:=dr*2*di+zi + dr:=dr*dr; di:=di*di + ar:=dr-di+zr + i++ + UNTIL (i>ITERDEPTH) OR (dr+di>$400000) + Plot(x,y,Mod(i,COLOURS)) + zr:=zr+sr + ENDFOR + ENDFOR + + EasyRequestArgs(NIL,[20,0,'Wake Up!','I''m finished!','Ok!'],0,NIL) + +EXCEPT DO + + closeclonescreen(screen,font,win) + + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "WIN"; WriteF('no window!\n') + ENDSELECT + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Kohonen.e b/amigae33a/E_v3.3a/Src/Src/Gfx/Kohonen.e new file mode 100644 index 0000000..4cbaf0d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/Kohonen.e @@ -0,0 +1,97 @@ +/* Kohonen Feature Maps in E, implemented with integers + +Kohonen feature maps are special types of neural nets, and +this implementation shows graphically how they organise themselves +after a while. Apologies for the primitive gfx display. + +*/ + +CONST ONE=1024*16, KSHIFT=14, KSIZE=7, MAXTIME=500, DELAY=0 +CONST KSTEP=ONE/KSIZE, KNODES=KSIZE+1, ARSIZE=KSIZE*KSIZE +CONST XRED=64, YRED=128, XOFF=10, YOFF=20 + +MODULE 'intuition/intuition', 'tools/exceptions' + +PROC main() HANDLE + DEF map,t,input,x,y,w=NIL + IF w:=OpenW(20,11,400,200,$200,$F,'Kohonen Feature Map Simulation',0,1,0) + map:=kohonen_init(KSIZE,KSIZE,2) + FOR t:=0 TO MAXTIME-1 + input:=[Rnd(KNODES)*KSTEP,Rnd(KNODES)*KSTEP] + x,y:=kohonen_BMU(map,input) + kohonen_plot(map,w,x,y) + kohonen_learn(map,x,y,MAXTIME-t*(ONE/MAXTIME),input) + ENDFOR + ELSE + Raise("WIN") + ENDIF + RefreshWindowFrame(w) + WaitIMessage(w) +EXCEPT DO + report_exception() + IF w THEN CloseW(w) +ENDPROC + +PROC kohonen_plot(map,wnd:PTR TO window,bx,by) + DEF x,y,n:PTR TO LONG,cx,cy,i,ii, + sx[ARSIZE]:ARRAY OF LONG,sy[ARSIZE]:ARRAY OF LONG + SetRast(wnd.rport,1) + FOR x:=0 TO KSIZE-1 + FOR y:=0 TO KSIZE-1 + n:=kohonen_node(map,x,y); i:=x*KSIZE+y; ii:=x-1*KSIZE+y + sx[i]:=cx:=s(n[0]/XRED+XOFF); sy[i]:=cy:=s(n[1]/YRED+YOFF) + IF x>0 THEN Line(sx[ii],sy[ii],cx,cy,2) + IF y>0 THEN Line(sx[i-1],sy[i-1],cx,cy,2) + ENDFOR + ENDFOR + n:=kohonen_node(map,bx,by) + Plot(s(n[0]/XRED+XOFF),s(n[1]/YRED+YOFF),2) + Delay(DELAY) +ENDPROC + +PROC s(c) IS IF c<0 THEN 0 ELSE IF c>1000 THEN 1000 ELSE c + +PROC kohonen_BMU(map,i:PTR TO LONG) + DEF x,y,act,bestx,besty,bestact=$FFFFFFF,n:PTR TO LONG,len,a + len:=ListLen(i)-1 + FOR x:=0 TO KSIZE-1 + FOR y:=0 TO KSIZE-1 + n:=kohonen_node(map,x,y) + act:=0 + FOR a:=0 TO len DO act:=Abs(n[a]-i[a])+act + IF act cityblock + IF d>0 + FOR a:=0 TO len DO n[a]:=n[a]+Shr(i[a]-n[a]*d,KSHIFT) + ENDIF + ENDFOR + ENDFOR +ENDPROC + +PROC kohonen_node(map:PTR TO LONG,x,y) + DEF r:PTR TO LONG + r:=map[x] +ENDPROC r[y] + +PROC kohonen_init(numx,numy,numw) + DEF m:PTR TO LONG,r:PTR TO LONG,w:PTR TO LONG,a,b,c + NEW m[numx] + FOR a:=0 TO numx-1 + m[a]:=NEW r[numy] + FOR b:=0 TO numy-1 + r[b]:=NEW w[numw] + FOR c:=0 TO numw-1 DO w[c]:=ONE/2 + ENDFOR + ENDFOR +ENDPROC m diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Mandel.e b/amigae33a/E_v3.3a/Src/Src/Gfx/Mandel.e new file mode 100644 index 0000000..54e88fc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/Mandel.e @@ -0,0 +1,24 @@ +-> mini fractal + +CONST CALCW=200,HEIGHT=100, DEPTH=25 + +PROC main() + DEF w,xmax,ymax,x,y,xr,width=3.5,height=2.8,left,top + IF w:=OpenW(20,11,240,130,$200,$E,'MiniFrac!',NIL,1,NIL) + top:=!0.0-1.6; left:=!0.0-2.0; xmax:=CALCW!; ymax:=HEIGHT-1! + FOR x:=0 TO CALCW-1 + xr:=x!/xmax*width+left + FOR y:=0 TO HEIGHT-1 DO Plot(x+20,y+20,calc(xr,y!/ymax*height+top)) + ENDFOR + WaitIMessage(w) + CloseW(w) + ENDIF +ENDPROC + +PROC calc(x,y) + DEF xtemp,it=0,xc,yc + xc:=x; yc:=y + WHILE (it++1 + FOR a:=x1+1 TO x2-1 DO plotxy(a,y1) + IF HEIGHT-1=y2 THEN FOR a:=x1+1 TO x2-1 DO plotxy(a,y2) + ENDIF + IF y2-y1>1 + FOR a:=y1+1 TO y2-1 DO plotxy(x1,a) + IF WIDTH-1=x2 THEN FOR a:=y1+1 TO y2-1 DO plotxy(x2,a) + ENDIF + ELSE + xm:=x1+x2/2 + ym:=y1+y2/2 + recmandel(x1,y1,xm,ym) + recmandel(xm,y1,x2,ym) + recmandel(x1,ym,xm,y2) + recmandel(xm,ym,x2,y2) + ENDIF + ENDIF +ENDPROC + +PROC calcxy(x,y) + DEF xr,yr + xr:=x!/xmax*width+left + yr:=y!/ymax*height+top +ENDPROC calc(256/FAC,xr,yr)*FAC + +PROC plotxy(x,y) + Plot(x,y,calcxy(x,y)) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/MandelCalc881.m b/amigae33a/E_v3.3a/Src/Src/Gfx/MandelCalc881.m new file mode 100644 index 0000000000000000000000000000000000000000..4881eb9b35257f7efe751273625f3782a9323138 GIT binary patch literal 184 zcmWlTu?fOp6ofyG8bJ|jl^{kCY_dQEg(wy=f)f}b7GjYmVEH?P8^p#^tQMU+vak;LbO Op@tl-D_80jMah5q*flf& literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/PPV.e b/amigae33a/E_v3.3a/Src/Src/Gfx/PPV.e new file mode 100644 index 0000000..1354dc8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/PPV.e @@ -0,0 +1,32 @@ +/* 256 greyscale preview of POVRAY files + + Quickly preview POV-ray's 24-bit output files on a 256 greyscale + AGA screen. No fancy implementation. + +*/ + +MODULE 'tools/file', 'tools/exceptions' + +PROC main() HANDLE + DEF scr=NIL,win=NIL,a,p,name,xs,ys,x,y + name:=IF arg[] THEN arg ELSE 'data.dis' + p:=readfile(name) + xs:=p[0]+(p[1]*256); ys:=p[2]+(p[3]*256); p:=p+4 + WriteF('POV-Ray Quick 256 Greyscale PreView, $#%!\n' + + 'file: "\s", (\dx\d) [mouse to quit]\n',name,xs,ys) + IF scr:=OpenS(xs,ys,8,$0,'') + IF win:=OpenW(0,0,xs,ys,$8,0,'',scr,15,0) + FOR a:=0 TO 255 DO SetColour(scr,a,a,a,a) + FOR y:=0 TO ys-1 + p:=p+2 + FOR x:=0 TO xs-1 DO Plot(x,y,p[x]+p[x+xs]+p[x+xs+xs]/3) + p:=xs*3+p + ENDFOR + WaitIMessage(win) + ENDIF + ENDIF +EXCEPT DO + CloseW(win) + CloseS(scr) + report_exception() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/RewriteGfx.e b/amigae33a/E_v3.3a/Src/Src/Gfx/RewriteGfx.e new file mode 100644 index 0000000..9bffbb9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/RewriteGfx.e @@ -0,0 +1,169 @@ +/* Using a (forth-featured) rewrite-grammar to plot + recursive (turtle) graphics + + a graphics plotting system that uses rewrite-grammars. the idea is + that the description of an image (much like some fractals i know) + is denoted in a grammar, which is then used to plot the gfx. + the system uses turtlegraphics for plotting, and some forth-heritage + for additional power. the program is not meant to actually "used"; + change to different graphics with the CONST in the sources, to + see what the grammars do. + + next to normal context-free grammars like S->ASA, + following (forth-lookalike) turtle commands may be used: + + up pen up + down pen down + set set absolute position + move move relative to last coordinates, distance + in direction , draw line if pen is down + degr set initial angle + rol rotate relative counter-clockwise (left) + rol rotate relative clockwise (right) + col set colour to plot with + push save x/y/angle/pen status at this point on stack + pop restore status + dup duplicate last item on stack + add add two integers + sub substract two integers (first-second) + mul multiply two integers + div divide two integers + eq see if two integers are equal + uneq see if two integers are unequal + if end conditional statement */ + +CONST CURGR=9 /* SET THIS ONE TO 0-11 TO GET A DIFFERENT GRAMMAR */ + +ENUM S=1000, A,B,C,D,E,F,G, Z +CONST R=20 + +DEF gr[20]:ARRAY OF LONG,win,stack[5000]:ARRAY OF LONG,sp=NIL:PTR TO LONG, + penf=TRUE,x=50.0,y=60.0,col=2,degr=0.0 + +/* don't build your own grammars if you don't know *exactly* what + you're doing. there are no error checks. */ + +PROC initgrammar() + + gr[0]:=[[S, A,A,A], /* lotsa triangles */ + [A, 25,"ror",D,D,D,D,D,D,"up",50,"move","down"], + [D, F,G,F,G,F,G,E], + [E, "up",R,"move",30,"rol",5,"move",30,"rol","down"], + [F, R,"move"], + [G, 120,"rol"]] + + gr[1]:=[[S, 100,20,"set",30,A], /* shell */ + [A, "dup","move",1,"sub","dup",0,"uneq","if",B,"end"], + [B, "dup","dup",90,"ror","move",180,"ror","up","move", + 90,"ror","down",20,"ror",A]] /* some figure */ + + gr[2]:=[[S, B,B,B,B,B,B,B,B,B,B,B,B,B,B,B], + [B, A,A,A,A,A,A,A,A,-10,"move"], + [A, "down",80,"move",183,"rol"]] + + + gr[4]:=[[S, 160,188,"set",90,"degr",30,A,1,"col",1,"move"], /* 45 tree */ + [A, "dup","dup","move","if","dup",115,"mul",150,"div","dup",45, + "rol",A,90,"ror",A,45,"rol","end",180,"rol","move",180,"rol"]] + + gr[5]:=[[S, 160,188,"set",90,"degr",60,A,1,"col",1,"move"], /* thin tree */ + [A, "dup","dup","move","if","dup",100,"mul",150,"div","dup",40, + "rol",A,69,"ror",196,"mul",191,"div",A,29,"rol","end",180, + "rol","move",180,"rol"]] + + gr[6]:=[[S, 160,188,"set",91,"degr",36,A,1,"col",1,"move"], /* slow tree */ + [A, "dup","dup","move","if","dup",120,"mul",150,"div","dup",20, + "rol",A,40,"ror",170,"mul",166,"div",A,20,"rol","end",180, + "rol","move",180,"rol"]] + + gr[7]:=[[S, 200,160,"set",90,"degr",30,A,1,"col",1,"move"],/* swirl tree */ + [A, "dup","dup","move","if","dup",135,"mul",150,"div","dup",29, + "rol",A,50,"ror",21,"mul",30,"div",A,21,"rol","end",180, + "rol","move",180,"rol"]] + + gr[8]:=[[S, 160,160,"set",90,"degr",36,A,1,"col",1,"move"], /* frond */ + [A, "dup","dup","move","if","dup",112,"mul",150,"div","dup",35, + "rol",A,120,"ror",A,85,"rol","end",180,"rol","move",180,"rol"]] + + gr[9]:=[[S, 160,188,"set",90,"degr",32,A,1,"col",1,"move"], /* nice tree */ + [A, "dup","dup","move","if","dup",85,"mul",150,"div","dup","dup", + 25,"rol",A,25,"ror",150,"mul",100,"div",A, + 25,"ror",A,25,"rol","end",180,"rol","move",180,"rol"]] + + gr[10]:=[[S, 160,188,"set",90,"degr",60,A,1,"col",1,"move"],/* sahara */ + [A, "dup","dup","move","if","dup",95,"mul",150,"div","dup",15, + "rol",A,30,"ror",A,15,"rol","end",180,"rol","move",180,"rol"]] + + gr[11]:=[[S, 134,188,"set",90,"degr",44,A, + 184,174,"set",94,"degr",36,A, + 158,191,"set",88,"degr",48,A, + 206,168,"set",90,"degr",14,A], /* sea oats */ + [A, "dup","dup","move","if","dup",60,"mul",150,"div","dup", + 114,"rol",A,2,"mul",100,"ror",A,14,"ror","end",180,"rol", + "move",180,"rol"]] + + +ENDPROC + +PROC main() + win:=OpenW(20,20,600,200,$200,$F,'Rewrite Graphics',NIL,1,NIL) + IF win=NIL + WriteF('Could not open window!\n') + ELSE + initgrammar() + sp:=stack+400 /* temp */ + dorewrite(S) + IF sp<>(stack+400) THEN WriteF('WARNING: stack not clean\n') + WaitIMessage(win) + CloseW(win) + ENDIF +ENDPROC + +PROC dorewrite(startsym) + DEF i:PTR TO LONG + ForAll({i},gr[CURGR],`IF i[0]=startsym THEN dolist(i) ELSE 0) +ENDPROC + +PROC dolist(list:PTR TO LONG) + DEF r=1,sym,rada,cosa,sina,xd,yd,xo,yo,a + WHILE rZ + SELECT sym + CASE "down"; penf:=TRUE + CASE "up"; penf:=FALSE + CASE "set"; y:=sp[]--!; x:=sp[]--! + CASE "col"; col:=sp[]-- + CASE "rol"; degr:=sp[]--!+degr + CASE "ror"; degr:=-sp[]--!+degr + CASE "degr"; degr:=sp[]--! + CASE "push"; sp[]++:=x; sp[]++:=y; sp[]++:=degr; sp[]++:=penf + CASE "pop"; sp[]--:=penf; sp[]--:=degr; sp[]--:=y; sp[]--:=x + CASE "dup"; a:=sp[]--; sp[]++:=a; sp[]++:=a + CASE "add"; sp[]++:=sp[]--+sp[]-- + CASE "sub"; a:=sp[]--; sp[]++:=sp[]---a + CASE "mul"; sp[]++:=sp[]--*sp[]-- + CASE "div"; a:=sp[]--; sp[]++:=sp[]--/a + CASE "eq"; sp[]++:=sp[]--=sp[]-- + CASE "uneq"; sp[]++:=sp[]--<>sp[]-- + CASE "end"; NOP + CASE "if"; IF sp[]--=FALSE THEN WHILE list[r++]<>"end" DO NOP + CASE "move" + xo:=x; yo:=y; x:=sp[]--!+x + rada:=!degr/180.0*3.14159 + cosa:=Fcos(rada); sina:=Fsin(rada) + xd:=!x-xo; yd:=!y-yo + x:=!xo+(!xd*cosa)-(!yd*sina) + y:=!yo+(!yd*cosa)-(!xd*sina) + IF penf THEN Line(!xo!*2,!yo!,!x!*2,!y!,col) + DEFAULT; WriteF('WARNING: unknown opcode\n') + ENDSELECT + ELSE + dorewrite(sym) + ENDIF + ENDIF + ENDWHILE +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/README b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/README new file mode 100644 index 0000000..560f15a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/README @@ -0,0 +1,46 @@ +texturemapping in E (and assembly :) +------------------------------------ + +This source code here is provided solely for educational +purposes, it is not solid enough code to base your project +on. I have a faster and more advanced version of this +engine available, but it is rather bulky and keeps +crashing. the version here is an older test version +which hopefully is more stable but is not guaranteed +to work on your machine either. + +Compile the example with "ec tmaptest" +Run the example on your favourite low res screenmode +(the program will present you with a requester). +The test program uses a builtin c2p routine optimized +for 030 and above AGA machines, and is unlikely to run +on graphic boards or other non standard screenmodes. + +assuming you get the program to run, you can use these keys +to influence the camera: + +n,m,d,c turn left,right,up,down resp. +v,b bank/tilt left,right resp. +s,x,a,z,w,e move down,up,forward,backward,right,left resp. +r,t lens zoom or wide angle +q quit + +About the engine: +The texturemapper is fully free-form, but not perspective +correct (use more polygons!), i.e. unlike Doom, more like +Descent. As you can see from the test it allows all six +degrees of freedom for the camera, and there are no restrictions +on the polygons either. + +The intersting bits to look at in the source code would +be in texturemapper.e. The 5 instructions between "inner:" +and "DBRA" is where the texturemapper spends 90% of its +time. + +The projection routine in geom.e implements a proper +fisheye projection (most engines use a flat approximation). + +Credits: +Mikael Kalms for his excellent CPU3BLIT1 c2p I used. +Jyrki O Saarinen for the tips he gave me on further + optimizing the inner texturemapping loop. diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/c2p_cpu3blit1.m b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/c2p_cpu3blit1.m new file mode 100644 index 0000000000000000000000000000000000000000..39b509e4de403f1725717aee47dba95931c37e26 GIT binary patch literal 1548 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 v{`;V0x7#Hg!Ux$#4WNRaj 3d geometry stuff + +OPT MODULE + +EXPORT OBJECT point + x,y,z +ENDOBJECT + +EXPORT OBJECT opoint OF point -> point with orientation e.g. a camera + turn,up,tilt +ENDOBJECT + +PROC sin(x,f) IS !Fsin(x!/1800.0*3.14159)*(f!)! -> replace by tables! +PROC cos(x,f) IS !Fcos(x!/1800.0*3.14159)*(f!)! +PROC atan(x,unit) IS !Fatan(x!/(unit!))/3.14159*1800.0! +PROC atanf(x,u) IS IF u>0 THEN atan(x,u) ELSE (IF u=0 THEN (IF x>0 THEN 900 ELSE -900) ELSE 1800-atan(x,-u)) + +EXPORT PROC project3d(camera:PTR TO opoint,p:PTR TO point,midx,midy,persp) + DEF x,y,z,t,old,sx,sy + x:=p.x-camera.x + y:=p.y-camera.y + z:=camera.z-p.z + IF t:=camera.turn*10 + x:=cos(t,old:=x)-sin(t,y) + y:=sin(t,old)+cos(t,y) + ENDIF + IF t:=camera.up*10 + z:=cos(t,old:=z)-sin(t,y) + y:=sin(t,old)+cos(t,y) + ENDIF + IF t:=camera.tilt*10 + x:=cos(t,old:=x)-sin(t,z) + z:=sin(t,old)+cos(t,z) + ENDIF + sx:=atanf(x,y)*(midx*2)/persp/10+midx + sy:=atanf(z,y)*(midy*2)/persp/10+midy +ENDPROC sx,sy diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/geom.m b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/geom.m new file mode 100644 index 0000000000000000000000000000000000000000..c5d6891d52205659a214decca0871fb43a6589e8 GIT binary patch literal 1188 zcmbVLO=}ZT6g_RGb_fH`B1mxKFt{j~ID*?Oid3mV)0Io1p^XyB#}E@}i;D?#Azes* zNb8~tL08SrWqyDgOBRDv>>`UGlRnR#%%o|Xy6A)Z-hKC;d+x`ZdHQl~1q&Fjv}r|J zGCUL9{lY82%EHK0)c3+?^~27s`~;%gzMWfse!Cal4jmM}B7yqaA83w5>60i}_hM9Z z9v5C0S~p;KZ_a*gP5V*hyTW~;Cw4g1@8OKv^}JUH?l_zgMK40_kwsqzUdROU-Wv{3 zCK%!jD+eTY>D8^AQo#pm_rRodZxO&lBOXIk`@IJS)|=sz_NT_q1(x+7Fi1 zX=qu37TS1*))To|OUyyM%`>$6k=5u1NHTVi_uc~QPF4-9tU9HoFL}=@l2@ux1IkGe zqu{&}$r*Y2^c-Kto;{4QJ*h9Q#GIMak8_TOmw84XW1eyCQ#or_u-{_rg`BCGIVXLN zvr3}kz74$bMC80y#tu+ zJ0M!3B;v~?!nh{FV8oEG6v#KMhQcb}1pm-QO2PwvQ9e-~K||7Q)ZdjhnvXZ>oZG`3 z7F3_=-Hl?k)F@`$OtrkZCEIq!Ej8Y|fKr$zq63{8>TbPUYw|u%Hf&J|HElcA^c~S| n(Q7nYjhbAjYcN~n;u24)S*{3&tTaXV=@I^j{{QTNAp!pYv|)`; literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/screenmodereq_db.e b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/screenmodereq_db.e new file mode 100644 index 0000000..84d6a1b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/screenmodereq_db.e @@ -0,0 +1,34 @@ +-> asl screenmode module for db + +OPT OSVERSION=38, MODULE +OPT EXPORT + +MODULE 'asl', 'libraries/asl', 'intuition/screens', 'tools/scrbuffer' + +PROC openreqscreen(xs,ys,depth,title) HANDLE + DEF fr:PTR TO screenmoderequester,scr:PTR TO screen + IF (aslbase:=OpenLibrary('asl.library',37))=NIL THEN Raise("ASL") + IF (fr:=AllocAslRequest(ASL_SCREENMODEREQUEST,NIL))=NIL THEN Raise("REQ") + IF AslRequest(fr, NIL) + IF (scr:=sb_OpenScreen( + [SA_WIDTH, xs, + SA_HEIGHT, ys, + SA_DEPTH, depth, + SA_TYPE, CUSTOMSCREEN, + SA_QUIET, TRUE, + SA_OVERSCAN, OSCAN_TEXT, + SA_AUTOSCROLL, TRUE, + SA_DISPLAYID, fr.displayid, + SA_TITLE, title, + NIL],0))=NIL THEN Raise("SCR") + RETURN scr + ENDIF +EXCEPT DO + IF fr THEN FreeAslRequest(fr) + IF aslbase THEN CloseLibrary(aslbase) + ReThrow() +ENDPROC NIL + +PROC closereqscreen(scr) + IF scr THEN sb_CloseScreen(scr) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/screenmodereq_db.m b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/screenmodereq_db.m new file mode 100644 index 0000000000000000000000000000000000000000..a6b1e50dcd8e798925e11e70f284fc047b931459 GIT binary patch literal 760 zcmY*VO-~b16g^YMI1+*lvLrfwU~HT+hIE031*Iiv8kh=|#D%7`@Tw$JI?S{Q7-J^> z0M{=30W1jVf{lAu#)V6EE?v59n%3uek3#WI&bjZtdtZCbU0EyTaSbXS0_*xf8rO$0 za^!8wZsGSGxQ^@)r^HdJBsFnRhZcODzrh#kdYkxr@k_ zSG}(o!>iICm_g#nd%*DreeXp6e7qz_a~mt`qdB`F`}3p8Z^ifx@WW1H+66hOd4kM2 z`@FJTWP2F5tu5d=ZpFZT<$?LZFwYKin)xR07bJr@!`fheI;`het9Or7R&lq2Jh4bj z6BC5#qHq9EF@w%5dg)$zF6TC`cuC7{s=}RBxT}inYyrzx>*Zs4Y^P`?sclRRmc5g|7G7YkQke`>^zWk}gk|ip&6Nq8j;g{%$R-hKEY(b;68c zd?FTNz$fxBk=*v1kqE_pv>ghu2Zr$l20s-hZ>g>sh`s+tI0RF6IWct*Ifs$6BZAgj zr?uPi1*C)(tJfJ=R8gx&f`##s{|4io=1?&{XnvtNqglPZ!Oly}h(>d#?ThGHtJ(A; rmqKdodR>Hb4fYdAMzu;#NiSdM)|!nDdz0*yDEXq5P;QLde8>0)wi?lV literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/texturemapper.e b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/texturemapper.e new file mode 100644 index 0000000..e0d58b5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/texturemapper.e @@ -0,0 +1,81 @@ +-> texturemapper + +OPT MODULE + +CONST FP=256,FPS=8,MAXROUND=2500 + +PROC scanline(x1,x2,tx1,tx2,ty1,ty2,thisy,cbuf,maxx,tmap) + DEF p,numpix,c:REG,stx:REG,sty:REG,cx:REG,cy,misx=0 + IF (x1>=maxx) OR (x2<0) THEN RETURN + numpix:=x2-x1+1 + IF x1<0 THEN (misx:=0-x1) BUT x1:=0 + IF x2>=maxx THEN x2:=maxx-1 + p:=thisy*maxx+x1+cbuf + ->IF numpix=0 THEN Raise("nump") + stx:=tx2-tx1*FP/numpix + sty:=ty2-ty1*FP/numpix + cx:=tx1*FP+(misx*stx) + cy:=ty1*FP+(misx*sty) + c:=x2-x1 + MOVE.L p,A0 + MOVE.L tmap,A1 + ROR.W #8,cx + ROR.W #8,stx + SUB.B stx,cx + ADD.W stx,cx + MOVE.L cy,A2 -> A2 is copy of cy +inner: + MOVE.L A2,D0 -> p[]++:=tmap[(cy/FP)*tmaxx+(cx/FP)] + ADD.L sty,A2 -> cy:=cy+sty + MOVE.B cx,D0 -> assumes FPS and tmaxx are 256 + ADDX.W stx,cx -> cx:=cx+stx + MOVE.B 0(A1,D0.L),(A0)+ + DBRA c,inner +ENDPROC + +EXPORT PROC tmap(coords:PTR TO LONG,cbuf,maxx,maxy,tmap,tmaxx=256,tmaxy=256) + DEF rx[MAXROUND]:ARRAY OF LONG,ry[MAXROUND]:ARRAY OF LONG,trx[MAXROUND]:ARRAY OF LONG, + try[MAXROUND]:ARRAY OF LONG,curr=0,a,b,dist,q, + x1,y1,x2,y2,tmx,tmy,f,stx,sty,outm1,outm2,outmi1=10000,outmi2=-10000,sides=0 + FOR a:=0 TO 6 STEP 2 -> for all 4 sides of the square + y1:=coords[a+1] + y2:=coords[a+3 AND 7] + IF dist:=Abs(y1-y2) + sides++ + x1:=coords[a] + x2:=coords[a+2 AND 7] + IF Abs(x1-x2)+dist>2000 THEN RETURN -> temp check + tmx:=IF a AND 2 THEN 0 ELSE tmaxx + tmy:=IF a AND 2 THEN tmaxy ELSE 0 + f:=IF a>=4 THEN -1 ELSE 1 + stx:=IF a+2 AND 4 THEN tmaxx ELSE 0 + sty:=IF a>=4 THEN tmaxy ELSE 0 + ->IF dist=0 THEN Raise("dist") + FOR q:=1 TO dist -> for each y pixel of a side + rx[curr]:=x2-x1*q/dist+x1 + ry[curr]:=y1+(q*Sign(y2-y1)) + trx[curr]:=stx+(q*tmx/dist*f) + try[curr]:=sty+(q*tmy/dist*f) + curr++ + ENDFOR + IF y2outm2 THEN (outm2:=y2) BUT outmi2:=curr-1 + ENDIF + ENDFOR + IF sides<1 THEN RETURN + IF outmi1>outmi2 + a:=outmi2 + outmi2:=outmi1 + outmi1:=a + ENDIF + FOR a:=outmi1 TO outmi2 -> for each scanline found + b:=IF a-outmi1<=outmi1 THEN outmi1-(a-outmi1) ELSE outmi2-(a-outmi2) + IF (ry[a]>=0) AND (ry[a]rx[a] + scanline(rx[a],rx[b],trx[a],trx[b],try[a],try[b],ry[a],cbuf,maxx,tmap) + ELSE + scanline(rx[b],rx[a],trx[b],trx[a],try[b],try[a],ry[a],cbuf,maxx,tmap) + ENDIF + ENDIF + ENDFOR +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/texturemapper.m b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/texturemapper.m new file mode 100644 index 0000000000000000000000000000000000000000..e6a2a327ff73b5f207bd4e90c133cf64983dfbe4 GIT binary patch literal 1620 zcmZ`(J!n%=6#iZklTd;NDIy~HECGX!#=+4cgO(_oV69I6v?@B(*oQx$+soq6siT8q zh9Zq*5Q&f>5tR->GgOEmwn)VcDUFh$Nc8%h`(BeK*az>vd(Zj4@11+jx%bq$^hxXh zo+ZF1Y|6-INRM8?c$m7VTFD=~U|}?&I_43?3VDPsmy>p~90%9YkS*vd+A;$3fSo;K z-v)vfCV{Vln9CzJZj;{<{u%oYu-k%IMN^a!6Pze#fDq@Q3&bPJ*>GhIJ8Q)94HMs{ z%_KKc=@`hasb9%*Oybx}+y0*Iu-G(4qEwyAdx@=Cr6PUQ`HbgV~VW>kA5 zgW$^Lm8(zv^|45X-l0$L!oJUA;h#aA|EPXhIJ=Bi>Pkv-luNJITcc^!cE2t6JMVsT zI)8QZ1aL@pQ8G^`MMgpuwWq1as^u@_RdpJkON_ZXZb$Ha*37^(k42d!wItR{wns7^ z81U8TTbj$OS{$j@@ZxlO9X@gvq#DNG@w{qA$nMi?h~C8i^;YR?P;YgsUM;T{q~3wr zj9X#vbJ5TddA8Ku&s>K1_mu(f5bZ(sg-`GIi+FYa_*nO#rL@N&@2z;;$b4E?n4vE7 zWgoL&wP1-tnTQ2uvpfxm+A8e9Mzi#~EFXyXo-k z49lE5rdbbxYK*5>+IMooN&~uQE5nD%}P4iGtpdwn~2HvaHh{;dJdq$4;%q%`W6^z^-;~ zkInm}-&e?ExOcCV^}S*oBWBU5n((`f_6S#nEcY?nvk4+Dm@N#w*5^RY5BPg)$DbSU z_tuVI?;wsiZxp_J`G%+P`vbcr$_zZ&_P^}`-NFC%)=u1m{~cWaKaMepgZ;zW|4mp} z?#Mka_Z0#Fyf(Z%wjRF?;}v}HKgdj3w8MzNKtSc-;at{0^v2B0y_@%AH?BXt70XOL SdL+Z+m@s7ETE@qKQouh1*m9i! literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/tmaptest.e b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/tmaptest.e new file mode 100644 index 0000000..d3dd2d6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/TextureMapping/tmaptest.e @@ -0,0 +1,121 @@ +-> tmap experiment + +OPT OSVERSION=39, LARGE, PREPROCESS + +CONST CWIDTH=320 -> in units of 64 seems best... +CONST CHEIGHT=240,SCOFF=8 +CONST SCHEIGHT=SCOFF*2+CHEIGHT,SCDEPTH=8 +CONST BUFS=CWIDTH*CHEIGHT + +MODULE '*geom', '*c2p_cpu3blit1', '*texturemapper', '*screenmodereq_db', + 'tools/exceptions', 'tools/scrbuffer', + 'intuition/screens', 'intuition/intuition', + 'graphics/rastport', 'graphics/gfx' + +PROC addc(p:PTR TO point,c,l,fishy) + DEF a,b + a,b:=project3d(c,p,CWIDTH/2,CHEIGHT/2,fishy) + ListAdd(l,[a,b]) +ENDPROC + +PROC render(cbuf,c:PTR TO opoint,fishy,pic) + DEF l[8]:LIST + clearmem(cbuf,CWIDTH*CHEIGHT,-1) + addc([100,100,0]:point,c,l,fishy) + addc([-100,100,0]:point,c,l,fishy) + addc([-100,-100,0]:point,c,l,fishy) + addc([100,-100,0]:point,c,l,fishy) + tmap(l,cbuf,CWIDTH,CHEIGHT,pic,64,64) + SetList(l,0) + addc([-100,-100,0]:point,c,l,fishy) + addc([100,-100,0]:point,c,l,fishy) + addc([100,-100,-200]:point,c,l,fishy) + addc([-100,-100,-200]:point,c,l,fishy) + tmap(l,cbuf,CWIDTH,CHEIGHT,pic,64,64) + SetList(l,0) + addc([100,-100,0]:point,c,l,fishy) + addc([100,100,0]:point,c,l,fishy) + addc([100,100,-200]:point,c,l,fishy) + addc([100,-100,-200]:point,c,l,fishy) + tmap(l,cbuf,CWIDTH,CHEIGHT,pic,64,64) +ENDPROC + +tmaplab: INCBIN 'car64x64x8.iff.cmchunky' + +PROC clearmem(mem,size,pat) + DEF e:REG,a:REG,b:REG,c:REG,d:REG + e:=size/16-1 + a:=b:=c:=d:=pat + MOVE.L mem,A0 + ADD.L size,A0 +clloop: + MOVEM.L a/b/c/d,-(A0) + DBRA e,clloop +ENDPROC + +PROC main() HANDLE + DEF dbs,scr=NIL:PTR TO screen,bm:PTR TO bitmap,win=NIL:PTR TO window,cam:PTR TO opoint, + cbuf,imsg:PTR TO intuimessage,key,frames=0,dframes,fsec,ssec,smic,esec,emic,fishy=60, + a,pic,tpic[17000]:ARRAY OF CHAR + cam:=[200,-200,150,-45,45,10]:opoint + pic:={tmaplab} + IF (dbs:=openreqscreen(CWIDTH,SCHEIGHT,SCDEPTH,'bla'))=NIL THEN Raise() -> OpenScreen + scr:=sb_GetScreen(dbs) + IF (win:=OpenW(0,0,CWIDTH-1,SCHEIGHT-1, + IDCMP_MOUSEBUTTONS OR IDCMP_VANILLAKEY, + WFLG_BORDERLESS OR WFLG_SIMPLE_REFRESH OR WFLG_BACKDROP OR WFLG_ACTIVATE OR WFLG_RMBTRAP, + '',scr,15,NIL))=NIL THEN Raise("WIN") + NEW cbuf[BUFS] + FOR a:=0 TO 255 DO SetColour(scr,a,pic[]++,pic[]++,pic[]++) + FOR a:=0 TO 64 DO CopyMem(a*64+pic,a*256+tpic,64) + SetRast(scr.rastport,255) + bm:=sb_NextBuffer(dbs) + SetRast(scr.rastport,255) + c2p_setup(gfxbase,CWIDTH,CHEIGHT,SCOFF,0 /* dummy */,NewM(CWIDTH*CHEIGHT,2)) + CurrentTime({ssec},{smic}) + REPEAT + render(cbuf,cam,fishy,tpic) + Colour(0,255) + ->TextF(0,SCHEIGHT-5,'x=\d y=\d z=\d turn=\d up=\d tilt=\d, wide=\d',cam.x,cam.y,cam.z,cam.turn,cam.up,cam.tilt,fishy) + bm:=sb_NextBuffer(dbs) + c2p(cbuf,bm.planes) + frames++ + IF imsg:=GetMsg(win.userport) + IF imsg.class=IDCMP_VANILLAKEY + key:=imsg.code + SELECT key + CASE "n"; cam.turn:=cam.turn+10 -> turnleft + CASE "m"; cam.turn:=cam.turn-10 -> turnright + CASE "d"; cam.up:=cam.up-10 -> lookdown + CASE "c"; cam.up:=cam.up+10 -> lookup + CASE "v"; cam.tilt:=cam.tilt-10 -> bankleft + CASE "b"; cam.tilt:=cam.tilt+10 -> bankright + CASE "s"; cam.z:=cam.z+10 -> down + CASE "x"; cam.z:=cam.z-10 -> up + CASE "a"; cam.y:=cam.y+10 -> yforward + CASE "z"; cam.y:=cam.y-10 -> ybackward + CASE "w"; cam.x:=cam.x+10 -> xright + CASE "e"; cam.x:=cam.x-10 -> xleft + CASE "r"; fishy:=fishy+10 -> zoom + CASE "t"; IF fishy>15 THEN fishy:=fishy-10 -> wide angle + -> "q" quits + ENDSELECT + ELSEIF imsg.class=IDCMP_MOUSEBUTTONS + ENDIF + ReplyMsg(imsg) + ENDIF + UNTIL key="q" + CurrentTime({esec},{emic}) + dframes:=Mul(esec-ssec,100)+Div(emic-smic,10000) + fsec:=Div(Mul(frames,10000),dframes) + IF frames THEN WriteF('calculated \d frames in \d.\z\d[2] seconds, giving \d.\z\d[2] f/s\n',frames,Div(dframes,100),Mod(dframes,100),Div(fsec,100),Mod(fsec,100)) +EXCEPT DO + IF win THEN CloseWindow(win) + closereqscreen(dbs) + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "REQ"; WriteF('Error: Could not allocate ASL request\n') + CASE "ASL"; WriteF('Error: Could not open ASL library\n') + ENDSELECT + report_exception() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/Trace.e b/amigae33a/E_v3.3a/Src/Src/Gfx/Trace.e new file mode 100644 index 0000000..555e00a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/Trace.e @@ -0,0 +1,65 @@ +/* This does something that looks like raytracing. + does absolutely nothing fancy. vary the positions of + the ball objects below to see the effect */ + +OBJECT ball + next,type,x,y,z,r,col +ENDOBJECT + +CONST S=100,T_BALL=1,SP=1,MI=$7FFFFFF0 + +DEF first:PTR TO ball,scr=NIL,last,next + +PROC main() + scr:=OpenS(320,256,4,0,'Tracing...') + IF scr + last:=[NIL,T_BALL,6500,5500,5000,500,3]:ball + next:=[last,T_BALL,5000,5500,6000,1500,4]:ball + first:=[next,T_BALL,4000,5500,5000,1000,1]:ball + traceall() + WHILE Mouse()<>1 DO NOP + leave(NIL) + ELSE + leave('Could not open screen!') + ENDIF +ENDPROC + +PROC traceall() + DEF x,y + FOR x:=1000 TO 9000 + FOR y:=1000 TO 9000 + Plot(x/S+20*SP,y/S+20*SP,tracepixel(5000,5000,1000,x,y,9000)) + y:=y+S + IF Mouse()=1 THEN RETURN + ENDFOR + x:=x+S + ENDFOR +ENDPROC + +PROC tracepixel(x,y,z,x2,y2,z2) /* traces beam, returns rgb */ + DEF fx,fy,f,bx,by,dx,dy,obj:PTR TO ball,o,fbest=MI + obj:=first; o:=first + REPEAT + f:=(obj.z-z*256)/(z2-z) + fx:=x2-x*f/256 /* get factor */ + fy:=y2-y*f/256 + bx:=obj.x-fx /* new scaled ball position */ + by:=obj.y-fy + dx:=bx-x /* distance ball <--> line */ + dy:=by-y + IF (fMI THEN obj.col ELSE 2 + +PROC leave(erstr) + IF scr THEN CloseS(scr) + IF erstr THEN WriteF('\s\n',erstr) + CleanUp(0) +ENDPROC + +PROC sqrt(x) IS !Fsqrt(x!)! diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/nice.e b/amigae33a/E_v3.3a/Src/Src/Gfx/nice.e new file mode 100644 index 0000000..3598883 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/nice.e @@ -0,0 +1,196 @@ +/* Evolutionary "nice" pictures. + + breed bitmaps. A fitness function will assign numbers according to + all sorts of perception criteria. mutation, the usual. + +possible "niceness" criteria: +- amount of surrounding pixels having a similar color -> smoothness +- amount of different colors used in total -> diversity +- longer stretching lines (hard to detect) +- symmetry / repetition / parallelism +- find longest path (fill-alg) + +*/ + +OPT OSVERSION=37, PREPROCESS, REG=5 + +-> fixed parameters + +DEF bmx=10,bmy=30, -> bitmap size + bmnum=3, -> #of bitmaps to breed at once + evrate=2, -> kill/birth rate of evolution. number of mutations each time + numrate=100 -> how many to rate + +#define MIRROR + +DEF bmt, -> total bytes per bitmap + hinum=0, -> best sofar + bmp=NIL:PTR TO LONG, + bmscore=NIL:PTR TO LONG, + bmcalc=NIL:PTR TO CHAR + +MODULE 'tools/easygui', 'tools/exceptions', 'tools/clonescreen', + 'intuition/screens' + +DEF scr=NIL:PTR TO screen,font + +DEF fmt,keepshowing=TRUE,iterations + +PROC main() HANDLE + DEF r + fmt:='%2ld' + LOOP + r:=easygui('Nice Pix', + [EQROWS, + [SLIDE,{setbmx},'bitmap x size: ',FALSE,3,99,bmx,10,fmt], + [SLIDE,{setbmy},'bitmap y size: ',FALSE,3,99,bmy,10,fmt], + [SLIDE,{setbmn},'#of bitmaps: ',FALSE,2,99,bmnum,10,fmt], + [SLIDE,{setevr},'kill/birth: ',FALSE,1,99,evrate,10,fmt], + [SLIDE,{setmut},'mutations: ',FALSE,1,99,nummut,10,fmt], + [SLIDE,{setrat},'rating: ',FALSE,1,999,numrate,10,fmt], + [BAR], + [COLS,[BUTTON,1,'Start'],[SPACEH],[BUTTON,0,'Cancel']] + ] + ) + evrate:=Bounds(evrate,1,bmnum-1) + IF r=0 THEN Raise() + actionreq() + ENDLOOP +EXCEPT + IF scr THEN closeclonescreen(scr,font) + report_exception() +ENDPROC + +PROC setbmx(i,n) IS bmx:=n +PROC setbmy(i,n) IS bmy:=n +PROC setbmn(i,n) IS bmnum:=n +PROC setevr(i,n) IS evrate:=n +PROC setmut(i,n) IS nummut:=n +PROC setrat(i,n) IS numrate:=n + +PROC actionreq() HANDLE + DEF gh=NIL:PTR TO guihandle,res=-1,count=0,a + gh:=guiinit('Nice Pix Action: BUSY', + [EQROWS, + [CHECK,{togglekeep},'keep showing picture:',keepshowing,TRUE], + [SLIDE,{setw1},'weight: ',FALSE,0,99,50,10,fmt], + [BAR], + [COLS,[BUTTON,{showpic},'Show Picture'],[SPACEH],[BUTTON,0,'Stop']] + ] + ) + setupsim() + IF scr THEN SetRast(scr.rastport,0) + WHILE res<0 + ->Wait(gh.sig) + res:=guimessage(gh) + FOR a:=1 TO 3 DO dosim() + IF keepshowing THEN IF count++ AND $F = 0 THEN showpic(0) + ENDWHILE +EXCEPT DO + deallocsim() + cleangui(gh) + IF exception THEN ReThrow() +ENDPROC res + +PROC setw1(i,n) IS n +PROC togglekeep(i,n) IS keepshowing:=n + +CONST XO=40,YO=40,XZ=2,YZ=2,COL=16,DEPTH=4 +CONST XO1=XO+XZ-1,YO1=YO+YZ-1,XZ2=XZ*2,YZ2=YZ*2 + +PROC showpic(i) + DEF x,y,bm + bm:=bmp[hinum] + IF scr=NIL + scr,font:=openclonescreen('Workbench','Nice!',DEPTH) + ENDIF + SetStdRast(scr.rastport) + Colour(2,0) + TextF(XO,YO-10,'hi = \d, it = \d ',bmscore[hinum],iterations) + FOR y:=YZ TO bmy*YZ STEP YZ + FOR x:=XZ TO bmx*XZ STEP XZ + #ifdef MIRROR + Box(bmx*XZ2-x+XO,y+YO,bmx*XZ2-x+XO1,y+YO1,bm[]) + Box(bmx*XZ2-x+XO,bmy*YZ2-y+YO,bmx*XZ2-x+XO1,bmy*YZ2-y+YO1,bm[]) + Box(x+XO,bmy*YZ2-y+YO,x+XO1,bmy*YZ2-y+YO1,bm[]) + #endif + Box(x+XO,y+YO,x+XO1,y+YO1,bm[]++) + ENDFOR + ENDFOR +ENDPROC + +PROC setupsim() + DEF a,bm,b + bmt:=bmx*bmy + hinum:=0 + iterations:=0 + NEW bmp[bmnum] + NEW bmcalc[bmnum] + NEW bmscore[bmnum] + FOR a:=0 TO bmnum-1 + bmp[a]:=bm:=FastNew(bmt) + FOR b:=0 TO bmt-1 DO bm[]++:=Rnd(COL) + ENDFOR +ENDPROC + +PROC deallocsim() + DEF a + IF bmp THEN FOR a:=0 TO bmnum-1 DO IF bmp[a] THEN FastDispose(bmp[a],bmt) + END bmp[bmnum] + END bmcalc[bmnum] + END bmscore[bmnum] +ENDPROC + +CONST MINSTART=$7FFFFFFF + +PROC dosim() + DEF a,b,min,minnum + iterations++ + FOR a:=0 TO bmnum-1 -> make sure all are rated + IF bmcalc[a]=FALSE + mutate(bmp[a]) + bmscore[a]:=rate(bmp[a]) -> mutate and rerate if necessary + IF bmscore[a]>bmscore[hinum] THEN hinum:=a -> keep track of best + bmcalc[a]:=TRUE + ENDIF + ENDFOR + FOR a:=1 TO evrate -> pick n victims + min:=MINSTART + FOR b:=0 TO bmnum-1 + IF (bmcalc[b]) AND b<>hinum + IF bmscore[b] calc worst + min:=bmscore[b] + minnum:=b + ENDIF + ENDIF + ENDFOR + IF min=MINSTART THEN Raise("prob") + bmcalc[minnum]:=FALSE + CopyMem(bmp[hinum],bmp[minnum],bmt) -> copy from best + ENDFOR +ENDPROC + +PROC mutate(bm) + DEF a + FOR a:=1 TO nummut DO bm[Rnd(bmt)]:=Rnd(COL) +ENDPROC + +PROC rate(bma) -> B: mixed environ + DEF a,c=0,tc,nc,bm + bm:=bma + FOR a:=0 TO bmt-1 + tc:=bm[] + nc:=0 + IF bm[-1]=tc THEN nc++ + IF bm[1]=tc THEN nc++ + IF bm[bmx]=tc THEN nc++ + IF bm[bmx-1]=tc THEN nc++ + IF bm[bmx+1]=tc THEN nc++ + IF bm[-bmx]=tc THEN nc++ + IF bm[-bmx-1]=tc THEN nc++ + IF bm[-bmx+1]=tc THEN nc++ + c:=c+(6-Abs(nc-2)) + bm++ + ENDFOR +ENDPROC c diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/paint.e b/amigae33a/E_v3.3a/Src/Src/Gfx/paint.e new file mode 100644 index 0000000..df63105 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/paint.e @@ -0,0 +1,23 @@ +/* example of using built-in font for images. 'paint.m' converted + from font-file with font2obj (aminet?) and o2m +*/ + +OPT OSVERSION=37 + +MODULE 'tools/clonescreen', '*paint', 'libraries/diskfont' + +PROC main() HANDLE + DEF screen=NIL,font=NIL,win=NIL,tf:PTR TO diskfontheader + tf:={paintf}; tf:=tf.tf + screen,font:=openclonescreen('Workbench','bla') + win:=backdropwindow(screen) + SetFont(stdrast:=screen+84,tf) + TextF(200,40,'A B C D E F G H ') + EasyRequestArgs(win,[20,0,'um','uhhh','zure'],0,NIL) +EXCEPT DO + closeclonescreen(screen,font,win) + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "WIN"; WriteF('no window!\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/paint.m b/amigae33a/E_v3.3a/Src/Src/Gfx/paint.m new file mode 100644 index 0000000000000000000000000000000000000000..d05ed2e891f6b4a9081144b46ac739145a0c509e GIT binary patch literal 496 zcmZ{gF;BxV5QU!|Ck`ki8KW-5TgDCyYy_!A9iUwq7zz@RV5lMl5@QAiHdaP{N`49> zBV$-KbSv2%Tqnb>lGb2i5@O1an2~!xE(+gC# z2bAwdr9d00V@H|U53xk1o*f-ppB~1lBjtq&K1fU75qs(q(YV!)PF_vWxa&xvs6!L5 zrH2rt&kZ5qKP9m)6KlVL2svBr8WH^%BdTC_MDZ$|QV~SQdnknU_1)^R!kVlgt>ube#``j} literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Gfx/sim_flock.e b/amigae33a/E_v3.3a/Src/Src/Gfx/sim_flock.e new file mode 100644 index 0000000..0e422b3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Gfx/sim_flock.e @@ -0,0 +1,112 @@ +-> silly little simulation + +OPT REG=5 + +MODULE 'intuition/intuition', 'exec/nodes', 'exec/lists', 'tools/constructors' + +OBJECT creature OF mln + x,y + loc:PTR TO LONG +ENDOBJECT + +DEF creatures=NIL:PTR TO LONG,creaturelist=NIL:PTR TO mlh,num_creatures=100 + +CONST SPACE_XS=64, + SPACE_YS=64, + SPACE_X=13, + SPACE_Y=28, + XBL=2, + YBL=2, + AND_X=$3f, + AND_Y=$3f + +CONST XSI=XBL*SPACE_XS, + YSI=YBL*SPACE_YS + +PROC main() HANDLE + DEF w=NIL:PTR TO window,m:PTR TO intuimessage,c=0,a,cc=0 + IF (a:=Val(arg))>1 THEN num_creatures:=a + IF w:=OpenW(20,20,XSI+42,YSI+42,IDCMP_CLOSEWINDOW OR IDCMP_MOUSEBUTTONS,$F, + arg,->'BacteriaMania', + NIL,1,NIL) + Box(SPACE_X-1,SPACE_Y-1,SPACE_XS*XBL+1+SPACE_X,SPACE_YS*YBL+1+SPACE_Y,1) + Box(SPACE_X,SPACE_Y,SPACE_XS*XBL+SPACE_X,SPACE_YS*YBL+SPACE_Y,0) + FOR a:=1 TO num_creatures DO new_creature() + REPEAT + move_creatures() + WHILE m:=GetMsg(w.userport) + IF (c:=m.class)=IDCMP_MOUSEBUTTONS + ENDIF + ENDWHILE + UNTIL c=IDCMP_CLOSEWINDOW + ENDIF +EXCEPT DO + CloseW(w) +ENDPROC + +PROC move_creatures() + DEF cr:PTR TO creature,d:PTR TO LONG,x,y,a,b,c,e,aa,bb,nbl=NIL:PTR TO LONG,nb:PTR TO creature,numnb + cr:=creaturelist.head + WHILE cr.succ + a:=0 -> check were to move + numnb:=0 + c:=-1 + FOR a:=-1 TO 1 + FOR b:=-1 TO 1 + aa:=a+cr.x; bb:=b+cr.y + d:=addrxy(aa,bb) + IF (d[]=NIL) AND (d[]<>cr) + IF (e:=countcrowd(aa,bb))>=c + ->IF (e:=countcrowd(d))>=c + IF IF e=c THEN Rnd(3)=0 ELSE TRUE + c:=e; x:=aa; y:=bb + ENDIF + ENDIF + ENDIF + ENDFOR + ENDFOR + d:=IF c>=0 THEN addrxy(x,y) ELSE 1 + IF d[]=NIL -> if possible, move + d[]:=cr + cr.loc[]:=NIL + cr.loc:=d + plotxy(x,y,2) + plotxy(cr.x,cr.y,0) + cr.x:=x + cr.y:=y + ENDIF + cr:=cr.succ + ENDWHILE +ENDPROC + +PROC countcrowd(x,y) + DEF n=0,a,b,d:PTR TO LONG + FOR a:=-1 TO 1 DO FOR b:=-1 TO 1 DO IF (d:=addrxy(x+a,y+b)) BUT d[] THEN n++ +ENDPROC n + +PROC new_creature() + DEF d:PTR TO LONG,a,x,y,cr:PTR TO creature + IF creatures=NIL + NEW creatures[SPACE_YS] + FOR a:=0 TO SPACE_YS-1 DO creatures[a]:=NEW d[SPACE_XS] + creaturelist:=newlist() + ENDIF + REPEAT + d:=addrxy(x:=Rnd(SPACE_XS),y:=Rnd(SPACE_YS)) + UNTIL d[]=NIL + d[]:=NEW cr + AddHead(creaturelist,cr) + cr.loc:=d + cr.x:=x + cr.y:=y + plotxy(x,y,3) +ENDPROC + +PROC addrxy(x,y) IS x AND AND_X*SIZEOF LONG+creatures[y AND AND_Y] + +PROC plotxy(x,y,c) + DEF xx,yy + xx:=x AND AND_X*XBL+SPACE_X + yy:=y AND AND_Y*YBL+SPACE_Y + IF XBL+YBL=2 THEN Plot(xx,yy,c) ELSE Box(xx,yy,XBL-1+xx,YBL-1+yy,c) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/address.e b/amigae33a/E_v3.3a/Src/Src/Guide/address.e new file mode 100644 index 0000000..a421d4b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/address.e @@ -0,0 +1,13 @@ +DEF x + +PROC main() + fred(2) +ENDPROC + +PROC fred(y) + DEF z + WriteF('x is at address \d\n', {x}) + WriteF('y is at address \d\n', {y}) + WriteF('z is at address \d\n', {z}) + WriteF('fred is at address \d\n', {fred}) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/args.e b/amigae33a/E_v3.3a/Src/Src/Guide/args.e new file mode 100644 index 0000000..d7eb4e0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/args.e @@ -0,0 +1,28 @@ +MODULE 'workbench/startup' + +PROC main() + DEF startup:PTR TO wbstartup, args:PTR TO wbarg, i, oldlock, len + IF (startup:=wbmessage)=NIL + WriteF('Started from Shell/CLI\n Arguments: "\s"\n', arg) + ELSE + WriteF('Started from Workbench\n') + args:=startup.arglist + FOR i:=1 TO startup.numargs /* Loop through the arguments */ + IF args[].lock=NIL + WriteF(' Argument \d: "\s" (no lock)\n', i, args[].name) + ELSE + oldlock:=CurrentDir(args[].lock) + len:=FileLength(args[].name) /* Do something with file */ + IF len=-1 + WriteF(' Argument \d: "\s" (file does not exist)\n', + i, args[].name) + ELSE + WriteF(' Argument \d: "\s", file length is \d bytes\n', + i, args[].name, len) + ENDIF + CurrentDir(oldlock) /* Important: restore current dir */ + ENDIF + args++ + ENDFOR + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/args.info b/amigae33a/E_v3.3a/Src/Src/Guide/args.info new file mode 100644 index 0000000000000000000000000000000000000000..3d83a9b5cf272b76f6ac1880cf8b7e163e7de306 GIT binary patch literal 802 zcmeH@u?~VT5QhI!F&!|npo@vVfQtih^$i$g_f2H=Ay zllJS~-`-t%_94(J#27t_g>vT0Hrb_oh6$Z`y(z?qs^GXAzF3r~<set.data + set.right:=add(i, set.right) + ENDIF + RETURN set + ENDIF +ENDPROC + +PROC show(set:PTR TO tree) + IF set<>NIL + show(set.left) + WriteF('\d ', set.data) + show(set.right) + ENDIF +ENDPROC + +PROC main() HANDLE + DEF s, i, j + Rnd(-999999) /* Initialise seed */ + s:=new_set(10) /* Initialise set s to contain the number 10 */ + WriteF('Input:\n') + FOR i:=1 TO 50 /* Generate 50 random numbers and add them to set s */ + j:=Rnd(100) + add(j, s) + WriteF('\d ',j) + ENDFOR + WriteF('\nOutput:\n') + show(s) /* Show the contents of the (sorted) set s */ + WriteF('\n') +EXCEPT + IF exception="NEW" THEN WriteF('Ran out of memory\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/csv-buff.e b/amigae33a/E_v3.3a/Src/Src/Guide/csv-buff.e new file mode 100644 index 0000000..4e1eac1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/csv-buff.e @@ -0,0 +1,68 @@ +PROC main() + DEF buffer, filehandle, len, filename + filename:='datafile' + /* Get the length of data in the file */ + IF 0<(len:=FileLength(filename)) + /* Allocate just enough room for the data + a terminating NIL */ + IF buffer:=New(len+1) + IF filehandle:=Open(filename, OLDFILE) + /* Read whole file, checking amount read */ + IF len=Read(filehandle, buffer, len) + /* Terminate buffer with a NIL just in case... */ + buffer[len]:=NIL + process_buffer(buffer, len) + ELSE + WriteF('Error: File reading error\n') + ENDIF + /* If Open() succeeded then we must Close() the file */ + Close(filehandle) + ELSE + WriteF('Error: Failed to open "\s"\n', filename) + ENDIF + /* Deallocate buffer (not really necessary in this example) */ + Dispose(buffer) + ELSE + WriteF('Error: Insufficient memory to load file\n') + ENDIF + ELSE + WriteF('Error: "\s" is an empty file\n', filename) + ENDIF +ENDPROC + +/* buffer is like a normal string since it's NIL-terminated */ +PROC process_buffer(buffer, len) + DEF start=0, end + REPEAT + /* Find the index of a linefeed after the start index */ + end:=InStr(buffer, '\n', start) + /* If a linefeed was found then terminate with a NIL */ + IF end<>-1 THEN buffer[end]:=NIL + process_record(buffer+start) + start:=end+1 + /* We've finished if at the end or no more linefeeds */ + UNTIL (start>=len) OR (end=-1) +ENDPROC + +PROC process_record(line) + DEF i=1, start=0, end, s + /* Show the whole line being processed */ + WriteF('Processing record: "\s"\n', line) + REPEAT + /* Find the index of a comma after the start index */ + end:=InStr(line, ',', start) + /* If a comma was found then terminate with a NIL */ + IF end<>-1 THEN line[end]:=NIL + /* Point to the start of the field */ + s:=line+start + IF s[] + /* At this point we could do something useful... */ + WriteF('\t\d) "\s"\n', i, s) + ELSE + WriteF('\t\d) Empty Field\n', i) + ENDIF + /* The new start is after the end we found */ + start:=end+1 + INC i + /* Once a comma is not found we've finished */ + UNTIL end=-1 +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/csv-estr.e b/amigae33a/E_v3.3a/Src/Src/Guide/csv-estr.e new file mode 100644 index 0000000..fa534f1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/csv-estr.e @@ -0,0 +1,50 @@ +/* A suitably large size for the record buffer */ +CONST BUFFERSIZE=512 + +PROC main() + DEF filehandle, status, buffer[BUFFERSIZE]:STRING, filename + filename:='datafile' + IF filehandle:=Open(filename, OLDFILE) + REPEAT + status:=ReadStr(filehandle, buffer) + /* This is the way to check ReadStr() actually read something */ + IF buffer[] OR (status<>-1) THEN process_record(buffer) + UNTIL status=-1 + /* If Open() succeeded then we must Close() the file */ + Close(filehandle) + ELSE + WriteF('Error: Failed to open "\s"\n', filename) + ENDIF +ENDPROC + +PROC process_record(line) + DEF i=1, start=0, end, len, s + /* Show the whole line being processed */ + WriteF('Processing record: "\s"\n', line) + REPEAT + /* Find the index of a comma after the start index */ + end:=InStr(line, ',', start) + /* Length is end index minus start index */ + len:=(IF end<>-1 THEN end ELSE EstrLen(line))-start + IF len>0 + /* Allocate an E-string of the correct length */ + IF s:=String(len) + /* Copy the portion of the line to the E-string s */ + MidStr(s, line, start, len) + /* At this point we could do something useful... */ + WriteF('\t\d) "\s"\n', i, s) + /* We've finished with the E-string so deallocate it */ + DisposeLink(s) + ELSE + /* It's a non-fatal error if the String() call fails */ + WriteF('\t\d) Memory exhausted! (len=\d)\n', len) + ENDIF + ELSE + WriteF('\t\d) Empty Field\n', i) + ENDIF + /* The new start is after the end we found */ + start:=end+1 + INC i + /* Once a comma is not found we've finished */ + UNTIL end=-1 +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/csv-norm.e b/amigae33a/E_v3.3a/Src/Src/Guide/csv-norm.e new file mode 100644 index 0000000..717fbdc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/csv-norm.e @@ -0,0 +1,42 @@ +/* A suitably large size for the record buffer */ +CONST BUFFERSIZE=512 + +PROC main() + DEF filehandle, status, buffer[BUFFERSIZE]:STRING, filename + filename:='datafile' + IF filehandle:=Open(filename, OLDFILE) + REPEAT + status:=ReadStr(filehandle, buffer) + /* This is the way to check ReadStr() actually read something */ + IF buffer[] OR (status<>-1) THEN process_record(buffer) + UNTIL status=-1 + /* If Open() succeeded then we must Close() the file */ + Close(filehandle) + ELSE + WriteF('Error: Failed to open "\s"\n', filename) + ENDIF +ENDPROC + +PROC process_record(line) + DEF i=1, start=0, end, s + /* Show the whole line being processed */ + WriteF('Processing record: "\s"\n', line) + REPEAT + /* Find the index of a comma after the start index */ + end:=InStr(line, ',', start) + /* If a comma was found then terminate with a NIL */ + IF end<>-1 THEN line[end]:=NIL + /* Point to the start of the field */ + s:=line+start + IF s[] + /* At this point we could do something useful... */ + WriteF('\t\d) "\s"\n', i, s) + ELSE + WriteF('\t\d) Empty Field\n', i) + ENDIF + /* The new start is after the end we found */ + start:=end+1 + INC i + /* Once a comma is not found we've finished */ + UNTIL end=-1 +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/csv.e b/amigae33a/E_v3.3a/Src/Src/Guide/csv.e new file mode 100644 index 0000000..ddf505e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/csv.e @@ -0,0 +1,72 @@ +/* Some constants for exceptions (ERR_NONE is zero: no error) */ +ENUM ERR_NONE, ERR_LEN, ERR_NEW, ERR_OPEN, ERR_READ + +/* Make some exceptions automatic */ +RAISE ERR_LEN IF FileLength()<=0, + ERR_NEW IF New()=NIL, + ERR_OPEN IF Open()=NIL + +PROC main() HANDLE + /* Note the careful initialisation of buffer and filehandle */ + DEF buffer=NIL, filehandle=NIL, len, filename + filename:='datafile' + /* Get the length of data in the file */ + len:=FileLength(filename) + /* Allocate just enough room for the data + a terminating NIL */ + buffer:=New(len+1) + filehandle:=Open(filename, OLDFILE) + /* Read whole file, checking amount read */ + IF len<>Read(filehandle, buffer, len) THEN Raise(ERR_READ) + /* Terminate buffer with a NIL just in case... */ + buffer[len]:=NIL + process_buffer(buffer, len) +EXCEPT DO + /* Both of these are safe thanks to the initialisations */ + IF buffer THEN Dispose(buffer) + IF filehandle THEN Close(filehandle) + /* Report error (if there was one) */ + SELECT exception + CASE ERR_LEN; WriteF('Error: "\s" is an empty file\n', filename) + CASE ERR_NEW; WriteF('Error: Insufficient memory to load file\n') + CASE ERR_OPEN; WriteF('Error: Failed to open "\s"\n', filename) + CASE ERR_READ; WriteF('Error: File reading error\n') + ENDSELECT +ENDPROC + +/* buffer is like a normal string since it's NIL-terminated */ +PROC process_buffer(buffer, len) + DEF start=0, end + REPEAT + /* Find the index of a linefeed after the start index */ + end:=InStr(buffer, '\n', start) + /* If a linefeed was found then terminate with a NIL */ + IF end<>-1 THEN buffer[end]:=NIL + process_record(buffer+start) + start:=end+1 + /* We've finished if at the end or no more linefeeds */ + UNTIL (start>=len) OR (end=-1) +ENDPROC + +PROC process_record(line) + DEF i=1, start=0, end, s + /* Show the whole line being processed */ + WriteF('Processing record: "\s"\n', line) + REPEAT + /* Find the index of a comma after the start index */ + end:=InStr(line, ',', start) + /* If a comma was found then terminate with a NIL */ + IF end<>-1 THEN line[end]:=NIL + /* Point to the start of the field */ + s:=line+start + IF s[] + /* At this point we could do something useful... */ + WriteF('\t\d) "\s"\n', i, s) + ELSE + WriteF('\t\d) Empty Field\n', i) + ENDIF + /* The new start is after the end we found */ + start:=end+1 + INC i + /* Once a comma is not found we've finished */ + UNTIL end=-1 +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/datafile b/amigae33a/E_v3.3a/Src/Src/Guide/datafile new file mode 100644 index 0000000..2a0841c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/datafile @@ -0,0 +1,6 @@ +datafile,for,CSV,programs +Field1,Field2,Field3 +10,19,-3 +fred,barney,wilma +,,last +first,, diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/dragon.e b/amigae33a/E_v3.3a/Src/Src/Guide/dragon.e new file mode 100644 index 0000000..00e3deb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/dragon.e @@ -0,0 +1,113 @@ +MODULE 'intuition/intuition', 'graphics/view' + +/* Screen size, use SIZEY=512 for a PAL screen */ +CONST SIZEX=640, SIZEY=400 + +/* Exception values */ +ENUM WIN=1, SCRN, STK, BRK + +/* Directions (DIRECTIONS gives number of directions) */ +ENUM NORTH, EAST, SOUTH, WEST, DIRECTIONS + +RAISE WIN IF OpenW()=NIL, + SCRN IF OpenS()=NIL + +/* Start off pointing WEST */ +DEF state=WEST, x, y, t + +/* Face left */ +PROC left() + state:=Mod(state-1+DIRECTIONS, DIRECTIONS) +ENDPROC + +/* Move right, changing the state */ +PROC right() + state:=Mod(state+1, DIRECTIONS) +ENDPROC + +/* Move in the direction we're facing */ +PROC move() + SELECT state + CASE NORTH; draw(0,t) + CASE EAST; draw(t,0) + CASE SOUTH; draw(0,-t) + CASE WEST; draw(-t,0) + ENDSELECT +ENDPROC + +/* Draw and move to specified relative position */ +PROC draw(dx, dy) + /* Check the line will be drawn within the window bounds */ + IF (x>=Abs(dx)) AND (x<=SIZEX-Abs(dx)) AND + (y>=Abs(dy)) AND (y<=SIZEY-10-Abs(dy)) + Line(x, y, x+dx, y+dy, 2) + ENDIF + x:=x+dx + y:=y+dy +ENDPROC + +PROC main() HANDLE + DEF sptr=NIL, wptr=NIL, i, m + /* Read arguments: [m [t [x [y]]]] */ + /* so you can say: dragon 16 */ + /* or: dragon 16 1 */ + /* or: dragon 16 1 450 */ + /* or: dragon 16 1 450 100 */ + /* m is depth of dragon, t is length of lines */ + /* (x,y) is the start position */ + m:=Val(arg, {i}) + t:=Val(arg:=arg+i, {i}) + x:=Val(arg:=arg+i, {i}) + y:=Val(arg:=arg+i, {i}) + /* If m or t is zero use a more sensible default */ + IF m=0 THEN m:=5 + IF t=0 THEN t:=5 + sptr:=OpenS(SIZEX,SIZEY,4,V_HIRES OR V_LACE,'Dragon Curve Screen') + wptr:=OpenW(0,10,SIZEX,SIZEY-10, + IDCMP_CLOSEWINDOW,WFLG_CLOSEGADGET, + 'Dragon Curve Window',sptr,$F,NIL) + /* Draw the dragon curve */ + dragon(m) + WHILE WaitIMessage(wptr)<>IDCMP_CLOSEWINDOW + ENDWHILE +EXCEPT DO + IF wptr THEN CloseW(wptr) + IF sptr THEN CloseS(sptr) + SELECT exception + CASE 0 + WriteF('Program finished successfully\n') + CASE WIN + WriteF('Could not open window\n') + CASE SCRN + WriteF('Could not open screen\n') + CASE STK + WriteF('Ran out of stack in recursion\n') + CASE BRK + WriteF('User aborted\n') + ENDSELECT +ENDPROC + +/* Draw the dragon curve (with left) */ +PROC dragon(m) + /* Check stack and ctrl-C before recursing */ + IF FreeStack()<1000 THEN Raise(STK) + IF CtrlC() THEN Raise(BRK) + IF m>0 + dragon(m-1) + left() + nogard(m-1) + ELSE + move() + ENDIF +ENDPROC + +/* Draw the dragon curve (with right) */ +PROC nogard(m) + IF m>0 + dragon(m-1) + right() + nogard(m-1) + ELSE + move() + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/except.e b/amigae33a/E_v3.3a/Src/Src/Guide/except.e new file mode 100644 index 0000000..fa08f7c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/except.e @@ -0,0 +1,22 @@ +ENUM FRED, BARNEY + +PROC main() + WriteF('Hello from main\n') + fred() + barney() + WriteF('Goodbye from main\n') +ENDPROC + +PROC fred() HANDLE + WriteF(' Hello from fred\n') + Raise(FRED) + WriteF(' Goodbye from fred\n') +EXCEPT + WriteF(' Handler fred: \d\n', exception) +ENDPROC + +PROC barney() + WriteF(' Hello from barney\n') + Raise(BARNEY) + WriteF(' Goodbye from barney\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/except2.e b/amigae33a/E_v3.3a/Src/Src/Guide/except2.e new file mode 100644 index 0000000..b602b47 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/except2.e @@ -0,0 +1,22 @@ +ENUM FRED, BARNEY + +PROC main() + WriteF('Hello from main\n') + fred() + WriteF('Goodbye from main\n') +ENDPROC + +PROC fred() HANDLE + WriteF(' Hello from fred\n') + barney() + Raise(FRED) + WriteF(' Goodbye from fred\n') +EXCEPT + WriteF(' Handler fred: \d\n', exception) +ENDPROC + +PROC barney() + WriteF(' Hello from barney\n') + Raise(BARNEY) + WriteF(' Goodbye from barney\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/float.e b/amigae33a/E_v3.3a/Src/Src/Guide/float.e new file mode 100644 index 0000000..3b76054 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/float.e @@ -0,0 +1,59 @@ +DEF f, i, s[20]:STRING + +PROC print_float() + WriteF('\tf is \s\n', RealF(s, !f, 8)) +ENDPROC + +PROC print_both() + WriteF('\ti is \d, ', i) + print_float() +ENDPROC + +/* Square a float */ +PROC square_float(f) IS !f*f + +/* Square an integer */ +PROC square_integer(i) IS i*i + +/* Converts a float to an integer */ +PROC convert_to_integer(f) IS Val(RealF(s, !f, 0)) + +/* Converts an integer to a float */ +PROC convert_to_float(i) IS RealVal(StringF(s, '\d', i)) + +/* This should be the same as Ftan */ +PROC my_tan(f) IS !Fsin(!f)/Fcos(!f) + +/* This should show float inaccuracies */ +PROC inaccurate(f) IS Fexp(Flog(!f)) + +PROC main() + WriteF('Next 2 lines should be the same\n') + f:=2.75; i:=!f! + print_both() + f:=2.75; i:=convert_to_integer(!f) + print_both() + + WriteF('Next 2 lines should be the same\n') + i:=10; f:=i! + print_both() + i:=10; f:=convert_to_float(i) + print_both() + + WriteF('f and i should be the same\n') + i:=square_integer(i) + f:=square_float(f) + print_both() + + WriteF('Next 2 lines should be the same\n') + f:=Ftan(.8) + print_float() + f:=my_tan(.8) + print_float() + + WriteF('Next 2 lines should be the same\n') + f:=.35 + print_float() + f:=inaccurate(f) + print_float() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/gadgets.e b/amigae33a/E_v3.3a/Src/Src/Guide/gadgets.e new file mode 100644 index 0000000..e5c3bb4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/gadgets.e @@ -0,0 +1,19 @@ +MODULE 'intuition/intuition' + +CONST GADGETBUFSIZE = 4 * GADGETSIZE + +PROC main() + DEF buf[GADGETBUFSIZE]:ARRAY, next, wptr + next:=Gadget(buf, NIL, 1, 0, 10, 30, 50, 'Hello') + next:=Gadget(next, buf, 2, 3, 70, 30, 50, 'World') + next:=Gadget(next, buf, 3, 1, 10, 50, 50, 'from') + next:=Gadget(next, buf, 4, 0, 70, 50, 70, 'gadgets') + wptr:=OpenW(20,50,200,100, 0, WFLG_ACTIVATE, + 'Gadgets in a window',NIL,1,buf) + IF wptr /* Check to see we opened a window */ + Delay(500) /* Wait a bit */ + CloseW(wptr) /* Close the window */ + ELSE + WriteF('Error -- could not open window!') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/graphics.e b/amigae33a/E_v3.3a/Src/Src/Guide/graphics.e new file mode 100644 index 0000000..09da6d2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/graphics.e @@ -0,0 +1,25 @@ +MODULE 'intuition/intuition' + +PROC main() + DEF wptr, i + wptr:=OpenW(20,50,200,100,IDCMP_CLOSEWINDOW, + WFLG_CLOSEGADGET OR WFLG_ACTIVATE, + 'Graphics demo window',NIL,1,NIL) + IF wptr /* Check to see we opened a window */ + Colour(1,3) + TextF(20,30,'Hello World') + SetTopaz(11) + TextF(20,60,'Hello World') + FOR i:=10 TO 150 STEP 8 /* Plot a few points */ + Plot(i,40,2) + ENDFOR + Line(160,40,160,70,3) + Line(160,70,170,40,2) + Box(10,75,160,85,1) + WHILE WaitIMessage(wptr)<>IDCMP_CLOSEWINDOW + ENDWHILE + CloseW(wptr) + ELSE + WriteF('Error -- could not open window!\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/idcmp.e b/amigae33a/E_v3.3a/Src/Src/Guide/idcmp.e new file mode 100644 index 0000000..aa7ada0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/idcmp.e @@ -0,0 +1,24 @@ +MODULE 'intuition/intuition' + +CONST GADGETBUFSIZE = GADGETSIZE, OURGADGET = 1 + +PROC main() + DEF buf[GADGETBUFSIZE]:ARRAY, wptr, class, gad:PTR TO gadget + Gadget(buf, NIL, OURGADGET, 1, 10, 30, 100, 'Press Me') + wptr:=OpenW(20,50,200,100, + IDCMP_CLOSEWINDOW OR IDCMP_GADGETUP, + WFLG_CLOSEGADGET OR WFLG_ACTIVATE, + 'Gadget message window',NIL,1,buf) + IF wptr /* Check to see we opened a window */ + WHILE (class:=WaitIMessage(wptr))<>IDCMP_CLOSEWINDOW + gad:=MsgIaddr() /* Our gadget clicked? */ + IF (class=IDCMP_GADGETUP) AND (gad.userdata=OURGADGET) + TextF(10,60, + IF gad.flags=0 THEN 'Gadget off ' ELSE 'Gadget on ') + ENDIF + ENDWHILE + CloseW(wptr) /* Close the window */ + ELSE + WriteF('Error -- could not open window!') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/screens.e b/amigae33a/E_v3.3a/Src/Src/Guide/screens.e new file mode 100644 index 0000000..6077273 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/screens.e @@ -0,0 +1,28 @@ +MODULE 'intuition/intuition', 'graphics/view' + +PROC main() + DEF sptr=NIL, wptr=NIL, i + sptr:=OpenS(640,200,4,V_HIRES,'Screen demo') + IF sptr + wptr:=OpenW(0,20,640,180,IDCMP_CLOSEWINDOW, + WFLG_CLOSEGADGET OR WFLG_ACTIVATE, + 'Graphics demo window',sptr,$F,NIL) + IF wptr + TextF(20,20,'Hello World') + FOR i:=0 TO 15 /* Draw a line and box in each colour */ + Line(20,30,620,30+(7*i),i) + Box(10+(40*i),140,30+(40*i),170,1) + Box(11+(40*i),141,29+(40*i),169,i) + ENDFOR + WHILE WaitIMessage(wptr)<>IDCMP_CLOSEWINDOW + ENDWHILE + WriteF('Program finished successfully\n') + ELSE + WriteF('Could not open window\n') + ENDIF + ELSE + WriteF('Could not open screen\n') + ENDIF + IF wptr THEN CloseW(wptr) + IF sptr THEN CloseS(sptr) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/screens2.e b/amigae33a/E_v3.3a/Src/Src/Guide/screens2.e new file mode 100644 index 0000000..0444cae --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/screens2.e @@ -0,0 +1,33 @@ +MODULE 'intuition/intuition', 'graphics/view' + +ENUM WIN=1, SCRN + +RAISE WIN IF OpenW()=NIL, + SCRN IF OpenS()=NIL + +PROC main() HANDLE + DEF sptr=NIL, wptr=NIL, i + sptr:=OpenS(640,200,4,V_HIRES,'Screen demo') + wptr:=OpenW(0,20,640,180,IDCMP_CLOSEWINDOW, + WFLG_CLOSEGADGET OR WFLG_ACTIVATE, + 'Graphics demo window',sptr,$F,NIL) + TextF(20,20,'Hello World') + FOR i:=0 TO 15 /* Draw a line and box in each colour */ + Line(20,30,620,30+(7*i),i) + Box(10+(40*i),140,30+(40*i),170,1) + Box(11+(40*i),141,29+(40*i),169,i) + ENDFOR + WHILE WaitIMessage(wptr)<>IDCMP_CLOSEWINDOW + ENDWHILE +EXCEPT DO + IF wptr THEN CloseW(wptr) + IF sptr THEN CloseS(sptr) + SELECT exception + CASE 0 + WriteF('Program finished successfully\n') + CASE WIN + WriteF('Could not open window\n') + CASE SCRN + WriteF('Could not open screen\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/set-use.e b/amigae33a/E_v3.3a/Src/Src/Guide/set-use.e new file mode 100644 index 0000000..c140713 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/set-use.e @@ -0,0 +1,24 @@ +MODULE '*set' + +PROC main() HANDLE + DEF s=NIL:PTR TO set + NEW s.create(20) + s.add(1) + s.add(-13) + s.add(91) + s.add(42) + s.add(-76) + IF s.member(1) THEN WriteF('1 is a member\n') + IF s.member(11) THEN WriteF('11 is a member\n') + WriteF('s = ') + s.print() + WriteF('\n') +EXCEPT DO + END s + SELECT exception + CASE "NEW" + WriteF('Out of memory\n') + CASE "full" + WriteF('Set is full\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/set.e b/amigae33a/E_v3.3a/Src/Src/Guide/set.e new file mode 100644 index 0000000..01dbdbd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/set.e @@ -0,0 +1,80 @@ +OPT MODULE -> Define class 'set' in a module +OPT EXPORT -> Export everything + +/* The data for the class */ +OBJECT set PRIVATE -> Make all the data private + elements:PTR TO LONG + maxsize, size +ENDOBJECT + +/* Creation constructor */ +/* Minimum size of 1, maximum 100000, default 100 */ +PROC create(sz=100) OF set + DEF p:PTR TO LONG + IF (sz>0) AND (sz<100000) -> Check size + self.maxsize:=sz + ELSE + self.maxsize:=100 + ENDIF + self.elements:=NEW p[self.maxsize] +ENDPROC + +/* Copy constructor */ +PROC copy(oldset:PTR TO set) OF set + DEF i + self.create(oldset.maxsize) -> Call create method! + FOR i:=0 TO oldset.size-1 -> Copy elements + self.elements[i]:=oldset.elements[i] + ENDFOR + self.size:=oldset.size +ENDPROC + +/* Destructor */ +PROC end() OF set + DEF p:PTR TO LONG + IF self.maxsize<>0 -> Check that it was allocated + p:=self.elements + END p[self.maxsize] + ENDIF +ENDPROC + +/* Add an element */ +PROC add(x) OF set + IF self.member(x)=FALSE -> Is it new? (Call member method!) + IF self.size=self.maxsize + Raise("full") -> The set is already full + ELSE + self.elements[self.size]:=x + self.size:=self.size+1 + ENDIF + ENDIF +ENDPROC + +/* Test for membership */ +PROC member(x) OF set + DEF i + FOR i:=0 TO self.size-1 + IF self.elements[i]=x THEN RETURN TRUE + ENDFOR +ENDPROC FALSE + +/* Test for emptiness */ +PROC empty() OF set IS self.size=0 + +/* Union (add) another set */ +PROC union(other:PTR TO set) OF set + DEF i + FOR i:=0 TO other.size-1 + self.add(other.elements[i]) -> Call add method! + ENDFOR +ENDPROC + +/* Print out the contents */ +PROC print() OF set + DEF i + WriteF('{ ') + FOR i:=0 TO self.size-1 + WriteF('\d ', self.elements[i]) + ENDFOR + WriteF('}') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/simple.e b/amigae33a/E_v3.3a/Src/Src/Guide/simple.e new file mode 100644 index 0000000..1983c62 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/simple.e @@ -0,0 +1,3 @@ +PROC main() + WriteF('My first program') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/static.e b/amigae33a/E_v3.3a/Src/Src/Guide/static.e new file mode 100644 index 0000000..c95cd89 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/static.e @@ -0,0 +1,12 @@ +PROC main() + DEF i, a[10]:ARRAY OF LONG, p:PTR TO LONG + FOR i:=0 TO 9 + a[i]:=[1, i, i*i] + /* This assignment is probably not what you want! */ + ENDFOR + FOR i:=0 TO 9 + p:=a[i] + WriteF('a[\d] is an array at address \d\n', i, p) + WriteF(' and the second element is \d\n', p[1]) + ENDFOR +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/static2.e b/amigae33a/E_v3.3a/Src/Src/Guide/static2.e new file mode 100644 index 0000000..409a52d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/static2.e @@ -0,0 +1,17 @@ +PROC main() + DEF i, a[10]:ARRAY OF LONG, p:PTR TO LONG + FOR i:=0 TO 9 + a[i]:=List(3) + /* Must check that the allocation succeeded before copying */ + IF a[i]<>NIL THEN ListCopy(a[i], [1, i, i*i], ALL) + ENDFOR + FOR i:=0 TO 9 + p:=a[i] + IF p=NIL + WriteF('Could not allocate memory for a[\d]\n', i) + ELSE + WriteF('a[\d] is an array at address \d\n', i, p) + WriteF(' and the second element is \d\n', p[1]) + ENDIF + ENDFOR +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/static3.e b/amigae33a/E_v3.3a/Src/Src/Guide/static3.e new file mode 100644 index 0000000..e4dff03 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/static3.e @@ -0,0 +1,12 @@ +PROC main() + DEF i, a[10]:ARRAY OF LONG, p:PTR TO LONG + FOR i:=0 TO 9 + a[i]:=NEW [1, i, i*i] + /* a[i] is now dynamically allocated */ + ENDFOR + FOR i:=0 TO 9 + p:=a[i] + WriteF('a[\d] is an array at address \d\n', i, p) + WriteF(' and the second element is \d\n', p[1]) + ENDFOR +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/timing.e b/amigae33a/E_v3.3a/Src/Src/Guide/timing.e new file mode 100644 index 0000000..641db68 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/timing.e @@ -0,0 +1,60 @@ +OPT LARGE + +MODULE 'dos/dos' + +CONST TICKS_PER_MINUTE=TICKS_PER_SECOND*60, LOTS_OF_TIMES=500000 + +DEF x, y, offset + +PROC fred(n) + DEF i + i:=n+x +ENDPROC + +/* Repeat evaluation of an expression */ +PROC repeat(exp) + DEF i + FOR i:=0 TO LOTS_OF_TIMES + Eval(exp) /* Evaluate the expresssion */ + ENDFOR +ENDPROC + +/* Time an expression, and set-up offset if not done already */ +PROC test(exp, message) + DEF t + IF offset=0 THEN offset:=time(`0) /* Calculate offset */ + t:=time(exp) + WriteF('\s:\t\d ticks\n', message, t-offset) +ENDPROC + +/* Time the repeated calls, and calculate number of ticks */ +PROC time(x) + DEF ds1:datestamp, ds2:datestamp + Forbid() + DateStamp(ds1) + repeat(x) + DateStamp(ds2) + Permit() + IF CtrlC() THEN CleanUp(1) +ENDPROC ((ds2.minute-ds1.minute)*TICKS_PER_MINUTE)+ds2.tick-ds1.tick + +PROC main() + x:=9999 + y:=1717 + test(`x+y, 'Addition') + test(`y-x, 'Subtraction') + test(`x*y, 'Multiplication') + test(`x/y, 'Division') + test(`x OR y, 'Bitwise OR') + test(`x AND y, 'Bitwise AND') + test(`x=y, 'Equality') + test(`x Make a module of these classes +OPT EXPORT -> Export everything + +/* ------------------------------- */ +/* The (abstract) base class, tree */ +/* ------------------------------- */ + +OBJECT tree PRIVATE -> All data is private + left:PTR TO tree, right:PTR TO tree +ENDOBJECT + +/* Count nodes */ +PROC nodes() OF tree + DEF tot=1 + IF self.left THEN tot:=tot+self.left.nodes() + IF self.right THEN tot:=tot+self.right.nodes() +ENDPROC tot + +/* Count leaves, and optionally show them */ +PROC leaves(show=FALSE) OF tree + DEF tot=0 + IF self.left + tot:=tot+self.left.leaves(show) + ENDIF + IF self.right + tot:=tot+self.right.leaves(show) + ELSEIF self.left=NIL -> Both NIL, so a leaf + IF show THEN self.print_node() + tot++ + ENDIF +ENDPROC tot + +/* Abstract method, add */ +PROC add(x) OF tree IS EMPTY + +/* Abstract method, print_node */ +PROC print_node() OF tree IS EMPTY + +/* Print the tree in order, left to right */ +PROC print() OF tree + IF self.left THEN self.left.print() + self.print_node() + IF self.right THEN self.right.print() +ENDPROC + + +/* ---------------------- */ +/* The integer_tree class */ +/* ---------------------- */ + +/* Inherit tree */ +OBJECT integer_tree OF tree PRIVATE -> All data is private + int +ENDOBJECT + +/* Constructor, start with one integer */ +PROC create(i) OF integer_tree + self.int:=i +ENDPROC + +/* Add an integer */ +PROC add(i) OF integer_tree + DEF p:PTR TO integer_tree + IF i < self.int + IF self.left + self.left.add(i) + ELSE + self.left:=NEW p.create(i) + ENDIF + ELSEIF i > self.int + IF self.right + self.right.add(i) + ELSE + self.right:=NEW p.create(i) + ENDIF + ENDIF +ENDPROC + +/* Print a node */ +PROC print_node() OF integer_tree + WriteF('\d ', self.int) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Guide/while.e b/amigae33a/E_v3.3a/Src/Src/Guide/while.e new file mode 100644 index 0000000..d18bce6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Guide/while.e @@ -0,0 +1,10 @@ +PROC main() + DEF x,y + x:=1 + y:=2 + WHILE (x<10) AND (y<10) + WriteF('x is \d and y is \d\n', x, y) + x:=x+2 + y:=y+2 + ENDWHILE +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/HelloWorld.e b/amigae33a/E_v3.3a/Src/Src/HelloWorld.e new file mode 100644 index 0000000..c55d09d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/HelloWorld.e @@ -0,0 +1,5 @@ +/* nominated for Most Boring Example */ + +PROC main() + WriteF('Hello, World!\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/HelloWorld.e.info b/amigae33a/E_v3.3a/Src/Src/HelloWorld.e.info new file mode 100644 index 0000000000000000000000000000000000000000..1eee0e7b7e1fd4ac9a2485ba51f2e8131ececbf6 GIT binary patch literal 1802 zcmeHGL5jja5bQ~UUXVB^~hz9^YuyIey5S$Fu9`5|S497@hV}P@u3tR>Jz@MNG=)n*u#Et+oF=jhqM~#u%C_-fH zzhUl+ZNPYLBHvg0SuD%oy!@Evy+?hQWF(ht Opening our public screen with a shell on it ... [nothing fancy] + +OPT OSVERSION=37 + +MODULE 'intuition/screens' + +ENUM OKAY,NOSCREEN,NOSIG + +PROC main() HANDLE + DEF s=NIL,sig=-1,name + IF (s:=OpenScreenTagList(0, /* get ourselves a public screen */ + [SA_DEPTH,4, + SA_DISPLAYID,$8000, + SA_PUBNAME,name:='PublicShell', + SA_TITLE,name, + SA_PUBSIG,IF (sig:=AllocSignal(-1))=NIL THEN Raise(NOSIG) ELSE sig, + SA_PUBTASK,NIL, + 0,0]))=NIL THEN Raise(NOSCREEN) + PubScreenStatus(s,0) /* make it available */ + SetDefaultPubScreen(name) + SetPubScreenModes(SHANGHAI) + Execute('NewShell WINDOW CON:10/20/400/100/bla',NIL,NIL) + /* other applications can use our screen also. + if we just want our shell on it, turn it private again */ + Wait(Shl(1,sig)) /* wait until all windows closed */ + SetDefaultPubScreen(NIL) /* workbench is default again */ +EXCEPT DO + IF s THEN CloseS(s) + IF sig>=0 THEN FreeSignal(sig) + IF exception=NOSCREEN + WriteF('Could not open screen!\n') + ELSEIF exception=NOSIG + WriteF('No signal available!\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Intui/ScrollerWindow.e b/amigae33a/E_v3.3a/Src/Src/Intui/ScrollerWindow.e new file mode 100644 index 0000000..e8b7810 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Intui/ScrollerWindow.e @@ -0,0 +1,308 @@ +/* ScrollerWindow.e + + Translated by Wouter from excellent example scrollerwindow.c + by Christoph Feck, TowerSystems (feck@informatik.uni-kl.de) + + needs E v2.1b / v39 emodules with fixed icclass.m to compile + +*/ + +MODULE 'exec/memory', 'exec/libraries', 'utility', 'utility/tagitem', + 'intuition/intuition', 'intuition/imageclass', 'intuition/screens', + 'intuition/classes', 'intuition/icclass', 'intuition/gadgetclass', + 'intuition/imageclass', + 'graphics/gfx', 'graphics/text', 'graphics/rastport' + +DEF screen:PTR TO screen,dri:PTR TO drawinfo,v39,bitmap:PTR TO bitmap + +DEF horizgadget:PTR TO object,vertgadget:PTR TO object, + leftgadget:PTR TO object,rightgadget:PTR TO object, + upgadget:PTR TO object,downgadget:PTR TO object + +ENUM HORIZ_GID=1,VERT_GID,LEFT_GID,RIGHT_GID,UP_GID,DOWN_GID + +DEF window:PTR TO window + +-> these are actually PTR TO object too + +DEF sizeimage:PTR TO image,leftimage:PTR TO image,rightimage:PTR TO image, + upimage:PTR TO image,downimage:PTR TO image + +DEF htotal,vtotal,hvisible,vvisible + +PROC max(x,y) IS IF x>y THEN x ELSE y +PROC min(x,y) IS IF x1), + TAG_MORE,taglist]) + +PROC newbuttonobject(image:PTR TO object,taglist) IS + NewObjectA(NIL,'buttongclass', + [ICA_TARGET,ICTARGET_IDCMP,GA_IMAGE,image,TAG_MORE,taglist]) + +PROC openscrollerwindow(taglist) + DEF resolution,topborder,sf:PTR TO textattr,w,h,bw,bh,rw,rh,gw,gh,gap + resolution:=sysisize() + sf:=screen.font + topborder:=screen.wbortop+sf.ysize+1 + w:=sizeimage.width + h:=sizeimage.height + bw:=IF resolution=SYSISIZE_LOWRES THEN 1 ELSE 2 + bh:=IF resolution=SYSISIZE_HIRES THEN 2 ELSE 1 + rw:=IF resolution=SYSISIZE_HIRES THEN 3 ELSE 2 + rh:=IF resolution=SYSISIZE_HIRES THEN 2 ELSE 1 + gh:=max(leftimage.height,h) + gh:=max(rightimage.height,gh) + gw:=max(upimage.width,w) + gw:=max(downimage.width,gw) + gap:=1 + horizgadget:=newpropobject(FREEHORIZ, + [GA_LEFT,rw+gap, + GA_RELBOTTOM,bh-gh+2, + GA_RELWIDTH,(-gw)-gap-leftimage.width-rightimage.width-rw-rw, + GA_HEIGHT,gh-bh-bh-2, + GA_BOTTOMBORDER,TRUE, + GA_ID,HORIZ_GID, + PGA_TOTAL,htotal, + PGA_VISIBLE,hvisible, + NIL]) + vertgadget:=newpropobject(FREEVERT, + [GA_RELRIGHT,bw-gw+3, + GA_TOP,topborder+rh, + GA_WIDTH,gw-bw-bw-4, + GA_RELHEIGHT,(-topborder)-h-upimage.height-downimage.height-rh-rh, + GA_RIGHTBORDER,TRUE, + GA_PREVIOUS,horizgadget, + GA_ID,VERT_GID, + PGA_TOTAL,vtotal, + PGA_VISIBLE,vvisible, + NIL]) + leftgadget:=newbuttonobject(leftimage, + [GA_RELRIGHT,(1)-leftimage.width-rightimage.width-gw, + GA_RELBOTTOM,(1)-leftimage.height, + GA_BOTTOMBORDER,TRUE, + GA_PREVIOUS,vertgadget, + GA_ID,LEFT_GID, + NIL]) + rightgadget:=newbuttonobject(rightimage, + [GA_RELRIGHT,(1)-rightimage.width-gw, + GA_RELBOTTOM,(1)-rightimage.height, + GA_BOTTOMBORDER,TRUE, + GA_PREVIOUS,leftgadget, + GA_ID,RIGHT_GID, + NIL]) + upgadget:=newbuttonobject(upimage, + [GA_RELRIGHT,(1)-upimage.width, + GA_RELBOTTOM,(1)-upimage.height-downimage.height-h, + GA_RIGHTBORDER,TRUE, + GA_PREVIOUS,rightgadget, + GA_ID,UP_GID, + NIL]) + downgadget:=newbuttonobject(downimage, + [GA_RELRIGHT,(1)-downimage.width, + GA_RELBOTTOM,(1)-downimage.height-h, + GA_RIGHTBORDER,TRUE, + GA_PREVIOUS,upgadget, + GA_ID,DOWN_GID, + NIL]) + IF downgadget + window:=OpenWindowTagList(NIL, + [WA_GADGETS,horizgadget, + WA_MINWIDTH,max(80,gw+gap+leftimage.width+rightimage.width+rw+rw+KNOBHMIN), + WA_MINHEIGHT,max(50,topborder+h+upimage.height+downimage.height+rh+rh+KNOBVMIN), + TAG_MORE,taglist]) + ENDIF +ENDPROC + +PROC closescrollerwindow() + IF window THEN CloseWindow(window) + DisposeObject(horizgadget) + DisposeObject(vertgadget) + DisposeObject(leftgadget) + DisposeObject(rightgadget) + DisposeObject(upgadget) + DisposeObject(downgadget) +ENDPROC + +PROC recalchvisible() IS window.width-window.borderleft-window.borderright +PROC recalcvvisible() IS window.height-window.bordertop-window.borderbottom + +PROC updateprop(gadget:PTR TO object,attr,value) + SetGadgetAttrsA(gadget,window,NIL,[attr,value,NIL]) +ENDPROC + +PROC copybitmap() + DEF srcx,srcy + GetAttr(PGA_TOP,horizgadget,{srcx}) + GetAttr(PGA_TOP,vertgadget,{srcy}) + BltBitMapRastPort(bitmap,srcx,srcy,window.rport,window.borderleft, + window.bordertop,min(htotal,hvisible),min(vtotal,vvisible),$C0) +ENDPROC + +PROC updatescrollerwindow() + hvisible:=recalchvisible() + updateprop(horizgadget,PGA_VISIBLE,hvisible) + vvisible:=recalcvvisible() + updateprop(vertgadget,PGA_VISIBLE,vvisible) + copybitmap() +ENDPROC + +PROC handlescrollerwindow() + DEF imsg:PTR TO intuimessage,quit=FALSE,oldtop,cl,v + WHILE quit=FALSE + WHILE (quit=FALSE) AND (imsg:=GetMsg(window.userport)) + cl:=imsg.class + SELECT cl + CASE IDCMP_CLOSEWINDOW + quit:=TRUE + CASE IDCMP_NEWSIZE + updatescrollerwindow() + CASE IDCMP_REFRESHWINDOW + BeginRefresh(window) + copybitmap() + EndRefresh(window,TRUE) + CASE IDCMP_IDCMPUPDATE + v:=GetTagData(GA_ID,0,imsg.iaddress) + SELECT v + CASE HORIZ_GID + copybitmap() + CASE VERT_GID + copybitmap() + CASE LEFT_GID + GetAttr(PGA_TOP,horizgadget,{oldtop}) + IF oldtop>0 + updateprop(horizgadget,PGA_TOP,oldtop-1) + copybitmap() + ENDIF + CASE RIGHT_GID + GetAttr(PGA_TOP,horizgadget,{oldtop}) + IF oldtop<(htotal-hvisible) + updateprop(horizgadget,PGA_TOP,oldtop+1) + copybitmap() + ENDIF + CASE UP_GID + GetAttr(PGA_TOP,vertgadget,{oldtop}) + IF oldtop>0 + updateprop(vertgadget,PGA_TOP,oldtop-1) + copybitmap() + ENDIF + CASE DOWN_GID + GetAttr(PGA_TOP,vertgadget,{oldtop}) + IF oldtop<(vtotal-vvisible) + updateprop(vertgadget,PGA_TOP,oldtop+1) + copybitmap() + ENDIF + ENDSELECT + ENDSELECT + ReplyMsg(imsg) + ENDWHILE + IF quit=FALSE THEN WaitPort(window.userport) + ENDWHILE +ENDPROC + +PROC doscrollerwindow() + DEF r:PTR TO rastport + IF screen:=LockPubScreen(NIL) + hvisible:=htotal:=screen.width + vvisible:=vtotal:=screen.height + r:=screen.rastport + IF bitmap:=createbitmap(htotal,vtotal,bitmapdepth(r.bitmap),0,r.bitmap) + BltBitMap(r.bitmap,0,0,bitmap,0,0,htotal,vtotal,$C0,-1,NIL) + IF dri:=GetScreenDrawInfo(screen) + sizeimage:=newimageobject(SIZEIMAGE) + leftimage:=newimageobject(LEFTIMAGE) + rightimage:=newimageobject(RIGHTIMAGE) + upimage:=newimageobject(UPIMAGE) + downimage:=newimageobject(DOWNIMAGE) + IF (sizeimage<>0) AND (leftimage<>0) AND (rightimage<>0) AND (upimage<>0) AND (downimage<>0) + openscrollerwindow([WA_PUBSCREEN,screen, + WA_TITLE,'ScrollerWindow', + WA_FLAGS,WFLG_CLOSEGADGET OR WFLG_SIZEGADGET OR WFLG_DRAGBAR OR WFLG_DEPTHGADGET OR WFLG_SIMPLE_REFRESH OR WFLG_ACTIVATE OR WFLG_NEWLOOKMENUS, + WA_IDCMP,IDCMP_CLOSEWINDOW OR IDCMP_NEWSIZE OR IDCMP_REFRESHWINDOW OR IDCMP_IDCMPUPDATE, + WA_INNERWIDTH,htotal, + WA_INNERHEIGHT,vtotal, + WA_MAXWIDTH,-1, + WA_MAXHEIGHT,-1, + NIL]) + IF window + updatescrollerwindow() + handlescrollerwindow() + ELSE + WriteF('no window!\n') + ENDIF + closescrollerwindow() + ELSE + WriteF('no images!\n') + ENDIF + DisposeObject(sizeimage) + DisposeObject(leftimage) + DisposeObject(rightimage) + DisposeObject(upimage) + DisposeObject(downimage) + FreeScreenDrawInfo(screen,dri) + ELSE + WriteF('no draw infos!\n') + ENDIF + WaitBlit() + deletebitmap(bitmap) + ELSE + WriteF('no bitmap!\n') + ENDIF + UnlockPubScreen(NIL,screen) + ELSE + WriteF('no pub screen!\n') + ENDIF +ENDPROC + +PROC main() + v39:=KickVersion(39) + IF utilitybase:=OpenLibrary('utility.library',37) + doscrollerwindow() + CloseLibrary(utilitybase) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Intui/Talk2Boopsi.e b/amigae33a/E_v3.3a/Src/Src/Intui/Talk2Boopsi.e new file mode 100644 index 0000000..32f3159 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Intui/Talk2Boopsi.e @@ -0,0 +1,29 @@ +/* Talk2Boopsi.e - free translation of Talk2Boopsi.c from RKRM libraries */ + +MODULE 'intuition/intuition', 'intuition/gadgetclass', 'intuition/icclass' + +DEF w:PTR TO window, prop:PTR TO gadget, integer:PTR TO gadget + +PROC main() + IF w:=OpenWindowTagList(NIL,[WA_FLAGS,$E,WA_IDCMP,$200,WA_WIDTH,120, + WA_HEIGHT,150,0]) + IF prop:=NewObjectA(NIL,'propgclass',[GA_ID,1,GA_TOP,w.bordertop+5, + GA_LEFT,w.borderleft+5,GA_WIDTH,10,GA_HEIGHT,80,ICA_MAP,[PGA_TOP, + STRINGA_LONGVAL,0],PGA_TOTAL,100,PGA_TOP,25,PGA_VISIBLE,10, + PGA_NEWLOOK,TRUE,0]) + IF integer:=NewObjectA(NIL,'strgclass',[GA_ID,2,GA_TOP,w.bordertop+5, + GA_LEFT,w.borderleft+30,GA_WIDTH,40,GA_HEIGHT,18,ICA_MAP, + [STRINGA_LONGVAL,PGA_TOP,0],ICA_TARGET,prop,GA_PREVIOUS,prop, + STRINGA_LONGVAL,25,STRINGA_MAXCHARS,3,0]) + SetGadgetAttrsA(prop,w,NIL,[ICA_TARGET,integer,0]) + AddGList(w,prop,-1,-1,NIL) + RefreshGList(prop,w,NIL,-1) + WaitIMessage(w) + RemoveGList(w,prop,-1) + DisposeObject(integer) + ENDIF + DisposeObject(prop) + ENDIF + CloseWindow(w) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Intui/gradient.e b/amigae33a/E_v3.3a/Src/Src/Intui/gradient.e new file mode 100644 index 0000000..b126951 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Intui/gradient.e @@ -0,0 +1,32 @@ +-> gradientslider in E! + +MODULE 'intuition/intuition', 'intuition/gadgetclass', 'intuition/icclass', + 'gadgets/gradientslider' + +DEF w:PTR TO window, grad:PTR TO gadget, gradbase, class, val + +PROC main() + IF w:=OpenWindowTagList(NIL,[WA_FLAGS,$E,WA_IDCMP,$268,WA_WIDTH,400,WA_HEIGHT,80,WA_TITLE,'Gradients in E!',0]) + SetStdRast(w.rport) + IF gradbase:=OpenLibrary('gadgets/gradientslider.gadget',39) + IF grad:=NewObjectA(NIL,'gradientslider.gadget',[GA_TOP,20,GA_LEFT,20,GA_WIDTH,350,GA_HEIGHT,30,GA_ID,1,GRAD_PENARRAY,[0,7,-1]:INT,GRAD_KNOBPIXELS,20,0]) + AddGList(w,grad,-1,-1,NIL) + RefreshGList(grad,w,NIL,-1) + WHILE (class:=WaitIMessage(w))<>IDCMP_CLOSEWINDOW + GetAttr(GRAD_CURVAL,grad,{val}) + TextF(20,60,'gradient value = \z$\h[4]',val) + ENDWHILE + RemoveGList(w,grad,-1) + DisposeObject(grad) + ELSE + WriteF('Could not create GradientSlider!\n') + ENDIF + CloseLibrary(gradbase) + ELSE + WriteF('Could not open "gradientslider.gadget"\n') + ENDIF + CloseWindow(w) + ELSE + WriteF('No Window!\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/EYacc/bcalc.y b/amigae33a/E_v3.3a/Src/Src/Lang/EYacc/bcalc.y new file mode 100644 index 0000000..bd7fcfb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/EYacc/bcalc.y @@ -0,0 +1,70 @@ +%{ + +/* calculator in E using E-Yacc: + + binary operators: + - * / % & | (precedence in this order) + unary operators: - ~ + grouping: ( ) + assignment: var = exp (vars 'a' .. 'f') + values: intnum var + exit: Q + +*/ + +DEF vars:PTR TO LONG + +%} + +%start stmt + +%token DIGIT LETTER QUIT + +%left '|' +%left '&' +%left '+' '-' +%left '*' '/' '%' +%left UMINUS '~' + +%% + +stmt : expr { PrintF('result: \d\n> ',$1); Flush(stdout) } + | LETTER '=' expr { IF vars=NIL THEN NEW vars[26]; vars[$1]:=$3; PrintF('> '); Flush(stdout) } + | QUIT { CleanUp(0) } + ; + +expr : '(' expr ')' { $$:=$2 } + | expr '+' expr { $$:=$1+$3 } + | expr '-' expr { $$:=$1-$3 } + | expr '*' expr { $$:=$1*$3 } + | expr '/' expr { $$:=$1/$3 } + | expr '%' expr { $$:=Mod($1,$3) } + | expr '|' expr { $$:=$1 OR $3 } + | expr '&' expr { $$:=$1 AND $3 } + | '~' expr { $$:=Not($2) } + | '-' expr %prec UMINUS { $$:=-$2 } + | LETTER { $$:=vars[$1] } + | number + ; + +number : DIGIT { $$:=$1 } + | number DIGIT { $$:=10*$1+$2 } + ; + +%% + +PROC yylex() + DEF c + WHILE (c:=FgetC(stdin))=" " DO NOP + IF c="\n" THEN RETURN 0 + IF (c="Q") OR (c=-1) THEN RETURN QUIT + IF (c>="a") AND (c<="z") THEN RETURN LETTER,c-"a" + IF (c>="0") AND (c<="9") THEN RETURN DIGIT,c-"0" +ENDPROC c + +PROC yyerror(n) + IF n=YYERRSTACK + PrintF('parse stack overflow!\n> ') + ELSEIF n=YYERRPARSE + PrintF('parse error!\n> ') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/EYacc/calcmain.e b/amigae33a/E_v3.3a/Src/Src/Lang/EYacc/calcmain.e new file mode 100644 index 0000000..1aa165e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/EYacc/calcmain.e @@ -0,0 +1,10 @@ +MODULE '*yyparse' + +PROC main() + Flush(stdin) + PutStr('E-Yacc Calc\n> ') + Flush(stdout) + LOOP + yyparse() + ENDLOOP +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Elex.e b/amigae33a/E_v3.3a/Src/Src/Lang/Elex.e new file mode 100644 index 0000000..af68121 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Elex.e @@ -0,0 +1,193 @@ +-> Tiny E Lexical Analyzer. Of little use sofar, but nice example + +OPT REG=5 + +MODULE 'tools/ctype', 'tools/file', 'class/hash' + +DEF src_begin=NIL, src_size, src_end, p:PTR TO CHAR, curline=1, x=" ",y, + keyhash:PTR TO hashtable,keylist:PTR TO LONG + +ENUM NONE,ER_GARBAGE,ER_STRING,ER_COMMENT + +OBJECT keylink OF hashlink + token:INT +ENDOBJECT + +PROC main() HANDLE + WriteF('Tiny E Lexical Analyzer (c) 1994 Wouter\n') + src_begin,src_size:=readfile(arg) + src_end:=(p:=src_begin)+src_size + lex_keys() + WHILE x<>256 + IF x<256 + WriteF('\c ',x) + ELSEIF x>512 + WriteF('\s ',{x}+2) + ELSEIF x>=300 + WriteF('{\s} ',keylist[x-300]) + ELSEIF x=260 + WriteF('"\s" ',y) + ELSE + WriteF('\d ',x-256) + ENDIF + x,y:=lex() + ENDWHILE + WriteF('\n') +EXCEPT DO + IF src_begin THEN freefile(src_begin) + SELECT exception + CASE NONE; WriteF('no errors.\n') + CASE "OPEN"; WriteF('no file!\n') + CASE "MEM"; WriteF('no mem!\n') + DEFAULT; printerr(exception) + ENDSELECT +ENDPROC + +PROC printerr(n) + DEF ers[200]:STRING,pos,a,b,e + b:=e:=p + WHILE b[]--<>"\n" DO NOP + b++ + WHILE e[]<>"\n" DO e++ + StrCopy(ers,b,e-b) + pos:=p-b-1 + WriteF('\nERROR: \s\nLINE: \d\n\s\n', + ListItem([ + '', + 'garbage in line', + 'unmatched \a or \q', + 'unmatched */', + '', + '', + '' + ],n),curline,ers) + IF pos>0 THEN FOR a:=1 TO pos DO WriteF(' ') + WriteF('^\n') +ENDPROC + +/*----------------------------LEX-----------------------------------*/ + +ENUM LEX_EOF=256, + LEX_EOL, + LEX_INTEGER, + LEX_FLOAT, + LEX_IDENT, + LEX_STRINGA, + LEX_STRINGQ + + +-> ; , := + - * / = > < >= <= <> ( ) : { } [ ] ^ . ` ! | ++ -- <=> :: /* */ -> + + +PROC lex() + DEF a,b,c,d,l:PTR TO keylink + LOOP + SELECT 256 OF c:=p[]++ + CASE ",","*","=","(",")","{","}","[","]","^",".","`","!","|" + RETURN c + CASE "+" + RETURN IF p[]="+" THEN p++ BUT "++" ELSE "+" + CASE "-" + IF (c:=p[])=">" + WHILE p[]++<>"\n" + ENDWHILE + curline++ + ELSEIF c="-" + p++ + RETURN "--" + ELSE + RETURN "-" + ENDIF + CASE "/" + IF p[]<>"*" THEN RETURN "/" + p++ + a:=1 + b:=p; d:=curline + REPEAT + IF (c:=b[]++)="/" + IF b[]="*" THEN b++ BUT a++ + ELSEIF c="*" + IF b[]="/" THEN b++ BUT a-- + ELSEIF c="\n" + IF b>src_end THEN Raise(ER_COMMENT) + d++ + ENDIF + UNTIL a=0 + p:=b + curline:=d + CASE ">" + RETURN IF p[]="=" THEN p++ BUT ">=" ELSE ">" + CASE "<" + IF (c:=p[])="=" + p++ + RETURN IF p[]=">" THEN p++ BUT "<=>" ELSE "<=" + ELSEIF c=">" + p++ + RETURN "<>" + ELSE + RETURN "<" + ENDIF + CASE ":" + RETURN IF (c:=p[])=":" THEN p++ BUT "::" ELSE IF c="=" THEN p++ BUT ":=" ELSE ":" + CASE ";","\n" + IF p>src_end THEN RETURN (p:=src_end) BUT LEX_EOF + curline++ + WriteF('\n[\d] ',curline) + RETURN LEX_EOL -> conditional + CASE " ", "\t" + /* whitespace, do nothing */ + CASE "0" TO "9", "$", "%" + a,b:=Val(p-1) + IF b=0 THEN RETURN c + p:=p+b-1 + RETURN LEX_INTEGER, a + CASE "a" TO "z", "A" TO "Z", "_" + a:=p-1; c:=p[] + WHILE isalnum(c) OR (c="_") DO p++ BUT c:=p[] + IF l:=keyhash.find(a,p-a) THEN RETURN l.token + NEW b[c:=p-a+1] + AstrCopy(b,a,c) + RETURN LEX_IDENT,b + CASE "\q", "\a" + a:=p + WHILE (a[]<>c) AND (a[]<>"\n") DO a++ + IF a[]="\n" THEN Raise(ER_STRING) + b:=p + p:=a+1 + RETURN IF c="\a" THEN LEX_STRINGQ ELSE LEX_STRINGA, b + DEFAULT + Raise(ER_GARBAGE) + ENDSELECT + ENDLOOP +ENDPROC + +ENUM K_PROC=300,K_ENDPROC,K_IF,K_ENDIF,K_VOID,K_WHILE,K_ENDWHILE,K_FOR, + K_ENDFOR,K_SELECT,K_CASE,K_DEFAULT,K_ENDSELECT,K_REPEAT,K_UNTIL, + K_JUMP,K_DEF,K_ELSE,K_INCBIN,K_LONG,K_INT,K_CHAR,K_INC,K_DEC,K_THEN, + K_LOOP,K_ENDLOOP,K_DO,K_AND,K_OR,K_CONST,K_OPT,K_MODULE,K_STACK, + K_EXIT,K_LARGE,K_ASM,K_NOWARN,K_TO,K_STEP,K_ARRAY,K_STRING,K_DIR, + K_PTR,K_OF,K_ELSEIF,K_LIST,K_OBJECT,K_ENDOBJECT,K_SIZEOF,K_RETURN, + K_OSVERSION,K_ENUM,K_SET,K_BUT,K_HANDLE,K_EXCEPT,K_RAISE,K_EXPORT, + K_REG,K_END,K_IS,K_NEW,K_PUBLIC,K_PRIVATE,K_SUPER + +PROC lex_keys() + DEF a,b,h,kl:PTR TO keylink,dat,datl + NEW keyhash.hashtable(HASH_NORMAL) + keylist:=[ + 'PROC','ENDPROC','IF','ENDIF','VOID','WHILE','ENDWHILE','FOR', + 'ENDFOR','SELECT','CASE','DEFAULT','ENDSELECT','REPEAT','UNTIL', + 'JUMP','DEF','ELSE','INCBIN','LONG','INT','CHAR','INC','DEC','THEN', + 'LOOP','ENDLOOP','DO','AND','OR','CONST','OPT','MODULE','STACK', + 'EXIT','LARGE','ASM','NOWARN','TO','STEP','ARRAY','STRING','DIR', + 'PTR','OF','ELSEIF','LIST','OBJECT','ENDOBJECT','SIZEOF','RETURN', + 'OSVERSION','ENUM','SET','BUT','HANDLE','EXCEPT','RAISE','EXPORT', + 'REG','END','IS','NEW','PUBLIC','PRIVATE','SUPER' + ] + FOR a:=0 TO ListLen(keylist)-1 + datl:=StrLen(dat:=keylist[a]) + b,h:=keyhash.find(dat,datl) + NEW kl + kl.token:=a+K_PROC + keyhash.add(kl,h,dat,datl) + ENDFOR +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Forth.e b/amigae33a/E_v3.3a/Src/Src/Lang/Forth.e new file mode 100644 index 0000000..7db69e9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Forth.e @@ -0,0 +1,125 @@ +/* TinyForth, a subset Forth interpreter + no functions *yet*, so may be used as funny calculator + with stack. exits on QUIT or */ + +CONST MAXSTACK=1000,MAXRSTACK=200 +ENUM NO_MES,OK,ER_UNDERFLOW,ER_OVERFLOW,ER_SYM + +DEF con=NIL,stop=FALSE,error=OK,crflag=TRUE, + inp[100]:STRING, + item[50]:STRING, item2[50]:STRING, + stack[MAXSTACK]:ARRAY OF LONG, rstack[MAXRSTACK]:ARRAY OF LONG, + sp:PTR TO LONG, rsp:PTR TO LONG + +RAISE "^C" IF CtrlC()=TRUE + +PROC main() HANDLE + con:=Open('CON:0/11/640/100/TinyForth',1005) + IF con + stdout:=con + WriteF('TinyForth interpreter v0.1 (c) 1992 by $#%!\n') + sp:=stack; rsp:=rstack + REPEAT + IF crflag=FALSE THEN WriteF('\n') + SELECT error + CASE OK; WriteF('Ok.\n') + CASE ER_UNDERFLOW; WriteF('STACK UNDERFLOW.\n') + CASE ER_OVERFLOW; WriteF('STACK OVERFLOW.\n') + CASE ER_SYM; WriteF('\s?\n',item) + ENDSELECT + WriteF('>') + ReadStr(con,inp) + CtrlC() + error:=OK; crflag:=TRUE + eval(inp) + UNTIL stop + ENDIF +EXCEPT DO + IF con THEN Close(con) +ENDPROC + +PROC eval(c) + DEF pos,end,symlong,p,i,j,k + pos:=c; end:=c+EstrLen(c) + WHILE (posR "; rpush(pop()) + CASE "R> "; push(rpop()) + CASE "R@ "; i:=rpop(); push(i); rpush(i) + + CASE "< "; push(Not(pop()<=pop())) + CASE "= "; push(pop()=pop()) + CASE "> "; push(Not(pop()>=pop())) + CASE "0< "; push(pop()<0) + CASE "0= "; push(0=pop()) + CASE "0> "; push(pop()>0) + CASE "D< "; push(Not(pop()<=pop())) + CASE "U< "; push(Not(pop()<=pop())) + CASE "NOT "; push(Not(pop())) + + CASE ". "; WriteF('\d ',pop()); crflag:=FALSE + CASE "CR "; WriteF('\n'); crflag:=TRUE + CASE "EMIT"; WriteF('\c',pop()); crflag:=FALSE + CASE "TYPE"; i:=pop(); j:=pop(); FOR k:=1 TO i DO WriteF('\c',j[]++) + CASE "SPAC"; IF Long(item2+4)="E " THEN i:=1 ELSE i:=pop(); FOR j:=1 TO i DO WriteF(' '); crflag:=FALSE + + CASE "+ "; push(pop()+pop()) + CASE "- "; i:=pop(); push(pop()-i) + CASE "* "; push(Mul(pop(),pop())) + CASE "/ "; i:=pop(); push(Div(pop(),i)) + + CASE "ABOR"; sp:=stack + CASE "QUIT"; stop:=TRUE + DEFAULT + IF Int(item)=$2E22 /* ." construction */ + crflag:=FALSE + Write(stdout,item+2,EstrLen(item)-3) + ELSE + IF item[0]="-" THEN p:=item+1 ELSE p:=item + i:=Val(p,{j}) + IF (j=0) THEN error:=ER_SYM + IF p<>item THEN i:=Mul(i,-1) + push(i) + ENDIF + ENDSELECT + ENDWHILE +ENDPROC + +PROC pop() RETURN IF sp<=stack THEN error:=ER_UNDERFLOW ELSE sp[]-- +PROC rpop() RETURN IF rsp<=rstack THEN error:=ER_UNDERFLOW ELSE rsp[]-- +PROC push(val); IF MAXSTACK*4+stack<=sp THEN error:=ER_OVERFLOW ELSE sp[]++:=val; ENDPROC +PROC rpush(val); IF MAXRSTACK*4+rstack<=rsp THEN error:=ER_OVERFLOW ELSE rsp[]++:=val; ENDPROC + +PROC getsym(p) + DEF p2 + p:=TrimStr(p) + IF p[0]="(" + p2:=InStr(p,')',0) + IF p2=-1 THEN p2:=1000 + p:=TrimStr(p+p2+1) + ENDIF + IF p[0]="." AND p[1]=34 + p2:=InStr(p,'"',2) + IF p2=-1 THEN p2:=1000 ELSE INC p2 + StrCopy(item,p,p2) + ELSE + p2:=InStr(p,' ',0) + IF p2=-1 THEN p2:=1000 + StrCopy(item,p,p2) + ENDIF +ENDPROC p+p2+1 diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Lambda.e b/amigae33a/E_v3.3a/Src/Src/Lang/Lambda.e new file mode 100644 index 0000000..f39deaf --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Lambda.e @@ -0,0 +1,74 @@ +/* lambda calc evaluator in E, makes heavy use of unification */ + +DEF nchar="a" + +ENUM ATOM,LAMBDA,APP + +PROC ev(exp) + DEF par,body,fun,arg + IF exp <=> [APP,fun,arg] + funval(fun) <=> [LAMBDA,par,body] + RETURN ev(replace(body,par,arg)) + ELSE + RETURN exp + ENDIF +ENDPROC + +PROC funval(exp) + DEF x,y + IF exp <=> [APP,x,y] + RETURN funval(ev(exp)) + ELSEIF exp <=> [ATOM,x] + RETURN funval(getdef(x)) + ELSE + RETURN exp + ENDIF +ENDPROC + +PROC replace(exp,old,new) + DEF fun,arg,par,body,a,n + IF exp <=> [APP,fun,arg] + RETURN NEW [APP,replace(fun,old,new),replace(arg,old,new)] + ELSEIF exp <=> [ATOM,a] + RETURN IF a=old THEN new ELSE exp + ELSEIF exp <=> [LAMBDA,par,body] + new <=> [ATOM,a] + IF par=a + RETURN NEW [LAMBDA,n,replace(replace(body,par,NEW [ATOM,nchar++]),old,new)] + ELSE + RETURN NEW [LAMBDA,par,replace(body,old,new)] + ENDIF + ENDIF +ENDPROC + +PROC pretty(exp) + DEF x,y + IF exp <=> [APP,x,y] + pretty(x) + PutStr(' (') + pretty(y) + PutStr(')') + ELSEIF exp <=> [LAMBDA,x,y] + PrintF('\\\c.',x) + pretty(y) + ELSEIF exp <=> [ATOM,x] + PrintF('\c',x) + ENDIF +ENDPROC + +PROC getdef(a) + SELECT a + CASE "t"; RETURN [LAMBDA,"x",[LAMBDA,"y",[ATOM,"x"]]] + CASE "f"; RETURN [LAMBDA,"x",[LAMBDA,"y",[ATOM,"y"]]] + DEFAULT; Raise() + ENDSELECT +ENDPROC + +PROC main() + DEF exp + exp:=[APP,[APP,[ATOM,"t"],[ATOM,"t"]],[ATOM,"f"]] + pretty(exp) + PutStr(' results in ') + pretty(ev(exp)) -> prints: 't (t) (f) results in t' + PutStr('\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/NGRC.e b/amigae33a/E_v3.3a/Src/Src/Lang/NGRC.e new file mode 100644 index 0000000..05797a6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/NGRC.e @@ -0,0 +1,742 @@ +/* Noise Compiler v1.0 + +Short: The noise compiler is a program that translates source files in + a type of "music programming language" into Noise/ProTracker (tm) + compatible files. + +The noise compiler reads ascii source files containing a description +of a musical piece, and then starts generating a sequence of notes by +recursively walking down your definition. finally, it will load all +samples and write all data to a ProTracker (tm) file. + +A noise grammar program (extension ".ngr") consist of one to unlimited +number of so called "rules" (it really helps if you already know something +about context free grammars). Each rule looks like: + + "->" ";" + +example: + +beat -> drum [C#,1] /* a C-flat */ + { [D,2] | [D#,2] | [Db,2] } /* D, D-sharp, D-flat */ + ( boomboom 1 ); /* index=1 */ + +every token may be separated by a whitespace, which denotes any number of +spaces/tabs/linefeeds, and comments which start with "/*" and end +with "*/", and may be nested infinitely. + +a is one or more s. an can be: + + + +will be recursively replaced by the definition of . + is optional and explained later +example: drum + + "(" ")" + +as , only an optional (default=500, range 0-1000) specifies +the chance of getting rewritten, with 0=no chance at all. +example: + +(beat) (250 beat) + +decide while generating if the defintion for "beat" gets played or +not, resp. 50% and 25% chance. + + "{" "|" ..... "}" + +any number of s may be between the {}, separated by a bar |. + is again optional, and again between 0-1000, only now +the default =1. With no weights, simply one of the s is +picked. examples: + +{ beat | boomboom | [Gb+,4] } /* chances: each 33% */ +{ 3 beat | 7 boomboom } /* chances: 30%,70% resp. */ + + + +an AmigaDos path to a sample, is an optional integer, range 0-64 +example: "samples:guitar.iff" + + "[" "," "]" + +a note specification, see below. + + + +a special effects spec., see below. + +Notes. +a is a character like: C D E F G A B +it may be followed by any number of modifiers, where: + +"#" = sharp +"b" = flat +"+" = octave up +"-" = octave down + +in general, you can get only one octave up/down, and the parser will +give an error if you write something like "E+++" +Any number of "#" and "b" are allowed, only in general you would +write "D" for "C##", or "F" for "E#" etc. Note that the current +version of the noise compiler only allows for C-major. Examples: + +C C (the one in the middle of a piano) +C#+ C-sharp one octave up +Dbb- C one octave down + +for those who are not at all familiar with classical notes, a note +may also be specified as an integer ranging from -12 to 23, with +0 being the middle C again, and negative numbers lower notes. + +the is an integer specifying the time in units spent +on playing the note, before starting the new one, range = 1-100 +A unit is about a quarter of a normal note, so a whole note should +be written "4" etc. examples: + +[C,1] +[F#,4] /* an F-sharp for one second */ + + +Sound Effects. +various souneffects may be used as an hexadecimal integer. +Such an effect only works with the next following note. +Example: + +mainpart -> $E01 drums solo drums + +puts hardware audio filter off before play. See protracker documentation +for a summary of effects. + +Indexing. +while () and {|||} are nice ways to either generate totally random music, or +just make your pieces sound more natural due to some variation, one often +wishes to have the random choices made repeated: for example, if +you design a symbol "beat" that you wish to re-use in certain parts of +your program, and the definition contains some random-variation, you +may want to have the random choices fixed for the second time you use it, +because it would sound totally random otherwise. for example, considering +the pseudo-definition of "beat" above: + +beats -> beat boomboom beat boomboom; + +this looks like a normal rhytm, but "beat" is replaced by two different +sequences of notes. with: + +beats -> beat1 boomboom2 beat1 boomboom2; + +you specify that with the first "beat", the random choices are recorded +and all others that are similar indexed will have their notes generated +according to the first. note that this doesn't work for samples, i.e: + +beats -> "bass.iff" beat1 "hihat.iff" beat1; + +will generate two exactly the same sequences, only played by different +instruments. + + +Symbols and Channels. +A symbol consists of any number of lowercase characters. As the +Amiga plays four channels simulanously, there's not one start +symbol for the grammar, but four, called: "one", "two", "three", +"four". Atleast one of these has to be defined in a grammar. +Example: + +one -> "dat:noiz/Dguitar" 20 aa1; +two -> "dat:noiz/drumz/bassdrum" aa1; + +aa -> a $E00 a $E01 a a; + +a -> { c d c c d d | d d | c d c d | c c }; + +c -> [C,1] [C#,3]; +d -> [D,2] [D,3]; + +plays the sequence "aa" simultanously over two channels, by two +different instruments, with volumes 20 and 64. the sequence "aa" +consists of several instances of "a", while switching filter +on/off. "a" consist of 4 possible sequences, which in turn +consist of notes to be played. (NOTE: don't try these examples, +they no pieces of real music, just "examples") + + +Designing Tunes. +For example, for a small guitar tune, we would start with +a defintion of some notes, a and b + +a -> [D,1] [E,3]; +b -> [D,1] [D#,7]; + +Then, we would combine them into a sequence: + +c -> a a a b; + +Finally, we play those over channel one, and define a sample: + +one -> guitar c c c a [C,16]; /* just one channel */ + +/* our set of instruments */ +guitar -> "dat:noiz/Dguitar"; + +note that notes get played by a certain instrument from the point it +is encountered in the grammar. + + +Using Randomness. +You may use randomness to bring subtle variations into your music, +for example, with: + +mynote -> { 10 [D,2] | 1 [D#,2] | 1 [Db,2] }; + +we define a note that is played like a "D" most of the time, but +occasionally flat or sharp. We can easily do the same thing with +the duration, or even with the order a certain sequence gets played. + +*/ + +OBJECT sym /* primairy structure of rewrite symbols */ + next,type,name,rptr +ENDOBJECT + +OBJECT rlist /* linked list structure for grammar */ + next,type,index,info +ENDOBJECT + +OBJECT optset /* structure for storing { | | } exp. */ + next,rptr,weight +ENDOBJECT + +OBJECT sample /* all data about a given sample */ + path,len,adr,vol +ENDOBJECT + +OBJECT i /* indexing of rewritten trees */ + start,len,isym +ENDOBJECT + +ENUM SYM,OPTSET,OPTION,NOTE,SAMPLE,SFX /* rlist.type */ +ENUM NOTYPE,REWRITE /* sym.type */ +ENUM NOMEM,NOFILE,NOFORM,NOGRAM,STACKFLOW, /* errors */ + BADSTRUCTURE,BREAK,WRITEMOD,READSAMPLE + +CONST MAXINDEX=1000,MAXROWS=64*4*64,MAXDURATION=100 +CONST MAXDATA=MAXROWS*4,MAXSAMPLE=31,MAXNOTE=23,MINNOTE=-12 +CONST PARSE_ER=100,GEN_ER=200,MASK=$0FFF0FFF + +RAISE NOMEM IF New()=NIL, /* define exceptions */ + NOMEM IF String()=NIL, + STACKFLOW IF FreeStack()<1000, + BREAK IF CtrlC()=TRUE + +DEF buf,flen,p,tokeninfo,symlist=NIL:PTR TO sym,ltoken=-1,numsample=0, + notes,np:PTR TO LONG,maxrows=0,cursample=0,cursfx=0,curglob=0,end, + timings:PTR TO INT,fh=NIL,notevals:PTR TO LONG + +DEF sdata[32]:ARRAY OF sample, + itab[MAXINDEX]:ARRAY OF i, + channel[4]:ARRAY OF i, + infile[100]:STRING,outfile[100]:STRING + +PROC main() HANDLE + WriteF('Noise Compiler v1.0\n') + WriteF('Translates NoiseGrammar programs into ProTracker modules!\n') + readgrammar() + WriteF('grammar "\s" loaded. Parsing...\n',infile) + parsegrammar() + WriteF('Grammar parsed succesfully. Generating...\n') + generate() + WriteF('Noise generated. Now loading samples...\n') + loadsamples() + WriteF('Now saving to file "\s".\n',outfile) + writemodule() + WriteF('done.\n') +EXCEPT + IF fh THEN Close(fh) /* lowest level exception handler: */ + WriteF('Terminating: ') /* general error report */ + SELECT exception + CASE NOFILE; WriteF('Could not load "\s" grammar file!\n',infile) + CASE NOMEM; WriteF('Not enough memory!\n') + CASE NOFORM; WriteF('Grammar format error!\n') + CASE STACKFLOW; WriteF('Stack overflow! (too heavy recursion?)\n') + CASE BADSTRUCTURE; WriteF('Problems while generating.\n') + CASE NOGRAM; WriteF('No rules rewritten!\n') + CASE BREAK; WriteF('Stopped by user\n') + CASE WRITEMOD; WriteF('Unable to write PT module "\s"!\n',outfile) + CASE READSAMPLE; WriteF('Unable to read sample(s)!\n') + ENDSELECT + DeleteFile(outfile) +ENDPROC + +PROC readgrammar() + StrCopy(infile,arg,ALL) + StrAdd(infile,'.ngr',ALL) /* '#?.ngr' = NoizGRammar */ + StrCopy(outfile,arg,ALL) /* '#?.mod' = ProTracker format */ + StrAdd(outfile,'.mod',ALL) + IF (flen:=FileLength(infile))<1 THEN Raise(NOFILE) + IF (fh:=Open(infile,OLDFILE))=NIL THEN Raise(NOFILE) + IF Read(fh,buf:=New(flen+1),flen)<>flen THEN Raise(NOFILE) + Close(fh) + fh:=NIL + buf[flen]:=";" /* for parser */ +ENDPROC + +/* this is the parser part. we use a simple but powerfull top-down + parser, and build our syntax tree here. */ + +ENUM ER_UNTOKEN=PARSE_ER,ER_UNEXPECTED,ER_QUOTE,ER_SYMEXP,ER_DOUBLE, + ER_ARROWEXP,ER_RPARENTHEXP,ER_RBRACEEXP,ER_EMPTY,ER_EOLEXP,ER_RANGE, + ER_COMMENT,ER_UNDEF,ER_RBRACKETEXP,ER_MAXSAMPLE,ER_NOSAMPLE, + ER_INTEGEREXP,ER_COMMAEXP,ER_NOTEEXP + +ENUM EOF,EOL,ARROW,BAR,COMMA, /* ; -> | , */ + RSYM,INTEGER,HEXINTEGER, /* sym 100 $E01 */ + ISTRING,NOTEVAL, /* "" C#+ */ + LBRACE,RBRACE,LPARENTH, /* { } ( */ + RPARENTH,LBRACKET,RBRACKET /* ) [ ] */ + +PROC parsegrammar() HANDLE + DEF end,spot,sl:PTR TO sym,s,i + notevals:=[9,11,0,2,4,5,7] + p:=buf + WHILE parserule() DO NOP + p:=NIL + IF (sl:=symlist)=NIL THEN Raise(NOGRAM) + IF numsample=0 THEN Raise(ER_NOSAMPLE) + REPEAT + IF sl.type=NOTYPE /* check for undefined symbols */ + s:=sl.name + Raise(ER_UNDEF) + ENDIF + UNTIL (sl:=sl.next)=NIL +EXCEPT /* re-throw if unknown exception */ + IF exception>=PARSE_ER THEN WriteF('ERROR: ') ELSE Raise(exception) + WriteF(ListItem(['Unexpected lexical item\n', + 'Unexpected characters in line!\n', + 'Unmatched quote "\n', + 'Symbol expected\n', + 'Double definition of symbol\n', /* language errors */ + '"->" expected\n', + '")" expected\n', + '"}" expected\n', + 'Empty rewrite-list\n', + 'End of rule expected\n', + 'Integer/Note value out of range\n', + 'Incorrectly nested comment(s)\n', + 'No rule defined for symbol "\s"\n', + '"]" expected\n', + 'Maximum of 32 samples exceeded\n', + 'Grammar needs atleast one sample\n', + 'Integer expected\n', + '"," expected\n', + 'Note expected'],exception-PARSE_ER),s) + IF p /* display very nice error indication */ + IF p[-1]=";" THEN DEC p + spot:=p + WHILE (p[]--<>";") AND (p[]<>10) AND (p<>buf) DO NOP + INC p + spot:=spot-p+5 + end:=p + WHILE (end[]<>";") AND (end[]++<>10) DO NOP + end[]--:=0 + WriteF('LINE: \s\n',p) + FOR i:=1 TO spot DO WriteF(' ') + WriteF('^\n') + ENDIF + Raise(NOFORM) +ENDPROC + +PROC parserule() + DEF token,csym:PTR TO sym + IF (token:=gettoken())=EOF + RETURN FALSE + ELSEIF token=RSYM + csym:=tokeninfo + IF csym.type<>NOTYPE THEN Raise(ER_DOUBLE) + IF gettoken()<>ARROW THEN Raise(ER_ARROWEXP) + csym.rptr:=parseitemlist() + csym.type:=REWRITE + IF gettoken()<>EOL THEN Raise(ER_EOLEXP) + ELSE + Raise(ER_SYMEXP) + ENDIF +ENDPROC TRUE + +PROC parseitemlist() + DEF item:PTR TO rlist,prev:PTR TO rlist,ilist=NIL + prev:={ilist} + WHILE (item:=parseitem())<>NIL + prev.next:=item + prev:=item + ENDWHILE + IF ilist=NIL THEN Raise(ER_EMPTY) +ENDPROC ilist + +PROC parseitem() + DEF token,item:PTR TO rlist,t2,prev:PTR TO optset, + curr:PTR TO optset,olist,totalw=0 + token:=gettoken() + IF token=RSYM + item:=New(SIZEOF rlist) + item.type:=SYM + item.info:=tokeninfo + IF (t2:=gettoken())=INTEGER + item.index:=checkinfo(1,MAXINDEX-1) + ELSE + putback(t2) + item.index:=0 + ENDIF + ELSEIF token=ISTRING + item:=New(SIZEOF rlist) + item.type:=SAMPLE + sdata[numsample].path:=tokeninfo + IF (t2:=gettoken())=INTEGER + sdata[numsample].vol:=checkinfo(0,64) + ELSE + putback(t2) + sdata[numsample].vol:=64 + ENDIF + item.info:=numsample++ + IF numsample=MAXSAMPLE THEN Raise(ER_MAXSAMPLE) + ELSEIF token=LBRACE /* parse { | | ... } */ + item:=New(SIZEOF rlist) + item.type:=OPTSET + prev:={olist} + REPEAT + curr:=New(SIZEOF optset) + IF (token:=gettoken())=INTEGER /* check for weight */ + curr.weight:=checkinfo(0,1000) + ELSE + curr.weight:=1 + putback(token) + ENDIF + totalw:=totalw+curr.weight + curr.rptr:=parseitemlist() + prev.next:=curr + prev:=curr + UNTIL (token:=gettoken())<>BAR + IF token<>RBRACE THEN Raise(ER_RBRACEEXP) + item.info:=olist + item.index:=totalw /* we store weight here */ + ELSEIF token=LPARENTH + item:=New(SIZEOF rlist) /* parse ( ) */ + item.type:=OPTION + IF (token:=gettoken())=INTEGER /* check for weight */ + item.index:=checkinfo(0,1000) + ELSE + item.index:=500 + putback(token) + ENDIF + item.info:=parseitemlist() + IF gettoken()<>RPARENTH THEN Raise(ER_RPARENTHEXP) + ELSEIF token=LBRACKET + item:=New(SIZEOF rlist) /* parse [note,duration] */ + item.type:=NOTE + token:=gettoken() + IF (token<>INTEGER) AND (token<>NOTEVAL) THEN Raise(ER_NOTEEXP) + item.info:=checkinfo(MINNOTE,MAXNOTE) + IF gettoken()<>COMMA THEN Raise(ER_COMMAEXP) + IF gettoken()<>INTEGER THEN Raise(ER_INTEGEREXP) + item.index:=checkinfo(1,MAXDURATION) + IF gettoken()<>RBRACKET THEN Raise(ER_RBRACKETEXP) + ELSEIF token=HEXINTEGER + item:=New(SIZEOF rlist) /* parse $SFX */ + item.type:=SFX + item.info:=checkinfo(0,$FFF) + ELSEIF (token=EOL) OR (token=RBRACE) OR (token=RPARENTH) OR (token=BAR) + putback(token) + RETURN NIL + ELSE + Raise(ER_UNTOKEN) + ENDIF +ENDPROC item + +/* the lexical analyser: called by the parser each time it + needs a token. attribute values are in "tokeninfo". allows + for one symbol lookahead, with putback() function */ + +PROC gettoken() + DEF c,x,start,len,syml:PTR TO sym,s,depth + FreeStack(); CtrlC() + IF ltoken<>-1 + x:=ltoken + ltoken:=-1 + RETURN x + ENDIF + tokeninfo:=0 + parse: + c:=p[]++ + SELECT c + CASE ";"; RETURN IF buf+flen

p++ + IF (p[0]="/") AND (p[1]="*") + INC depth + INC p + ENDIF + IF (p[0]="*") AND (p[1]="/") + DEC depth + INC p + ENDIF + IF depth=0 + INC p + BRA parse + ENDIF + ENDWHILE + p:=x + Raise(ER_COMMENT) + ENDIF + Raise(ER_UNEXPECTED) + CASE 34 + start:=p + WHILE (p[]<>";") AND (p[]<>10) AND (p[]++<>34) DO NOP + IF p[-1]=";" THEN p-- BUT Raise(ER_QUOTE) + len:=p-start-1 + tokeninfo:=String(len) + StrCopy(tokeninfo,start,len) + RETURN ISTRING + DEFAULT + IF (c>="a") AND (c<="z") + start:=p-- + WHILE (p[]>="a") AND (p[]++<="z") DO NOP + len:=p---start + s:=String(len) + StrCopy(s,start,len) + syml:=symlist + WHILE syml + IF StrCmp(s,syml.name,ALL) THEN BRA found + syml:=syml.next + ENDWHILE + syml:=New(SIZEOF sym) + syml.next:=symlist + syml.name:=s + syml.type:=NOTYPE + symlist:=tokeninfo:=syml + RETURN RSYM + found: + tokeninfo:=syml + RETURN RSYM + ELSEIF (c>="A") AND (c<="G") + tokeninfo:=notevals[c-"A"] + LOOP + x:=p[]++ + SELECT x + CASE "+"; tokeninfo:=tokeninfo+12 /* octave up */ + CASE "-"; tokeninfo:=tokeninfo-12 /* octave down */ + CASE "#"; tokeninfo:=tokeninfo+1 /* sharp */ + CASE "b"; tokeninfo:=tokeninfo-1 /* flat */ + DEFAULT + DEC p + RETURN NOTEVAL + ENDSELECT + ENDLOOP + ELSEIF ((c>="0") AND (c<="9")) OR (c="-") OR (c="$") + tokeninfo,x:=Val(p--) + p:=p+x + RETURN IF c="$" THEN HEXINTEGER ELSE INTEGER + ENDIF + IF c>32 THEN Raise(ER_UNEXPECTED) ELSE BRA parse + ENDSELECT +ENDPROC + +PROC putback(token) + ltoken:=token +ENDPROC + +PROC checkinfo(min,max) RETURN IF (tokeninfomax) THEN + Raise(ER_RANGE) ELSE tokeninfo + +ENUM NOCHANNEL=GEN_ER,LARGESONG,CROSSINDEX + +PROC generate() HANDLE + DEF x,ci:PTR TO i,syms:PTR TO LONG,numc=0 + Rnd(-Shl(VbeamPos(),14)) /* initialise seed */ + ci:=itab + FOR x:=0 TO MAXINDEX-1 DO ci[].start++:=NIL + ci:=channel + timings:=[856,808,762,720,678,640,604,570,538,508,480,453, + 428,404,381,360,339,320,302,285,269,254,240,226, + 214,202,190,180,170,160,151,143,135,127,120,113]:INT + /* C- C#- D- D#- E- F- F#- G- G#- A- A#- B- + C C# D D# E F F# G G# A A# B + C+ C#+ D+ D#+ E+ F+ F#+ G+ G#+ A+ A#+ B+ */ + WriteF('s\d\n',MAXDURATION*4+100+MAXDATA) + np:=notes:=New(MAXDURATION*4+100+MAXDATA) + end:=np+MAXDATA + syms:=['one','two','three','four'] + FOR x:=0 TO 3 + ci[x].start:=np + IF findsym(syms[x]) + ci[x].len:=np-ci[x].start + IF ci[x].len>maxrows THEN maxrows:=ci[x].len + INC numc + ELSE + ci[x].start:=NIL + ENDIF + ENDFOR + IF numc=0 THEN Raise(NOCHANNEL) + IF maxrows=0 THEN Raise(NOGRAM) + IF maxrows>MAXROWS THEN Raise(LARGESONG) +EXCEPT + IF exception>=GEN_ER THEN WriteF('ERROR: ') + SELECT exception + CASE NOCHANNEL; WriteF('Atleast one channel must be defined\n') + CASE LARGESONG; WriteF('Song too large!\n') + CASE CROSSINDEX; WriteF('No cross-symbol indexing allowed\n') + DEFAULT; Raise(exception) /* re-throw if unknown */ + ENDSELECT + Raise(BADSTRUCTURE) /* terminate */ +ENDPROC + +PROC findsym(name) + DEF s:PTR TO sym + s:=symlist + WHILE s + IF StrCmp(s.name,name,ALL) THEN BRA.S continue + s:=s.next + ENDWHILE + RETURN FALSE + continue: + rewritelist(s.rptr) +ENDPROC TRUE + +PROC rewritelist(list:PTR TO rlist) + WHILE list + rewritesym(list) + list:=list.next + ENDWHILE +ENDPROC + +PROC rewritesym(rsym:PTR TO rlist) + DEF t,sl:PTR TO sym,rnd,c1,c2,ol:PTR TO optset,x,i,st:PTR TO LONG,l,n + FreeStack(); CtrlC() + t:=rsym.type + SELECT t + CASE SYM + sl:=rsym.info + IF i:=rsym.index + st:=itab[i].start + l:=itab[i].len + IF st + IF np+l>=end THEN Raise(LARGESONG) + IF sl<>itab[i].isym THEN Raise(CROSSINDEX) + l:=Shr(l,2) + IF l THEN FOR x:=1 TO l DO np[]++:=IF n:=st[]++ THEN + n AND MASK OR curglob ELSE 0 + ELSE + st:=np + rewritelist(sl.rptr) + itab[i].len:=np-st + itab[i].start:=st + itab[i].isym:=sl + ENDIF + ELSE + rewritelist(sl.rptr) + ENDIF + CASE OPTION + IF Rnd(1001)=c1) AND (rnd1 THEN FOR x:=2 TO rsym.index DO np[]++:=0 + IF np>=end THEN Raise(LARGESONG) + cursfx:=0 + CASE SAMPLE + cursample:=rsym.info + curglob:=Shl(cursample+1 AND $F,12) OR Shl(cursample+1 AND $F0,24) + CASE SFX + cursfx:=rsym.info + ENDSELECT +ENDPROC + +PROC loadsamples() HANDLE + DEF s:PTR TO sample,i,l,r,f:PTR TO LONG + s:=sdata + FOR i:=1 TO numsample + IF (l:=FileLength(s.path))<10 THEN Raise(0) + s.len:=l + s.adr:=New(l) + IF (fh:=Open(s.path,OLDFILE))=NIL THEN Raise(0) + r:=Read(fh,s.adr,l) + Close(fh) + fh:=NIL + IF r<10 THEN Raise(0) + f:=s.adr + IF f[]="FORM" + WHILE f[]++<>"BODY" DO IF s.adr+l=numsample + Write(fh,[0,0,0,0,0,0,0,0],30) + ELSE + Write(fh,sdata[x].path,21) + Out(fh,0) + Write(fh,[wl,sdata[x].vol,0,1]:INT,8) /* or [,,wl,] */ + ENDIF + ENDFOR + IF (pnum:=maxrows/256)*256<>maxrows THEN INC pnum + Out(fh,pnum) + Out(fh,120) /* 127 */ + FOR x:=0 TO pnum-1 DO Out(fh,x) + FOR x:=pnum TO 127 DO Out(fh,0) + Write(fh,["M.K."],4) + nument:=pnum*64-1 + FOR x:=0 TO nument + FOR n:=0 TO 3 + ch:=channel[n].start + IF ch + len:=channel[n].len + IF len + dat[n]:=ch[]++ + channel[n].start:=ch + channel[n].len:=len-4 + ELSE + dat[n]:=0 + ENDIF + ELSE + dat[n]:=0 + ENDIF + ENDFOR + Write(fh,dat,16) + ENDFOR + FOR x:=0 TO numsample-1 + Write(fh,sdata[x].adr,sdata[x].len) + ENDFOR + Close(fh) + fh:=NIL +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Yax/QuickSort.yax b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/QuickSort.yax new file mode 100644 index 0000000..189c8f9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/QuickSort.yax @@ -0,0 +1,83 @@ +/* quick sort in yax, by Ben Schaeffer Nov 1993 */ +(write 'Enter array size: ''') +(set size (readint)) +(array original size) +(array test size) +(set pivot 0) + +/* guess at stack size*/ +(array stack (/ (+ 1 size) 2)) +(set sp 0) + +/* set up original values */ +(for i 0 (- size 1) + (set (original i) (rnd 1000)) +) + +/* set up test values */ +(for i 0 (- size 1) + (set (test i) (original i)) +) + +/* quick sort functions defined here */ + +/* this function must only change pivot */ +(defun partition (low high) + (when (? pivot low) + (set temp (test low)) + (set (test low) (test pivot)) + (set (test pivot) temp) + ) + (set pivot low) + (inc low) + /* now organize data such that all values greater than pivot will be */ + /* gathered on the higher end of the array and all values less than */ + /* pivot will be on the lower end of the array */ + (while (not (> low high)) + (if (not (> (test low) (test pivot))) + (inc low) + (if (> (test high) (test pivot)) + (dec high) + (do + (set temp (test low)) + (set (test low) (test high)) + (set (test high) temp) + ) + ) + ) + ) + /* this repositions pivot so that it is truly in its ordered location */ + (when (? high pivot) + (set temp (test high)) + (set (test high) (test pivot)) + (set (test pivot) temp) + ) + (set pivot high) +) + + +(defun quicksort (lo hi) + (when (< lo hi) + (set pivot (/ (+ lo hi) 2)) + (partition lo hi) + (when (< lo pivot) + (quicksort lo (- pivot 1)) + ) + (when (> hi pivot) + (quicksort (+ pivot 1) hi) + ) + ) +) + +(write 'beginning quick sort') +(quicksort 0 (- size 1)) +(write 'ended quick sort')(readint) + +(write 'checking order') +/* show sorted array */ +(for i 1 (- size 1) + (when (< (test 1) (test 0)) + (write (test i)' _ ' i) + ) +) +(write 'done') \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Yax/Yax.e b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/Yax.e new file mode 100644 index 0000000..623052b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/Yax.e @@ -0,0 +1,742 @@ +/* YAX (Yet Another Instruction Code Set) Interpreter v1.2 + simple procedural/(functional) language with lisp-lookalike syntax. + eats sources with extension .yax for dinner. */ + +-> note: code is a little oldfashioned by now + +OPT STACK=25000 /* we do heavy recursion */ + +OBJECT var /* this is where we store our runtime values */ + type:LONG + name:LONG + value:LONG +ENDOBJECT + +/* intermediate codes */ +ENUM ENDSOURCE,VALUE,ISTRING,IDENT,LBRACKET,RBRACKET + +/* keywords */ +ENUM FWRITE=100,FADD,FEQ,FUNEQ,FSUB,FMUL,FDIV,FAND,FORX,FNOT,FIF,FDO, + FSELECT,FSET,FFOR,FWHILE,FUNTIL,FDEFUN,FLAMBDA,FAPPLY,FREADINT, + FARRAY,FGREATER,FSMALLER,FLOCATE,FCLS,FDUMP,FWINDOW,FTELL,FTOLD, + FSEE,FSEEN,FSTRING,FREAD,FGET,FPUT,FFILELEN,FLINE,FPLOT,FBOX, + FMOUSEX,FMOUSEY,FMOUSE,FTEXT,FABS,FMOD,FEOR,FSWAP,FPOWER,FREQ, + FINC,FDEC,FRND,FRNDQ,FKICK,FWHEN,FELSE,FWIN,FSCREEN,FMESSAGE, + FGADGET,FGADNUM,FHEX,FEXIT,LAST + +CONST KEYWORDSIZE=8, + NRKEYWORDS=LAST-99, + IDENTNAMESPACE=30000, + VARSTACKSPACE=50000, + MAXARGS=5, + ERLEN=60 + +/* errors */ +ENUM ER_WORKSPACE=1,ER_BUF,ER_GARBAGE,ER_SYNTAX,ER_EXPKEYWORD,ER_EXPRBRACKET, + ER_EXPEXP,ER_QUOTE,ER_COMMENT,ER_INFILE,ER_SOURCEMEM,ER_EXPIDENT, + ER_ARGS,ER_TYPE,ER_EXPLBRACKET,ER_STACK,ER_ALLOC,ER_ARRAY,ER_FILE, + ER_GFXWIN,ER_VALUES,ER_KICK + +/* variable types */ +ENUM TINTEGER=1,TSTRING,TFUNC,TARRAY + +DEF source,slen,erpos=NIL, + ilen,ibuf,ipos:PTR TO INT,p:PTR TO INT,idents, + name[100]:STRING,wfile, + inputbuf[100]:STRING,winspec[100]:STRING, + vartop,varbottom,vars,rec,globvar, + infile,outfile,oldout,oldin,ownstdin, + gfxwindow=NIL,curwindow=NIL,curscreen=NIL,gadnum=-1 + +PROC main() + WriteF(''); ownstdin:=stdout + loadsource() + ilen:=Mul(slen,4)+1000 /* guess the needed workspace */ + ibuf:=New(ilen+10) + idents:=String(IDENTNAMESPACE) + vars:=New(VARSTACKSPACE) + vartop:=vars; varbottom:=vars + IF (ibuf=NIL) OR (idents=NIL) OR (vars=NIL) + error(ER_WORKSPACE) + ELSE + lexanalyse() /* translate to intermediate format */ + p:=ibuf + WHILE p[]<>ENDSOURCE DO eval() /* run the code */ + ENDIF + error(0) +ENDPROC + +PROC lexanalyse() + DEF pos,end,c,count,ident[50]:STRING,pos2,keypos,a,nr,ident2[50]:STRING + pos:=source; end:=pos+slen; ipos:=ibuf; erpos:=pos + StrCopy(idents,' ',1) + loop: + c:=pos[]++ + IF c>96 /* an identifier */ + pos2:=pos-1 + WHILE pos[]++>96 DO NOP; DEC pos + StrCopy(ident,pos2,pos-pos2) + StrCopy(ident2,ident,ALL) + StrAdd(ident,'..............',ALL) + keypos:={keywords} + nr:=0 + FOR a:=1 TO NRKEYWORDS /* lookup keywords */ + IF StrCmp(ident,keypos,KEYWORDSIZE) + nr:=99+a + JUMP found + ENDIF + keypos:=keypos+KEYWORDSIZE + ENDFOR + found: + IF nr>0 /* keyword */ + iword(nr) + ELSE /* own identifier */ + iword(IDENT) + StrCopy(ident,' ',1) + StrAdd(ident,ident2,ALL) + StrAdd(ident,' ',1) + pos2:=InStr(idents,ident,0) + IF pos2=-1 + ilong(EstrLen(idents)+idents) + StrAdd(idents,ident2,ALL) + StrAdd(idents,' ',1) + IF EstrLen(idents)=StrMax(idents) THEN error(ER_WORKSPACE) + ELSE + ilong(pos2+idents+1) + ENDIF + ENDIF + ELSE + SELECT c /* anything else */ + CASE " " + IF pos"*" + iword(FDIV) + ELSE /* comment (like this one) */ + INC pos + WHILE pos-1" + iword(FGREATER) + CASE "<" + iword(FSMALLER) + CASE "?" + iword(FUNEQ) + CASE "'" /* string constant */ + iword(ISTRING) + count:=0; pos2:=pos + WHILE pos[]++<>"'" + INC count + IF pos=end THEN error(ER_QUOTE) + ENDWHILE + iword(count) + ilong(pos2) /* char adress */ + CASE 10 + IF posTARRAY THEN error(ER_TYPE) + x:=adr.value + a:=eval() + IF (a<0) OR (a>x[]) THEN error(ER_ARRAY) + r:=x[a+1] + ENDIF + ELSE + IF ins<100 THEN error(ER_EXPKEYWORD) + SELECT ins + CASE FWRITE /* output string constants + expressions */ + x:=TRUE + WHILE p[]<>RBRACKET + IF p[]=ISTRING + Write(stdout,Long(p+4),p[1]) + IF (p[1]=0) AND (p[4]=RBRACKET) THEN x:=FALSE + p:=p+8 + ELSEIF p[]=IDENT + IF (Int(findvar(Long(p+2)))=TSTRING) + WriteF('\s',eatstring()) + ELSE + WriteF('\d',eval()) + ENDIF + ELSE + WriteF('\d',eval()) + ENDIF + ENDWHILE + IF x THEN WriteF('\n') + CASE FEQ + r:=TRUE + x:=eval() + WHILE p[]<>RBRACKET DO IF x<>eval() THEN r:=FALSE + CASE FUNEQ; r:=eval()<>eval() + CASE FGREATER; r:=eval()>eval() + CASE FSMALLER; r:=eval()RBRACKET DO r:=r+eval() + CASE FSUB; r:=eval(); WHILE p[]<>RBRACKET DO r:=r-eval() + CASE FMUL; r:=eval(); WHILE p[]<>RBRACKET DO r:=Mul(r,eval()) + CASE FDIV; r:=eval(); WHILE p[]<>RBRACKET DO r:=r/eval() + CASE FAND; r:=eval(); WHILE p[]<>RBRACKET DO r:=r AND eval() + CASE FORX; r:=eval(); WHILE p[]<>RBRACKET DO r:=r OR eval() + CASE FEOR; r:=eval(); WHILE p[]<>RBRACKET DO r:=Eor(r,eval()) + CASE FNOT; r:=Not(eval()) + CASE FABS; r:=Abs(eval()) + CASE FRND; r:=Rnd(eval()) + CASE FRNDQ; r:=RndQ(eval()) + CASE FKICK; r:=KickVersion(eval()) + CASE FMOD; r:=Mod(eval(),eval()) + CASE FWHEN + IF eval() + WHILE (p[]<>FELSE) AND (p[]<>RBRACKET) DO r:=eval() + IF p[]=FELSE + p++ + WHILE (p[]<>RBRACKET) DO skip() + ENDIF + ELSE + WHILE (p[]<>FELSE) AND (p[]<>RBRACKET) DO skip() + IF p[]=FELSE + p++ + WHILE (p[]<>RBRACKET) DO r:=eval() + ENDIF + ENDIF + CASE FIF + IF eval() + r:=eval() + IF p[]<>RBRACKET THEN skip() + ELSE + skip() + IF p[]<>RBRACKET THEN r:=eval() + ENDIF + CASE FDO; WHILE p[]<>RBRACKET DO r:=eval() + CASE FSELECT + x:=eval() + WHILE p[]<>RBRACKET DO IF x=eval() THEN r:=eval() ELSE skip() + CASE FSET + IF p[]=LBRACKET + p:=p+2 + erpos:=^p++ + x:=varvalue(eatident(),TARRAY) + a:=eval() + IF (a<0) OR (a>x[0]) THEN error(ER_ARRAY) + IF p[]++<>RBRACKET THEN error(ER_EXPRBRACKET) + x[a+1]:=eval() + ELSE + x:=eatident() + IF (p[]=LBRACKET) AND (p[3]=FLAMBDA) + p:=p+8 + adr:=findvar(x) + letvar(adr,p,TFUNC) + WHILE p[]<>RBRACKET DO skip() + p:=p+2 + ELSEIF p[]=ISTRING + r:=eatstring() + x:=findvar(x) + letvar(x,r,TSTRING) + ELSE + r:=eval() + x:=findvar(x) + letvar(x,r,TINTEGER) + ENDIF + ENDIF + CASE FINC + x:=eatident() + r:=varvalue(x,TINTEGER) + x:=findvar(x) + letvar(x,r+1,TINTEGER) + CASE FDEC + x:=eatident() + r:=varvalue(x,TINTEGER) + x:=findvar(x) + letvar(x,r-1,TINTEGER) + CASE FSWAP + x:=eatident() + r:=varvalue(x,TINTEGER) + x:=findvar(x) + adr:=eatident() + a:=varvalue(adr,TINTEGER) + adr:=findvar(adr) + letvar(x,a,TINTEGER) + letvar(adr,r,TINTEGER) + r:=0 + CASE FPOWER + r:=adr:=eval() + x:=eval() + IF x>1 THEN FOR a:=2 TO x DO r:=r*adr + CASE FFOR + x:=eatident() + r:=eval() + adr:=findvar(x) + x:=eval() + p2:=p + IF r>x /* downto */ + FOR a:=r TO x STEP -1 + p:=p2 + letvar(adr,a,TINTEGER) + WHILE p[]<>RBRACKET DO eval() + ENDFOR + ELSE + FOR a:=r TO x + p:=p2 + letvar(adr,a,TINTEGER) + WHILE p[]<>RBRACKET DO eval() + ENDFOR + ENDIF + r:=0 + CASE FWHILE + p2:=p + WHILE eval() + WHILE p[]<>RBRACKET DO eval() + p:=p2 + ENDWHILE + WHILE p[]<>RBRACKET DO skip() + r:=0 + CASE FUNTIL + p2:=p + WHILE eval()=FALSE + WHILE p[]<>RBRACKET DO eval() + p:=p2 + ENDWHILE + WHILE p[]<>RBRACKET DO skip() + r:=0 + CASE FDEFUN + x:=eatident() + adr:=findvar(x) + letvar(adr,p,TFUNC) + WHILE p[]<>RBRACKET DO skip() + CASE FLAMBDA; error(ER_SYNTAX) + CASE FAPPLY + IF p[]<>IDENT + IF (p[]<>LBRACKET) OR (p[3]<>FLAMBDA) THEN error(ER_EXPIDENT) + p:=p+8; adr:=p + WHILE p[]<>RBRACKET DO skip() + p:=p+2 + r:=dofunc(adr) + ELSE + p:=p+2 + r:=dofunc(varvalue(^p++,TFUNC)) + ENDIF + CASE FREADINT + IF ReadStr(ownstdin,inputbuf)=-1 + r:=0 + ELSE + r:=Val(inputbuf) + ENDIF + CASE FARRAY + adr:=findvar(eatident()) + a:=eval() + x:=New(Mul(a,4)+8) + IF x=NIL THEN error(ER_ALLOC) + letvar(adr,x,TARRAY) + x[]++:=a + WHILE (p[]++=VALUE) + IF a-->=0 THEN x[]++:=^p++ ELSE p:=p+4 + ENDWHILE + p-- + CASE FLOCATE; WriteF('\e[\d;\dH',eval(),eval()) + CASE FCLS; Out(stdout,12) + CASE FDUMP + adr:=varbottom + WriteF('\n') + WHILE adr" " DO INC x + Write(stdout,a,x-a) + x:=adr.type + SELECT x + CASE TINTEGER; WriteF(' = \d (int)\n',adr.value) + CASE TSTRING; WriteF(' = "\s" (string)\n',adr.value) + CASE TFUNC; WriteF(' (function)\n') + CASE TARRAY; WriteF('[\d] (array)\n',Long(adr.value)) + ENDSELECT + adr:=adr+SIZEOF var + ENDWHILE + WriteF('\n') + CASE FWINDOW + StringF(winspec,'CON:\d/\d/\d/\d/',eval(),eval(),eval(),eval()) + x:=eatstring() + StrAdd(winspec,x,ALL) + wfile:=Open(winspec,1006) + IF wfile=NIL THEN error(ER_FILE) + IF conout<>NIL THEN Close(conout) + stdout:=wfile + conout:=stdout + ownstdin:=stdout + adr:=OpenWorkBench() + Forbid() + a:=NIL + IF adr<>NIL + adr:=Long(adr+4) + WHILE (adr<>NIL) AND (a=NIL) + IF StrCmp(x,Long(adr+32),ALL) THEN a:=adr + adr:=^adr + ENDWHILE + ENDIF + Permit() + IF a THEN gfxwindow:=a + CASE FREQ + IF KickVersion(37)=FALSE THEN error(ER_KICK) + r:=EasyRequestArgs(IF curwindow THEN curwindow ELSE NIL, + [20,0,eatstring(),eatstring(),eatstring()],0,NIL) + CASE FTELL + IF outfile<>NIL THEN Close(outfile) + outfile:=NIL + outfile:=Open(eatstring(),1006) + IF outfile=NIL THEN error(ER_FILE) + oldout:=stdout + stdout:=outfile + CASE FTOLD + IF outfile<>NIL THEN Close(outfile) + outfile:=NIL + stdout:=oldout + CASE FSEE + IF infile<>NIL THEN Close(infile) + infile:=NIL + infile:=Open(eatstring(),1005) + IF infile=NIL THEN error(ER_FILE) + oldin:=ownstdin + ownstdin:=infile + CASE FSEEN + IF infile<>NIL THEN Close(infile) + infile:=NIL + ownstdin:=oldin + CASE FSTRING + adr:=String(250) + IF adr=NIL THEN error(ER_ALLOC) + letvar(findvar(eatident()),adr,TSTRING) + CASE FREAD + x:=varvalue(eatident(),TSTRING) + r:=ReadStr(ownstdin,x) + CASE FGET; r:=Inp(ownstdin) + CASE FPUT; r:=eval(); IF r<>-1 THEN Out(stdout,r) + CASE FFILELEN + r:=FileLength(eatstring()) + IF r=-1 THEN r:=0 + CASE FLINE; getrast(); Line(eval(),eval(),eval(),eval(),eval()) + CASE FPLOT; getrast(); Plot(eval(),eval(),eval()) + CASE FBOX + getrast() + a:=eval(); x:=eval(); p2:=eval(); r:=eval() + IF a>p2 + adr:=a; a:=p2; p2:=adr + ENDIF + IF x>r + adr:=x; x:=r; r:=adr + ENDIF + IF (a<0) OR (x<0) OR (p2>10000) OR (r>10000) THEN error(ER_VALUES) + Box(a,x,p2,r,eval()) + r:=0 + CASE FMOUSEX; r:=MouseX(getwin()) + CASE FMOUSEY; r:=MouseY(getwin()) + CASE FMOUSE; r:=Mouse() + CASE FTEXT + adr:=getrast() + a:=eval(); x:=eval() + Colour(eval(),eval()) + TextF(a,x,eatstring()) + r:=0 + CASE FMESSAGE + r:=WaitIMessage(getwin()) + gadnum:=IF (r=$20) OR (r=$40) THEN Long(MsgIaddr()+40) ELSE -1 + CASE FGADNUM + r:=gadnum + CASE FGADGET + IF (adr:=New(GADGETSIZE))=NIL THEN error(ER_ALLOC) + Gadget(adr,NIL,eval(),0,eval(),eval(),eval(),eatstring()) + AddGadget(getwin(),adr,-1) + RefreshGList(adr,getwin(),NIL,1) + CASE FSCREEN + CloseS(curscreen) + curscreen:=NIL + curscreen:=OpenS(eval(),eval(),eval(),eval(),eatstring()) + CASE FWIN + CloseW(curwindow) + curwindow:=NIL + gfxwindow:=NIL + curwindow:=OpenW(eval(),eval(),eval(),eval(), + eval(),eval(),eatstring(), + IF curscreen THEN curscreen ELSE NIL, + IF curscreen THEN 15 ELSE 1,NIL) + gfxwindow:=curwindow + CASE FHEX + WriteF('$\z\h[8]',eval()) + CASE FEXIT + error(0) + ENDSELECT + ENDIF + IF p[]++<>RBRACKET THEN error(ER_EXPRBRACKET) + DEFAULT + IF (i=RBRACKET) OR (i=ISTRING) THEN error(ER_EXPEXP) ELSE error(ER_SYNTAX) + ENDSELECT +ENDPROC r + +PROC getwin() + IF gfxwindow=NIL THEN error(ER_GFXWIN) +ENDPROC gfxwindow + +PROC getrast() + DEF r + IF curwindow=NIL + IF curscreen=NIL + IF gfxwindow=NIL THEN error(ER_GFXWIN) + r:=Long(gfxwindow+50) + ELSE + r:=curscreen+84 + ENDIF + ELSE + r:=Long(curwindow+50) + ENDIF + SetStdRast(r) +ENDPROC r + +PROC eatstring() + DEF adr,x + IF p[]=ISTRING + p:=p+2; x:=p[]++; adr:=^p++ + adr[x]:=0 + ELSE + adr:=varvalue(eatident(),TSTRING) + ENDIF +ENDPROC adr + +PROC eatident() + IF p[]++<>IDENT THEN error(ER_EXPIDENT) +ENDPROC ^p++ + +PROC dofunc(lcode) + DEF args[MAXARGS]:ARRAY OF LONG,a=0,oldvarb,oldvart,oldp,x,r=0,olderpos + checkstop() + WHILE p[]<>RBRACKET + IF a=MAXARGS THEN error(ER_ARGS) + args[a]:=eval() + INC a + ENDWHILE + IF rec=0 THEN globvar:=vartop + oldvarb:=varbottom; varbottom:=vartop; oldvart:=vartop; + oldp:=p; p:=lcode; olderpos:=erpos; INC rec + IF p[]++<>LBRACKET THEN error(ER_EXPLBRACKET) + erpos:=^p++ + WHILE p[]<>RBRACKET + IF a=0 THEN error(ER_ARGS) + x:=findvar(eatident()) + letvar(x,args[]++,TINTEGER) + DEC a + ENDWHILE + IF a<>0 THEN error(ER_ARGS) + p:=p+2 + WHILE p[]<>RBRACKET DO r:=eval() + varbottom:=oldvarb; vartop:=oldvart; p:=oldp; erpos:=olderpos; DEC rec +ENDPROC r + +PROC findvar(id) + DEF loc=0:PTR TO var,a:PTR TO var + IF vartop<>varbottom + a:=varbottom /* check existing local vars */ + WHILE (a0) AND (globvar>vars) /* check global vars */ + a:=vars + WHILE (atype) AND (adr.type<>TINTEGER) THEN error(ER_TYPE) + checkstop() + adr.type:=type + adr.value:=value +ENDPROC + +PROC varvalue(id,type) + DEF adr:PTR TO var + checkstop() + adr:=findvar(id) + IF adr.type<>type THEN error(ER_TYPE) +ENDPROC adr.value + +PROC skip() /* skip *one* expression */ + DEF deep=0,i + REPEAT + i:=p[]++ + IF (i=VALUE) OR (i=LBRACKET) OR (i=IDENT) THEN p:=p+4 + IF i=ISTRING THEN p:=p+6 + IF i=LBRACKET THEN INC deep + IF i=RBRACKET THEN IF deep=0 THEN error(ER_EXPEXP) ELSE DEC deep + IF i=ENDSOURCE THEN error(ER_EXPRBRACKET) + UNTIL deep=0 +ENDPROC + +PROC iword(x) + IF ibuf+ilen>ipos THEN ipos[]++:=x ELSE error(ER_BUF) +ENDPROC + +PROC ilong(x) + IF ibuf+ilen>ipos THEN ^ipos++:=x ELSE error(ER_BUF) +ENDPROC + +PROC loadsource() + DEF suxxes=FALSE,handle,read + IF StrCmp(arg,'?',ALL) OR StrCmp(arg,'',ALL) + WriteF('USAGE: Yax (default ext. ".yax")\n') + error(0) + ELSE + StrCopy(name,arg,ALL) + StrAdd(name,'.yax',4) + slen:=FileLength(name) + handle:=Open(name,1005) + IF (handle=NIL) OR (slen=-1) + error(ER_INFILE) + ELSE + source:=New(slen+10) + IF source=NIL + error(ER_SOURCEMEM) + ELSE + read:=Read(handle,source,slen) + Close(handle) + IF read=slen + suxxes:=TRUE + source[slen]:=0 + ELSE + error(ER_INFILE) + ENDIF + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC error(nr) + DEF erstr[ERLEN]:STRING,a + IF outfile + IF stdout=outfile THEN stdout:=oldout + Close(outfile) + ENDIF + IF infile + IF ownstdin=infile THEN ownstdin:=oldin + Close(infile) + ENDIF + CloseW(curwindow) + CloseS(curscreen) + WriteF('\n') + IF nr>0 + WriteF('ERROR: ') + SELECT nr + CASE ER_WORKSPACE; WriteF('Could not allocate workspace!\n') + CASE ER_BUF; WriteF('Buffer overflow!\n') + CASE ER_GARBAGE; WriteF('Garbage in line\n') + CASE ER_SYNTAX; WriteF('Your syntax sucks\n') + CASE ER_EXPKEYWORD; WriteF('Keyword identifier expected\n') + CASE ER_EXPRBRACKET; WriteF('Right bracket expected\n') + CASE ER_EXPEXP; WriteF('Evaluateable expression expected\n') + CASE ER_QUOTE; WriteF('Missing quote \a\n') + CASE ER_COMMENT; WriteF('Missing "*/"\n') + CASE ER_SOURCEMEM; WriteF('No Memory for source!\n') + CASE ER_INFILE; WriteF('Could not open file "\s".\n',name) + CASE ER_EXPIDENT; WriteF('Identifier expected\n') + CASE ER_ARGS; WriteF('Illegal #of arguments\n') + CASE ER_TYPE; WriteF('Wrong type of variable/expression\n') + CASE ER_EXPLBRACKET; WriteF('Left bracket expected\n') + CASE ER_STACK; WriteF('Nearly stack overflow: \d deep\n',rec) + CASE ER_ALLOC; WriteF('Dynamic allocation failed!\n') + CASE ER_ARRAY; WriteF('Array index out of bounds\n') + CASE ER_FILE; WriteF('File error\n') + CASE ER_GFXWIN; WriteF('No User-window for graphics\n') + CASE ER_VALUES; WriteF('Illegal value(s)\n') + CASE ER_KICK; WriteF('You need OS 37+ for this function\n') + ENDSELECT + IF erpos<>NIL + StrCopy(erstr,erpos,ALL) + FOR a:=0 TO ERLEN-1 DO IF erstr[a]=10 THEN erstr[a]:=32 + WriteF('NEARBY: \s\n',erstr) + ENDIF + ELSEIF nr=-1 + WriteF('*** Program halted.\n') + ENDIF + IF conout<>NIL THEN WriteF('Press to continue ...\n') + CleanUp(0) +ENDPROC + +keywords: +CHAR 'write...', 'add.....', 'eq......', 'uneq....', 'sub.....', + 'mul.....', 'div.....', 'and.....', 'or......', 'not.....', + 'if......', 'do......', 'select..', 'set.....', 'for.....', + 'while...', 'until...', 'defun...', 'lambda..', 'apply...', + 'readint.', 'array...', 'greater.', 'smaller.', 'locate..', + 'cls.....', 'dump....', 'window..', 'tell....', 'told....', + 'see.....', 'seen....', 'string..', 'read....', 'get.....', + 'put.....', 'filelen.', 'line....', 'plot....', 'box.....', + 'mousex..', 'mousey..', 'mouse...', 'text....', 'abs.....', + 'mod.....', 'eor.....', 'swap....', 'power...', 'req.....', + 'inc.....', 'dec.....', 'rnd.....', 'rndq....', 'kick....', + 'when....', 'else....', 'win.....', 'screen..', 'message.', + 'gadget..', 'gadid...', 'hex.....', 'exit....' + diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Yax/fac.yax b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/fac.yax new file mode 100644 index 0000000..86cfba9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/fac.yax @@ -0,0 +1,2 @@ +(defun fac (n) (if (eq n 1) 1 (* (fac (sub n 1)) n))) +(write 'compute factorial of: ' (fac (readint))) diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Yax/pi.yax b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/pi.yax new file mode 100644 index 0000000..1e40a0b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/pi.yax @@ -0,0 +1,42 @@ +(defun pi (nr) + (set max (* nr 4)) + (array a max) + (set m nr) + (for i 0 max (set (a i) 0)) + (set k (- (/ (* m 3321) 1000) 1) ) + (for n k 1 + (set (a 0) (+ (a 0) 2)) + (set p (+ 1 (* 2 n))) + (set c 0) + (for i 0 m + (set c (+ (* 10 c) (* n (a i)))) + (set (a i) (/ c p)) + (set c (- c (* (a i) p))) + ) + (locate 5 20) + (write n ' ' '') + ) + (for i m 1 + (if (greater (a i) 9) + (do + (set (a i) (- (a i) 10) ) + (set (a (- i 1)) (+ (a (- i 1)) 1)) + ) + ) + ) + (cls) + (write) + (write 'pi=3.' '') + (for i 1 m + (write (a i) '') + ) + (write) +) + + +(window 0 11 400 150 'PI calc') +(write '#of decimals: ' '') +(set deci (readint)) +(write 'busy ....') +(pi deci) +(write) diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Yax/sincosdemo.yax b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/sincosdemo.yax new file mode 100644 index 0000000..2f13aff --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/sincosdemo.yax @@ -0,0 +1,66 @@ +/* SinCosDemo.yax freeware v0.4 @ Ben Schaeffer1993 +Sine and cosine arrays in degrees, 0 to 360 inclusive. */ + +/* modified by wouter */ + +(array sin 361 + 0 4 9 13 18 22 27 31 36 40 44 49 53 58 62 66 71 75 79 83 88 92 96 100 104 108 + 112 116 120 124 128 132 136 139 143 147 150 154 158 161 165 168 171 175 178 + 181 184 187 190 193 196 199 202 204 207 210 212 215 217 219 222 224 226 228 + 230 232 234 236 237 239 241 242 243 245 246 247 248 249 250 251 252 253 254 + 254 255 255 255 256 256 256 256 256 256 256 255 255 255 254 254 253 252 251 + 250 249 248 247 246 245 243 242 241 239 237 236 234 232 230 228 226 224 222 + 219 217 215 212 210 207 204 202 199 196 193 190 187 184 181 178 175 171 168 + 165 161 158 154 150 147 143 139 136 132 128 124 120 116 112 108 104 100 96 + 92 88 83 79 75 71 66 62 58 53 49 44 40 36 31 27 22 18 13 9 4 0 + -4 -9 -13 -18 -22 -27 -31 -36 -40 -44 -49 -53 -58 -62 -66 -71 -75 -79 -83 + -88 -92 -96 -100 -104 -108 -112 -116 -120 -124 -128 -132 -136 -139 -143 -147 + -150 -154 -158 -161 -165 -168 -171 -175 -178 -181 -184 -187 -190 -193 -196 + -199 -202 -204 -207 -210 -212 -215 -217 -219 -222 -224 -226 -228 -230 -232 + -234 -236 -237 -239 -241 -242 -243 -245 -246 -247 -248 -249 -250 -251 -252 + -253 -254 -254 -255 -255 -255 -256 -256 -256 -256 -256 -256 -256 -255 -255 + -255 -254 -254 -253 -252 -251 -250 -249 -248 -247 -246 -245 -243 -242 -241 + -239 -237 -236 -234 -232 -230 -228 -226 -224 -222 -219 -217 -215 -212 -210 + -207 -204 -202 -199 -196 -193 -190 -187 -184 -181 -178 -175 -171 -168 -165 + -161 -158 -154 -150 -147 -143 -139 -136 -132 -128 -124 -120 -116 -112 -108 + -104 -100 -96 -92 -88 -83 -79 -75 -71 -66 -62 -58 -53 -49 -44 -40 -36 -31 -27 + -22 -18 -13 -9 -4 0 +) + +(defun cos (a) (sin (if (> a 270) (- a 270) (+ a 90)))) +(defun wait () (while (uneq (mouse) 0))) + +(window 0 0 600 180 'circle') + +(for n 0 360 + (line (+ 300 (/ (* 160 (cos n)) 256)) + (+ 95 (/ (* 75 (sin n)) 256)) + (+ 300 (/ (* 80 (cos n)) 256)) + (+ 95 (/ (* 37 (sin n)) 256)) n) +) + +(for n 0 360 + (plot (+ 300 (/ (* 40 (cos n)) 256)) (+ 95 (/ (* 19 (sin n)) 256)) n) +) + +(write 'click to continue') +(wait) +(while (eq (mouse) 0)) +(cls) +(set m 181) +(wait) +(while (eq (mouse) 0) + (for n 0 360 + (line (+ 300 (/ (* 160 (cos n)) 256)) + (+ 95 (/ (* 75 (sin (- 360 n))) 256)) + (+ 300 (/ (* 80 (cos n)) 256)) + (+ 95 (/ (* 37 (sin n)) 256)) 2) + (line (+ 300 (/ (* 160 (cos m)) 256)) + (+ 95 (/ (* 75 (sin (- 360 m))) 256)) + (+ 300 (/ (* 80 (cos m)) 256)) + (+ 95 (/ (* 37 (sin m)) 256)) 1) + (set m (+ m 1)) + (if (eq m 361) (set m 0)) + (if (uneq (mouse) 0) (exit)) + ) +) diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Yax/xpaint.yax b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/xpaint.yax new file mode 100644 index 0000000..4e48b71 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/xpaint.yax @@ -0,0 +1,75 @@ +/* paint program using the new intuition functions */ + +(when (not (kick 37)) (write 'I need v37+!') (exit)) + +(string title) +(set title 'Xpaint++ v0.1 by $#%!') +(set maxx 320) (set maxy 200) +(set col 1) (set tool 0) (set ox -1) (set oy -1) +(set f 0) (set mode 0) (set off 30) + +(set depth (+ (req title 'number of colours?' '4|8|16|2') 1)) +(set flags (* (req title 'mode?' 'hires|lowres') $8000)) +(set flags (+ flags (* (req title 'lace?' 'yes|no') 4))) +(set maxy (+ maxy (* (req title 'pal?' 'yes|no') 56))) +(if (> flags $7FFF) (set maxx (* maxx 2))) +(if (and flags 4) (set maxy (* maxy 2))) + +(screen maxx maxy depth flags title) +(win 0 1 maxx (- maxy 1) $268 $100E title) +(line 0 (- off 1) maxx (- off 1) 1) +(gadget 1 5 15 55 'colour') +(gadget 2 65 15 55 'tools') +(gadget 3 125 15 55 'mode') +(gadget 4 185 15 55 'clear') +(gadget 5 245 15 55 'about') +(set noquit 1) + +(defun ymouse () (if (or (< (set d (mousey)) off) (> d maxy)) off d)) + +(defun dogad () + (select (gadid) + 1 (set col (req title 'pick colour:' '1|2|3|4|5|6|7|0')) + 2 (do + (set tool (req title 'use tool:' 'poly|line|box|dot|free')) + (set ox -1) (set oy -1) (set f 0) + ) + 3 (set mode (req title 'mode:' 'cycle|mirror|norm')) + 4 (box 0 off maxx maxy 0) + 5 (req title 'Xpaint++ written in YAX!' 'ok') + ) +) + +(defun dotool (x y) + (if (eq ox -1) (set ox x)) + (if (eq oy -1) (set oy y)) + (select mode + 1 (set col (if (eq col 15) 1 (+ col 1))) + 2 (set tool 4) + ) + (select tool + 0 (do + (while (eq (mouse) 1) + (set ox x) (set oy y) + (line ox oy (set x (mousex)) (set y (ymouse)) col) + ) + ) + 1 (line ox oy x y col) + 2 (do (if f (line ox oy x y col)) (set f (- 1 f))) + 3 (do (if f (box ox oy x y col)) (set f (- 1 f))) + 4 (do + (box x y (+ x 2) (+ y 2) col) + (if (eq mode 2) (box (- maxx x) y (+ (- maxx x) 2) (+ y 2) col)) + ) + ) + (set ox x) (set oy y) +) + +(while noquit + (select (message) + $200 (set noquit 0) + $040 (dogad) + $020 (dogad) + $008 (dotool (mousex) (ymouse)) + ) +) diff --git a/amigae33a/E_v3.3a/Src/Src/Lang/Yax/yax.doc b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/yax.doc new file mode 100644 index 0000000..46d1bcf --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Lang/Yax/yax.doc @@ -0,0 +1,224 @@ + + +---------------------------------------+ + | | + | Amiga YAX Interpreter v1.1 | + | | + | (c) 1992/93 $#%! | + | M A N U A L | + | | + +---------------------------------------+ + +/* v1.2 now includes as mass of new functions! look at end of this doc. */ + + 1. Introduction + 2. The Language + 3. Built-in Functions + + +---------------------------------------+ + | 1. Introduction | + +---------------------------------------+ + +update from v0.x/1.0 to 1.1: +bug fixes: +- negative number division failed! +- box accepted illegal values + +update from v1.1 to 1.2: +- new functions, see below. + +YAX stands for "Yet Another Instruction Code Set", as the author couldn't +think of better name. YAX is a procedural language with LISP-syntax and +evaluation, as well as somewhat lambda function application. + +In this manual it is assumed the reader possesses knowledge of other +languages, as all 'obvious' explanations are left out. Readers for whom +YAX would be their first programming language are advised to read +a standard text on the subject 8-). + + +---------------------------------------+ + | 2. The Language | + +---------------------------------------+ + +Structure. +The basic building block of a YAX program is called a term. +Examples of terms are: + +integer constants: 1 2 100 -1 +string constants: 'a' 'hi folks!' +variables: a count +function calls: (+ 1 2) (* 3 (- 4 5)) + +a function call is a list '()' with as first item the name of the +function to be applied, followed by its arguments. With few execeptions, +arguments to functions are again terms, so expressions may be built +to infinite complexity. The main task of the interpreter is to +evaluate these terms recursively. + +Format. +between any two lexical elements, any number of spaces, tabs and linefeeds +may be placed. Comments start with '/*' and end with '*/', may extend +over several lines, and may be nested. following two statements are equal: + +(if(eq a 1)(for b 1 10(write'blabla'))) /* ugly */ + +(if (eq a 1) + (for b 1 10 (write 'blabla')) /* better */ +) + + + +---------------------------------------+ + | 3. Built-in Functions | + +---------------------------------------+ + +If not explicitly stated, functions return 0. type of arguments: + + any term + term that evaluates to integer + term that evaluates to string + term that is a variable + term that is a string variable + term that evaluates to a function +... any number of terms of the same type may follow + + --> INTEGER MATH <-- + +(add ...) or (+ ...) +(sub ...) or (- ...) +(mul ...) or (* ...) +(div ...) or (/ ...) + +(and ...) +(or ...) +(not ) + +(eq ...) +(uneq ) +(smaller ) +(greater ) + +These functions perform the functions you'd expect them to do. +All boolean logic functions return true (-1) or false (0). and/or/not +work as logical as well as bitwise operators. +except for the last three, all functions handle any number of arguments, +i.e. (eq 10 (+ 1 2 3 4) (* 2 5)) is a valid term. + + --> PROGRAM STRUCTURE <-- + +(for ...) +(if ) + /* also returns value of term */ +(do ...) +(select ...) + /* is matched agains even items of s, and + corresponding odd is executed */ +(while ...) +(until ...) +(set ) + +(defun ( ...) ...) +(lambda (var ...) ...) + /* returns function as value (may only be used in (set) and (apply) */ +(apply ...) + +(array ) +(string ) + + + --> INPUT OUTPUT <-- + +(write ...) +(locate ) +(cls) +(window ) + +(tell ) open a file for writing +(told) close file +(see ) open a file for reading +(seen) close file +(filelen ) get filelength + +(readint) read an integer +(read ) read a string +(get) read one character +(put ) write one character + +(dump) show all variables + + + --> GRAPHICS <-- + +(line ) +(plot ) +(box ) +(text ) +(mousex), (mousey) intuition +(mouse) non-intuition + + + +NEW IN VERSION 1.2: +- changes to existing functions: + (>) as equivalent for (greater) + (<) as equivalent for (smaller) + (array ...) /* inits array with s (opt) */ + (set ) +- additional functions: + math etc.: + (abs ) + (mod ) /* (mod 20 3) => 2 */ + (eor ...) + (swap ) /* currently vars only */ + (power ) /* (power 2 5) => 32 */ + (inc ) + (dec ) + system: + (kick ) /* (if (kick 37) ... ) */ + (exit) + control: + (when ... /* (if (do ...) */ + else ...) /* (do ...)) */ + input/output: + (hex ) /* writes num in hexadecimal */ + intuition: + (req ) /* (req 'YAX req' 'choose:' 'a|b|c') */ + (screen w h d flags title) /* opens screen */ + (win x y w h IDCMP flags title) /* opens gfx-only window and closes + any previous w. if (screen) was + used, (win) opens on it */ + (gadget id x y width title) /* makes gadget on cur. window */ + (message) /* Wait()s and returns IDCMP */ + (gadid) /* returns gadnum in event */ + + NOTE: - now that there's (win) and (screen), graphics and intuition + functions should not be used on windows opened with (window) + (these are for stdio only), it will be possible however to use + graphics functions on them for backward compatability with 1.1. + - (req) is 2.04+, all others are 1.2+ + + +POSSIBLE ENHANCEMENTS: +- true lambda's for function calls +- (cond) + +ben: +- string commands +- run another yax prog from yax code +- (see) twice --> problems? better file support. +- yax compiler (to E) +- (/) moet weer 32bit. + check div by zero. +- !! select break mogelijkheid!! + +BUGS: +- array uitlezen een index te weinig + + +ETC: check ben's correspondentie, 24 april '93 + +>> YAX divide algorithm using YAXv1.0's unsigned 32 bit division: +>> if (denominator) +>> answer = (abs(numerator)/abs(denominator)) +>> if (numerator eor denominator < 0) +>> answer = -answer +>> otherwise +>> ERROR_DIV_BY_ZERO + diff --git a/amigae33a/E_v3.3a/Src/Src/Library/Pgs/gio.m b/amigae33a/E_v3.3a/Src/Src/Library/Pgs/gio.m new file mode 100644 index 0000000000000000000000000000000000000000..d49905338029b8c20df88eebd615ebc648b1ae93 GIT binary patch literal 1334 zcmY+EF>ljQ5XY~vn9{ z_5qfV95Qjeb`zk1WkF?AjMsHsrZqz^dv3qo+VnPi0B5l@L+K5!*Y&-Y@AQnPZah@= zya%gq7>~2vcig6fcjBv|esly7C3z^c09eGtkjaTgADt~#$UQtS;kiCaQkjWe$v*6m z3BgWT&>>$evM@DX3%dJBsAKFHdi$|VqIjBfJCthbxu$|jM>kwo!3kxk0-Y<9BUV8w zN0fsyrh6*b%|pCw3E!YZspL=x6RxxdMP(mUYCTBwuE0b%FAFARF-((8YBAtyiQNok zsplZwai~NpwZ=QB6SqdGh)R>;b}U6G3+zTj4`KfuSrmC;I(2tk%A)EHz3bl8UN!#v zQ~SJm%>xyc15xs8EO=PnNYvm!OT3NhcogQ9m#oLpXkxTf_md>k<3uNUW*E)l=~yRe zq7RN$&ms}(JWs1Mob|aVQ=@2L%!^^3=EZ(2Wd(VvFY!Z=St!FKr;9kdcl${e;^64~p3XQln&}5RSKr1m+8@cD zeI2CuL^GRHd?tIQpqMYFx=OQx1 + g.error:=LOAD_ABORTED + ELSE + g.width:=width + g.height:=height + g.depth:=24 + g.error:=LOAD_OK + ENDIF +ENDPROC g.error + +PROC gioRead(g:PTR TO giodata,z) + DEF x,y,p:PTR TO CHAR,d + pgsbase:=g.pgsbase + SetProgress('Creating Noisy image...',0); + FOR y:=0 TO g.height-1 + IF y AND $F = 0 + IF SetProgress(0,y*100/g.height)<>1 + g.error:=LOAD_ABORTED + RETURN g.error + ENDIF + ENDIF + p:=GetLine(g,y) + FOR x:=0 TO g.width-1 DO FOR d:=1 TO 3 DO p[]++:=d*16+x*y ->Rnd(256) + ReleaseLine(g,y) + ENDFOR + g.error:=NIL +ENDPROC g.error + +PROC gioWrite(g:PTR TO giodata,z) + g.error:=LOAD_WRONGTYPE +ENDPROC g.error diff --git a/amigae33a/E_v3.3a/Src/Src/Library/Pgs/pgs.m b/amigae33a/E_v3.3a/Src/Src/Library/Pgs/pgs.m new file mode 100644 index 0000000000000000000000000000000000000000..831adcb5ea3fc50364c1db5608a9ec55fdd93330 GIT binary patch literal 1005 zcmZ9LUr*aG6vdswSlXykKFJjSfx#n#c0wykRnT51(_WQ`;B<}w?bE|ey7+W^%DLBx zf7jlE`9;JfRkOuM;@(l7TO;l(NW~eiwY@ zwg+ShvIJRzEJ2naOOPeV5@ZRo>dEEPm33>X({Z^YxAe`{Q_CLQQHX`Os+*REGQWTH zMBiRQXxxf^^U&FJa7kforSczdz6vx?MH1I>0A=z;V>dVR`O?-D0>=~I!hzITXAdW~ z53~y>n~H>ci^@?dR#X$`zc0EsyV?Fr_xRJv=g#9bbN-3B-=z)lu4LReygOMO2wp09 zsopAxT literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Library/README b/amigae33a/E_v3.3a/Src/Src/Library/README new file mode 100644 index 0000000..51a055b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Library/README @@ -0,0 +1,5 @@ +This directory contains some examples of libraries. Both show clearly how to +interface with other languages/systems: the stack.library allows C to call +methods from an E class, and noisy.gio is a library that can be used from the +Photogenics (tm) image processing software (of which the main program is also +written in E!). diff --git a/amigae33a/E_v3.3a/Src/Src/Library/Stack/stack_pragmas.h b/amigae33a/E_v3.3a/Src/Src/Library/Stack/stack_pragmas.h new file mode 100644 index 0000000..47d74df --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Library/Stack/stack_pragmas.h @@ -0,0 +1,5 @@ +#pragma libcall stackbase Stack 1e 0 +#pragma libcall stackbase End 24 001 +#pragma libcall stackbase Push 2a 0802 +#pragma libcall stackbase Pop 30 001 +#pragma libcall stackbase Isempty 36 001 diff --git a/amigae33a/E_v3.3a/Src/Src/Library/Stack/stacklib.e b/amigae33a/E_v3.3a/Src/Src/Library/Stack/stacklib.e new file mode 100644 index 0000000..e8f7d8f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Library/Stack/stacklib.e @@ -0,0 +1,26 @@ +/* A stack library. uses the stack class. */ + +LIBRARY 'stack.library',1,1,'bla' IS stack,end,push,pop,isempty + +MODULE 'class/stack' + +PROC stack() HANDLE + DEF x=NIL:PTR TO stack + NEW x.stack() +EXCEPT DO -> prevent "NEW" exceptions being thrown out of the library +ENDPROC x + +PROC end(st:PTR TO stack) + END st +ENDPROC + +PROC push(st:PTR TO stack,v) HANDLE + st.push(v) +EXCEPT DO +ENDPROC + +PROC pop(st:PTR TO stack) IS st.pop() +PROC isempty(st:PTR TO stack) IS st.is_empty() + +PROC main() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Library/Stack/stackuse.c b/amigae33a/E_v3.3a/Src/Src/Library/Stack/stackuse.c new file mode 100644 index 0000000..9149395 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Library/Stack/stackuse.c @@ -0,0 +1,21 @@ +/* This uses an E stack-class from C + the pragmas were generated from the .fd file outputted by + `ShowModule -c stack.m' + (finally true OO programming for C! ;-) +*/ + +#include "stack_pragmas.h" +#include + +int main() { + int s,a,stackbase; + if(stackbase=OpenLibrary("stack.library",0)) { + if(s=Stack()) { + for(a=1;a<=12;a++) Push(s,a); + while(!Isempty(s)) printf("element = %ld\n",Pop(s)); + End(s); + }; + CloseLibrary(stackbase); + }; + return 0; +}; diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/animationclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/animationclass.e new file mode 100644 index 0000000..e688265 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/animationclass.e @@ -0,0 +1,81 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'graphics/gfx', + 'graphics/view' + +#define ANIMATIONDTCLASS 'animation.datatype' + +CONST ADTA_DUMMY=$80001258, + ADTA_MODEID=$800010C8, + ADTA_KEYFRAME=$800010CA, + ADTA_COLORREGISTERS=$800010CB, + ADTA_CREGS=$800010CC, + ADTA_GREGS=$800010CD, + ADTA_COLORTABLE=$800010CE, + ADTA_COLORTABLE2=$800010CF, + ADTA_ALLOCATED=$800010D0, + ADTA_NUMCOLORS=$800010D1, + ADTA_NUMALLOC=$800010D2, + ADTA_REMAP=$800010D3, + ADTA_SCREEN=$800010D4, + ADTA_NUMSPARSE=$800010D9, -> Data for this tag is unsigned INT + ADTA_SPARSETABLE=$800010DA, + ADTA_WIDTH=$80001259, + ADTA_HEIGHT=$8000125A, + ADTA_DEPTH=$8000125B, + ADTA_FRAMES=$8000125C, + ADTA_FRAME=$8000125D, + ADTA_FRAMESPERSECOND=$8000125E, + ADTA_FRAMEINCREMENT=$8000125F, + ADTA_SAMPLE=$800011F6, + ADTA_SAMPLELENGTH=$800011F7, + ADTA_PERIOD=$800011F8, + ADTA_VOLUME=$800011F9, + ADTA_CYCLES=$800011FA, + ID_ANIM="ANIM", + ID_ANHD="ANHD", + ID_DLTA="DLTA" + +OBJECT animheader + operation:CHAR + mask:CHAR + width:INT -> This is unsigned + height:INT -> This is unsigned + left:INT + top:INT + abstime:LONG + reltime:LONG + interleave:CHAR + pad0:CHAR + flags:LONG + pad[16]:ARRAY +ENDOBJECT + +CONST ADTM_DUMMY=$700, + ADTM_LOADFRAME=$701, + ADTM_UNLOADFRAME=$702, + ADTM_START=$703, + ADTM_PAUSE=$704, + ADTM_STOP=$705, + ADTM_LOCATE=$706 + +OBJECT adtframe + methodid:LONG + timestamp:LONG + frame:LONG + duration:LONG + bitmap:PTR TO bitmap + cmap:PTR TO colormap + sample:PTR TO CHAR + samplelength:LONG + period:LONG + userdata:LONG +ENDOBJECT + +OBJECT adtstart + methodid:LONG + frame:LONG +ENDOBJECT diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypes.e b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypes.e new file mode 100644 index 0000000..4d2faa7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypes.e @@ -0,0 +1,107 @@ +OPT MODULE +OPT EXPORT + +MODULE 'dos/dos', + 'exec/libraries', + 'exec/lists', + 'exec/nodes', + 'libraries/iffparse', + 'utility/tagitem' + +CONST ID_DTYP=$44545950, + ID_DTHD=$44544844 + +OBJECT datatypeheader + name:PTR TO CHAR + basename:PTR TO CHAR + pattern:PTR TO CHAR + mask:PTR TO INT + groupid:LONG + id:LONG + masklen:INT + pad:INT + flags:INT -> This is unsigned + priority:INT -> This is unsigned +ENDOBJECT /* SIZEOF=32 */ + +CONST DTF_TYPE_MASK=15, + DTF_BINARY=0, + DTF_ASCII=1, + DTF_IFF=2, + DTF_MISC=3, + DTF_CASE=16, + DTF_SYSTEM1=$1000, + GID_SYSTEM=$73797374, + GID_TEXT=$74657874, + GID_DOCUMENT=$646F6375, + GID_SOUND=$736F756E, + GID_INSTRUMENT=$696E7374, + GID_MUSIC=$6D757369, + GID_PICTURE=$70696374, + GID_ANIMATION=$616E696D, + GID_MOVIE=$6D6F7669, + ID_CODE=$44544344, + DTHSIZE=32 + +OBJECT dthookcontext + sysbase:PTR TO lib + dosbase:PTR TO lib + iffparsebase:PTR TO lib + utilitybase:PTR TO lib + lock:LONG + fib:PTR TO fileinfoblock + filehandle:LONG + iff:PTR TO iffhandle + buffer:PTR TO CHAR + bufferlength:LONG +ENDOBJECT /* SIZEOF=40 */ + +CONST ID_TOOL=$4454544C + +OBJECT tool + which:INT -> This is unsigned + flags:INT -> This is unsigned + program:PTR TO CHAR +ENDOBJECT /* SIZEOF=8 */ + +CONST TW_INFO=1, + TW_BROWSE=2, + TW_EDIT=3, + TW_PRINT=4, + TW_MAIL=5, + TF_LAUNCH_MASK=15, + TF_SHELL=1, + TF_WORKBENCH=2, + TF_RX=3, + ID_TAGS=$44545447 + +OBJECT datatype + node1:ln + node2:ln + header:PTR TO datatypeheader + toollist:lh + functionname:PTR TO CHAR + attrlist:PTR TO tagitem + length:LONG +ENDOBJECT /* SIZEOF=58 */ + +OBJECT toolnode + node:ln + tool:tool + length:LONG +ENDOBJECT /* SIZEOF=26 */ + +CONST ID_NAME=$4E414D45, + DTERROR_UNKNOWN_DATATYPE=$7D0, + DTERROR_COULDNT_SAVE=$7D1, + DTERROR_COULDNT_OPEN=$7D2, + DTERROR_COULDNT_SEND_MESSAGE=$7D3, + DTERROR_COULDNT_OPEN_CLIPBOARD=$7D4, + DTERROR_RESERVED=$7D5, + DTERROR_UNKNOWN_COMPRESSION=$7D6, + DTERROR_NOT_ENOUGH_DATA=$7D7, + DTERROR_INVALID_DATA=$7D8, + DTMSG_TYPE_OFFSET=$834, + DTNSIZE=58, + TNSIZE=26 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypesclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypesclass.e new file mode 100644 index 0000000..84933b9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/datatypesclass.e @@ -0,0 +1,234 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define DATATYPESCLASS 'datatypesclass' + +MODULE 'exec/io', + 'exec/semaphores', + 'graphics/gfx', + 'graphics/rastport', + 'graphics/view', + 'intuition/cghooks', + 'intuition/screens', + 'utility/tagitem' + +CONST DTA_DUMMY=$80001000, + DTA_TEXTATTR=$8000100A, + DTA_TOPVERT=$8000100B, + DTA_VISIBLEVERT=$8000100C, + DTA_TOTALVERT=$8000100D, + DTA_VERTUNIT=$8000100E, + DTA_TOPHORIZ=$8000100F, + DTA_VISIBLEHORIZ=$80001010, + DTA_TOTALHORIZ=$80001011, + DTA_HORIZUNIT=$80001012, + DTA_NODENAME=$80001013, + DTA_TITLE=$80001014, + DTA_TRIGGERMETHODS=$80001015, + DTA_DATA=$80001016, + DTA_TEXTFONT=$80001017, + DTA_METHODS=$80001018, + DTA_PRINTERSTATUS=$80001019, + DTA_PRINTERPROC=$8000101A, + DTA_LAYOUTPROC=$8000101B, + DTA_BUSY=$8000101C, + DTA_SYNC=$8000101D, + DTA_BASENAME=$8000101E, + DTA_GROUPID=$8000101F, + DTA_ERRORLEVEL=$80001020, + DTA_ERRORNUMBER=$80001021, + DTA_ERRORSTRING=$80001022, + DTA_CONDUCTOR=$80001023, + DTA_CONTROLPANEL=$80001024, + DTA_IMMEDIATE=$80001025, + DTA_REPEAT=$80001026, + DTA_NAME=$80001064, + DTA_SOURCETYPE=$80001065, + DTA_HANDLE=$80001066, + DTA_DATATYPE=$80001067, + DTA_DOMAIN=$80001068, + DTA_LEFT=$80001069, + DTA_TOP=$8000106A, + DTA_WIDTH=$8000106B, + DTA_HEIGHT=$8000106C, + DTA_OBJNAME=$8000106D, + DTA_OBJAUTHOR=$8000106E, + DTA_OBJANNOTATION=$8000106F, + DTA_OBJCOPYRIGHT=$80001070, + DTA_OBJVERSION=$80001071, + DTA_OBJECTID=$80001072, + DTA_USERDATA=$80001073, + DTA_FRAMEINFO=$80001074, + DTA_RELRIGHT=$80001075, + DTA_RELBOTTOM=$80001076, + DTA_RELWIDTH=$80001077, + DTA_RELHEIGHT=$80001078, + DTA_SELECTDOMAIN=$80001079, + DTA_TOTALPVERT=$8000107A, + DTA_TOTALPHORIZ=$8000107B, + DTA_NOMINALVERT=$8000107C, + DTA_NOMINALHORIZ=$8000107D, + DTA_DESTCOLS=$80001190, + DTA_DESTROWS=$80001191, + DTA_SPECIAL=$80001192, -> Data for this tag is unsigned INT + DTA_RASTPORT=$80001193, + DTA_AREXXPORTNAME=$80001194, + DTST_RAM=1, + DTST_FILE=2, + DTST_CLIPBOARD=3, + DTST_HOTLINK=4 + + +OBJECT dtspecialinfo + lock:ss + flags:LONG + topvert:LONG + visvert:LONG + totvert:LONG + otopvert:LONG + vertunit:LONG + tophoriz:LONG + vishoriz:LONG + tothoriz:LONG + otophoriz:LONG + horizunit:LONG +ENDOBJECT /* SIZEOF=90 */ + +CONST DTSIF_LAYOUT=1, + DTSIF_NEWSIZE=2, + DTSIF_DRAGGING=4, + DTSIF_DRAGSELECT=8, + DTSIF_HIGHLIGHT=16, + DTSIF_PRINTING=$20, + DTSIF_LAYOUTPROC=$40 + +OBJECT dtmethod + label:PTR TO CHAR + command:PTR TO CHAR + method:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST DTM_FRAMEBOX=$601, + DTM_PROCLAYOUT=$602, + DTM_ASYNCLAYOUT=$603, + DTM_REMOVEDTOBJECT=$604, + DTM_SELECT=$605, + DTM_CLEARSELECTED=$606, + DTM_COPY=$607, + DTM_PRINT=$608, + DTM_ABORTPRINT=$609, + DTM_NEWMEMBER=$610, + DTM_DISPOSEMEMBER=$611, + DTM_GOTO=$630, + DTM_TRIGGER=$631, + DTM_OBTAINDRAWINFO=$640, + DTM_DRAW=$641, + DTM_RELEASEDRAWINFO=$642, + DTM_WRITE=$650 + +OBJECT frameinfo + propertyflags:LONG + resolution:tpoint + redbits:CHAR + greenbits:CHAR + bluebits:CHAR + width:LONG + height:LONG + depth:LONG + screen:PTR TO screen + colormap:PTR TO colormap + flags:LONG +ENDOBJECT /* SIZEOF=35 */ + +CONST FIF_SCALABLE=1, + FIF_SCROLLABLE=2, + FIF_REMAPPABLE=4 + +OBJECT dtgeneral + methodid:LONG + ginfo:PTR TO gadgetinfo +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT dtselect + methodid:LONG + ginfo:PTR TO gadgetinfo + select:rectangle +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT dtframebox + methodid:LONG + ginfo:PTR TO gadgetinfo + contentsinfo:PTR TO frameinfo + frameinfo:PTR TO frameinfo + sizeframeinfo:LONG + frameflags:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST FRAMEF_SPECIFY=1 + +OBJECT dtgoto + methodid:LONG + ginfo:PTR TO gadgetinfo + nodename:PTR TO CHAR + attrlist:PTR TO tagitem +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT dttrigger + methodid:LONG + ginfo:PTR TO gadgetinfo + function:LONG + data:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST STM_PAUSE=1, + STM_PLAY=2, + STM_CONTENTS=3, + STM_INDEX=4, + STM_RETRACE=5, + STM_BROWSE_PREV=6, + STM_BROWSE_NEXT=7, + STM_NEXT_FIELD=8, + STM_PREV_FIELD=9, + STM_ACTIVATE_FIELD=10, + STM_COMMAND=11, + STM_REWIND=12, + STM_FASTFORWARD=13, + STM_STOP=14, + STM_RESUME=15, + STM_LOCATE=16 + +-> Um, this object was missing +OBJECT dtprint + methodid:LONG + ginfo:PTR TO gadgetinfo +-> a) next is unioned with "iodrp:PTR TO iodrpreq" +-> b) next is unioned with "iopc:PTR TO ioprtcmdreq"" + ios:PTR TO iostd + attrlist:PTR TO tagitem +ENDOBJECT + +OBJECT dtdraw + methodid:LONG + rport:PTR TO rastport + left:LONG + top:LONG + width:LONG + height:LONG + tophoriz:LONG + topvert:LONG + attrlist:PTR TO tagitem +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT dtwrite + methodid:LONG + ginfo:PTR TO gadgetinfo + filehandle:LONG + mode:LONG + attrlist:PTR TO tagitem +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST DTWM_IFF=0, + DTWM_RAW=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/pictureclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/pictureclass.e new file mode 100644 index 0000000..1479fb6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/pictureclass.e @@ -0,0 +1,67 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +CONST PDTA_MODEID=$800010C8, + PDTA_BITMAPHEADER=$800010C9, + PDTA_BITMAP=$800010CA, + PDTA_COLORREGISTERS=$800010CB, + PDTA_CREGS=$800010CC, + PDTA_GREGS=$800010CD, + PDTA_COLORTABLE=$800010CE, + PDTA_COLORTABLE2=$800010CF, + PDTA_ALLOCATED=$800010D0, + PDTA_NUMCOLORS=$800010D1, + PDTA_NUMALLOC=$800010D2, + PDTA_REMAP=$800010D3, + PDTA_SCREEN=$800010D4, + PDTA_FREESOURCEBITMAP=$800010D5, + PDTA_GRAB=$800010D6, + PDTA_DESTBITMAP=$800010D7, + PDTA_CLASSBITMAP=$800010D8, + PDTA_NUMSPARSE=$800010D9, -> Data for this tag is unsigned INT + PDTA_SPARSETABLE=$800010DA, + MSKNONE=0, + MSKHASMASK=1, + MSKHASTRANSPARENTCOLOR=2, + MSKLASSO=3, + MSKHASALPHA=4, + CMPNONE=0, + CMPBYTERUN1=1, + CMPBYTERUN2=2 + +#define PICTUREDTCLASS 'picture.datatype' + +OBJECT bitmapheader + width:INT -> This is unsigned + height:INT -> This is unsigned + left:INT + top:INT + depth:CHAR + masking:CHAR + compression:CHAR + pad:CHAR + transparent:INT -> This is unsigned + xaspect:CHAR + yaspect:CHAR + pagewidth:INT + pageheight:INT +ENDOBJECT /* SIZEOF=20 */ + +OBJECT colorregister + red:CHAR + green:CHAR + blue:CHAR +ENDOBJECT /* SIZEOF=3 */ + +CONST ID_ILBM=$494C424D, + ID_BMHD=$424D4844, + ID_BODY=$424F4459, + ID_CMAP=$434D4150, + ID_CRNG=$43524E47, + ID_GRAB=$47524142, + ID_SPRT=$53505254, + ID_DEST=$44455354, + ID_CAMG=$43414D47 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/soundclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/soundclass.e new file mode 100644 index 0000000..bc8d624 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/soundclass.e @@ -0,0 +1,34 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +CONST SDTA_DUMMY=$800011F4, + SDTA_VOICEHEADER=$800011F5, + SDTA_SAMPLE=$800011F6, + SDTA_SAMPLELENGTH=$800011F7, + SDTA_PERIOD=$800011F8, -> Data for this tag is unsigned INT + SDTA_VOLUME=$800011F9, -> Data for this tag is unsigned INT + SDTA_CYCLES=$800011FA, + SDTA_SIGNALTASK=$800011FB, + SDTA_SIGNALBIT=$800011FC, + SDTA_CONTINUOUS=$800011FD + +#define SOUNDDTCLASS 'sound.datatype' + +OBJECT voiceheader + oneshothisamples:LONG + repeathisamples:LONG + samplesperhicycle:LONG + samplespersec:INT -> This is unsigned + octaves:CHAR + compression:CHAR + volume:LONG +ENDOBJECT /* SIZEOF=20 */ + +CONST CMP_NONE=0, + CMP_FIBDELTA=1, + ID_8SVX=$38535658, + ID_VHDR=$56484452, + ID_BODY=$424F4459 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/textclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/textclass.e new file mode 100644 index 0000000..df5e15e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/datatypes/textclass.e @@ -0,0 +1,38 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/nodes' + +CONST TDTA_BUFFER=$8000112C, + TDTA_BUFFERLEN=$8000112D, + TDTA_LINELIST=$8000112E, + TDTA_WORDSELECT=$8000112F, + TDTA_WORDDELIM=$80001130, + TDTA_WORDWRAP=$80001131 + +#define TEXTDTCLASS 'text.datatype' + +OBJECT line + link:mln + text:PTR TO CHAR + textlen:LONG + xoffset:INT -> This is unsigned + yoffset:INT -> This is unsigned + width:INT -> This is unsigned + height:INT -> This is unsigned + flags:INT -> This is unsigned + fgpen:CHAR -> This is signed + bgpen:CHAR -> This is signed + style:LONG + data:LONG +ENDOBJECT /* SIZEOF=36 */ + +CONST LNF_LF=1, + LNF_LINK=2, + LNF_OBJECT=4, + LNF_SELECTED=8, + ID_FTXT=$46545854, + ID_CHRS=$43485253 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/audio.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/audio.e new file mode 100644 index 0000000..cb7f64c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/audio.e @@ -0,0 +1,43 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/io', + 'exec/ports' + +#define AUDIONAME 'audio.device' + +CONST ADHARD_CHANNELS=4, + ADALLOC_MINPREC=$FFFFFF80, + ADALLOC_MAXPREC=$7F, + ADCMD_FREE=9, + ADCMD_SETPREC=10, + ADCMD_FINISH=11, + ADCMD_PERVOL=12, + ADCMD_LOCK=13, + ADCMD_WAITCYCLE=14, + ADCMD_ALLOCATE=$20, + ADIOB_PERVOL=4, + ADIOF_PERVOL=16, + ADIOB_SYNCCYCLE=5, + ADIOF_SYNCCYCLE=$20, + ADIOB_NOWAIT=6, + ADIOF_NOWAIT=$40, + ADIOB_WRITEMESSAGE=7, + ADIOF_WRITEMESSAGE=$80, + ADIOERR_NOALLOCATION=-10, + ADIOERR_ALLOCFAILED=-11, + ADIOERR_CHANNELSTOLEN=-12 + +OBJECT ioaudio + io:io + allockey:INT + data:PTR TO CHAR + length:LONG + period:INT -> This is unsigned + volume:INT -> This is unsigned + cycles:INT -> This is unsigned + writemsg:mn +ENDOBJECT /* SIZEOF=68 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/bootblock.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/bootblock.e new file mode 100644 index 0000000..d29bb21 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/bootblock.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +OBJECT bb + id[4]:ARRAY + chksum:LONG + dosblock:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST BOOTSECTS=2, + BBNAME_DOS=$444F5300, + BBNAME_KICK=$4B49434B diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/cd.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/cd.e new file mode 100644 index 0000000..4a7df38 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/cd.e @@ -0,0 +1,172 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +CONST CD_RESET=1, + CD_READ=2, + CD_WRITE=3, + CD_UPDATE=4, + CD_CLEAR=5, + CD_STOP=6, + CD_START=7, + CD_FLUSH=8, + CD_MOTOR=9, + CD_SEEK=10, + CD_FORMAT=11, + CD_REMOVE=12, + CD_CHANGENUM=13, + CD_CHANGESTATE=14, + CD_PROTSTATUS=15, + CD_GETDRIVETYPE=18, + CD_GETNUMTRACKS=19, + CD_ADDCHANGEINT=20, + CD_REMCHANGEINT=21, + CD_GETGEOMETRY=22, + CD_EJECT=23, + CD_INFO=32, + CD_CONFIG=33, + CD_TOCMSF=34, + CD_TOCLSN=35, + CD_READXL=36, + CD_PLAYTRACK=37, + CD_PLAYMSF=38, + CD_PLAYLSN=39, + CD_PAUSE=40, + CD_SEARCH=41, + CD_QCODEMSF=42, + CD_QCODELSN=43, + CD_ATTENUATE=44, + CD_ADDFRAMEINT=45, + CD_REMFRAMEINT=46, + CDERR_OPENFAIL=-1, + CDERR_ABORTED=-2, + CDERR_NOCMD=-3, + CDERR_BADLENGTH=-4, + CDERR_BADADDRESS=-5, + CDERR_UNITBUSY=-6, + CDERR_SELFTEST=-7, + CDERR_NOTSPECIFIED=20, + CDERR_NOSECHDR=21, + CDERR_BADSECPREAMBLE=22, + CDERR_BADSECID=23, + CDERR_BADHDRSUM=24, + CDERR_BADSECSUM=25, + CDERR_TOOFEWSECS=26, + CDERR_BADSECHDR=27, + CDERR_WRITEPROT=28, + CDERR_NODISK=29, + CDERR_SEEKERROR=30, + CDERR_NOMEM=31, + CDERR_BADUNITNUM=32, + CDERR_BADDRIVETYPE=33, + CDERR_DRIVEINUSE=34, + CDERR_POSTRESET=35, + CDERR_BADDATATYPE=36, + CDERR_INVALIDSTATE=37, + CDERR_PHASE=42, + CDERR_NOBOARD=50, + TAGCD_PLAYSPEED=1, + TAGCD_READSPEED=2, + TAGCD_READXLSPEED=3, + TAGCD_SECTORSIZE=4, + TAGCD_XLECC=5, + TAGCD_EJECTRESET=6 + +OBJECT cdinfo + playspeed:INT -> This is unsigned + readspeed:INT -> This is unsigned + readxlspeed:INT -> This is unsigned + sectorsize:INT -> This is unsigned + xlecc:INT -> This is unsigned + ejectreset:INT -> This is unsigned + reserved1[4]:ARRAY OF INT -> Array is unsigned + maxspeed:INT -> This is unsigned + audioprecision:INT -> This is unsigned + status:INT -> This is unsigned + reserved2[4]:ARRAY OF INT -> Array is unsigned +ENDOBJECT + +CONST CDSTSB_CLOSED=0, + CDSTSB_DISK=1, + CDSTSB_SPIN=2, + CDSTSB_TOC=3, + CDSTSB_CDROM=4, + CDSTSB_PLAYING=5, + CDSTSB_PAUSED=6, + CDSTSB_SEARCH=7, + CDSTSB_DIRECTION=8, + CDSTSF_CLOSED=1, + CDSTSF_DISK=2, + CDSTSF_SPIN=4, + CDSTSF_TOC=8, + CDSTSF_CDROM=$10, + CDSTSF_PLAYING=$20, + CDSTSF_PAUSED=$40, + CDSTSF_SEARCH=$80, + CDSTSF_DIRECTION=$100, + CDMODE_NORMAL=0, + CDMODE_FFWD=1, + CDMODE_FREV=2 + +OBJECT rmsf + reserved:CHAR + minute:CHAR + second:CHAR + frame:CHAR +ENDOBJECT + +OBJECT lsnmsf +-> a) next is unioned with "lsn:LONG" + msf:rmsf +ENDOBJECT + +OBJECT cdxl + node:mln + buffer:PTR TO CHAR + length:LONG + actual:LONG + intdata:LONG + intcode:LONG +ENDOBJECT + +OBJECT tocsummary + firsttrack:CHAR + lasttrack:CHAR + leadout:lsnmsf +ENDOBJECT + +OBJECT tocentry + ctladr:CHAR + track:CHAR + position:lsnmsf +ENDOBJECT + +OBJECT cdtoc +-> a) next is unioned with "summary:tocsummary" + entry:tocentry +ENDOBJECT + +OBJECT qcode + ctladr:CHAR + track:CHAR + index:CHAR + zero:CHAR + trackposition:lsnmsf + diskposition:lsnmsf +ENDOBJECT + +CONST CTLADR_CTLMASK=$F0, + CTL_CTLMASK=$D0, + CTL_2AUD=0, + CTL_2AUDEMPH=$10, + CTL_4AUD=$80, + CTL_4AUDEMPH=$90, + CTL_DATA=$40, + CTL_COPYMASK=$20, + CTL_COPY=$20, + CTLADR_ADRMASK=$F, + ADR_POSITION=1, + ADR_UPC=2, + ADR_ISRC=3, + ADR_HYBRID=5 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/clipboard.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/clipboard.e new file mode 100644 index 0000000..12db9fd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/clipboard.e @@ -0,0 +1,47 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/devices', + 'exec/nodes', + 'exec/ports' + +CONST DEVICES_CLIPBOARD_I=1, + CBD_POST=9, + CBD_CURRENTREADID=10, + CBD_CURRENTWRITEID=11, + CBD_CHANGEHOOK=12, + CBERR_OBSOLETEID=1 + +OBJECT clipboardunitpartial + node:ln + unitnum:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT ioclipreq + message:mn + device:PTR TO dd + unit:PTR TO clipboardunitpartial + command:INT -> This is unsigned + flags:CHAR + error:CHAR -> This is signed + actual:LONG + length:LONG + data:PTR TO CHAR + offset:LONG + clipid:LONG +ENDOBJECT /* SIZEOF=52 */ + +CONST PRIMARY_CLIP=0 + +OBJECT satisfymsg + msg:mn + unit:INT -> This is unsigned + clipid:LONG +ENDOBJECT /* SIZEOF=26 */ + +OBJECT cliphookmsg + type:LONG + changecmd:LONG + clipid:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/console.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/console.e new file mode 100644 index 0000000..9bad7a9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/console.e @@ -0,0 +1,62 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +CONST CD_ASKKEYMAP=9, + CD_SETKEYMAP=10, + CD_ASKDEFAULTKEYMAP=11, + CD_SETDEFAULTKEYMAP=12, + SGR_PRIMARY=0, + SGR_BOLD=1, + SGR_ITALIC=3, + SGR_UNDERSCORE=4, + SGR_NEGATIVE=7, + SGR_NORMAL=22, + SGR_NOTITALIC=23, + SGR_NOTUNDERSCORE=24, + SGR_POSITIVE=27, + SGR_BLACK=30, + SGR_RED=31, + SGR_GREEN=$20, + SGR_YELLOW=$21, + SGR_BLUE=$22, + SGR_MAGENTA=$23, + SGR_CYAN=$24, + SGR_WHITE=$25, + SGR_DEFAULT=$27, + SGR_BLACKBG=$28, + SGR_REDBG=$29, + SGR_GREENBG=$2A, + SGR_YELLOWBG=$2B, + SGR_BLUEBG=$2C, + SGR_MAGENTABG=$2D, + SGR_CYANBG=$2E, + SGR_WHITEBG=$2F, + SGR_DEFAULTBG=$31, + SGR_CLR0=30, + SGR_CLR1=31, + SGR_CLR2=$20, + SGR_CLR3=$21, + SGR_CLR4=$22, + SGR_CLR5=$23, + SGR_CLR6=$24, + SGR_CLR7=$25, + SGR_CLR0BG=$28, + SGR_CLR1BG=$29, + SGR_CLR2BG=$2A, + SGR_CLR3BG=$2B, + SGR_CLR4BG=$2C, + SGR_CLR5BG=$2D, + SGR_CLR6BG=$2E, + SGR_CLR7BG=$2F, + DSR_CPR=6, + CTC_HSETTAB=0, + CTC_HCLRTAB=2, + CTC_HCLRTABSALL=5, + TBC_HCLRTAB=0, + TBC_HCLRTABSALL=3, + M_LNM=20 + +#define M_ASM '>1' +#define M_AWM '?7' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/conunit.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/conunit.e new file mode 100644 index 0000000..46e2f72 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/conunit.e @@ -0,0 +1,57 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/keymap', + 'exec/ports', + 'graphics/text', + 'intuition/intuition' + +CONST CONU_LIBRARY=-1, + CONU_STANDARD=0, + CONU_CHARMAP=1, + CONU_SNIPMAP=3, + CONFLAG_DEFAULT=0, + CONFLAG_NODRAW_ON_NEWSIZE=1, + PMB_ASM=21, + PMB_AWM=22, + MAXTABS=$50 + +OBJECT conunit + mp:mp + window:PTR TO window + xcp:INT + ycp:INT + xmax:INT + ymax:INT + xrsize:INT + yrsize:INT + xrorigin:INT + yrorigin:INT + xrextant:INT + yrextant:INT + xminshrink:INT + yminshrink:INT + xccp:INT + yccp:INT + keymapstruct:keymap + tabstops[$50]:ARRAY OF INT -> Array is unsigned + mask:CHAR -> This is signed + fgpen:CHAR -> This is signed + bgpen:CHAR -> This is signed + aolpen:CHAR -> This is signed + drawmode:CHAR -> This is signed + obsolete1:CHAR + obsolete2:LONG + minterms[8]:ARRAY + font:PTR TO textfont + algostyle:CHAR + txflags:CHAR + txheight:INT -> This is unsigned + txwidth:INT -> This is unsigned + txbaseline:INT -> This is unsigned + txspacing:INT + modes[3]:ARRAY +-> Um, have to fiddle alignment in .m file + rawevents[3]:ARRAY +ENDOBJECT /* SIZEOF=296 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/gameport.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/gameport.e new file mode 100644 index 0000000..ed23a0a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/gameport.e @@ -0,0 +1,27 @@ +OPT MODULE +OPT EXPORT + +CONST GPD_READEVENT=9, + GPD_ASKCTYPE=10, + GPD_SETCTYPE=11, + GPD_ASKTRIGGER=12, + GPD_SETTRIGGER=13, + GPTB_DOWNKEYS=0, + GPTF_DOWNKEYS=1, + GPTB_UPKEYS=1, + GPTF_UPKEYS=2 + +OBJECT gameporttrigger + keys:INT -> This is unsigned + timeout:INT -> This is unsigned + xdelta:INT -> This is unsigned + ydelta:INT -> This is unsigned +ENDOBJECT /* SIZEOF=8 */ + +CONST GPCT_ALLOCATED=-1, + GPCT_NOCONTROLLER=0, + GPCT_MOUSE=1, + GPCT_RELJOYSTICK=2, + GPCT_ABSJOYSTICK=3, + GPDERR_SETCTYPE=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/hardblocks.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/hardblocks.e new file mode 100644 index 0000000..7119321 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/hardblocks.e @@ -0,0 +1,134 @@ +OPT MODULE +OPT EXPORT + +OBJECT rigiddiskblock + id:LONG + summedlongs:LONG + chksum:LONG + hostid:LONG + blockbytes:LONG + flags:LONG + badblocklist:LONG + partitionlist:LONG + filesysheaderlist:LONG + driveinit:LONG + reserved1[6]:ARRAY OF LONG + cylinders:LONG + sectors:LONG + heads:LONG + interleave:LONG + park:LONG + reserved2[3]:ARRAY OF LONG + writeprecomp:LONG + reducedwrite:LONG + steprate:LONG + reserved3[5]:ARRAY OF LONG + rdbblockslo:LONG + rdbblockshi:LONG + locylinder:LONG + hicylinder:LONG + cylblocks:LONG + autoparkseconds:LONG + highrdskblock:LONG + reserved4:LONG + diskvendor[8]:ARRAY + diskproduct[16]:ARRAY + diskrevision[4]:ARRAY + controllervendor[8]:ARRAY + controllerproduct[16]:ARRAY + controllerrevision[4]:ARRAY + reserved5[10]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=256 */ + +CONST IDNAME_RIGIDDISK=$5244534B, + RDB_LOCATION_LIMIT=16, + RDBFB_LAST=0, + RDBFF_LAST=1, + RDBFB_LASTLUN=1, + RDBFF_LASTLUN=2, + RDBFB_LASTTID=2, + RDBFF_LASTTID=4, + RDBFB_NORESELECT=3, + RDBFF_NORESELECT=8, + RDBFB_DISKID=4, + RDBFF_DISKID=16, + RDBFB_CTRLRID=5, + RDBFF_CTRLRID=$20, + RDBFB_SYNCH=6, + RDBFF_SYNCH=$40 + +OBJECT badblockentry + badblock:LONG + goodblock:LONG +ENDOBJECT /* SIZEOF=8 */ + +OBJECT badblockblock + id:LONG + summedlongs:LONG + chksum:LONG + hostid:LONG + next:LONG + reserved:LONG + blockpairs[61]:ARRAY OF badblockentry +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST IDNAME_BADBLOCK=$42414442 + +OBJECT partitionblock + id:LONG + summedlongs:LONG + chksum:LONG + hostid:LONG + next:LONG + flags:LONG + reserved1[2]:ARRAY OF LONG + devflags:LONG + drivename[32]:ARRAY + reserved2[15]:ARRAY OF LONG + environment[17]:ARRAY OF LONG + ereserved[15]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=256 */ + +CONST IDNAME_PARTITION=$50415254, + PBFF_BOOTABLE=0, + PBFF_BOOTABLE=1, + PBFF_NOMOUNT=1, + PBFF_NOMOUNT=2 + +OBJECT filesysheaderblock + id:LONG + summedlongs:LONG + chksum:LONG + hostid:LONG + next:LONG + flags:LONG + reserved1[2]:ARRAY OF LONG + dostype:LONG + version:LONG + patchflags:LONG + type:LONG + task:LONG + lock:LONG + handler:LONG + stacksize:LONG + priority:LONG + startup:LONG + seglistblocks:LONG + globalvec:LONG + reserved2[23]:ARRAY OF LONG + reserved3[21]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=256 */ + +CONST IDNAME_FILESYSHEADER=$46534844 + +OBJECT loadsegblock + id:LONG + summedlongs:LONG + chksum:LONG + hostid:LONG + next:LONG + loaddata[123]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST IDNAME_LOADSEG=$4C534547 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/input.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/input.e new file mode 100644 index 0000000..61ff5d3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/input.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +CONST IND_ADDHANDLER=9, + IND_REMHANDLER=10, + IND_WRITEEVENT=11, + IND_SETTHRESH=12, + IND_SETPERIOD=13, + IND_SETMPORT=14, + IND_SETMTYPE=15, + IND_SETMTRIG=16 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/inputevent.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/inputevent.e new file mode 100644 index 0000000..39d2cd2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/inputevent.e @@ -0,0 +1,135 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/timer', + 'intuition/screens', + 'utility/hooks', + 'utility/tagitem' + +CONST IECLASS_NULL=0, + IECLASS_RAWKEY=1, + IECLASS_RAWMOUSE=2, + IECLASS_EVENT=3, + IECLASS_POINTERPOS=4, + IECLASS_TIMER=6, + IECLASS_GADGETDOWN=7, + IECLASS_GADGETUP=8, + IECLASS_REQUESTER=9, + IECLASS_MENULIST=10, + IECLASS_CLOSEWINDOW=11, + IECLASS_SIZEWINDOW=12, + IECLASS_REFRESHWINDOW=13, + IECLASS_NEWPREFS=14, + IECLASS_DISKREMOVED=15, + IECLASS_DISKINSERTED=16, + IECLASS_ACTIVEWINDOW=17, + IECLASS_INACTIVEWINDOW=18, + IECLASS_NEWPOINTERPOS=19, + IECLASS_MENUHELP=20, + IECLASS_CHANGEWINDOW=21, + IECLASS_MAX=21, + IESUBCLASS_COMPATIBLE=0, + IESUBCLASS_PIXEL=1, + IESUBCLASS_TABLET=2, + IESUBCLASS_NEWTABLET=3 + +OBJECT iepointerpixel + screen:PTR TO screen + positionx:INT + positiony:INT +ENDOBJECT /* SIZEOF=8 */ + +OBJECT iepointertablet + rangex:INT -> This is unsigned + rangey:INT -> This is unsigned + valuex:INT -> This is unsigned + valuey:INT -> This is unsigned + pressure:INT +ENDOBJECT /* SIZEOF=10 */ + +OBJECT ienewtablet + callback:PTR TO hook + scaledx:INT -> This is unsigned + scaledy:INT -> This is unsigned + scaledxfraction:INT -> This is unsigned + scaledyfraction:INT -> This is unsigned + tabletx:LONG + tablety:LONG + rangex:LONG + rangey:LONG + taglist:PTR TO tagitem +ENDOBJECT /* SIZEOF=32 */ + +CONST IECODE_UP_PREFIX=$80, + IECODEB_UP_PREFIX=7, + IECODE_KEY_CODE_FIRST=0, + IECODE_KEY_CODE_LAST=$77, + IECODE_COMM_CODE_FIRST=$78, + IECODE_COMM_CODE_LAST=$7F, + IECODE_C0_FIRST=0, + IECODE_C0_LAST=31, + IECODE_ASCII_FIRST=$20, + IECODE_ASCII_LAST=$7E, + IECODE_ASCII_DEL=$7F, + IECODE_C1_FIRST=$80, + IECODE_C1_LAST=$9F, + IECODE_LATIN1_FIRST=$A0, + IECODE_LATIN1_LAST=$FF, + IECODE_LBUTTON=$68, + IECODE_RBUTTON=$69, + IECODE_MBUTTON=$6A, + IECODE_NOBUTTON=$FF, + IECODE_NEWACTIVE=1, + IECODE_NEWSIZE=2, + IECODE_REFRESH=3, + IECODE_REQSET=1, + IECODE_REQCLEAR=0, + IEQUALIFIER_LSHIFT=1, + IEQUALIFIER_RSHIFT=2, + IEQUALIFIER_CAPSLOCK=4, + IEQUALIFIER_CONTROL=8, + IEQUALIFIER_LALT=16, + IEQUALIFIER_RALT=$20, + IEQUALIFIER_LCOMMAND=$40, + IEQUALIFIER_RCOMMAND=$80, + IEQUALIFIER_NUMERICPAD=$100, + IEQUALIFIER_REPEAT=$200, + IEQUALIFIER_INTERRUPT=$400, + IEQUALIFIER_MULTIBROADCAST=$800, + IEQUALIFIER_MIDBUTTON=$1000, + IEQUALIFIER_RBUTTON=$2000, + IEQUALIFIER_LEFTBUTTON=$4000, + IEQUALIFIER_RELATIVEMOUSE=$8000, + IEQUALIFIERB_LSHIFT=0, + IEQUALIFIERB_RSHIFT=1, + IEQUALIFIERB_CAPSLOCK=2, + IEQUALIFIERB_CONTROL=3, + IEQUALIFIERB_LALT=4, + IEQUALIFIERB_RALT=5, + IEQUALIFIERB_LCOMMAND=6, + IEQUALIFIERB_RCOMMAND=7, + IEQUALIFIERB_NUMERICPAD=8, + IEQUALIFIERB_REPEAT=9, + IEQUALIFIERB_INTERRUPT=10, + IEQUALIFIERB_MULTIBROADCAST=11, + IEQUALIFIERB_MIDBUTTON=12, + IEQUALIFIERB_RBUTTON=13, + IEQUALIFIERB_LEFTBUTTON=14, + IEQUALIFIERB_RELATIVEMOUSE=15 + +OBJECT inputevent + nextevent:PTR TO inputevent + class:CHAR + subclass:CHAR + code:INT -> This is unsigned + qualifier:INT -> This is unsigned +-> a) next four CHARs are unioned as "eventaddress:LONG" +-> b) next two CHARs are unioned as "x:INT" + prev1downcode:CHAR + prev1downqual:CHAR +-> b) next two CHARs are unioned "y:INT" + prev2downcode:CHAR + prev2downqual:CHAR + timestamp:timeval +ENDOBJECT /* SIZEOF=22 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/keyboard.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/keyboard.e new file mode 100644 index 0000000..f02388f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/keyboard.e @@ -0,0 +1,9 @@ +OPT MODULE +OPT EXPORT + +CONST KBD_READEVENT=9, + KBD_READMATRIX=10, + KBD_ADDRESETHANDLER=11, + KBD_REMRESETHANDLER=12, + KBD_RESETHANDLERDONE=13 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/keymap.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/keymap.e new file mode 100644 index 0000000..3f5a301 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/keymap.e @@ -0,0 +1,49 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', + 'exec/nodes' + +OBJECT keymap + lokeymaptypes:PTR TO CHAR + lokeymap:PTR TO LONG + locapsable:PTR TO CHAR + lorepeatable:PTR TO CHAR + hikeymaptypes:PTR TO CHAR + hikeymap:PTR TO LONG + hicapsable:PTR TO CHAR + hirepeatable:PTR TO CHAR +ENDOBJECT /* SIZEOF=32 */ + +OBJECT keymapnode + node:ln + keymap:keymap +ENDOBJECT /* SIZEOF=46 */ + +OBJECT keymapresource + node:ln + list:lh +ENDOBJECT /* SIZEOF=28 */ + +CONST KCB_NOP=7, + KCF_NOP=$80, + KC_NOQUAL=0, + KC_VANILLA=7, + KCB_SHIFT=0, + KCF_SHIFT=1, + KCB_ALT=1, + KCF_ALT=2, + KCB_CONTROL=2, + KCF_CONTROL=4, + KCB_DOWNUP=3, + KCF_DOWNUP=8, + KCB_DEAD=5, + KCF_DEAD=$20, + KCB_STRING=6, + KCF_STRING=$40, + DPB_MOD=0, + DPF_MOD=1, + DPB_DEAD=3, + DPF_DEAD=8, + DP_2DINDEXMASK=15, + DP_2DFACSHIFT=4 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/narrator.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/narrator.e new file mode 100644 index 0000000..c90fc6a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/narrator.e @@ -0,0 +1,95 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/io' + +CONST DEFPITCH=$6E, + DEFRATE=$96, + DEFVOL=$40, + DEFFREQ=$56B8, + NATURALF0=0, + ROBOTICF0=1, + MANUALF0=2, + MALE=0, + FEMALE=1, + DEFSEX=0, + DEFMODE=0, + DEFARTIC=$64, + DEFCENTRAL=0, + DEFF0PERT=0, + DEFF0ENTHUS=$20, + DEFPRIORITY=$64, + MINRATE=$28, + MAXRATE=$190, + MINPITCH=$41, + MAXPITCH=$140, + MINFREQ=$1388, + MAXFREQ=$6D60, + MINVOL=0, + MAXVOL=$40, + MINCENT=0, + MAXCENT=$64, + ND_NOTUSED=-1, + ND_NOMEM=-2, + ND_NOAUDLIB=-3, + ND_MAKEBAD=-4, + ND_UNITERR=-5, + ND_CANTALLOC=-6, + ND_UNIMPL=-7, + ND_NOWRITE=-8, + ND_EXPUNGED=-9, + ND_PHONERR=-20, + ND_RATEERR=-21, + ND_PITCHERR=-22, + ND_SEXERR=-23, + ND_MODEERR=-24, + ND_FREQERR=-25, + ND_VOLERR=-26, + ND_DCENTERR=-27, + ND_CENTPHONERR=-28, + NDB_NEWIORB=0, + NDB_WORDSYNC=1, + NDB_SYLSYNC=2, + NDF_NEWIORB=1, + NDF_WORDSYNC=2, + NDF_SYLSYNC=4 + +OBJECT ndi + iostd:iostd + rate:INT -> This is unsigned + pitch:INT -> This is unsigned + mode:INT -> This is unsigned + sex:INT -> This is unsigned + chmasks:PTR TO CHAR + nummasks:INT -> This is unsigned + volume:INT -> This is unsigned + sampfreq:INT -> This is unsigned + mouths:CHAR + chanmask:CHAR + numchan:CHAR + flags:CHAR + f0enthusiasm:CHAR + f0perturb:CHAR + f1adj:CHAR -> This is signed + f2adj:CHAR -> This is signed + f3adj:CHAR -> This is signed + a1adj:CHAR -> This is signed + a2adj:CHAR -> This is signed + a3adj:CHAR -> This is signed + articulate:CHAR + centralize:CHAR + centphon:PTR TO CHAR + avbias:CHAR -> This is signed + afbias:CHAR -> This is signed + priority:CHAR -> This is signed + pad1:CHAR +ENDOBJECT /* SIZEOF=88 */ + +OBJECT mrb + ndi:ndi + width:CHAR + height:CHAR + shape:CHAR + sync:CHAR +ENDOBJECT /* SIZEOF=92 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/parallel.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/parallel.e new file mode 100644 index 0000000..133c5c3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/parallel.e @@ -0,0 +1,59 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/io' + +CONST PARERR_DEVBUSY=1, + PARERR_BUFTOOBIG=2, + PARERR_INVPARAM=3, + PARERR_LINEERR=4, + PARERR_NOTOPEN=5, + PARERR_PORTRESET=6, + PARERR_INITERR=7, + PDCMD_QUERY=9, + PDCMD_SETPARAMS=10, + PAR_DEVFINISH=10, + PARB_SHARED=5, + PARF_SHARED=$20, + PARB_SLOWMODE=4, + PARF_SLOWMODE=16, + PARB_FASTMODE=3, + PARF_FASTMODE=8, + PARB_RAD_BOOGIE=3, + PARF_RAD_BOOGIE=8, + PARB_ACKMODE=2, + PARF_ACKMODE=4, + PARB_EOFMODE=1, + PARF_EOFMODE=2, + IOPARB_QUEUED=6, + IOPARF_QUEUED=$40, + IOPARB_ABORT=5, + IOPARF_ABORT=$20, + IOPARB_ACTIVE=4, + IOPARF_ACTIVE=16, + IOPTB_RWDIR=3, + IOPTF_RWDIR=8, + IOPTB_PARSEL=2, + IOPTF_PARSEL=4, + IOPTB_PAPEROUT=1, + IOPTF_PAPEROUT=2, + IOPTB_PARBUSY=0, + IOPTF_PARBUSY=1 + +#define PARALLELNAME 'parallel.device' + +OBJECT ioparray +-> Um, names were wrong and illegal + ptermarray0:LONG + ptermarray1:LONG +ENDOBJECT /* SIZEOF=8 */ + +OBJECT ioextpar + iostd:iostd + pextflags:LONG + parstatus:CHAR + parflags:CHAR + ptermarray:ioparray +ENDOBJECT /* SIZEOF=62 */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/printer.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/printer.e new file mode 100644 index 0000000..ad18f7d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/printer.e @@ -0,0 +1,143 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/io', + 'graphics/rastport', + 'graphics/view' + +CONST DEVICES_PRINTER_I=1, + PRD_RAWWRITE=9, + PRD_PRTCOMMAND=10, + PRD_DUMPRPORT=11, + PRD_QUERY=12, + ARIS=0, + ARIN=1, + AIND=2, + ANEL=3, + ARI=4, + ASGR0=5, + ASGR3=6, + ASGR23=7, + ASGR4=8, + ASGR24=9, + ASGR1=10, + ASGR22=11, + ASFC=12, + ASBC=13, + ASHORP0=14, + ASHORP2=15, + ASHORP1=16, + ASHORP4=17, + ASHORP3=18, + ASHORP6=19, + ASHORP5=20, + ADEN6=21, + ADEN5=22, + ADEN4=23, + ADEN3=24, + ADEN2=25, + ADEN1=26, + ASUS2=27, + ASUS1=28, + ASUS4=29, + ASUS3=30, + ASUS0=31, + APLU=$20, + APLD=$21, + AFNT0=$22, + AFNT1=$23, + AFNT2=$24, + AFNT3=$25, + AFNT4=$26, + AFNT5=$27, + AFNT6=$28, + AFNT7=$29, + AFNT8=$2A, + AFNT9=$2B, + AFNT10=$2C, + APROP2=$2D, + APROP1=$2E, + APROP0=$2F, + ATSS=$30, + AJFY5=$31, + AJFY7=$32, + AJFY6=$33, + AJFY0=$34, + AJFY2=$35, + AJFY3=$36, + AVERP0=$37, + AVERP1=$38, + ASLPP=$39, + APERF=$3A, + APERF0=$3B, + ALMS=$3C, + ARMS=$3D, + ATMS=$3E, + ABMS=$3F, + ASTBM=$40, + ASLRM=$41, + ACAM=$42, + AHTS=$43, + AVTS=$44, + ATBC0=$45, + ATBC3=$46, + ATBC1=$47, + ATBC4=$48, + ATBCALL=$49, + ATBSALL=$4A, + AEXTEND=$4B, + ARAW=$4C + +OBJECT ioprtcmdreq + io:io + prtcommand:INT -> This is unsigned + parm0:CHAR + parm1:CHAR + parm2:CHAR + parm3:CHAR +ENDOBJECT /* SIZEOF=38 */ + +OBJECT iodrpreq + io:io + rastport:PTR TO rastport + colormap:PTR TO colormap + modes:LONG + srcx:INT -> This is unsigned + srcy:INT -> This is unsigned + srcwidth:INT -> This is unsigned + srcheight:INT -> This is unsigned + destcols:LONG + destrows:LONG + special:INT -> This is unsigned +ENDOBJECT /* SIZEOF=62 */ + +CONST SPECIAL_MILCOLS=1, + SPECIAL_MILROWS=2, + SPECIAL_FULLCOLS=4, + SPECIAL_FULLROWS=8, + SPECIAL_FRACCOLS=16, + SPECIAL_FRACROWS=$20, + SPECIAL_CENTER=$40, + SPECIAL_ASPECT=$80, + SPECIAL_DENSITY1=$100, + SPECIAL_DENSITY2=$200, + SPECIAL_DENSITY3=$300, + SPECIAL_DENSITY4=$400, + SPECIAL_DENSITY5=$500, + SPECIAL_DENSITY6=$600, + SPECIAL_DENSITY7=$700, + SPECIAL_NOFORMFEED=$800, + SPECIAL_TRUSTME=$1000, + SPECIAL_NOPRINT=$2000, + PDERR_NOERR=0, + PDERR_CANCEL=1, + PDERR_NOTGRAPHICS=2, + PDERR_INVERTHAM=3, + PDERR_BADDIMENSION=4, + PDERR_DIMENSIONOVFLOW=5, + PDERR_INTERNALMEMORY=6, + PDERR_BUFFERMEMORY=7, + PDERR_TOOKCONTROL=8, + SPECIAL_DENSITYMASK=$700, + SPECIAL_DIMENSIONSMASK=$bf + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/prtbase.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/prtbase.e new file mode 100644 index 0000000..4a9ffdc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/prtbase.e @@ -0,0 +1,116 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/serial', + 'devices/timer', + 'exec/libraries', + 'exec/ports', + 'exec/tasks', + 'intuition/preferences' + +CONST DEVICES_PRTBASE_I=1 + +OBJECT devicedata + lib:lib + segment:LONG + execbase:LONG + cmdvectors:LONG + cmdbytes:PTR TO CHAR + numcommands:INT -> This is unsigned +ENDOBJECT /* SIZEOF=52 */ + +CONST DU_FLAGS=9, + IOF_QUEUED=16, + IOF_CURRENT=$20, + IOF_SERVICING=$40, + IOF_DONE=$80, + DUF_STOPPED=1, + P_PRIORITY=0, + P_OLDSTKSIZE=$800, + P_STKSIZE=$1000, + P_BUFSIZE=$100, + P_SAFESIZE=$80, + PF_IOR0=1, + PF_IOR1=2, + PF_EXPUNGED=$80 + +OBJECT printerdata + dd:devicedata + unit:mp + printersegment:LONG + printertype:INT -> This is unsigned + segmentdata:PTR TO printersegment + printbuf:PTR TO CHAR + pwrite:LONG + pbothready:LONG +-> Um, these were both wrong +-> a) next is unioned with "p0:ioextpar" + s0:ioextser +-> a) next is unioned with "p1:ioextpar" + s1:ioextser + tior:timerequest + iorport:mp + tc:tc + oldstk[$800]:ARRAY + flags:CHAR + pad:CHAR + preferences:preferences + pwaitenabled:CHAR + pad1:CHAR + stk[$1000]:ARRAY +ENDOBJECT /* SIZEOF=6778 */ + +CONST PPCB_GFX=0, + PPCF_GFX=1, + PPCB_COLOR=1, + PPCF_COLOR=2, + PPC_BWALPHA=0, + PPC_BWGFX=1, + PPC_COLORALPHA=2, + PPC_COLORGFX=3, + PCC_BW=1, + PCC_YMC=2, + PCC_YMC_BW=3, + PCC_YMCB=4, + PCC_4COLOR=4, + PCC_ADDITIVE=8, + PCC_WB=9, + PCC_BGR=10, + PCC_BGR_WB=11, + PCC_BGRW=12, + PCC_MULTI_PASS=16 + +OBJECT printerextendeddata + printername:PTR TO CHAR + init:LONG + expunge:LONG + open:LONG + close:LONG + printerclass:CHAR + colorclass:CHAR + maxcolumns:CHAR + numcharsets:CHAR + numrows:INT -> This is unsigned + maxxdots:LONG + maxydots:LONG + xdotsinch:INT -> This is unsigned + ydotsinch:INT -> This is unsigned + commands:PTR TO LONG + dospecial:LONG + render:LONG + timeoutsecs:LONG +-> Um, this had an illegal name + x8bitchars:PTR TO LONG + printmode:LONG + convfunv:LONG +ENDOBJECT /* SIZEOF=66 */ + +OBJECT printersegment + nextsegment:LONG + runalert:LONG + version:INT -> This is unsigned + revision:INT -> This is unsigned +-> Um, this was missing + ped:printerextendeddata +ENDOBJECT /* SIZEOF=NONE !!! */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/prtgfx.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/prtgfx.e new file mode 100644 index 0000000..235e3f5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/prtgfx.e @@ -0,0 +1,62 @@ +OPT MODULE +OPT EXPORT + +MODULE 'graphics/rastport' + +CONST PCMYELLOW=0, + PCMMAGENTA=1, + PCMCYAN=2, + PCMBLACK=3, + PCMBLUE=0, + PCMGREEN=1, + PCMRED=2, + PCMWHITE=3 + +OBJECT colorentry +-> a) next four CHARs are unioned as "colorlong:LONG" +-> b) also unioned as "colorsbyte[4]:ARRAY", which is signed CHARs + colorbyte[4]:ARRAY +ENDOBJECT /* SIZEOF=4 */ + +OBJECT prtinfo + render:LONG + rp:PTR TO rastport + temprp:PTR TO rastport + rowbuf:PTR TO INT -> Target is unsigned + hambuf:PTR TO INT -> Target is unsigned + colormap:PTR TO colorentry + colorint:PTR TO colorentry + hamint:PTR TO colorentry + dest1int:PTR TO colorentry + dest2int:PTR TO colorentry + scalex:PTR TO INT -> Target is unsigned + scalexalt:PTR TO INT -> Target is unsigned + dmatrix:PTR TO CHAR + topbuf:PTR TO INT -> Target is unsigned + botbuf:PTR TO INT -> Target is unsigned + rowbufsize:INT -> This is unsigned + hambufsize:INT -> This is unsigned + colormapsize:INT -> This is unsigned + colorintsize:INT -> This is unsigned + hamintsize:INT -> This is unsigned + dest1intsize:INT -> This is unsigned + dest2intsize:INT -> This is unsigned + scalexsize:INT -> This is unsigned + scalexaltsize:INT -> This is unsigned + prefsflags:INT -> This is unsigned + special:LONG + xstart:INT -> This is unsigned + ystart:INT -> This is unsigned + width:INT -> This is unsigned + height:INT -> This is unsigned + pc:LONG + pr:LONG + ymult:INT -> This is unsigned + ymod:INT -> This is unsigned + ety:INT + xpos:INT -> This is unsigned + threshold:INT -> This is unsigned + tempwidth:INT -> This is unsigned + flags:INT -> This is unsigned +ENDOBJECT /* SIZEOF=114 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/scsidisk.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/scsidisk.e new file mode 100644 index 0000000..f5124e1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/scsidisk.e @@ -0,0 +1,36 @@ +OPT MODULE +OPT EXPORT + +CONST DEVICES_SCSIDISK_I=1, + HD_SCSICMD=28 + +OBJECT scsicmd + data:PTR TO INT -> Target is unsigned + length:LONG + actual:LONG + command:PTR TO CHAR + cmdlength:INT -> This is unsigned + cmdactual:INT -> This is unsigned + flags:CHAR + status:CHAR + sensedata:PTR TO CHAR + senselength:INT -> This is unsigned + senseactual:INT -> This is unsigned +ENDOBJECT /* SIZEOF=30 */ + +CONST SCSIF_WRITE=0, + SCSIF_READ=1, + SCSIB_READ_WRITE=0, + SCSIF_NOSENSE=0, + SCSIF_AUTOSENSE=2, + SCSIF_OLDAUTOSENSE=6, + SCSIB_AUTOSENSE=1, + SCSIB_OLDAUTOSENSE=2, + HFERR_SELFUNIT=$28, + HFERR_DMA=$29, + HFERR_PHASE=$2A, + HFERR_PARITY=$2B, + HFERR_SELTIMEOUT=$2C, + HFERR_BADSTATUS=$2D, + HFERR_NOBOARD=$32 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/serial.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/serial.e new file mode 100644 index 0000000..641ed3b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/serial.e @@ -0,0 +1,75 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/io' + +CONST SER_DEFAULT_CTLCHAR=$11130000, + SDCMD_QUERY=9, + SDCMD_BREAK=10, + SDCMD_SETPARAMS=11, + SER_DEVFINISH=11, + SERB_XDISABLED=7, + SERF_XDISABLED=$80, + SERB_EOFMODE=6, + SERF_EOFMODE=$40, + SERB_SHARED=5, + SERF_SHARED=$20, + SERB_RAD_BOOGIE=4, + SERF_RAD_BOOGIE=16, + SERB_QUEUEDBRK=3, + SERF_QUEUEDBRK=8, + SERB_7WIRE=2, + SERF_7WIRE=4, + SERB_PARTY_ODD=1, + SERF_PARTY_ODD=2, + SERB_PARTY_ON=0, + SERF_PARTY_ON=1, + IOSTB_XOFFREAD=4, + IOSTF_XOFFREAD=16, + IOSTB_XOFFWRITE=3, + IOSTF_XOFFWRITE=8, + IOSTB_READBREAK=2, + IOSTF_READBREAK=4, + IOSTB_WROTEBREAK=1, + IOSTF_WROTEBREAK=2, + IOSTB_OVERRUN=0, + IOSTF_OVERRUN=1, + SEXTB_MSPON=1, + SEXTF_MSPON=2, + SEXTB_MARK=0, + SEXTF_MARK=1 + +OBJECT termarray + ta0:LONG + ta1:LONG +ENDOBJECT /* SIZEOF=8 */ + +OBJECT ioextser + iostd:iostd + ctlchar:LONG + rbuflen:LONG + extflags:LONG + baud:LONG + brktime:LONG + termarray:termarray + readlen:CHAR + writelen:CHAR + stopbits:CHAR + serflags:CHAR + status:INT -> This is unsigned +ENDOBJECT /* SIZEOF=82 */ + +CONST SERERR_DEVBUSY=1, + SERERR_BAUDMISMATCH=2, + SERERR_BUFERR=4, + SERERR_INVPARAM=5, + SERERR_LINEERR=6, + SERERR_PARITYERR=9, + SERERR_TIMERERR=11, + SERERR_BUFOVERFLOW=12, + SERERR_NODSR=13, + SERERR_DETECTEDBREAK=15 + +#define SERIALNAME 'serial.device' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/timer.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/timer.e new file mode 100644 index 0000000..4783ae6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/timer.e @@ -0,0 +1,34 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/io' + +CONST UNIT_MICROHZ=0, + UNIT_VBLANK=1, + UNIT_ECLOCK=2, + UNIT_WAITUNTIL=3, + UNIT_WAITECLOCK=4 + +#define TIMERNAME 'timer.device' + +OBJECT timeval + secs:LONG + micro:LONG +ENDOBJECT /* SIZEOF=8 */ + +OBJECT eclockval + hi:LONG + lo:LONG +ENDOBJECT /* SIZEOF=8 */ + +OBJECT timerequest + io:io + time:timeval +ENDOBJECT /* SIZEOF=40 */ + +CONST TR_ADDREQUEST=9, + TR_GETSYSTIME=10, + TR_SETSYSTIME=11 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/devices/trackdisk.e b/amigae33a/E_v3.3a/Src/Src/Modules/devices/trackdisk.e new file mode 100644 index 0000000..800623a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/devices/trackdisk.e @@ -0,0 +1,116 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/devices', + 'exec/io' + +CONST NUMSECS=11, + NUMUNITS=4, + TD_SECTOR=$200, + TD_SECSHIFT=9, + TDF_EXTCOM=$8000, + TD_MOTOR=9, + TD_SEEK=10, + TD_FORMAT=11, + TD_REMOVE=12, + TD_CHANGENUM=13, + TD_CHANGESTATE=14, + TD_PROTSTATUS=15, + TD_RAWREAD=16, + TD_RAWWRITE=17, + TD_GETDRIVETYPE=18, + TD_GETNUMTRACKS=19, + TD_ADDCHANGEINT=20, + TD_REMCHANGEINT=21, + TD_GETGEOMETRY=22, + TD_EJECT=23, + TD_LASTCOMM=24, + ETD_WRITE=$8003, + ETD_READ=$8002, + ETD_MOTOR=$8009, + ETD_SEEK=$800A, + ETD_FORMAT=$800B, + ETD_UPDATE=$8004, + ETD_CLEAR=$8005, + ETD_RAWREAD=$8010, + ETD_RAWWRITE=$8011 + +#define TD_NAME 'trackdisk.device' + +OBJECT ioexttd + iostd:iostd + count:LONG + seclabel:LONG +ENDOBJECT /* SIZEOF=56 */ + +OBJECT drivegeometry + sectorsize:LONG + totalsectors:LONG + cylinders:LONG + cylsectors:LONG + heads:LONG + tracksectors:LONG + bufmemtype:LONG + devicetype:CHAR + flags:CHAR + reserved:INT +ENDOBJECT /* SIZEOF=32 */ + +CONST DG_DIRECT_ACCESS=0, + DG_SEQUENTIAL_ACCESS=1, + DG_PRINTER=2, + DG_PROCESSOR=3, + DG_WORM=4, + DG_CDROM=5, + DG_SCANNER=6, + DG_OPTICAL_DISK=7, + DG_MEDIUM_CHANGER=8, + DG_COMMUNICATION=9, + DG_UNKNOWN=31, + DGB_REMOVABLE=0, + DGF_REMOVABLE=1, + IOTDB_INDEXSYNC=4, + IOTDF_INDEXSYNC=16, + IOTDB_WORDSYNC=5, + IOTDF_WORDSYNC=$20, + TD_LABELSIZE=16, + TDB_ALLOW_NON_3_5=0, + TDF_ALLOW_NON_3_5=1, + DRIVE3_5=1, + DRIVE5_25=2, + DRIVE3_5_150RPM=3, + TDERR_NOTSPECIFIED=20, + TDERR_NOSECHDR=21, + TDERR_BADSECPREAMBLE=22, + TDERR_BADSECID=23, + TDERR_BADHDRSUM=24, + TDERR_BADSECSUM=25, + TDERR_TOOFEWSECS=26, + TDERR_BADSECHDR=27, + TDERR_WRITEPROT=28, + TDERR_DISKCHANGED=29, + TDERR_SEEKERROR=30, + TDERR_NOMEM=31, + TDERR_BADUNITNUM=$20, + TDERR_BADDRIVETYPE=$21, + TDERR_DRIVEINUSE=$22, + TDERR_POSTRESET=$23 + +OBJECT publicunit + unit:unit + comp01track:INT -> This is unsigned + comp10track:INT -> This is unsigned + comp11track:INT -> This is unsigned + stepdelay:LONG + settledelay:LONG + retrycnt:CHAR + pubflags:CHAR + currtrk:INT -> This is unsigned + calibratedelay:LONG + counter:LONG +ENDOBJECT /* SIZEOF=64 */ + +CONST TDPB_NOCLICK=0, + TDPF_NOCLICK=1 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfont.e b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfont.e new file mode 100644 index 0000000..5d10156 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfont.e @@ -0,0 +1,71 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes', + 'graphics/text' + +CONST MAXFONTPATH=$100 + +OBJECT fc + filename[$100]:ARRAY + ysize:INT -> This is unsigned + style:CHAR + flags:CHAR +ENDOBJECT /* SIZEOF=260 */ + +OBJECT tfc + filename[$fe]:ARRAY + tagcount:INT -> This is unsigned + ysize:INT -> This is unsigned + style:CHAR + flags:CHAR +ENDOBJECT /* SIZEOF=260 */ + +CONST FCH_ID=$F00, + TFCH_ID=$F02, + OFCH_ID=$F03 + +OBJECT fch + fileid:INT -> This is unsigned + numentries:INT -> This is unsigned +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST DFH_ID=$F80, + MAXFONTNAME=$20 + +OBJECT diskfontheader + df:ln + fileid:INT -> This is unsigned + revision:INT -> This is unsigned + segment:LONG + name[$20]:ARRAY + tf:textfont +ENDOBJECT /* SIZEOF=106 */ + +CONST DFH_TAGLIST=18, + AFB_MEMORY=0, + AFF_MEMORY=1, + AFB_DISK=1, + AFF_DISK=2, + AFB_SCALED=2, + AFF_SCALED=4, + AFB_BITMAP=3, + AFF_BITMAP=8, + AFB_TAGGED=16, + AFF_TAGGED=$10000, + AFF_TTATTR=$10000 + +OBJECT af + type:INT -> This is unsigned + attr:textattr +ENDOBJECT /* SIZEOF=10 */ + +OBJECT taf + type:INT -> This is unsigned + attr:ttextattr +ENDOBJECT /* SIZEOF=14 */ + +OBJECT afh + numentries:INT -> This is unsigned +ENDOBJECT /* SIZEOF=NONE !!! */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfonttag.e b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfonttag.e new file mode 100644 index 0000000..ceec845 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/diskfonttag.e @@ -0,0 +1,89 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define OTSUFFIX '.otag' +#define OTE_BULLET 'bullet' + +CONST OT_LEVEL0=$80000000, + OT_LEVEL1=$80001000, + OT_LEVEL2=$80002000, + OT_LEVEL3=$80003000, + OT_INDIRECT=$8000, + OT_DEVICEDPI=$80000001, + OT_DOTSIZE=$80000002, + OT_POINTHEIGHT=$80000008, + OT_SETFACTOR=$80000009, + OT_SHEARSIN=$8000000A, + OT_SHEARCOS=$8000000B, + OT_ROTATESIN=$8000000C, + OT_ROTATECOS=$8000000D, + OT_EMBOLDENX=$8000000E, + OT_EMBOLDENY=$8000000F, + OT_POINTSIZE=$80000010, + OT_GLYPHCODE=$80000011, + OT_GLYPHCODE2=$80000012, + OT_GLYPHWIDTH=$80000013, + OT_OTAGPATH=$80008014, + OT_OTAGLIST=$80008015, + OT_GLYPHMAP=$80008020, + OT_WIDTHLIST=$80008021, + OT_TEXTKERNPAIR=$80008022, + OT_DESIGNKERNPAIR=$80008023, + OT_UNDERLINED=$80000024, -> Data for this tag is unsigned INT + OTUL_NONE=0, + OTUL_SOLID=1, + OTUL_BROKEN=2, + OTUL_DOUBLESOLID=3, + OUTL_DOUBLEBROKEN=4, + OT_STRIKETHROUGH=$80000025, + OT_FILEIDENT=$80001001, + OT_ENGINE=$80009002, + OT_FAMILY=$80009003, + OT_BNAME=$8000A005, + OT_INAME=$8000A006, + OT_BINAME=$8000A007, + OT_SYMBOLSET=$80001010, + OT_YSIZEFACTOR=$80001011, + OT_SPACEWIDTH=$80002012, + OT_ISFIXED=$80002013, + OT_SERIFFLAG=$80001014, + OT_STEMWEIGHT=$80001015, + OTS_ULTRATHIN=8, + OTS_EXTRATHIN=24, + OTS_THIN=$28, + OTS_EXTRALIGHT=$38, + OTS_LIGHT=$48, + OTS_DEMILIGHT=$58, + OTS_SEMILIGHT=$68, + OTS_BOOK=$78, + OTS_MEDIUM=$88, + OTS_SEMIBOLD=$98, + OTS_DEMIBOLD=$A8, + OTS_BOLD=$B8, + OTS_EXTRABOLD=$C8, + OTS_BLACK=$D8, + OTS_EXTRABLACK=$E8, + OTS_ULTRABLACK=$F8, + OT_SLANTSTYLE=$80001016, + OTS_UPRIGHT=0, + OTS_ITALIC=1, + OTS_LEFTITALIC=2, + OT_HORIZSTYLE=$80001017, + OTH_ULTRACOMPRESSED=16, + OTH_EXTRACOMPRESSED=$30, + OTH_COMPRESSED=$50, + OTH_CONDENSED=$70, + OTH_NORMAL=$90, + OTH_SEMIEXPANDED=$B0, + OTH_EXPANDED=$D0, + OTH_EXTRAEXPANDED=$F0, + OT_SPACEFACTOR=$80002018, + OT_INHIBITALGOSTYLE=$80002019, + OT_AVAILSIZES=$80009020, + OT_MAXAVAILSIZES=20, + OT_SPECCOUNT=$80001100, + OT_SPEC=$80001100, + OT_SPEC1=$80001101 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/glyph.e b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/glyph.e new file mode 100644 index 0000000..910db2d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/glyph.e @@ -0,0 +1,36 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/libraries', + 'exec/nodes' + +CONST DISKFONT_GLYPH_I=1 + +OBJECT glyphengine + library:PTR TO lib + name:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT glyphmap + bmmodulo:INT -> This is unsigned + bmrows:INT -> This is unsigned + blackleft:INT -> This is unsigned + blacktop:INT -> This is unsigned + blackwidth:INT -> This is unsigned + blackheight:INT -> This is unsigned + xorigin:LONG + yorigin:LONG + x0:INT + y0:INT + x1:INT + y1:INT + width:LONG + bitmap:PTR TO CHAR +ENDOBJECT /* SIZEOF=36 */ + +OBJECT glyphwidthentry + node:mln + code:INT -> This is unsigned + width:LONG +ENDOBJECT /* SIZEOF=14 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/oterrors.e b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/oterrors.e new file mode 100644 index 0000000..d8db1d3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/diskfont/oterrors.e @@ -0,0 +1,18 @@ +OPT MODULE +OPT EXPORT + +CONST OTERR_FAILURE=-1, + OTERR_SUCCESS=0, + OTERR_BADTAG=1, + OTERR_UNKNOWNTAG=2, + OTERR_BADDATA=3, + OTERR_NOMEMORY=4, + OTERR_NOFACE=5, + OTERR_BADFACE=6, + OTERR_NOGLYPH=7, + OTERR_BADGLYPH=8, + OTERR_NOSHEAR=9, + OTERR_NOROTATE=10, + OTERR_TOOSMALL=11, + OTERR_UNKNOWNGLYPH=12 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/datetime.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/datetime.e new file mode 100644 index 0000000..89a5de9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/datetime.e @@ -0,0 +1,25 @@ +OPT MODULE +OPT EXPORT + +MODULE 'dos/dos' + +OBJECT datetime + stamp:datestamp + format:CHAR + flags:CHAR + strday:PTR TO CHAR + strdate:PTR TO CHAR + strtime:PTR TO CHAR +ENDOBJECT /* SIZEOF=26 */ + +CONST LEN_DATSTRING=16, + DTB_SUBST=0, + DTF_SUBST=1, + DTB_FUTURE=1, + DTF_FUTURE=2, + FORMAT_DOS=0, + FORMAT_INT=1, + FORMAT_USA=2, + FORMAT_CDN=3, + FORMAT_MAX=3 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/dos.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dos.e new file mode 100644 index 0000000..29c6257 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dos.e @@ -0,0 +1,187 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define DOSNAME 'dos.library' +#define BADDR(x) (Shl((x),2)) +#define MKBADDR(x) (Shr((x),2)) + +CONST DOSTRUE=-1, + DOSFALSE=0, + MODE_OLDFILE=$3ED, + MODE_NEWFILE=$3EE, + MODE_READWRITE=$3EC, + OFFSET_BEGINNING=-1, + OFFSET_CURRENT=0, + OFFSET_END=1, + OFFSET_BEGINING=-1, + BITSPERBYTE=8, + BYTESPERLONG=4, + BITSPERLONG=$20, + MAXINT=$7FFFFFFF, + MININT=$80000000, + SHARED_LOCK=-2, + ACCESS_READ=-2, + EXCLUSIVE_LOCK=-1, + ACCESS_WRITE=-1 + +OBJECT datestamp + days:LONG + minute:LONG + tick:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST TICKS_PER_SECOND=$32 + +OBJECT fileinfoblock + diskkey:LONG + direntrytype:LONG + filename[108]:ARRAY + protection:LONG + entrytype:LONG + size:LONG + numblocks:LONG + datestamp:datestamp + comment[80]:ARRAY + owneruid:INT -> This is unsigned + ownergid:INT -> This is unsigned + reserved[32]:ARRAY +ENDOBJECT /* SIZEOF=260 */ + +CONST FIBB_OTR_READ=15, + FIBB_OTR_WRITE=14, + FIBB_OTR_EXECUTE=13, + FIBB_OTR_DELETE=12, + FIBB_GRP_READ=11, + FIBB_GRP_WRITE=10, + FIBB_GRP_EXECUTE=9, + FIBB_GRP_DELETE=8, + FIBB_SCRIPT=6, + FIBB_PURE=5, + FIBB_ARCHIVE=4, + FIBB_READ=3, + FIBB_WRITE=2, + FIBB_EXECUTE=1, + FIBB_DELETE=0, + FIBF_OTR_READ=$8000, + FIBF_OTR_WRITE=$4000, + FIBF_OTR_EXECUTE=$2000, + FIBF_OTR_DELETE=$1000, + FIBF_GRP_READ=$800, + FIBF_GRP_WRITE=$400, + FIBF_GRP_EXECUTE=$200, + FIBF_GRP_DELETE=$100, + FIBF_SCRIPT=$40, + FIBF_PURE=$20, + FIBF_ARCHIVE=16, + FIBF_READ=8, + FIBF_WRITE=4, + FIBF_EXECUTE=2, + FIBF_DELETE=1, + FAULT_MAX=$52 + + +OBJECT infodata + numsofterrors:LONG + unitnumber:LONG + diskstate:LONG + numblocks:LONG + numblocksused:LONG + bytesperblock:LONG + disktype:LONG + volumenode:LONG + inuse:LONG +ENDOBJECT /* SIZEOF=36 */ + +CONST ID_WRITE_PROTECTED=$50, + ID_VALIDATING=$51, + ID_VALIDATED=$52, + ID_NO_DISK_PRESENT=-1, + ID_UNREADABLE_DISK=$42414400, + ID_NOT_REALLY_DOS=$4E444F53, + ID_DOS_DISK=$444F5300, + ID_FFS_DISK=$444F5301, + ID_INTER_DOS_DISK=$444F5302, + ID_INTER_FFS_DISK=$444F5303, + ID_FASTDIR_DOS_DISK=$444F5304, + ID_FASTDIR_FFS_DISK=$444F5305, + ID_KICKSTART_DISK=$4B49434B, + ID_MSDOS_DISK=$4D534400, + ERROR_NO_FREE_STORE=$67, + ERROR_TASK_TABLE_FULL=$69, + ERROR_BAD_TEMPLATE=$72, + ERROR_BAD_NUMBER=$73, + ERROR_REQUIRED_ARG_MISSING=$74, + ERROR_KEY_NEEDS_ARG=$75, + ERROR_TOO_MANY_ARGS=$76, + ERROR_UNMATCHED_QUOTES=$77, + ERROR_LINE_TOO_LONG=$78, + ERROR_FILE_NOT_OBJECT=$79, + ERROR_INVALID_RESIDENT_LIBRARY=$7A, + ERROR_NO_DEFAULT_DIR=$C9, + ERROR_OBJECT_IN_USE=$CA, + ERROR_OBJECT_EXISTS=$CB, + ERROR_DIR_NOT_FOUND=$CC, + ERROR_OBJECT_NOT_FOUND=$CD, + ERROR_BAD_STREAM_NAME=$CE, + ERROR_OBJECT_TOO_LARGE=$CF, + ERROR_ACTION_NOT_KNOWN=$D1, + ERROR_INVALID_COMPONENT_NAME=$D2, + ERROR_INVALID_LOCK=$D3, + ERROR_OBJECT_WRONG_TYPE=$D4, + ERROR_DISK_NOT_VALIDATED=$D5, + ERROR_DISK_WRITE_PROTECTED=$D6, + ERROR_RENAME_ACROSS_DEVICES=$D7, + ERROR_DIRECTORY_NOT_EMPTY=$D8, + ERROR_TOO_MANY_LEVELS=$D9, + ERROR_DEVICE_NOT_MOUNTED=$DA, + ERROR_SEEK_ERROR=$DB, + ERROR_COMMENT_TOO_BIG=$DC, + ERROR_DISK_FULL=$DD, + ERROR_DELETE_PROTECTED=$DE, + ERROR_WRITE_PROTECTED=$DF, + ERROR_READ_PROTECTED=$E0, + ERROR_NOT_A_DOS_DISK=$E1, + ERROR_NO_DISK=$E2, + ERROR_NO_MORE_ENTRIES=$E8, + ERROR_IS_SOFT_LINK=$E9, + ERROR_OBJECT_LINKED=$EA, + ERROR_BAD_HUNK=$EB, + ERROR_NOT_IMPLEMENTED=$EC, + ERROR_RECORD_NOT_LOCKED=$F0, + ERROR_LOCK_COLLISION=$F1, + ERROR_LOCK_TIMEOUT=$F2, + ERROR_UNLOCK_ERROR=$F3, + RETURN_OK=0, + RETURN_WARN=5, + RETURN_ERROR=10, + RETURN_FAIL=20, + SIGBREAKF_CTRL_C=$1000, + SIGBREAKF_CTRL_D=$2000, + SIGBREAKF_CTRL_E=$4000, + SIGBREAKF_CTRL_F=$8000, + SIGBREAKB_CTRL_C=12, + SIGBREAKB_CTRL_D=13, + SIGBREAKB_CTRL_E=14, + SIGBREAKB_CTRL_F=15, + LOCK_DIFFERENT=-1, + LOCK_SAME=0, + LOCK_SAME_VOLUME=1, + LOCK_SAME_HANDLER=1, + CHANGE_LOCK=0, + CHANGE_FH=1, + LINK_HARD=0, + LINK_SOFT=1, + ITEM_EQUAL=-2, + ITEM_ERROR=-1, + ITEM_NOTHING=0, + ITEM_UNQUOTED=1, + ITEM_QUOTED=2, + DOS_FILEHANDLE=0, + DOS_EXALLCONTROL=1, + DOS_FIB=2, + DOS_STDPKT=3, + DOS_CLI=4, + DOS_RDARGS=5 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/dos_lib.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dos_lib.e new file mode 100644 index 0000000..527a93c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dos_lib.e @@ -0,0 +1,6 @@ +OPT MODULE +OPT EXPORT + +CONST RESERVE=4, + VSIZE=6 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/dosasl.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dosasl.e new file mode 100644 index 0000000..7f41e68 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dosasl.e @@ -0,0 +1,71 @@ +OPT MODULE +OPT EXPORT + +MODULE 'dos/dos' + +OBJECT anchorpath + base:PTR TO achain + last:PTR TO achain + breakbits:LONG + foundbreak:LONG + flags:CHAR -> This is signed + reserved:CHAR + strlen:INT + info:fileinfoblock +-> Um, what about 'buf[1]:ARRAY'? +ENDOBJECT /* SIZEOF=280 */ + +CONST APB_DOWILD=0, + APF_DOWILD=1, + APB_ITSWILD=1, + APF_ITSWILD=2, + APB_DODIR=2, + APF_DODIR=4, + APB_DIDDIR=3, + APF_DIDDIR=8, + APB_NOMEMERR=4, + APF_NOMEMERR=16, + APB_DODOT=5, + APF_DODOT=$20, + APB_DIRCHANGED=6, + APF_DIRCHANGED=$40, + APB_FOLLOWHLINKS=7, + APF_FOLLOWHLINKS=$80 + +OBJECT achain + child:PTR TO achain + parent:PTR TO achain + lock:LONG + info:fileinfoblock + flags:CHAR -> This is signed +-> Um, what about 'string[1]:ARRAY'? +ENDOBJECT /* SIZEOF=273 */ + +CONST DDB_PATTERNBIT=0, + DDF_PATTERNBIT=1, + DDB_EXAMINEDBIT=1, + DDF_EXAMINEDBIT=2, + DDB_COMPLETED=2, + DDF_COMPLETED=4, + DDB_ALLBIT=3, + DDF_ALLBIT=8, + DDB_SINGLE=4, + DDF_SINGLE=16, + P_ANY=$80, + P_SINGLE=$81, + P_ORSTART=$82, + P_ORNEXT=$83, + P_OREND=$84, + P_NOT=$85, + P_NOTEND=$86, + P_NOTCLASS=$87, + P_CLASS=$88, + P_REPBEG=$89, + P_REPEND=$8A, + P_STOP=$8B, + COMPLEX_BIT=1, + EXAMINE_BIT=2, + ERROR_BUFFER_OVERFLOW=$12F, + ERROR_BREAK=$130, + ERROR_NOT_EXECUTABLE=$131 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/dosextens.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dosextens.e new file mode 100644 index 0000000..e8160cc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dosextens.e @@ -0,0 +1,349 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/timer', + 'dos/dos', + 'exec/libraries', + 'exec/lists', + 'exec/nodes', + 'exec/ports', + 'exec/semaphores', + 'exec/tasks' + +OBJECT process + task:tc + msgport:mp + pad:INT + seglist:LONG + stacksize:LONG + globvec:LONG + tasknum:LONG + stackbase:LONG + result2:LONG + currentdir:LONG + cis:LONG + cos:LONG + consoletask:LONG + filesystemtask:LONG + cli:LONG + returnaddr:LONG + pktwait:LONG + windowptr:LONG + homedir:LONG + flags:LONG + exitcode:LONG + exitdata:LONG + arguments:PTR TO CHAR + localvars:mlh + shellprivate:LONG + ces:LONG +ENDOBJECT /* SIZEOF=228 */ + +CONST PRB_FREESEGLIST=0, + PRF_FREESEGLIST=1, + PRB_FREECURRDIR=1, + PRF_FREECURRDIR=2, + PRB_FREECLI=2, + PRF_FREECLI=4, + PRB_CLOSEINPUT=3, + PRF_CLOSEINPUT=8, + PRB_CLOSEOUTPUT=4, + PRF_CLOSEOUTPUT=16, + PRB_FREEARGS=5, + PRF_FREEARGS=$20 + +OBJECT filehandle + link:PTR TO mn + interactive:PTR TO mp + type:PTR TO mp + buf:LONG + pos:LONG + end:LONG + funcs:LONG + func2:LONG + func3:LONG + args:LONG + arg2:LONG +ENDOBJECT /* SIZEOF=44 */ + +OBJECT dospacket + link:PTR TO mn + port:PTR TO mp +-> a) next is unioned with "action:LONG" + type:LONG +-> a) next is unioned with "status:LONG" + res1:LONG +-> a) next is unioned with "status2:LONG" + res2:LONG +-> a) next is unioned with "bufaddr:LONG" + arg1:LONG + arg2:LONG + arg3:LONG + arg4:LONG + arg5:LONG + arg6:LONG + arg7:LONG +ENDOBJECT /* SIZEOF=48 */ + +OBJECT standardpacket + msg:mn + pkt:dospacket +ENDOBJECT /* SIZEOF=68 */ + +CONST ACTION_NIL=0, + ACTION_STARTUP=0, + ACTION_GET_BLOCK=2, + ACTION_SET_MAP=4, + ACTION_DIE=5, + ACTION_EVENT=6, + ACTION_CURRENT_VOLUME=7, + ACTION_LOCATE_OBJECT=8, + ACTION_RENAME_DISK=9, + ACTION_WRITE=$57, + ACTION_READ=$52, + ACTION_FREE_LOCK=15, + ACTION_DELETE_OBJECT=16, + ACTION_RENAME_OBJECT=17, + ACTION_MORE_CACHE=18, + ACTION_COPY_DIR=19, + ACTION_WAIT_CHAR=20, + ACTION_SET_PROTECT=21, + ACTION_CREATE_DIR=22, + ACTION_EXAMINE_OBJECT=23, + ACTION_EXAMINE_NEXT=24, + ACTION_DISK_INFO=25, + ACTION_INFO=26, + ACTION_FLUSH=27, + ACTION_SET_COMMENT=28, + ACTION_PARENT=29, + ACTION_TIMER=30, + ACTION_INHIBIT=31, + ACTION_DISK_TYPE=$20, + ACTION_DISK_CHANGE=$21, + ACTION_SET_DATE=$22, + ACTION_SCREEN_MODE=$3E2, + ACTION_READ_RETURN=$3E9, + ACTION_WRITE_RETURN=$3EA, + ACTION_SEEK=$3F0, + ACTION_FINDUPDATE=$3EC, + ACTION_FINDINPUT=$3ED, + ACTION_FINDOUTPUT=$3EE, + ACTION_END=$3EF, + ACTION_SET_FILE_SIZE=$3FE, + ACTION_WRITE_PROTECT=$3FF, + ACTION_SAME_LOCK=$28, + ACTION_CHANGE_SIGNAL=$3E3, + ACTION_FORMAT=$3FC, + ACTION_MAKE_LINK=$3FD, + ACTION_READ_LINK=$400, + ACTION_FH_FROM_LOCK=$402, + ACTION_IS_FILESYSTEM=$403, + ACTION_CHANGE_MODE=$404, + ACTION_COPY_DIR_FH=$406, + ACTION_PARENT_FH=$407, + ACTION_EXAMINE_ALL=$409, + ACTION_EXAMINE_FH=$40A, + ACTION_LOCK_RECORD=$7D8, + ACTION_FREE_RECORD=$7D9, + ACTION_ADD_NOTIFY=$1001, + ACTION_REMOVE_NOTIFY=$1002, + ACTION_EXAMINE_ALL_END=$40B, + ACTION_SET_OWNER=$40C, + ACTION_SERIALIZE_DISK=$1068 + +OBJECT errorstring + nums:PTR TO LONG + strings:PTR TO CHAR +ENDOBJECT /* SIZEOF=8 */ + +OBJECT doslibrary + lib:lib + root:PTR TO rootnode + gv:LONG + a2:LONG + a5:LONG + a6:LONG + errors:PTR TO errorstring + timereq:PTR TO timerequest + utilitybase:PTR TO lib + intuitionbase:PTR TO lib +ENDOBJECT /* SIZEOF=70 */ + +OBJECT rootnode + taskarray:LONG + consolesegment:LONG + time:datestamp + restartseg:LONG + info:LONG + filehandlersegment:LONG + clilist:mlh + bootproc:PTR TO mp + shellsegment:LONG + flags:LONG +ENDOBJECT /* SIZEOF=56 */ + +CONST RNB_WILDSTAR=24, + RNF_WILDSTAR=$1000000, + RNB_PRIVATE1=1, + RNF_PRIVATE1=2 + +OBJECT cliproclist + node:mln + first:LONG +-> Um, this is really PTR TO PTR TO mp + array:PTR TO LONG +ENDOBJECT /* SIZEOF=16 */ + +OBJECT dosinfo + mcname:LONG + devinfo:LONG + devices:LONG + handlers:LONG + nethand:LONG + devlock:ss + entrylock:ss + deletelock:ss +ENDOBJECT /* SIZEOF=158 */ + +OBJECT segment + next:LONG + uc:LONG + seg:LONG + name[4]:ARRAY +ENDOBJECT /* SIZEOF=16 */ + +CONST CMD_SYSTEM=-1, + CMD_INTERNAL=-2, + CMD_DISABLED=$FFFFFC19 + +OBJECT commandlineinterface + result2:LONG + setname:PTR TO CHAR + commanddir:LONG + returncode:LONG + commandname:PTR TO CHAR + faillevel:LONG + prompt:PTR TO CHAR + standardinput:LONG + currentinput:LONG + commandfile:PTR TO CHAR + interactive:LONG + background:LONG + currentoutput:LONG + defaultstack:LONG + standardoutput:LONG + module:LONG +ENDOBJECT /* SIZEOF=64 */ + +OBJECT devlist + next:LONG + type:LONG + task:PTR TO mp + lock:LONG + volumedate:datestamp + locklist:LONG + disktype:LONG + unused:LONG + name:PTR TO CHAR +ENDOBJECT /* SIZEOF=44 */ + +OBJECT devinfo + next:LONG + type:LONG + task:LONG + lock:LONG + handler:PTR TO CHAR + stacksize:LONG + priority:LONG + startup:LONG + seglist:LONG + globvec:LONG + name:PTR TO CHAR +ENDOBJECT /* SIZEOF=44 */ + +OBJECT doslist + next:LONG + type:LONG + task:PTR TO mp + lock:LONG + +-> a) next 3 LONGs are unioned with "volumedate:datestamp" +-> b) next LONG is unioned with "handler:PTR TO CHAR" + assignname:PTR TO CHAR +-> b) next LONG is unioned with "stacksize:LONG" + list:PTR TO assignlist + priority:LONG +-> a) next LONG is unioned with "locklist:LONG" + startup:LONG +-> a) next LONG is unioned with "disktype:LONG" + seglist:LONG + globvec:LONG + name:PTR TO CHAR +ENDOBJECT /* SIZEOF=44 */ + +-> Um, this object was missing +OBJECT assignlist + next:PTR TO assignlist + lock:LONG +ENDOBJECT + +CONST DLT_DEVICE=0, + DLT_DIRECTORY=1, + DLT_VOLUME=2, + DLT_LATE=3, + DLT_NONBINDING=4, + DLT_PRIVATE=-1 + +OBJECT devproc + port:PTR TO mp + lock:LONG + flags:LONG + devnode:PTR TO doslist +ENDOBJECT /* SIZEOF=16 */ + +CONST DVPB_UNLOCK=0, + DVPF_UNLOCK=1, + DVPB_ASSIGN=1, + DVPF_ASSIGN=2, + LDB_DEVICES=2, + LDF_DEVICES=4, + LDB_VOLUMES=3, + LDF_VOLUMES=8, + LDB_ASSIGNS=4, + LDF_ASSIGNS=16, + LDB_ENTRY=5, + LDF_ENTRY=$20, + LDB_DELETE=6, + LDF_DELETE=$40, + LDB_READ=0, + LDF_READ=1, + LDB_WRITE=1, + LDF_WRITE=2, + LDF_ALL=28 + +OBJECT filelock + link:LONG + key:LONG + access:LONG + task:PTR TO mp + volume:LONG +ENDOBJECT /* SIZEOF=20 */ + +CONST REPORT_STREAM=0, + REPORT_TASK=1, + REPORT_LOCK=2, + REPORT_VOLUME=3, + REPORT_INSERT=4, + ABORT_DISK_ERROR=$128, + ABORT_BUSY=$120, + RUN_EXECUTE=-1, + RUN_SYSTEM=-2, + RUN_SYSTEM_ASYNCH=-3, + ST_ROOT=1, + ST_USERDIR=2, + ST_SOFTLINK=3, + ST_LINKDIR=4, + ST_FILE=-3, + ST_LINKFILE=-4, + ST_PIPEFILE=-5 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/doshunks.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/doshunks.e new file mode 100644 index 0000000..96ae4e3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/doshunks.e @@ -0,0 +1,53 @@ +OPT MODULE +OPT EXPORT + +CONST HUNK_UNIT=$3E7, + HUNK_NAME=$3E8, + HUNK_CODE=$3E9, + HUNK_DATA=$3EA, + HUNK_BSS=$3EB, + HUNK_RELOC32=$3EC, + HUNK_ABSRELOC32=$3EC, + HUNK_RELOC16=$3ED, + HUNK_RELRELOC16=$3ED, + HUNK_RELOC8=$3EE, + HUNK_RELRELOC8=$3EE, + HUNK_EXT=$3EF, + HUNK_SYMBOL=$3F0, + HUNK_DEBUG=$3F1, + HUNK_END=$3F2, + HUNK_HEADER=$3F3, + HUNK_OVERLAY=$3F5, + HUNK_BREAK=$3F6, + HUNK_DREL32=$3F7, + HUNK_DREL16=$3F8, + HUNK_DREL8=$3F9, + HUNK_LIB=$3FA, + HUNK_INDEX=$3FB, + HUNK_RELOC32SHORT=$3FC, + HUNK_RELRELOC32=$3FD, + HUNK_ABSRELOC16=$3FE, + HUNKF_ADVISORY=$20000000, + HUNKF_CHIP=$40000000, + HUNKF_FAST=$80000000, + EXT_SYMB=0, + EXT_DEF=1, + EXT_ABS=2, + EXT_RES=3, + EXT_COMMONDEF=4, + EXT_REF32=$81, + EXT_ABSREF32=$81, + EXT_COMMON=$82, + EXT_ABSCOMMON=$82, + EXT_REF16=$83, + EXT_RELREF16=$83, + EXT_REF8=$84, + EXT_RELREF8=$84, + EXT_DEXT32=$85, + EXT_DEXT16=$86, + EXT_DEXT8=$87, + EXT_RELREF32=$88, + EXT_RELCOMMON=$89, + EXT_ABSREF16=$8A, + EXT_ABSREF8=$8B + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/dostags.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dostags.e new file mode 100644 index 0000000..99e2361 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/dostags.e @@ -0,0 +1,41 @@ +OPT MODULE +OPT EXPORT + +CONST SYS_DUMMY=$80000020, + SYS_INPUT=$80000021, + SYS_OUTPUT=$80000022, + SYS_ASYNCH=$80000023, + SYS_USERSHELL=$80000024, + SYS_CUSTOMSHELL=$80000025, + NP_DUMMY=$800003E8, + NP_SEGLIST=$800003E9, + NP_FREESEGLIST=$800003EA, + NP_ENTRY=$800003EB, + NP_INPUT=$800003EC, + NP_OUTPUT=$800003ED, + NP_CLOSEINPUT=$800003EE, + NP_CLOSEOUTPUT=$800003EF, + NP_ERROR=$800003F0, + NP_CLOSEERROR=$800003F1, + NP_CURRENTDIR=$800003F2, + NP_STACKSIZE=$800003F3, + NP_NAME=$800003F4, + NP_PRIORITY=$800003F5, + NP_CONSOLETASK=$800003F6, + NP_WINDOWPTR=$800003F7, + NP_HOMEDIR=$800003F8, + NP_COPYVARS=$800003F9, + NP_CLI=$800003FA, + NP_PATH=$800003FB, + NP_COMMANDNAME=$800003FC, + NP_ARGUMENTS=$800003FD, + NP_NOTIFYONDEATH=$800003FE, + NP_SYNCHRONOUS=$800003FF, + NP_EXITCODE=$80000400, + NP_EXITDATA=$80000401, + ADO_DUMMY=$800007D0, + ADO_FH_MODE=$800007D1, + ADO_DIRLEN=$800007D2, + ADO_COMMNAMELEN=$800007D3, + ADO_COMMFILELEN=$800007D4, + ADO_PROMPTLEN=$800007D5 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/exall.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/exall.e new file mode 100644 index 0000000..2c7b2df --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/exall.e @@ -0,0 +1,34 @@ +OPT MODULE +OPT EXPORT + +MODULE 'utility/hooks' + +CONST ED_NAME=1, + ED_TYPE=2, + ED_SIZE=3, + ED_PROTECTION=4, + ED_DATE=5, + ED_COMMENT=6, + ED_OWNER=7 + +OBJECT exalldata + next:PTR TO exalldata + name:PTR TO CHAR + type:LONG + size:LONG + prot:LONG + days:LONG + mins:LONG + ticks:LONG + comment:PTR TO CHAR + owneruid:INT -> This is unsigned + ownergid:INT -> This is unsigned +ENDOBJECT /* SIZEOF=40 */ + +OBJECT exallcontrol + entries:LONG + lastkey:LONG + matchstring:PTR TO CHAR + matchfunc:PTR TO hook +ENDOBJECT /* SIZEOF=16 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/filehandler.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/filehandler.e new file mode 100644 index 0000000..dfbb59d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/filehandler.e @@ -0,0 +1,70 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/ports' + +OBJECT dosenvec + tablesize:LONG + sizeblock:LONG + secorg:LONG + surfaces:LONG + sectorperblock:LONG + blockspertrack:LONG + reserved:LONG + prealloc:LONG + interleave:LONG + lowcyl:LONG + highcyl:LONG + numbuffers:LONG + bufmemtype:LONG + maxtransfer:LONG + mask:LONG + bootpri:LONG + dostype:LONG + baud:LONG + control:LONG + bootblocks:LONG +ENDOBJECT /* SIZEOF=80 */ + +CONST DE_TABLESIZE=0, + DE_SIZEBLOCK=1, + DE_SECORG=2, + DE_NUMHEADS=3, + DE_SECSPERBLK=4, + DE_BLKSPERTRACK=5, + DE_RESERVEDBLKS=6, + DE_PREFAC=7, + DE_INTERLEAVE=8, + DE_LOWCYL=9, + DE_UPPERCYL=10, + DE_NUMBUFFERS=11, + DE_MEMBUFTYPE=12, + DE_BUFMEMTYPE=12, + DE_MAXTRANSFER=13, + DE_MASK=14, + DE_BOOTPRI=15, + DE_DOSTYPE=16, + DE_BAUD=17, + DE_CONTROL=18, + DE_BOOTBLOCKS=19 + +OBJECT filesysstartupmsg + unit:LONG + device:PTR TO CHAR + environ:LONG + flags:LONG +ENDOBJECT /* SIZEOF=16 */ + +OBJECT devicenode + next:PTR TO CHAR + type:LONG + task:PTR TO mp + lock:LONG + handler:PTR TO CHAR + stacksize:LONG + priority:LONG + startup:LONG + seglist:LONG + globalvec:LONG + name:PTR TO CHAR +ENDOBJECT /* SIZEOF=44 */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/notify.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/notify.e new file mode 100644 index 0000000..984be21 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/notify.e @@ -0,0 +1,45 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/ports', + 'exec/tasks' + +CONST NOTIFY_CLASS=$40000000, + NOTIFY_CODE=$1234 + +OBJECT notifymessage + execmessage:mn + class:LONG + code:INT -> This is unsigned + nreq:PTR TO notifyrequest + donottouch:LONG + donottouch2:LONG +ENDOBJECT /* SIZEOF=38 */ + +OBJECT notifyrequest + name:PTR TO CHAR + fullname:PTR TO CHAR + userdata:LONG + flags:LONG +-> a) next LONG is unioned with "task:PTR TO tc" + port:PTR TO mp + signalnum:CHAR + pada:CHAR + padb[2]:ARRAY + reserved[4]:ARRAY OF LONG + msgcount:LONG + handler:PTR TO mp +ENDOBJECT /* SIZEOF=48 */ + +CONST NRF_SEND_MESSAGE=1, + NRF_SEND_SIGNAL=2, + NRF_WAIT_REPLY=8, + NRF_NOTIFY_INITIAL=16, + NRF_MAGIC=$80000000, + NRB_SEND_MESSAGE=0, + NRB_SEND_SIGNAL=1, + NRB_WAIT_REPLY=3, + NRB_NOTIFY_INITIAL=4, + NRB_MAGIC=31, + NR_HANDLER_FLAGS=$FFFF0000 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/rdargs.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/rdargs.e new file mode 100644 index 0000000..edfc0d8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/rdargs.e @@ -0,0 +1,27 @@ +OPT MODULE +OPT EXPORT + +OBJECT csource + buffer:PTR TO CHAR + length:LONG + curchr:LONG +ENDOBJECT /* SIZEOF=12 */ + +OBJECT rdargs + source:csource + dalist:LONG + buffer:PTR TO CHAR + bufsiz:LONG + exthelp:PTR TO CHAR + flags:LONG +ENDOBJECT /* SIZEOF=32 */ + +CONST RDAB_STDIN=0, + RDAF_STDIN=1, + RDAB_NOALLOC=1, + RDAF_NOALLOC=2, + RDAB_NOPROMPT=2, + RDAF_NOPROMPT=4, + MAX_TEMPLATE_ITEMS=$64, + MAX_MULTIARGS=$80 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/record.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/record.e new file mode 100644 index 0000000..e50972a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/record.e @@ -0,0 +1,15 @@ +OPT MODULE +OPT EXPORT + +CONST REC_EXCLUSIVE=0, + REC_EXCLUSIVE_IMMED=1, + REC_SHARED=2, + REC_SHARED_IMMED=3 + +OBJECT recordlock + fh:LONG + offset:LONG + length:LONG + mode:LONG +ENDOBJECT /* SIZEOF=16 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/stdio.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/stdio.e new file mode 100644 index 0000000..45c2b88 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/stdio.e @@ -0,0 +1,20 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +CONST DOS_STDIO_I=1, + BUF_LINE=0, + BUF_FULL=1, + BUF_NONE=2, + ENDSTREAMCH=-1 + +/* Wouter said he was going to fix macros so ReadChar() would be allowed... */ +#define ReadChar FgetC(Input()) +#define WriteChar(c) FputC(Output(),(c)) +#define UnReadChar(c) UnGetC(Input(),(c)) +/* next one is inefficient */ +#define ReadChars(buf,num) Fread(Input(),(buf),1,(num)) +#define ReadLn(buf,len) Fgets(Input(),(buf),(len)) +#define WriteStr(s) Fputs(Output(),(s)) +#define Vwritef(format,argv) VfWritef(Output(),(format),(argv)) diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/dos/var.e b/amigae33a/E_v3.3a/Src/Src/Modules/dos/var.e new file mode 100644 index 0000000..ef3f9d9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/dos/var.e @@ -0,0 +1,26 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +OBJECT localvar + node:ln + flags:INT -> This is unsigned + value:PTR TO CHAR + len:LONG +ENDOBJECT /* SIZEOF=24 */ + +CONST LV_VAR=0, + LV_ALIAS=1, + LVB_IGNORE=7, + LVF_IGNORE=$80, + GVB_GLOBAL_ONLY=8, + GVF_GLOBAL_ONLY=$100, + GVB_LOCAL_ONLY=9, + GVF_LOCAL_ONLY=$200, + GVB_BINARY_VAR=10, + GVF_BINARY_VAR=$400, + GVB_DONT_NULL_TERM=11, + GVF_DONT_NULL_TERM=$800, + GVB_SAVE_VAR=12, + GVF_SAVE_VAR=$1000 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/alerts.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/alerts.e new file mode 100644 index 0000000..ccb253d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/alerts.e @@ -0,0 +1,163 @@ +OPT MODULE +OPT EXPORT + +CONST ACPU_BUSERR=$80000002, + ACPU_ADDRESSERR=$80000003, + ACPU_INSTERR=$80000004, + ACPU_DIVZERO=$80000005, + ACPU_CHK=$80000006, + ACPU_TRAPV=$80000007, + ACPU_PRIVERR=$80000008, + ACPU_TRACE=$80000009, + ACPU_LINEA=$8000000A, + ACPU_LINEF=$8000000B, + ACPU_FORMAT=$8000000E, + ACPU_SPURIOUS=$80000018, + ACPU_AUTOVEC1=$80000019, + ACPU_AUTOVEC2=$8000001A, + ACPU_AUTOVEC3=$8000001B, + ACPU_AUTOVEC4=$8000001C, + ACPU_AUTOVEC5=$8000001D, + ACPU_AUTOVEC6=$8000001E, + ACPU_AUTOVEC7=$8000001F, + AT_DEADEND=$80000000, + AT_RECOVERY=0, + AG_NOMEMORY=$10000, + AG_MAKELIB=$20000, + AG_OPENLIB=$30000, + AG_OPENDEV=$40000, + AG_OPENRES=$50000, + AG_IOERROR=$60000, + AG_NOSIGNAL=$70000, + AG_BADPARM=$80000, + AG_CLOSELIB=$90000, + AG_CLOSEDEV=$A0000, + AG_PROCCREATE=$B0000, + AO_EXECLIB=$8001, + AO_GRAPHICSLIB=$8002, + AO_LAYERSLIB=$8003, + AO_INTUITION=$8004, + AO_MATHLIB=$8005, + AO_DOSLIB=$8007, + AO_RAMLIB=$8008, + AO_ICONLIB=$8009, + AO_EXPANSIONLIB=$800A, + AO_DISKFONTLIB=$800B, + AO_UTILITYLIB=$800C, + AO_KEYMAPLIB=$800D, + AO_AUDIODEV=$8010, + AO_CONSOLEDEV=$8011, + AO_GAMEPORTDEV=$8012, + AO_KEYBOARDDEV=$8013, + AO_TRACKDISKDEV=$8014, + AO_TIMERDEV=$8015, + AO_CIARSRC=$8020, + AO_DISKRSRC=$8021, + AO_MISCRSRC=$8022, + AO_BOOTSTRAP=$8030, + AO_WORKBENCH=$8031, + AO_DISKCOPY=$8032, + AO_GADTOOLS=$8033, + AO_UNKNOWN=$8035, + AN_EXECLIB=$1000000, + AN_EXCPTVECT=$1000001, + AN_BASECHKSUM=$1000002, + AN_LIBCHKSUM=$1000003, + AN_MEMCORRUPT=$81000005, + AN_INTRMEM=$81000006, + AN_INITAPTR=$1000007, + AN_SEMCORRUPT=$1000008, + AN_FREETWICE=$1000009, + AN_BOGUSEXCPT=$8100000A, + AN_BADQUICKINT=$810000FF, + AN_IOUSEDTWICE=$100000B, + AN_MEMORYINSANE=$100000C, + AN_IOAFTERCLOSE=$100000D, + AN_STACKPROBE=$100000E, + AN_BADFREEADDR=$100000F, + AN_BADSEMAPHORE=$1000010, + AN_GRAPHICSLIB=$2000000, + AN_GFXNOMEM=$82010000, + AN_GFXNOMEMMSPC=$82010001, + AN_LONGFRAME=$82010006, + AN_SHORTFRAME=$82010007, + AN_TEXTTMPRAS=$2010009, + AN_BLTBITMAP=$8201000A, + AN_REGIONMEMORY=$8201000B, + AN_MAKEVPORT=$82010030, + AN_GFXNEWERROR=$200000C, + AN_GFXFREEERROR=$200000D, + AN_GFXNOLCM=$82011234, + AN_OBSOLETEFONT=$2000401, + AN_LAYERSLIB=$3000000, + AN_LAYERSNOMEM=$83010000, + AN_INTUITION=$4000000, + AN_GADGETTYPE=$84000001, + AN_BADGADGET=$4000001, + AN_CREATEPORT=$84010002, + AN_ITEMALLOC=$4010003, + AN_SUBALLOC=$4010004, + AN_PLANEALLOC=$84010005, + AN_ITEMBOXTOP=$84000006, + AN_OPENSCREEN=$84010007, + AN_OPENSCRNRAST=$84010008, + AN_SYSSCRNTYPE=$84000009, + AN_ADDSWGADGET=$8401000A, + AN_OPENWINDOW=$8401000B, + AN_BADSTATE=$8400000C, + AN_BADMESSAGE=$8400000D, + AN_WEIRDECHO=$8400000E, + AN_NOCONSOLE=$8400000F, + AN_NOISEM=$4000010, + AN_ISEMORDER=$4000011, + AN_MATHLIB=$5000000, + AN_DOSLIB=$7000000, + AN_STARTMEM=$7010001, + AN_ENDTASK=$7000002, + AN_QPKTFAIL=$7000003, + AN_ASYNCPKT=$7000004, + AN_FREEVEC=$7000005, + AN_DISKBLKSEQ=$7000006, + AN_BITMAP=$7000007, + AN_KEYFREE=$7000008, + AN_BADCHKSUM=$7000009, + AN_DISKERROR=$700000A, + AN_KEYRANGE=$700000B, + AN_BADOVERLAY=$700000C, + AN_BADINITFUNC=$700000D, + AN_FILERECLOSED=$700000E, + AN_RAMLIB=$8000000, + AN_BADSEGLIST=$8000001, + AN_ICONLIB=$9000000, + AN_EXPANSIONLIB=$A000000, + AN_BADEXPANSIONFREE=$A000001, + AN_DISKFONTLIB=$B000000, + AN_AUDIODEV=$10000000, + AN_CONSOLEDEV=$11000000, + AN_NOWINDOW=$11000001, + AN_GAMEPORTDEV=$12000000, + AN_KEYBOARDDEV=$13000000, + AN_TRACKDISKDEV=$14000000, + AN_TDCALIBSEEK=$14000001, + AN_TDDELAY=$14000002, + AN_TIMERDEV=$15000000, + AN_TMBADREQ=$15000001, + AN_TMBADSUPPLY=$15000002, + AN_CIARSRC=$20000000, + AN_DISKRSRC=$21000000, + AN_DRHASDISK=$21000001, + AN_DRINTNOACT=$21000002, + AN_MISCRSRC=$22000000, + AN_BOOTSTRAP=$30000000, + AN_BOOTERROR=$30000001, + AN_WORKBENCH=$31000000, + AN_NOFONTS=$B1000001, + AN_WBBADSTARTUPMSG1=$31000001, + AN_WBBADSTARTUPMSG2=$31000002, + AN_WBBADIOMSG=$31000003, + AN_WBRELAYOUTTOOLMENU=$B1010009, + AN_DISKCOPY=$32000000, + AN_GADTOOLS=$33000000, + AN_UTILITYLIB=$34000000, + AN_UNKNOWN=$35000000 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/devices.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/devices.e new file mode 100644 index 0000000..ba0149c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/devices.e @@ -0,0 +1,20 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/libraries', + 'exec/ports' + +OBJECT dd + lib:lib +ENDOBJECT /* SIZEOF=34 */ + +OBJECT unit + mp:mp + flags:CHAR + pad:CHAR + opencnt:INT -> This is unsigned +ENDOBJECT /* SIZEOF=38 */ + +CONST UNITF_ACTIVE=1, + UNITF_INTASK=2 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/errors.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/errors.e new file mode 100644 index 0000000..84c8872 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/errors.e @@ -0,0 +1,13 @@ +OPT MODULE +OPT EXPORT + + +CONST IOERR_OPENFAIL=-1, + IOERR_ABORTED=-2, + IOERR_NOCMD=-3, + IOERR_BADLENGTH=-4, + IOERR_BADADDRESS=-5, + IOERR_UNITBUSY=-6, + IOERR_SELFTEST=-7, + ERR_OPENDEVICE=-1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/execbase.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/execbase.e new file mode 100644 index 0000000..24469f4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/execbase.e @@ -0,0 +1,116 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', + 'exec/libraries', + 'exec/interrupts', + 'exec/tasks' + +OBJECT execbase + lib:lib + softver:INT -> This is unsigned + lowmemchksum:INT + chkbase:LONG + coldcapture:LONG + coolcapture:LONG + warmcapture:LONG + sysstkupper:LONG + sysstklower:LONG + maxlocmem:LONG + debugentry:LONG + debugdata:LONG + alertdata:LONG + maxextmem:LONG + chksum:INT -> This is unsigned + ivtbe:iv + ivdskblk:iv + ivsoftint:iv + ivports:iv + ivcoper:iv + ivvertb:iv + ivblit:iv + ivaud0:iv + ivaud1:iv + ivaud2:iv + ivaud3:iv + ivrbf:iv + ivdsksync:iv + ivexter:iv + ivinten:iv + ivnmi:iv + thistask:PTR TO tc + idlecount:LONG + dispcount:LONG + quantum:INT -> This is unsigned + elapsed:INT -> This is unsigned + sysflags:INT -> This is unsigned + idnestcnt:CHAR -> This is signed + tdnestcnt:CHAR -> This is signed + attnflags:INT -> This is unsigned + attnresched:INT -> This is unsigned + resmodules:LONG + tasktrapcode:LONG + taskexceptcode:LONG + taskexitcode:LONG + tasksigalloc:LONG + tasktrapalloc:INT -> This is unsigned + memlist:lh + resourcelist:lh + devicelist:lh + intrlist:lh + liblist:lh + portlist:lh + taskready:lh + taskwait:lh + softints[5]:ARRAY OF sh + lastalert[4]:ARRAY OF LONG + vblankfrequency:CHAR + powersupplyfrequency:CHAR + semaphorelist:lh + kickmemptr:LONG + kicktagptr:LONG + kickchecksum:LONG + pad0:INT + launchpoint:LONG + ramlibprivate:LONG + eclockfrequency:LONG + cachecontrol:LONG + taskid:LONG + reserved1[5]:ARRAY OF LONG + mmulock:LONG + reserved2[3]:ARRAY OF LONG + memhandlers:mlh + memhandler:LONG +ENDOBJECT /* SIZEOF=632 */ + +CONST AFB_68010=0, + AFB_68020=1, + AFB_68030=2, + AFB_68040=3, + AFB_68881=4, + AFB_68882=5, + AFB_FPU40=6, + AFB_PRIVATE=15, + AFF_68010=1, + AFF_68020=2, + AFF_68030=4, + AFF_68040=8, + AFF_68881=16, + AFF_68882=$20, + AFF_FPU40=$40, + AFF_PRIVATE=$8000, + CACRF_ENABLEI=1, + CACRF_FREEZEI=2, + CACRF_CLEARI=8, + CACRF_IBE=16, + CACRF_ENABLED=$100, + CACRF_FREEZED=$200, + CACRF_CLEARD=$800, + CACRF_DBE=$1000, + CACRF_WRITEALLOCATE=$2000, + CACRF_ENABLEE=$40000000, + CACRF_COPYBACK=$80000000, + DMAF_CONTINUE=2, + DMAF_NOMODIFY=4, + DMAF_READFROMRAM=8 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/interrupts.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/interrupts.e new file mode 100644 index 0000000..52281dd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/interrupts.e @@ -0,0 +1,32 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', + 'exec/nodes' + +OBJECT is + ln:ln + data:LONG + code:LONG +ENDOBJECT /* SIZEOF=22 */ + +OBJECT iv + data:LONG + code:LONG + node:PTR TO ln +ENDOBJECT /* SIZEOF=12 */ + +CONST SF_SAR=$8000, + SF_TQE=$4000, + SF_SINT=$2000 + +OBJECT sh + lh:lh + pad:INT +ENDOBJECT /* SIZEOF=16 */ + +CONST SIH_PRIMASK=$F0, + SIH_QUEUES=5, + INTB_NMI=15, + INTF_NMI=$8000 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/io.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/io.e new file mode 100644 index 0000000..18bfee0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/io.e @@ -0,0 +1,43 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/ports', + 'exec/devices' + +OBJECT io + mn:mn + device:PTR TO dd + unit:PTR TO unit + command:INT -> This is unsigned + flags:CHAR + error:CHAR -> This is signed +ENDOBJECT /* SIZEOF=32 */ + +OBJECT iostd + mn:mn + device:PTR TO dd + unit:PTR TO unit + command:INT -> This is unsigned + flags:CHAR + error:CHAR -> This is signed + actual:LONG + length:LONG + data:LONG + offset:LONG +ENDOBJECT /* SIZEOF=48 */ + +CONST IOB_QUICK=0, + IOF_QUICK=1, + CMD_INVALID=0, + CMD_RESET=1, + CMD_READ=2, + CMD_WRITE=3, + CMD_UPDATE=4, + CMD_CLEAR=5, + CMD_STOP=6, + CMD_START=7, + CMD_FLUSH=8, + CMD_NONSTD=9, + DEV_BEGINIO=-30, + DEV_ABORTIO=-36 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/libraries.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/libraries.e new file mode 100644 index 0000000..bce057b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/libraries.e @@ -0,0 +1,34 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +CONST LIB_VECTSIZE=6, + LIB_RESERVED=4, + LIB_BASE=-6, + LIB_USERDEF=-30, + LIB_NONSTD=-30, + LIB_OPEN=-6, + LIB_CLOSE=-12, + LIB_EXPUNGE=-18, + LIB_EXTFUNC=-24 + +OBJECT lib + ln:ln + flags:CHAR + pad:CHAR + negsize:INT -> This is unsigned + possize:INT -> This is unsigned + version:INT -> This is unsigned + revision:INT -> This is unsigned + idstring:PTR TO CHAR + sum:LONG + opencnt:INT -> This is unsigned +ENDOBJECT /* SIZEOF=34 */ + +CONST LIBF_SUMMING=1, + LIBF_CHANGED=2, + LIBF_SUMUSED=4, + LIBF_DELEXP=8, + LIBF_EXP0CNT=16 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/lists.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/lists.e new file mode 100644 index 0000000..4ba2c83 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/lists.e @@ -0,0 +1,24 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/nodes' + +#define IsListEmpty(x) (x::mlh.tailpred = (x)) +#define IsMsgPortEmpty(x) (x::mp.ln.tailpred = x::mp.ln) + +OBJECT lh + head:PTR TO ln + tail:PTR TO ln + tailpred:PTR TO ln + type:CHAR + pad:CHAR +ENDOBJECT /* SIZEOF=14 */ + +OBJECT mlh + head:PTR TO mln + tail:PTR TO mln + tailpred:PTR TO mln +ENDOBJECT /* SIZEOF=12 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/memory.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/memory.e new file mode 100644 index 0000000..f2da0d6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/memory.e @@ -0,0 +1,58 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +OBJECT ml + ln:ln + numentries:INT -> This is unsigned +-> Um, what about 'me[1]:ARRAY OF me' +ENDOBJECT /* SIZEOF=16 */ + +OBJECT me +-> a) next LONG is unioned with "reqs:LONG" + addr:LONG + length:LONG +ENDOBJECT /* SIZEOF=8 */ + +CONST MEMF_ANY=0, + MEMF_PUBLIC=1, + MEMF_CHIP=2, + MEMF_FAST=4, + MEMF_LOCAL=$100, + MEMF_24BITDMA=$200, + MEMF_KICK=$400, + MEMF_CLEAR=$10000, + MEMF_LARGEST=$20000, + MEMF_REVERSE=$40000, + MEMF_TOTAL=$80000, + MEMF_NO_EXPUNGE=$80000000, + MEM_BLOCKSIZE=8, + MEM_BLOCKMASK=7 + +OBJECT memhandlerdata + requestsize:LONG + requestflags:LONG + flags:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST MEMHF_RECYCLE=1, + MEM_DID_NOTHING=0, + MEM_ALL_DONE=-1, + MEM_TRY_AGAIN=1 + +OBJECT mh + ln:ln + attributes:INT -> This is unsigned + first:PTR TO mc + lower:LONG + upper:LONG + free:LONG +ENDOBJECT /* SIZEOF=32 */ + +OBJECT mc + next:PTR TO mc + bytes:LONG +-> Um, 'size:LONG' was an error +ENDOBJECT /* SIZEOF=NONE !!! */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/nodes.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/nodes.e new file mode 100644 index 0000000..28ff685 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/nodes.e @@ -0,0 +1,39 @@ +OPT MODULE +OPT EXPORT + +OBJECT ln + succ:PTR TO ln + pred:PTR TO ln + type:CHAR + pri:CHAR -> This is signed + name:PTR TO CHAR +ENDOBJECT /* SIZEOF=14 */ + +OBJECT mln + succ:PTR TO mln + pred:PTR TO mln +ENDOBJECT /* SIZEOF=8 */ + +CONST NT_UNKNOWN=0, + NT_TASK=1, + NT_INTERRUPT=2, + NT_DEVICE=3, + NT_MSGPORT=4, + NT_MESSAGE=5, + NT_FREEMSG=6, + NT_REPLYMSG=7, + NT_RESOURCE=8, + NT_LIBRARY=9, + NT_MEMORY=10, + NT_SOFTINT=11, + NT_FONT=12, + NT_PROCESS=13, + NT_SEMAPHORE=14, + NT_SIGNALSEM=15, + NT_BOOTNODE=16, + NT_KICKMEM=17, + NT_GRAPHICS=18, + NT_DEATHMESSAGE=19, + NT_USER=$FE, + NT_EXTENDED=$FF + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/ports.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/ports.e new file mode 100644 index 0000000..cfdc61d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/ports.e @@ -0,0 +1,26 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', + 'exec/nodes' + +OBJECT mp + ln:ln + flags:CHAR + sigbit:CHAR + sigtask:LONG + msglist:lh +ENDOBJECT /* SIZEOF=34 */ + +CONST MP_SOFTINT=16, + PF_ACTION=3, + PA_SIGNAL=0, + PA_SOFTINT=1, + PA_IGNORE=2 + +OBJECT mn + ln:ln + replyport:PTR TO mp + length:INT -> This is unsigned +ENDOBJECT /* SIZEOF=20 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/resident.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/resident.e new file mode 100644 index 0000000..6d3be93 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/resident.e @@ -0,0 +1,24 @@ +OPT MODULE +OPT EXPORT + +OBJECT rt + matchword:INT -> This is unsigned + matchtag:PTR TO rt + endskip:LONG + flags:CHAR + version:CHAR + type:CHAR + pri:CHAR -> This is signed + name:PTR TO CHAR + idstring:PTR TO CHAR + init:LONG +ENDOBJECT /* SIZEOF=26 */ + +CONST RTC_MATCHWORD=$4AFC, + RTF_COLDSTART=1, + RTF_SINGLETASK=2, + RTF_AFTERDOS=4, + RTF_AUTOINIT=$80, + RTW_NEVER=0, + RTW_COLDSTART=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/semaphores.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/semaphores.e new file mode 100644 index 0000000..23b6685 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/semaphores.e @@ -0,0 +1,37 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', + 'exec/nodes', + 'exec/ports', + 'exec/tasks' + +OBJECT ssr + mln:mln + waiter:PTR TO tc +ENDOBJECT /* SIZEOF=12 */ + +OBJECT ss + ln:ln + nestcount:INT + waitqueue:mlh + multiplelink:ssr + owner:PTR TO tc + queuecount:INT +ENDOBJECT /* SIZEOF=46 */ + +OBJECT semaphoremessage + mn:mn + semaphore:PTR TO ss +ENDOBJECT /* SIZEOF=24 */ + +OBJECT sm + mp:mp + bids:INT +ENDOBJECT /* SIZEOF=36 */ + +CONST SM_LOCKMSG=16, + SM_SHARED=1, + SM_EXCLUSIVE=0 + + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/strings.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/strings.e new file mode 100644 index 0000000..8f283a7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/strings.e @@ -0,0 +1,11 @@ +OPT MODULE +OPT EXPORT + +CONST EOS=0, + BELL=7, + LF=10, + CR=13, + BS=8, + DEL=$7F, + NL=10 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/tasks.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/tasks.e new file mode 100644 index 0000000..5ae7de9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/tasks.e @@ -0,0 +1,92 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', + 'exec/nodes', + 'exec/ports' + +OBJECT tc + ln:ln + flags:CHAR + state:CHAR + idnestcnt:CHAR -> This is signed + tdnestcnt:CHAR -> This is signed + sigalloc:LONG + sigwait:LONG + sigrecvd:LONG + sigexcept:LONG +-> a) next two INTS unioned "etask:PTR TO etask" + trapalloc:INT -> This is unsigned + trapable:INT -> This is unsigned + exceptdata:LONG + exceptcode:LONG + trapdata:LONG + trapcode:LONG + spreg:LONG + splower:LONG + spupper:LONG + switch:LONG + launch:LONG + mementry:lh + userdata:LONG +ENDOBJECT /* SIZEOF=92 */ + +OBJECT etask + mn:mn + parent:PTR TO tc + uniqueid:LONG + children:mlh + trapalloc:INT -> This is unsigned + trapable:INT -> This is unsigned + result1:LONG + result2:LONG + taskmsgport:mp +ENDOBJECT /* SIZEOF=86 */ + +CONST CHILD_NOTNEW=1, + CHILD_NOTFOUND=2, + CHILD_EXITED=3, + CHILD_ACTIVE=4 + +OBJECT stackswapstruct + lower:LONG + upper:LONG + pointer:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST TB_PROCTIME=0, + TB_ETASK=3, + TB_STACKCHK=4, + TB_EXCEPT=5, + TB_SWITCH=6, + TB_LAUNCH=7, + TF_PROCTIME=1, + TF_ETASK=8, + TF_STACKCHK=16, + TF_EXCEPT=$20, + TF_SWITCH=$40, + TF_LAUNCH=$80, + TS_INVALID=0, + TS_ADDED=1, + TS_RUN=2, + TS_READY=3, + TS_WAIT=4, + TS_EXCEPT=5, + TS_REMOVED=6, + SIGB_ABORT=0, + SIGB_CHILD=1, + SIGB_BLIT=4, + SIGB_SINGLE=4, + SIGB_INTUITION=5, + SIGB_NET=7, + SIGB_DOS=8, + SIGF_ABORT=1, + SIGF_CHILD=2, + SIGF_BLIT=16, + SIGF_SINGLE=16, + SIGF_INTUITION=$20, + SIGF_NET=$80, + SIGF_DOS=$100, + SYS_SIGALLOC=$FFFF, + SYS_TRAPALLOC=$8000 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/exec/types.e b/amigae33a/E_v3.3a/Src/Src/Modules/exec/types.e new file mode 100644 index 0000000..2164f65 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/exec/types.e @@ -0,0 +1,7 @@ +OPT MODULE +OPT EXPORT + +CONST INCLUDE_VERSION=40, + LIBRARY_MINIMUM=$21, + BYTEMASK=$ff + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/button.e b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/button.e new file mode 100644 index 0000000..1c43d8c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/button.e @@ -0,0 +1,15 @@ +OPT MODULE +OPT EXPORT + +MODULE 'utility/tagitem' + +CONST BUTTON_DUMMY=TAG_USER+$4000000 + +CONST BUTTON_PUSHBUTTON=BUTTON_DUMMY+1, + BUTTON_GLYPH=BUTTON_DUMMY+2, + BUTTON_ARRAY=BUTTON_DUMMY+3, + BUTTON_TEXTPEN=BUTTON_DUMMY+5, + BUTTON_FILLPEN=BUTTON_DUMMY+6, + BUTTON_FILLTEXTPEN=BUTTON_DUMMY+7, + BUTTON_BACKGROUNDPEN=BUTTON_DUMMY+8, + BUTTON_CURRENT=BUTTON_DUMMY+9 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/calendar.e b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/calendar.e new file mode 100644 index 0000000..ff93a7a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/calendar.e @@ -0,0 +1,25 @@ +OPT MODULE +OPT EXPORT + +MODULE 'utility/tagitem' + +ENUM DL_TEXTPEN, DL_BACKGROUNDPEN, DL_FILLTEXTPEN, DL_FILLPEN, MAX_DL_PENS + +OBJECT daylabel + label:PTR TO CHAR + pen1:INT, pen2:INT, pen3:INT, pen4:INT + attrs:PTR TO tagitem + flags:LONG +ENDOBJECT + +SET DLF_SELECTED, DLF_DISABLED + +CONST CALENDAR_DUMMY=TAG_USER+$4000000 + +CONST CALENDAR_DAY=CALENDAR_DUMMY+1, + CALENDAR_CLOCKDATA=CALENDAR_DUMMY+2, + CALENDAR_FIRSTWEEKDAY=CALENDAR_DUMMY+3, + CALENDAR_DAYS=CALENDAR_DUMMY+4, + CALENDAR_MULTISELECT=CALENDAR_DUMMY+5, + CALENDAR_LABELS=CALENDAR_DUMMY+6, + CALENDAR_LABEL=CALENDAR_DUMMY+7 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/colorwheel.e b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/colorwheel.e new file mode 100644 index 0000000..8eb65d4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/colorwheel.e @@ -0,0 +1,31 @@ +OPT MODULE +OPT EXPORT + +OBJECT colorwheelhsb + hue:LONG + saturation:LONG + brightness:LONG +ENDOBJECT /* SIZEOF=12 */ + +OBJECT colorwheelrgb + red:LONG + green:LONG + blue:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST WHEEL_DUMMY=$84000000, + WHEEL_HUE=$84000001, + WHEEL_SATURATION=$84000002, + WHEEL_BRIGHTNESS=$84000003, + WHEEL_HSB=$84000004, + WHEEL_RED=$84000005, + WHEEL_GREEN=$84000006, + WHEEL_BLUE=$84000007, + WHEEL_RGB=$84000008, + WHEEL_SCREEN=$84000009, + WHEEL_ABBRV=$8400000A, + WHEEL_DONATION=$8400000B, + WHEEL_BEVELBOX=$8400000C, + WHEEL_GRADIENTSLIDER=$8400000D, + WHEEL_MAXPENS=$8400000E + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/gradientslider.e b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/gradientslider.e new file mode 100644 index 0000000..921c523 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/gradientslider.e @@ -0,0 +1,10 @@ +OPT MODULE +OPT EXPORT + +CONST GRAD_DUMMY=$85000000, + GRAD_MAXVAL=$85000001, + GRAD_CURVAL=$85000002, + GRAD_SKIPVAL=$85000003, + GRAD_KNOBPIXELS=$85000004, + GRAD_PENARRAY=$85000005 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tabs.e b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tabs.e new file mode 100644 index 0000000..0d94906 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tabs.e @@ -0,0 +1,17 @@ +OPT MODULE +OPT EXPORT + +MODULE 'utility/tagitem' + +ENUM TL_TEXTPEN, TL_BACKGROUNDPEN, TL_FILLTEXTPEN, TL_FILLPEN, MAX_TL_PENS + +OBJECT tablabel + label:PTR TO CHAR + pen1:INT, pen2:INT, pen3:INT, pen4:INT + attrs:PTR TO tagitem +ENDOBJECT + +CONST TABS_DUMMY=TAG_USER+$4000000 + +CONST TABS_LABELS=TABS_DUMMY+1, + TABS_CURRENT=TABS_DUMMY+2 \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tapedeck.e b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tapedeck.e new file mode 100644 index 0000000..904e34d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/gadgets/tapedeck.e @@ -0,0 +1,17 @@ +OPT MODULE +OPT EXPORT + +CONST TDECK_DUMMY=$85000000, + TDECK_MODE=$85000001, + TDECK_PAUSED=$85000002, + TDECK_TAPE=$85000003, + TDECK_FRAMES=$8500000B, + TDECK_CURRENTFRAME=$8500000C, + BUT_REWIND=0, + BUT_PLAY=1, + BUT_FORWARD=2, + BUT_STOP=3, + BUT_PAUSE=4, + BUT_BEGIN=5, + BUT_FRAME=6, + BUT_END=7 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/clip.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/clip.e new file mode 100644 index 0000000..11ed119 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/clip.e @@ -0,0 +1,73 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/semaphores', + 'graphics/gfx', + 'graphics/layers', + 'graphics/rastport', + 'graphics/regions', + 'utility/hooks' + +CONST NEWLOCKS=1 + +OBJECT layer + front:PTR TO layer + back:PTR TO layer + cliprect:PTR TO cliprect + rp:PTR TO rastport + minx:INT + miny:INT + maxx:INT + maxy:INT + reserved[4]:ARRAY + priority:INT -> This is unsigned + flags:INT -> This is unsigned + superbitmap:PTR TO bitmap + supercliprect:PTR TO cliprect + window:LONG + scroll_x:INT + scroll_y:INT + cr:PTR TO cliprect + cr2:PTR TO cliprect + crnew:PTR TO cliprect + supersavercliprects:PTR TO cliprect +-> Um, this had an illegal name + cliprects_:PTR TO cliprect + layerinfo:PTR TO layer_info + lock:ss + backfill:PTR TO hook + reserved1:LONG + clipregion:PTR TO region + savecliprects:PTR TO region + reserved2[22]:ARRAY + damagelist:PTR TO region +ENDOBJECT /* SIZEOF=160 */ + +OBJECT cliprect + next:PTR TO cliprect + prev:PTR TO cliprect + lobs:PTR TO layer + bitmap:PTR TO bitmap + minx:INT + miny:INT + maxx:INT + maxy:INT +-> Um, these had illegal names + p1_:LONG + p2_:LONG + reserved:LONG + flags:LONG +ENDOBJECT /* SIZEOF=40 */ + +CONST CR_NEEDS_NO_CONCEALED_RASTERS=1, + CR_NEEDS_NO_LAYERBLIT_DAMAGE=2, + ISLESSX=1, + ISLESSY=2, + ISGRTRX=4, + ISGRTRY=8, + LR_FRONT=0, + LR_BACK=4, + LR_RASTPORT=12, + CR_PREV=4, + CR_LOBS=8 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/coerce.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/coerce.e new file mode 100644 index 0000000..9ad1695 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/coerce.e @@ -0,0 +1,8 @@ +OPT MODULE +OPT EXPORT + +CONST PRESERVE_COLORS=1, + AVOID_FLICKER=2, + IGNORE_MCOMPAT=4, + BIDTAG_COERCE=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/collide.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/collide.e new file mode 100644 index 0000000..a1cc346 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/collide.e @@ -0,0 +1,8 @@ +OPT MODULE +OPT EXPORT + +CONST BORDERHIT=0, + TOPHIT=1, + BOTTOMHIT=2, + LEFTHIT=4, + RIGHTHIT=8 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/copper.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/copper.e new file mode 100644 index 0000000..a7fb11b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/copper.e @@ -0,0 +1,79 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'graphics/view' + +CONST COPPER_MOVE=0, + COPPER_WAIT=1, + CPRNXTBUF=2, + CPR_NT_LOF=$8000, + CPR_NT_SHT=$4000, + CPR_NT_SYS=$2000 + +OBJECT copins + opcode:INT +-> a) next two INTs are unioned with "nxtlist:PTR TO coplist" +-> b) next INT is unioned with "destaddr:INT" + vwaitpos:INT +-> b) next INT is unioned with "destdata:INT" + hwaitpos:INT +ENDOBJECT /* SIZEOF=6 */ + +#define VWAITPOS vwaitpos +#define DESTADDR vwaitpos +#define HWAITPOS hwaitpos +#define DESTDATA hwaitpos + +OBJECT cprlist + next:PTR TO cprlist + start:PTR TO INT -> Target is unsigned + maxcount:INT +ENDOBJECT /* SIZEOF=10 */ + +OBJECT coplist + next:PTR TO coplist +-> Um, these had illegal names + coplist_:PTR TO coplist + viewport_:PTR TO viewport + copins:PTR TO copins + copptr:PTR TO copins + coplstart:PTR TO INT -> Target is unsigned + copsstart:PTR TO INT -> Target is unsigned + count:INT + maxcount:INT + dyoffset:INT +-> Um, if V1_3 only? +-> cop2start:PTR TO INT +-> cop3start:PTR TO INT +-> cop4start:PTR TO INT +-> cop5start:PTR TO INT + slrepeat:INT -> This is unsigned + flags:INT -> This is unsigned +ENDOBJECT /* SIZEOF=50 */ + +CONST EXACT_LINE=1, + HALF_LINE=2 + +OBJECT ucoplist + next:PTR TO ucoplist + firstcoplist:PTR TO coplist + coplist:PTR TO coplist +ENDOBJECT /* SIZEOF=12 */ + +OBJECT copinit + vsync_hblank[2]:ARRAY OF INT -> Array is unsigned + diagstrt[12]:ARRAY OF INT -> Array is unsigned + fm0[2]:ARRAY OF INT -> Array is unsigned + diwstart[10]:ARRAY OF INT -> Array is unsigned + bplcon2[2]:ARRAY OF INT -> Array is unsigned + sprfix[16]:ARRAY OF INT -> Array is unsigned + sprstrtup[32]:ARRAY OF INT -> Array is unsigned + wait14[2]:ARRAY OF INT -> Array is unsigned + norm_hblank[2]:ARRAY OF INT -> Array is unsigned + jump[2]:ARRAY OF INT -> Array is unsigned + wait_forever[6]:ARRAY OF INT -> Array is unsigned + sprstop[8]:ARRAY OF INT -> Array is unsigned +ENDOBJECT /* SIZEOF=192 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/display.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/display.e new file mode 100644 index 0000000..346523b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/display.e @@ -0,0 +1,20 @@ +OPT MODULE +OPT EXPORT + +CONST MODE_640=$8000, + PLNCNTMSK=7, + PLNCNTSHFT=12, + PF2PRI=$40, + COLORON=$200, + DBLPF=$400, + HOLDNMODIFY=$800, + INTERLACE=4, + PFA_FINE_SCROLL=15, + PFB_FINE_SCROLL_SHIFT=4, + PF_FINE_SCROLL_MASK=15, + DIW_HORIZ_POS=$7F, + DIW_VRTCL_POS=$1FF, + DIW_VRTCL_POS_SHIFT=7, + DFTCH_MASK=$FF, + VPOSRLOF=$8000 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/displayinfo.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/displayinfo.e new file mode 100644 index 0000000..29bfa6e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/displayinfo.e @@ -0,0 +1,117 @@ +OPT MODULE +OPT EXPORT + +MODULE 'graphics/gfx', + 'graphics/monitor' + +CONST DTAG_DISP=$80000000, + DTAG_DIMS=$80001000, + DTAG_MNTR=$80002000, + DTAG_NAME=$80003000, + DTAG_VEC=$80004000 + +OBJECT qh + structid:LONG + displayid:LONG + skipid:LONG + length:LONG +ENDOBJECT /* SIZEOF=16 */ + +OBJECT displayinfo + qh:qh + notavailable:INT -> This is unsigned + propertyflags:LONG + resolution:tpoint + pixelspeed:INT -> This is unsigned + numstdsprites:INT -> This is unsigned + paletterange:INT -> This is unsigned + spriteresolution:tpoint + pad[4]:ARRAY + redbits:CHAR + greenbits:CHAR + bluebits:CHAR + pad2a:CHAR + pad2b[4]:ARRAY + reserved[2]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=56 */ + +CONST DI_AVAIL_NOCHIPS=1, + DI_AVAIL_NOMONITOR=2, + DI_AVAIL_NOTWITHGENLOCK=4, + DIPF_IS_LACE=1, + DIPF_IS_DUALPF=2, + DIPF_IS_PF2PRI=4, + DIPF_IS_HAM=8, + DIPF_IS_ECS=16, + DIPF_IS_AA=$10000, + DIPF_IS_PAL=$20, + DIPF_IS_SPRITES=$40, + DIPF_IS_GENLOCK=$80, + DIPF_IS_WB=$100, + DIPF_IS_DRAGGABLE=$200, + DIPF_IS_PANELLED=$400, + DIPF_IS_BEAMSYNC=$800, + DIPF_IS_EXTRAHALFBRITE=$1000, + DIPF_IS_SPRITES_ATT=$2000, + DIPF_IS_SPRITES_CHNG_RES=$4000, + DIPF_IS_SPRITES_BORDER=$8000, + DIPF_IS_SCANDBL=$20000, + DIPF_IS_SPRITES_CHNG_BASE=$40000, + DIPF_IS_SPRITES_CHNG_PRI=$80000, + DIPF_IS_DBUFFER=$100000, + DIPF_IS_PROGBEAM=$200000, + DIPF_IS_FOREIGN=$80000000 + +OBJECT dimensioninfo + qh:qh + maxdepth:INT -> This is unsigned + minrasterwidth:INT -> This is unsigned + minrasterheight:INT -> This is unsigned + maxrasterwidth:INT -> This is unsigned + maxrasterheight:INT -> This is unsigned + nominal:rectangle + maxoscan:rectangle + videooscan:rectangle + txtoscan:rectangle + stdoscan:rectangle + pad[14]:ARRAY + reserved[2]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=88 */ + +OBJECT monitorinfo + qh:qh + mspc:PTR TO monitorspec + viewposition:tpoint + viewresolution:tpoint + viewpositionrange:rectangle + totalrows:INT -> This is unsigned + totalcolorclocks:INT -> This is unsigned + minrow:INT -> This is unsigned + compatibility:INT + pad[32]:ARRAY + mousetick:tpoint + defaultviewposition:tpoint + preferredmodeid:LONG + reserved[2]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=96 */ + +CONST MCOMPAT_MIXED=0, + MCOMPAT_SELF=1, + MCOMPAT_NOBODY=-1, + DISPLAYNAMELEN=$20 + +OBJECT nameinfo + qh:qh + name[32]:ARRAY + reserved[2]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=56 */ + +OBJECT vecinfo + qh:qh + vec:LONG + data:LONG + type:INT -> This is unsigned + pad[3]:ARRAY OF INT -> Array is unsigned + reserved[2]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=40 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gels.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gels.e new file mode 100644 index 0000000..5c7be58 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gels.e @@ -0,0 +1,118 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +CONST SUSERFLAGS=$FF, + VSF_VSPRITE=1, + VSF_SAVEBACK=2, + VSF_OVERLAY=4, + VSF_MUSTDRAW=8, + VSF_BACKSAVED=$100, + VSF_BOBUPDATE=$200, + VSF_GELGONE=$400, + VSF_VSOVERFLOW=$800, + BUSERFLAGS=$FF, + BF_SAVEBOB=1, + BF_BOBISCOMP=2, + BF_BWAITING=$100, + BF_BDRAWN=$200, + BF_BOBSAWAY=$400, + BF_BOBNIX=$800, + BF_SAVEPRESERVE=$1000, + BF_OUTSTEP=$2000, + ANFRACSIZE=6, + ANIMHALF=$20, + RINGTRIGGER=1 + +OBJECT vs + nextvsprite:PTR TO vs + prevvsprite:PTR TO vs + drawpath:PTR TO vs + clearpath:PTR TO vs + oldy:INT + oldx:INT + vsflags:INT + y:INT + x:INT + height:INT + width:INT + depth:INT + memask:INT + hitmask:INT + imagedata:PTR TO INT + borderline:PTR TO INT + collmask:PTR TO INT + sprcolors:PTR TO INT + vsbob:PTR TO bob + planepick:CHAR -> This is signed + planeonoff:CHAR -> This is signed + vuserext:LONG +ENDOBJECT /* SIZEOF=58 */ + +OBJECT bob + bobflags:INT + savebuffer:PTR TO INT + imageshadow:PTR TO INT + before:PTR TO bob + after:PTR TO bob + bobvsprite:PTR TO vs + bobcomp:PTR TO ac + dbuffer:PTR TO dbp + buserext:LONG +ENDOBJECT /* SIZEOF=30 */ + +OBJECT ac + compflags:INT + timer:INT + timeset:INT + nextcomp:PTR TO ac + prevcomp:PTR TO ac + nextseq:PTR TO ac + prevseq:PTR TO ac + animcroutine:LONG + ytrans:INT + xtrans:INT + headob:PTR TO ao + animbob:PTR TO bob +ENDOBJECT /* SIZEOF=38 */ + +OBJECT ao + nextob:PTR TO ao + prevob:PTR TO ao + clock:LONG + anoldy:INT + anoldx:INT + any:INT + anx:INT + yvel:INT + xvel:INT + yaccel:INT + xaccel:INT + ringytrans:INT + ringxtrans:INT + animoroutine:LONG + headcomp:PTR TO ac + auserext:LONG +ENDOBJECT /* SIZEOF=40 */ + +OBJECT dbp + bufy:INT + bufx:INT + bufpath:PTR TO vs + bufbuffer:PTR TO INT +-> Um, 'bufplanes' not in .h file + bufplanes:PTR TO LONG +ENDOBJECT /* SIZEOF=16 */ + +#define InitAnimate(animKey) PutLong(animKey,NIL) +#define RemBob(b) PutInt(b, Int(b) OR BF_BOBSAWAY) + +CONST B2NORM=0, + B2SWAP=1, + B2BOBBER=2 + +-> Um, this was in 'graphics/view' +OBJECT colltable + collptrs[16]:ARRAY OF LONG +ENDOBJECT diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfx.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfx.e new file mode 100644 index 0000000..4f0bb44 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfx.e @@ -0,0 +1,55 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define RASSIZE(w,h) (Mul((h),Shr((w)+15,3) AND $FFFE)) + +CONST BITSET=$8000, + BITCLR=0, + AGNUS=1, + DENISE=1 + +OBJECT bitmap + bytesperrow:INT -> This is unsigned + rows:INT -> This is unsigned + flags:CHAR + depth:CHAR + pad:INT + planes[8]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=40 */ + +OBJECT rectangle + minx:INT + miny:INT + maxx:INT + maxy:INT +ENDOBJECT /* SIZEOF=8 */ + +OBJECT rect32 + minx:LONG + miny:LONG + maxx:LONG + maxy:LONG +ENDOBJECT /* SIZEOF=16 */ + +OBJECT tpoint + x:INT + y:INT +ENDOBJECT /* SIZEOF=4 */ + +CONST BMB_CLEAR=0, + BMB_DISPLAYABLE=1, + BMB_INTERLEAVED=2, + BMB_STANDARD=3, + BMB_MINPLANES=4, + BMF_CLEAR=1, + BMF_DISPLAYABLE=2, + BMF_INTERLEAVED=4, + BMF_STANDARD=8, + BMF_MINPLANES=16, + BMA_HEIGHT=0, + BMA_DEPTH=4, + BMA_WIDTH=8, + BMA_FLAGS=12 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxbase.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxbase.e new file mode 100644 index 0000000..ad37247 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxbase.e @@ -0,0 +1,170 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/interrupts', + 'exec/libraries', + 'exec/lists', + 'exec/semaphores', + 'exec/tasks', + 'graphics/copper', + 'graphics/monitor', + 'graphics/sprite', + 'graphics/text', + 'graphics/view', + 'hardware/blit' + +OBJECT gfxbase +-> Um, this was missing + lib:lib + actiview:PTR TO view + copinit:PTR TO copinit + cia:PTR TO LONG + blitter:PTR TO LONG + loflist:PTR TO INT -> Target is unsigned + shflist:PTR TO INT -> Target is unsigned + blthd:PTR TO bltnode + blttl:PTR TO bltnode + bsblthd:PTR TO bltnode + bsblttl:PTR TO bltnode + vbsrv:is + timsrv:is + bltsrv:is + textfonts:lh + defaultfont:PTR TO textfont + modes:INT -> This is unsigned + vblank:CHAR -> This is signed + debug:CHAR -> This is signed + beamsync:INT + system_bplcon0:INT + spritereserved:CHAR + bytereserved:CHAR + flags:INT -> This is unsigned + blitlock:INT + blitnest:INT + blitwaitq:lh + blitowner:PTR TO tc + tof_waitq:lh + displayflags:INT -> This is unsigned +-> This is really PTR TO PTR TO simplesprite + simplesprites:PTR TO LONG + maxdisplayrow:INT -> This is unsigned + maxdisplaycolumn:INT -> This is unsigned + normaldisplayrows:INT -> This is unsigned + normaldisplaycolumns:INT -> This is unsigned + normaldpmx:INT -> This is unsigned + normaldpmy:INT -> This is unsigned + lastchancememory:PTR TO ss + lcmptr:PTR TO INT -> Target is unsigned + microsperline:INT -> This is unsigned + mindisplaycolumn:INT -> This is unsigned + chiprevbits0:CHAR + memtype:CHAR + crb_reserved[4]:ARRAY + monitor_id:INT -> This is unsigned + hedley[8]:ARRAY OF LONG + hedley_sprites[8]:ARRAY OF LONG + hedley_sprites1[8]:ARRAY OF LONG + hedley_count:INT + hedley_flags:INT -> This is unsigned + hedley_tmp:INT + hash_table:PTR TO LONG + current_tot_rows:INT -> This is unsigned + current_tot_cclks:INT -> This is unsigned + hedley_hint:CHAR + hedley_hint2:CHAR + nreserved[4]:ARRAY OF LONG + a2024_sync_raster:PTR TO LONG + control_delta_pal:INT -> This is unsigned + control_delta_ntsc:INT -> This is unsigned + current_monitor:PTR TO monitorspec + monitorlist:lh + default_monitor:PTR TO monitorspec + monitorlistsemaphore:PTR TO ss + displayinfodatabase:LONG + topline:INT -> This is unsigned + activiewcprsemaphore:PTR TO ss + utilbase:PTR TO LONG + execbase:PTR TO LONG + bwshifts:PTR TO CHAR + strtfetchmasks:PTR TO INT -> Target is unsigned + stopfetchmasks:PTR TO INT -> Target is unsigned + overrun:PTR TO INT -> Target is unsigned + realstops:PTR TO INT + spritewidth:INT -> This is unsigned + spritefmode:INT -> This is unsigned + softsprites:CHAR -> This is signed + arraywidth:CHAR -> This is signed + defaultspritewidth:INT -> This is unsigned + sprmovedisable:CHAR -> This is signed + wantchips:CHAR + boardmemtype:CHAR + bugs:CHAR + layersbase:PTR TO LONG + colormask:LONG + ivector:LONG + idata:LONG + specialcounter:LONG + dblist:LONG + monitorflags:INT -> This is unsigned + scandoubledsprites:CHAR + bp3bits:CHAR + monitorvblank:analogsignalinterval + natural_monitor:PTR TO monitorspec + progdata:LONG + extsprites:CHAR + pad3:CHAR + gfxflags:INT -> This is unsigned + vbcounter:LONG + hashtablesemaphore:PTR TO ss + hwemul[9]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=497 */ + +#define chunkytoplanarptr hwemul[0] + +CONST OWNBLITTERN=0, + QBOWNERN=1, + BLITMSG_FAULTN=2, + BLITMSG_FAULT=4, + QBOWNER=2, + GBFLAGSF_TIMER=$40, + GBFLAGSF_LASTBLIT=$80, + GFXB_BIG_BLITS=0, + GFXB_HR_AGNUS=0, + GFXB_HR_DENISE=1, + GFXB_AA_ALICE=2, + GFXB_AA_LISA=3, + GFXB_AA_MLISA=4, + GFXF_BIG_BLITS=1, + GFXF_HR_AGNUS=1, + GFXF_HR_DENISE=2, + GFXF_AA_ALICE=4, + GFXF_AA_LISA=8, + GFXF_AA_MLISA=16, + SETCHIPREV_A=1, + SETCHIPREV_ECS=3, + SETCHIPREV_AA=15, + SETCHIPREV_BEST=-1, + BUS_16=0, + NML_CAS=0, + BUS_32=1, + DBL_CAS=2, + BANDWIDTH_1X=0, + BANDWIDTH_2XNML=1, + BANDWIDTH_2XDBL=2, + BANDWIDTH_4X=3, + NEW_DATABASE=1, + NTSCN=0, + NTSC=1, + GENLOCN=1, + GENLOC=2, + PALN=2, + PAL=4, + TODA_SAFEN=3, + TODA_SAFE=8, + REALLY_PALN=4, + REALLY_PAL=16, + LPEN_SWAP_FRAMES=32 + +#define GRAPHICSNAME 'graphics.library' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxmacros.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxmacros.e new file mode 100644 index 0000000..97630e8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxmacros.e @@ -0,0 +1,44 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +-> These need 'graphics/gfx', 'hardware/custom', 'hardware/dmabits' +#define ON_DISPLAY PutInt(CUSTOMADDR+DMACON,BITSET OR DMAF_RASTER) +#define OFF_DISPLAY PutInt(CUSTOMADDR+DMACON,BITCLR OR DMAF_RASTER) +#define ON_SPRITE PutInt(CUSTOMADDR+DMACON,BITSET OR DMAF_SPRITE) +#define OFF_SPRITE PutInt(CUSTOMADDR+DMACON,BITCLR OR DMAF_SPRITE) + +-> Same, but 'hardware/intbits' instead of 'hardware/dmabits' +#define ON_VBLANK PutInt(CUSTOMADDR+INTENA,BITSET OR INTF_VERTB) +#define OFF_VBLANK PutInt(CUSTOMADDR+INTENA,BITCLR OR INTF_VERTB) + +#define SetDrPt(w,p) (PutInt((w)+RP_LINEPTRN,(p)) BUT \ + PutInt((w)+RP_FLAGS,Int((w)+RP_FLAGS) OR FRST_DOT) BUT \ + PutChar((w)+RP_LINPATCNT,15)) +#define SetAfPt(w,p,n) (PutLong((w)+RP_AREAPTRN,(p)) BUT \ + PutChar((w)+RP_AREAPTSZ,(n))) + +#define SetOPen(w,c) (PutChar((w)+RP_AOLPEN,(c)) BUT \ + PutInt((w)+RP_FLAGS,Int((w)+RP_FLAGS) OR RPF_AREAOUTLINE)) +#define SetWrMsk(w,m) PutChar((w)+RP_MASK,(m)) + +#define SafeSetOutlinePen(w,c) (IF KickVersion(39) THEN SetOutlinePen((w),(c)) \ + ELSE SetOPen(w,c)) +#define SafeSetWriteMask(w,m) (IF KickVersion(39) THEN SetWriteMask((w),(m)) \ + ELSE SetWrMsk(w,m)) + +#define GetOutlinePen(rp) GetOPen((rp)) + +#define BNDRYOFF(w) PutInt((w)+RP_FLAGS,Int((w)+RP_FLAGS) AND Not(RPF_AREAOUTLINE)) + +#define CINIT(c,n) UcopperListInit((c),(n)) +#define CMOVE(c,a,b) (Cmove((c),{a},(b)) BUT Cbump((c))) +-> CMOVE is a little hard to use due to {a}. CMOVEA() is the same except it +-> expects the address, so it may be easier to use... +#define CMOVEA(c,d,b) (Cmove((c),(d),(b)) BUT Cbump((c))) +#define CWAIT(c,a,b) (Cwait((c),(a),(b)) BUT Cbump((c))) +#define CEND(c) CWAIT((c),10000,255) + +#define DrawCircle(rp,cx,cy,r) DrawEllipse((rp),(cx),(cy),(r),(r)) +#define AreaCircle(rp,cx,cy,r) AreaEllipse((rp),(cx),(cy),(r),(r)) diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxnodes.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxnodes.e new file mode 100644 index 0000000..592258b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/gfxnodes.e @@ -0,0 +1,23 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +OBJECT xln + succ:PTR TO ln + pred:PTR TO ln + type:CHAR + pri:CHAR -> This is signed + name:PTR TO CHAR + subsystem:CHAR + subtype:CHAR + library:LONG + init:LONG +ENDOBJECT /* SIZEOF=24 */ + +CONST SS_GRAPHICS=2, + VIEW_EXTRA_TYPE=1, + VIEWPORT_EXTRA_TYPE=2, + SPECIAL_MONITOR_TYPE=3, + MONITOR_SPEC_TYPE=4 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/graphint.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/graphint.e new file mode 100644 index 0000000..1a4871a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/graphint.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +OBJECT isrvstr + ln:ln + iptr:PTR TO isrvstr + code:LONG + ccode:LONG + carg:LONG +ENDOBJECT diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/layers.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/layers.e new file mode 100644 index 0000000..e60ffb7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/layers.e @@ -0,0 +1,41 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', + 'exec/semaphores', + 'graphics/clip' + +CONST LAYERSIMPLE=1, + LAYERSMART=2, + LAYERSUPER=4, + LAYERUPDATING=16, + LAYERBACKDROP=$40, + LAYERREFRESH=$80, + LAYERIREFRESH=$200, + LAYERIREFRESH2=$400, + LAYER_CLIPRECTS_LOST=$100 + +OBJECT layer_info + top_layer:PTR TO layer + check_lp:PTR TO layer + obs:PTR TO cliprect + freecliprects:PTR TO cliprect + privatereserve1:LONG + privatereserve2:LONG + lock:ss + gs_head:mlh + privatereserve3:INT + privatereserve4:LONG + flags:INT -> This is unsigned + fatten_count:CHAR + locklayerscount:CHAR + privatereserve5:INT + blankhook:LONG + layerinfo_extra:LONG +ENDOBJECT /* SIZEOF=102 */ + +CONST NEWLAYERINFO_CALLED=1, + ALERTLAYERSNOMEM=$83010000, + LAYERS_NOBACKFILL=1, + LAYERS_BACKFILL=0 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/modeid.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/modeid.e new file mode 100644 index 0000000..50f7f56 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/modeid.e @@ -0,0 +1,253 @@ +OPT MODULE +OPT EXPORT + +CONST INVALID_ID=-1, + MONITOR_ID_MASK=$FFFF1000, + DEFAULT_MONITOR_ID=0, + NTSC_MONITOR_ID=$11000, + PAL_MONITOR_ID=$21000, + LORES_KEY=0, + HIRES_KEY=$8000, + SUPER_KEY=$8020, + HAM_KEY=$800, + LORESLACE_KEY=4, + HIRESLACE_KEY=$8004, + SUPERLACE_KEY=$8024, + HAMLACE_KEY=$804, + LORESDPF_KEY=$400, + HIRESDPF_KEY=$8400, + SUPERDPF_KEY=$8420, + LORESLACEDPF_KEY=$404, + HIRESLACEDPF_KEY=$8404, + SUPERLACEDPF_KEY=$8424, + LORESDPF2_KEY=$440, + HIRESDPF2_KEY=$8440, + SUPERDPF2_KEY=$8460, + LORESLACEDPF2_KEY=$444, + HIRESLACEDPF2_KEY=$8444, + SUPERLACEDPF2_KEY=$8464, + EXTRAHALFBRITE_KEY=$80, + EXTRAHALFBRITELACE_KEY=$84, + HIRESHAM_KEY=$8800, + SUPERHAM_KEY=$8820, + HIRESEHB_KEY=$8080, + SUPEREHB_KEY=$80A0, + HIRESHAMLACE_KEY=$8804, + SUPERHAMLACE_KEY=$8824, + HIRESEHBLACE_KEY=$8084, + SUPEREHBLACE_KEY=$80A4, + LORESSDBL_KEY=8, + LORESHAMSDBL_KEY=$808, + LORESEHBSDBL_KEY=$88, + HIRESHAMSDBL_KEY=$8808, + VGA_MONITOR_ID=$31000, + VGAEXTRALORES_KEY=$31004, + VGALORES_KEY=$39004, + VGAPRODUCT_KEY=$39024, + VGAHAM_KEY=$31804, + VGAEXTRALORESLACE_KEY=$31005, + VGALORESLACE_KEY=$39005, + VGAPRODUCTLACE_KEY=$39025, + VGAHAMLACE_KEY=$31805, + VGAEXTRALORESDPF_KEY=$31404, + VGALORESDPF_KEY=$39404, + VGAPRODUCTDPF_KEY=$39424, + VGAEXTRALORESLACEDPF_KEY=$31405, + VGALORESLACEDPF_KEY=$39405, + VGAPRODUCTLACEDPF_KEY=$39425, + VGAEXTRALORESDPF2_KEY=$31444, + VGALORESDPF2_KEY=$39444, + VGAPRODUCTDPF2_KEY=$39464, + VGAEXTRALORESLACEDPF2_KEY=$31445, + VGALORESLACEDPF2_KEY=$39445, + VGAPRODUCTLACEDPF2_KEY=$39465, + VGAEXTRAHALFBRITE_KEY=$31084, + VGAEXTRAHALFBRITELACE_KEY=$31085, + VGAPRODUCTHAM_KEY=$39824, + VGALORESHAM_KEY=$39804, + VGAEXTRALORESHAM_KEY=$31804, + VGAPRODUCTHAMLACE_KEY=$39825, + VGALORESHAMLACE_KEY=$39805, + VGAEXTRALORESHAMLACE_KEY=$31805, + VGAEXTRALORESEHB_KEY=$31084, + VGAEXTRALORESEHBLACE_KEY=$31085, + VGALORESEHB_KEY=$39084, + VGALORESEHBLACE_KEY=$39085, + VGAEHB_KEY=$390A4, + VGAEHBLACE_KEY=$390A5, + VGAEXTRALORESDBL_KEY=$31000, + VGALORESDBL_KEY=$39000, + VGAPRODUCTDBL_KEY=$39020, + VGAEXTRALORESHAMDBL_KEY=$31800, + VGALORESHAMDBL_KEY=$39800, + VGAPRODUCTHAMDBL_KEY=$39820, + VGAEXTRALORESEHBDBL_KEY=$31080, + VGALORESEHBDBL_KEY=$39080, + VGAPRODUCTEHBDBL_KEY=$390A0, + A2024_MONITOR_ID=$41000, + A2024TENHERTZ_KEY=$41000, + A2024FIFTEENHERTZ_KEY=$49000, + PROTO_MONITOR_ID=$51000, + EURO72_MONITOR_ID=$61000, + EURO72EXTRALORES_KEY=$61004, + EURO72LORES_KEY=$69004, + EURO72PRODUCT_KEY=$69024, + EURO72HAM_KEY=$61804, + EURO72EXTRALORESLACE_KEY=$61005, + EURO72LORESLACE_KEY=$69005, + EURO72PRODUCTLACE_KEY=$69025, + EURO72HAMLACE_KEY=$61805, + EURO72EXTRALORESDPF_KEY=$61404, + EURO72LORESDPF_KEY=$69404, + EURO72PRODUCTDPF_KEY=$69424, + EURO72EXTRALORESLACEDPF_KEY=$61405, + EURO72LORESLACEDPF_KEY=$69405, + EURO72PRODUCTLACEDPF_KEY=$69425, + EURO72EXTRALORESDPF2_KEY=$61444, + EURO72LORESDPF2_KEY=$69444, + EURO72PRODUCTDPF2_KEY=$69464, + EURO72EXTRALORESLACEDPF2_KEY=$61445, + EURO72LORESLACEDPF2_KEY=$69445, + EURO72PRODUCTLACEDPF2_KEY=$69465, + EURO72EXTRAHALFBRITE_KEY=$61084, + EURO72EXTRAHALFBRITELACE_KEY=$61085, + EURO72PRODUCTHAM_KEY=$69824, + EURO72PRODUCTHAMLACE_KEY=$69825, + EURO72LORESHAM_KEY=$69804, + EURO72LORESHAMLACE_KEY=$69805, + EURO72EXTRALORESHAM_KEY=$61804, + EURO72EXTRALORESHAMLACE_KEY=$61805, + EURO72EXTRALORESEHB_KEY=$61084, + EURO72EXTRALORESEHBLACE_KEY=$61085, + EURO72LORESEHB_KEY=$69084, + EURO72LORESEHBLACE_KEY=$69085, + EURO72EHB_KEY=$690A4, + EURO72EHBLACE_KEY=$690A5, + EURO72EXTRALORESDBL_KEY=$61000, + EURO72LORESDBL_KEY=$69000, + EURO72PRODUCTDBL_KEY=$69020, + EURO72EXTRALORESHAMDBL_KEY=$61800, + EURO72LORESHAMDBL_KEY=$69800, + EURO72PRODUCTHAMDBL_KEY=$69820, + EURO72EXTRALORESEHBDBL_KEY=$61080, + EURO72LORESEHBDBL_KEY=$69080, + EURO72PRODUCTEHBDBL_KEY=$690A0, + EURO36_MONITOR_ID=$71000, + SUPER72_MONITOR_ID=$81000, + SUPER72LORESDBL_KEY=$81008, + SUPER72HIRESDBL_KEY=$89008, + SUPER72SUPERDBL_KEY=$89028, + SUPER72LORESHAMDBL_KEY=$81808, + SUPER72HIRESHAMDBL_KEY=$89808, + SUPER72SUPERHAMDBL_KEY=$89828, + SUPER72LORESEHBDBL_KEY=$81088, + SUPER72HIRESEHBDBL_KEY=$89088, + SUPER72SUPEREHBDBL_KEY=$890A8, + DBLNTSC_MONITOR_ID=$91000, + DBLNTSCLORES_KEY=$91000, + DBLNTSCLORESFF_KEY=$91004, + DBLNTSCLORESHAM_KEY=$91800, + DBLNTSCLORESHAMFF_KEY=$91804, + DBLNTSCLORESEHB_KEY=$91080, + DBLNTSCLORESEHBFF_KEY=$91084, + DBLNTSCLORESLACE_KEY=$91005, + DBLNTSCLORESHAMLACE_KEY=$91805, + DBLNTSCLORESEHBLACE_KEY=$91085, + DBLNTSCLORESDPF_KEY=$91400, + DBLNTSCLORESDPFFF_KEY=$91404, + DBLNTSCLORESDPFLACE_KEY=$91405, + DBLNTSCLORESDPF2_KEY=$91440, + DBLNTSCLORESDPF2FF_KEY=$91444, + DBLNTSCLORESDPF2LACE_KEY=$91445, + DBLNTSCHIRES_KEY=$99000, + DBLNTSCHIRESFF_KEY=$99004, + DBLNTSCHIRESHAM_KEY=$99800, + DBLNTSCHIRESHAMFF_KEY=$99804, + DBLNTSCHIRESLACE_KEY=$99005, + DBLNTSCHIRESHAMLACE_KEY=$99805, + DBLNTSCHIRESEHB_KEY=$99080, + DBLNTSCHIRESEHBFF_KEY=$99084, + DBLNTSCHIRESEHBLACE_KEY=$99085, + DBLNTSCHIRESDPF_KEY=$99400, + DBLNTSCHIRESDPFFF_KEY=$99404, + DBLNTSCHIRESDPFLACE_KEY=$99405, + DBLNTSCHIRESDPF2_KEY=$99440, + DBLNTSCHIRESDPF2FF_KEY=$99444, + DBLNTSCHIRESDPF2LACE_KEY=$99445, + DBLNTSCEXTRALORES_KEY=$91200, + DBLNTSCEXTRALORESHAM_KEY=$91A00, + DBLNTSCEXTRALORESEHB_KEY=$91280, + DBLNTSCEXTRALORESDPF_KEY=$91600, + DBLNTSCEXTRALORESDPF2_KEY=$91640, + DBLNTSCEXTRALORESFF_KEY=$91204, + DBLNTSCEXTRALORESHAMFF_KEY=$91A04, + DBLNTSCEXTRALORESEHBFF_KEY=$91284, + DBLNTSCEXTRALORESDPFFF_KEY=$91604, + DBLNTSCEXTRALORESDPF2FF_KEY=$91644, + DBLNTSCEXTRALORESLACE_KEY=$91205, + DBLNTSCEXTRALORESHAMLACE_KEY=$91A05, + DBLNTSCEXTRALORESEHBLACE_KEY=$91285, + DBLNTSCEXTRALORESDPFLACE_KEY=$91605, + DBLNTSCEXTRALORESDPF2LACE_KEY=$91645, + DBLPAL_MONITOR_ID=$A1000, + DBLPALLORES_KEY=$A1000, + DBLPALLORESFF_KEY=$A1004, + DBLPALLORESHAM_KEY=$A1800, + DBLPALLORESHAMFF_KEY=$A1804, + DBLPALLORESEHB_KEY=$A1080, + DBLPALLORESEHBFF_KEY=$A1084, + DBLPALLORESLACE_KEY=$A1005, + DBLPALLORESHAMLACE_KEY=$A1805, + DBLPALLORESEHBLACE_KEY=$A1085, + DBLPALLORESDPF_KEY=$A1400, + DBLPALLORESDPFFF_KEY=$A1404, + DBLPALLORESDPFLACE_KEY=$A1405, + DBLPALLORESDPF2_KEY=$A1440, + DBLPALLORESDPF2FF_KEY=$A1444, + DBLPALLORESDPF2LACE_KEY=$A1445, + DBLPALHIRES_KEY=$A9000, + DBLPALHIRESFF_KEY=$A9004, + DBLPALHIRESHAM_KEY=$A9800, + DBLPALHIRESHAMFF_KEY=$A9804, + DBLPALHIRESLACE_KEY=$A9005, + DBLPALHIRESHAMLACE_KEY=$A9805, + DBLPALHIRESEHB_KEY=$A9080, + DBLPALHIRESEHBFF_KEY=$A9084, + DBLPALHIRESEHBLACE_KEY=$A9085, + DBLPALHIRESDPF_KEY=$A9400, + DBLPALHIRESDPFFF_KEY=$A9404, + DBLPALHIRESDPFLACE_KEY=$A9405, + DBLPALHIRESDPF2_KEY=$A9440, + DBLPALHIRESDPF2FF_KEY=$A9444, + DBLPALHIRESDPF2LACE_KEY=$A9445, + DBLPALEXTRALORES_KEY=$A1200, + DBLPALEXTRALORESHAM_KEY=$A1A00, + DBLPALEXTRALORESEHB_KEY=$A1280, + DBLPALEXTRALORESDPF_KEY=$A1600, + DBLPALEXTRALORESDPF2_KEY=$A1640, + DBLPALEXTRALORESFF_KEY=$A1204, + DBLPALEXTRALORESHAMFF_KEY=$A1A04, + DBLPALEXTRALORESEHBFF_KEY=$A1284, + DBLPALEXTRALORESDPFFF_KEY=$A1604, + DBLPALEXTRALORESDPF2FF_KEY=$A1644, + DBLPALEXTRALORESLACE_KEY=$A1205, + DBLPALEXTRALORESHAMLACE_KEY=$A1A05, + DBLPALEXTRALORESEHBLACE_KEY=$A1285, + DBLPALEXTRALORESDPFLACE_KEY=$A1605, + DBLPALEXTRALORESDPF2LACE_KEY=$A1645, + MUST_FLAGS=$100E, + SPECIAL_FLAGS=$100E, + BIDTAG_DIPFMUSTHAVE=$80000001, + BIDTAG_DIPFMUSTNOTHAVE=$80000002, + BIDTAG_VIEWPORT=$80000003, + BIDTAG_NOMINALWIDTH=$80000004, + BIDTAG_NOMINALHEIGHT=$80000005, + BIDTAG_DESIREDWIDTH=$80000006, + BIDTAG_DESIREDHEIGHT=$80000007, + BIDTAG_DEPTH=$80000008, + BIDTAG_MONITORID=$80000009, + BIDTAG_SOURCEID=$8000000A, + BIDTAG_REDBITS=$8000000B, + BIDTAG_BLUEBITS=$8000000C, + BIDTAG_GREENBITS=$8000000D, + BIDTAG_GFXPRIVATE=$8000000E diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/monitor.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/monitor.e new file mode 100644 index 0000000..32b46b7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/monitor.e @@ -0,0 +1,126 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/lists', + 'exec/semaphores', + 'graphics/gfx', + 'graphics/gfxnodes' + +OBJECT analogsignalinterval + start:INT -> This is unsigned + stop:INT -> This is unsigned +ENDOBJECT /* SIZEOF=4 */ + +OBJECT specialmonitor + xln:xln + flags:INT -> This is unsigned + do_monitor:LONG + reserved1:LONG + reserved2:LONG + reserved3:LONG + hblank:analogsignalinterval + vblank:analogsignalinterval + hsync:analogsignalinterval + vsync:analogsignalinterval +ENDOBJECT /* SIZEOF=58 */ + +OBJECT monitorspec + xln:xln + flags:INT -> This is unsigned + ratioh:LONG + ratiov:LONG + total_rows:INT -> This is unsigned + total_colorclocks:INT -> This is unsigned + denisemaxdisplaycolumn:INT -> This is unsigned + beamcon0:INT -> This is unsigned + min_row:INT -> This is unsigned + special:PTR TO specialmonitor + opencount:INT -> This is unsigned + transform:LONG + translate:LONG + scale:LONG + xoffset:INT -> This is unsigned + yoffset:INT -> This is unsigned + legalview:rectangle + maxoscan:LONG + videoscan:LONG + denisemindisplaycolumn:INT -> This is unsigned + displaycompatible:LONG + displayinfodatabase:lh + didbsemaphore:ss + mrgcop:LONG + loadview:LONG + killview:LONG +ENDOBJECT /* SIZEOF=160 */ + +CONST MSB_REQUEST_NTSC=0, + MSB_REQUEST_PAL=1, + MSB_REQUEST_SPECIAL=2, + MSB_REQUEST_A2024=3, + MSB_DOUBLE_SPRITES=4, + MSF_REQUEST_NTSC=1, + MSF_REQUEST_PAL=2, + MSF_REQUEST_SPECIAL=4, + MSF_REQUEST_A2024=8, + MSF_DOUBLE_SPRITES=16, + STANDARD_VIEW_X=$81, + STANDARD_VIEW_Y=$2C, + TO_MONITOR=0, + FROM_MONITOR=1, + STANDARD_XOFFSET=9, + STANDARD_YOFFSET=0, + REQUEST_NTSC=1, + REQUEST_PAL=2, + REQUEST_SPECIAL=4, + REQUEST_A2024=8, + STANDARD_MONITOR_MASK=3, + STANDARD_NTSC_ROWS=262, + STANDARD_PAL_ROWS=312, + STANDARD_COLORCLOCKS=226, + STANDARD_DENISE_MAX=455, + STANDARD_DENISE_MIN=93, + STANDARD_NTSC_BEAMCON=0, + STANDARD_PAL_BEAMCON=$20, + SPECIAL_BEAMCON=$1b8a, + MIN_NTSC_ROW=21, + MIN_PAL_ROW=29, + STANDARD_VIEW_X=$81, + STANDARD_VIEW_Y=$2C, + STANDARD_HBSTRT=$6, + STANDARD_HSSTRT=$B, + STANDARD_HSSTOP=$1C, + STANDARD_HBSTOP=$2C, + STANDARD_VBSTRT=$122, + STANDARD_VSSTRT=$2A6, + STANDARD_VSSTOP=$3AA, + STANDARD_VBSTOP=$1066, + VGA_COLORCLOCKS=113, + VGA_TOTAL_ROWS=131, + VGA_DENISE_MIN=59, + MIN_VGA_ROW=29, + VGA_HBSTRT=$8, + VGA_HSSTRT=$0E, + VGA_HSSTOP=$1C, + VGA_HBSTOP=$1E, + VGA_VBSTRT=0, + VGA_VSSTRT=$153, + VGA_VSSTOP=$235, + VGA_VBSTOP=$CCD, + BROADCAST_HBSTRT=$1, + BROADCAST_HSSTRT=$6, + BROADCAST_HSSTOP=$17, + BROADCAST_HBSTOP=$27, + BROADCAST_VBSTRT=0, + BROADCAST_VSSTRT=$2A6, + BROADCAST_VSSTOP=$054C, + BROADCAST_VBSTOP=$1C40, + BROADCAST_BEAMCON=$808, + RATIO_FIXEDPART=4, + RATIO_UNITY=16 + +#define DEFAULT_MONITOR_NAME 'default.monitor' +#define NTSC_MONITOR_NAME 'ntsc.monitor' +#define PAL_MONITOR_NAME 'pal.monitor' +#define VGA_MONITOR_NAME 'vga.monitor' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/rastport.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/rastport.e new file mode 100644 index 0000000..db1c198 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/rastport.e @@ -0,0 +1,101 @@ +OPT MODULE +OPT EXPORT + +MODULE 'graphics/clip', + 'graphics/gels', + 'graphics/gfx', + 'graphics/text', + 'graphics/view' + +OBJECT tmpras + rasptr:PTR TO CHAR + size:LONG +ENDOBJECT /* SIZEOF=8 */ + +OBJECT gelsinfo + sprrsrvd:CHAR -> This is signed + flags:CHAR + gelhead:PTR TO vs + geltail:PTR TO vs + nextline:PTR TO INT +-> This is actually PTR TO PTR TO INT + lastcolor:PTR TO LONG + collhandler:PTR TO colltable + leftmost:INT + rightmost:INT + topmost:INT + bottommost:INT + firstblissobj:LONG + lastblissobj:LONG +ENDOBJECT /* SIZEOF=38 */ + +CONST RPF_FRST_DOT=1, + RPF_ONE_DOT=2, + RPF_DBUFFER=4, + RPF_AREAOUTLINE=8, + RPF_NOCROSSFILL=$20, + RP_JAM1=0, + RP_JAM2=1, + RP_COMPLEMENT=2, + RP_INVERSVID=4, + RPF_TXSCALE=1 + +CONST RP_AREAPTRN=8, + RP_MASK=24, + RP_AOLPEN=27, + RP_AREAPTSZ=29, + RP_LINPATCNT=30, + RP_FLAGS=32, + RP_LINEPTRN=34 + +OBJECT rastport + layer:PTR TO layer + bitmap:PTR TO bitmap + areaptrn:PTR TO INT -> Target is unsigned + tmpras:PTR TO tmpras + areainfo:PTR TO areainfo + gelsinfo:PTR TO gelsinfo + mask:CHAR + fgpen:CHAR -> This is signed + bgpen:CHAR -> This is signed + aolpen:CHAR -> This is signed + drawmode:CHAR -> This is signed + areaptsz:CHAR -> This is signed + linpatcnt:CHAR -> This is signed + dummy:CHAR + flags:INT -> This is unsigned + lineptrn:INT -> This is unsigned + cp_x:INT + cp_y:INT + minterms[8]:ARRAY + penwidth:INT + penheight:INT + font:PTR TO textfont + algostyle:CHAR + txflags:CHAR + txheight:INT -> This is unsigned + txwidth:INT -> This is unsigned + txbaseline:INT -> This is unsigned + txspacing:INT + rp_user:PTR TO LONG + longreserved[2]:ARRAY OF LONG + wordreserved[7]:ARRAY OF INT -> Array is unsigned + reserved[8]:ARRAY +ENDOBJECT /* SIZEOF=100 */ + +OBJECT areainfo + vctrtbl:PTR TO INT + vctrptr:PTR TO INT + flagtbl:PTR TO CHAR -> Target is signed + flagptr:PTR TO CHAR -> Target is signed + count:INT + maxcount:INT + firstx:INT + firsty:INT +ENDOBJECT /* SIZEOF=24 */ + +CONST ONE_DOTN=1, + ONE_DOT=2, + FRST_DOTN=0, + FRST_DOT=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/regions.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/regions.e new file mode 100644 index 0000000..49bff02 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/regions.e @@ -0,0 +1,16 @@ +OPT MODULE +OPT EXPORT + +MODULE 'graphics/gfx' + +OBJECT region + bounds:rectangle + regionrectangle:PTR TO regionrectangle +ENDOBJECT /* SIZEOF=12 */ + +OBJECT regionrectangle + next:PTR TO regionrectangle + prev:PTR TO regionrectangle + bounds:rectangle +ENDOBJECT /* SIZEOF=16 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/rpattr.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/rpattr.e new file mode 100644 index 0000000..5043a34 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/rpattr.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +CONST RPTAG_FONT=$80000000, + RPTAG_APEN=$80000002, + RPTAG_BPEN=$80000003, + RPTAG_DRMD=$80000004, + RPTAG_OUTLINEPEN=$80000005, + RPTAG_WRITEMASK=$80000006, + RPTAG_MAXPEN=$80000007, + RPTAG_DRAWBOUNDS=$80000008 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/scale.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/scale.e new file mode 100644 index 0000000..7a41c73 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/scale.e @@ -0,0 +1,27 @@ +OPT MODULE +OPT EXPORT + +MODULE 'graphics/gfx' + +OBJECT bitscaleargs + srcx:INT -> This is unsigned + srcy:INT -> This is unsigned + srcwidth:INT -> This is unsigned + srcheight:INT -> This is unsigned + xsrcfactor:INT -> This is unsigned + ysrcfactor:INT -> This is unsigned + destx:INT -> This is unsigned + desty:INT -> This is unsigned + destwidth:INT -> This is unsigned + destheight:INT -> This is unsigned + xdestfactor:INT -> This is unsigned + ydestfactor:INT -> This is unsigned + srcbitmap:PTR TO bitmap + destbitmap:PTR TO bitmap + flags:LONG + xdda:INT -> This is unsigned + ydda:INT -> This is unsigned + reserved1:LONG + reserved2:LONG +ENDOBJECT /* SIZEOF=48 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/sprite.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/sprite.e new file mode 100644 index 0000000..1636a68 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/sprite.e @@ -0,0 +1,28 @@ +OPT MODULE +OPT EXPORT + +OBJECT simplesprite + posctldata:PTR TO INT -> Target is unsigned + height:INT -> This is unsigned + x:INT -> This is unsigned + y:INT -> This is unsigned + num:INT -> This is unsigned +ENDOBJECT /* SIZEOF=12 */ + +OBJECT extsprite + simplesprite:simplesprite + wordwidth:INT -> This is unsigned + flags:INT -> This is unsigned +ENDOBJECT /* SIZEOF=16 */ + +CONST SPRITEA_WIDTH=$81000000, + SPRITEA_XREPLICATION=$81000002, + SPRITEA_YREPLICATION=$81000004, + SPRITEA_OUTPUTHEIGHT=$81000006, + SPRITEA_ATTACHED=$81000008, + SPRITEA_OLDDATAFORMAT=$8100000A, + GSTAG_SPRITE_NUM=$82000020, + GSTAG_ATTACHED=$82000022, + GSTAG_SOFTSPRITE=$82000024, + GSTAG_SCANDOUBLED=$83000000 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/text.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/text.e new file mode 100644 index 0000000..0a9d041 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/text.e @@ -0,0 +1,119 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/ports', + 'graphics/gfx', + 'utility/tagitem' + +CONST FS_NORMAL=0, + FSB_UNDERLINED=0, + FSF_UNDERLINED=1, + FSB_BOLD=1, + FSF_BOLD=2, + FSB_ITALIC=2, + FSF_ITALIC=4, + FSB_EXTENDED=3, + FSF_EXTENDED=8, + FSB_COLORFONT=6, + FSF_COLORFONT=$40, + FSB_TAGGED=7, + FSF_TAGGED=$80, + FPB_ROMFONT=0, + FPF_ROMFONT=1, + FPB_DISKFONT=1, + FPF_DISKFONT=2, + FPB_REVPATH=2, + FPF_REVPATH=4, + FPB_TALLDOT=3, + FPF_TALLDOT=8, + FPB_WIDEDOT=4, + FPF_WIDEDOT=16, + FPB_PROPORTIONAL=5, + FPF_PROPORTIONAL=$20, + FPB_DESIGNED=6, + FPF_DESIGNED=$40, + FPB_REMOVED=7, + FPF_REMOVED=$80 + +OBJECT textattr + name:LONG + ysize:INT -> This is unsigned + style:CHAR + flags:CHAR +ENDOBJECT /* SIZEOF=8 */ + +OBJECT ttextattr + name:LONG + ysize:INT -> This is unsigned + style:CHAR + flags:CHAR + tags:PTR TO tagitem +ENDOBJECT /* SIZEOF=12 */ + +CONST TA_DEVICEDPI=$80000001, + MAXFONTMATCHWEIGHT=$7FFF + +OBJECT textfont + mn:mn + ysize:INT -> This is unsigned + style:CHAR + flags:CHAR + xsize:INT -> This is unsigned + baseline:INT -> This is unsigned + boldsmear:INT -> This is unsigned + accessors:INT -> This is unsigned + lochar:CHAR + hichar:CHAR + chardata:PTR TO CHAR + modulo:INT -> This is unsigned + charloc:PTR TO INT + charspace:PTR TO INT + charkern:PTR TO INT +ENDOBJECT /* SIZEOF=52 */ + +CONST TE0B_NOREMFONT=0, + TE0F_NOREMFONT=1 + +OBJECT textfontextension + matchword:INT -> This is unsigned + flags0:CHAR + flags1:CHAR + backptr:PTR TO textfont + origreplyport:PTR TO mp + tags:PTR TO tagitem + ofontpatchs:PTR TO INT -> Target is unsigned + ofontpatchk:PTR TO INT -> Target is unsigned +ENDOBJECT /* SIZEOF=24 */ + +CONST CT_COLORFONT=1, + CT_GREYFONT=2, + CT_ANTIALIAS=4, + CTB_MAPCOLOR=0, + CTF_MAPCOLOR=1, + CT_COLORMASK=$f + +OBJECT colorfontcolors + reserved:INT + count:INT -> This is unsigned + colortable:PTR TO INT -> Target is unsigned +ENDOBJECT /* SIZEOF=8 */ + +OBJECT colortextfont + textfont:textfont + flags:INT -> This is unsigned + depth:CHAR + fgcolor:CHAR + low:CHAR + high:CHAR + planepick:CHAR + planeonoff:CHAR + colorfontcolors:PTR TO colorfontcolors + chardata[8]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=96 */ + +OBJECT textextent + width:INT -> This is unsigned + height:INT -> This is unsigned + extent:rectangle +ENDOBJECT /* SIZEOF=12 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/videocontrol.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/videocontrol.e new file mode 100644 index 0000000..194da8c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/videocontrol.e @@ -0,0 +1,71 @@ +OPT MODULE +OPT EXPORT + +CONST VTAG_END_CM=0, + VTAG_CHROMAKEY_CLR=$80000000, + VTAG_CHROMAKEY_SET=$80000001, + VTAG_BITPLANEKEY_CLR=$80000002, + VTAG_BITPLANEKEY_SET=$80000003, + VTAG_BORDERBLANK_CLR=$80000004, + VTAG_BORDERBLANK_SET=$80000005, + VTAG_BORDERNOTRANS_CLR=$80000006, + VTAG_BORDERNOTRANS_SET=$80000007, + VTAG_CHROMA_PEN_CLR=$80000008, + VTAG_CHROMA_PEN_SET=$80000009, + VTAG_CHROMA_PLANE_SET=$8000000A, + VTAG_ATTACH_CM_SET=$8000000B, + VTAG_NEXTBUF_CM=$8000000C, + VTAG_BATCH_CM_CLR=$8000000D, + VTAG_BATCH_CM_SET=$8000000E, + VTAG_NORMAL_DISP_GET=$8000000F, + VTAG_NORMAL_DISP_SET=$80000010, + VTAG_COERCE_DISP_GET=$80000011, + VTAG_COERCE_DISP_SET=$80000012, + VTAG_VIEWPORTEXTRA_GET=$80000013, + VTAG_VIEWPORTEXTRA_SET=$80000014, + VTAG_CHROMAKEY_GET=$80000015, + VTAG_BITPLANEKEY_GET=$80000016, + VTAG_BORDERBLANK_GET=$80000017, + VTAG_BORDERNOTRANS_GET=$80000018, + VTAG_CHROMA_PEN_GET=$80000019, + VTAG_CHROMA_PLANE_GET=$8000001A, + VTAG_ATTACH_CM_GET=$8000001B, + VTAG_BATCH_CM_GET=$8000001C, + VTAG_BATCH_ITEMS_GET=$8000001D, + VTAG_BATCH_ITEMS_SET=$8000001E, + VTAG_BATCH_ITEMS_ADD=$8000001F, + VTAG_VPMODEID_GET=$80000020, + VTAG_VPMODEID_SET=$80000021, + VTAG_VPMODEID_CLR=$80000022, + VTAG_USERCLIP_GET=$80000023, + VTAG_USERCLIP_SET=$80000024, + VTAG_USERCLIP_CLR=$80000025, + VTAG_PF1_BASE_GET=$80000026, + VTAG_PF2_BASE_GET=$80000027, + VTAG_SPEVEN_BASE_GET=$80000028, + VTAG_SPODD_BASE_GET=$80000029, + VTAG_PF1_BASE_SET=$8000002A, + VTAG_PF2_BASE_SET=$8000002B, + VTAG_SPEVEN_BASE_SET=$8000002C, + VTAG_SPODD_BASE_SET=$8000002D, + VTAG_BORDERSPRITE_GET=$8000002E, + VTAG_BORDERSPRITE_SET=$8000002F, + VTAG_BORDERSPRITE_CLR=$80000030, + VTAG_SPRITERESN_SET=$80000031, + VTAG_SPRITERESN_GET=$80000032, + VTAG_PF1_TO_SPRITEPRI_SET=$80000033, + VTAG_PF1_TO_SPRITEPRI_GET=$80000034, + VTAG_PF2_TO_SPRITEPRI_SET=$80000035, + VTAG_PF2_TO_SPRITEPRI_GET=$80000036, + VTAG_IMMEDIATE=$80000037, + VTAG_FULLPALETTE_SET=$80000038, + VTAG_FULLPALETTE_GET=$80000039, + VTAG_FULLPALETTE_CLR=$8000003A, + VTAG_DEFSPRITERESN_SET=$8000003B, + VTAG_DEFSPRITERESN_GET=$8000003C, + VC_INTERMEDIATECLUPDATE=$80000080, + VC_INTERMEDIATECLUPDATE_QUERY=$80000081, + VC_NOCOLORPALETTELOAD=$80000082, + VC_NOCOLORPALETTELOAD_QUERY=$80000083, + VC_DUALPF_DISABLE=$80000084, + VC_DUALPF_DISABLE_QUERY=$80000085 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/graphics/view.e b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/view.e new file mode 100644 index 0000000..dba6812 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/graphics/view.e @@ -0,0 +1,202 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/ports', + 'exec/semaphores', + 'graphics/copper', + 'graphics/gfx', + 'graphics/gfxnodes', + 'graphics/monitor', + 'utility/tagitem' + +CONST GENLOCK_VIDEO=2, + V_LACE=4, + V_DOUBLESCAN=8, + V_SUPERHIRES=$20, + V_PFBA=$40, + V_EXTRA_HALFBRITE=$80, + GENLOCK_AUDIO=$100, + V_DUALPF=$400, + V_HAM=$800, + V_EXTENDED_MODE=$1000, + V_VP_HIDE=$2000, + V_SPRITES=$4000, + V_HIRES=$8000, + EXTEND_VSTRUCT=$1000, + VPF_A2024=$40, + VPF_TENHZ=16, + VPB_A2024=6, + VPB_TENHZ=4 + +OBJECT colormap + flags:CHAR + type:CHAR + count:INT -> This is unsigned + colortable:LONG + vpe:PTR TO viewportextra + lowcolorbits:LONG + transparencyplane:CHAR + spriteresolution:CHAR + spriteresdefault:CHAR + auxflags:CHAR + vp:PTR TO viewport + normaldisplayinfo:LONG + coercedisplayinfo:LONG + batch_items:PTR TO tagitem + vpmodeid:LONG + palextra:PTR TO paletteextra + spritebase_even:INT -> This is unsigned + spritebase_odd:INT -> This is unsigned + bp_0_base:INT -> This is unsigned + bp_1_base:INT -> This is unsigned +ENDOBJECT /* SIZEOF=52 */ + +CONST CM_TRANSPARENYPLANE=16, + COLORMAP_TYPE_V1_2=0, + COLORMAP_TYPE_V1_4=1, + COLORMAP_TYPE_V36=1, + COLORMAP_TYPE_V39=2, + COLORMAP_TRANSPARENCY=1, + COLORPLANE_TRANSPARENCY=2, + BORDER_BLANKING=4, + BORDER_NOTRANSPARENCY=8, + VIDEOCONTROL_BATCH=16, + USER_COPPER_CLIP=$20, + BORDER_SPRITES=$40, + CMF_CMTRANS=1, + CMF_CPTRANS=2, + CMF_BRDRBLNK=4, + CMF_BRDNTRAN=8, + CMF_BRDRSPRT=$40, + CMB_CMTRANS=0, + CMB_CPTRANS=1, + CMB_BRDRBLNK=2, + CMB_BRDNTRAN=3, + CMB_BRDRSPRT=6, + SPRITERESN_ECS=0, + SPRITERESN_140NS=1, + SPRITERESN_70NS=2, + SPRITERESN_35NS=3, + SPRITERESN_DEFAULT=-1, + CMAF_FULLPALETTE=1, + CMAB_FULLPALETTE=0, + CMAF_NO_INTERMED_UPDATE=2, + CMAB_NO_INTERMED_UPDATE=1, + CMAF_NO_COLOR_LOAD=4, + CMAB_NO_COLOR_LOAD=2, + CMAF_DUALPF_DISABLE=3, + CMAB_DUALPF_DISABLE=8 + +OBJECT paletteextra + semaphore:ss + firstfree:INT -> This is unsigned + nfree:INT -> This is unsigned + firstshared:INT -> This is unsigned + nshared:INT -> This is unsigned + refcnt:LONG + alloclist:LONG + viewport:PTR TO viewport + sharablecolors:INT -> This is unsigned +ENDOBJECT /* SIZEOF=68 */ + +CONST PRECISION_EXACT=-1, + PRECISION_IMAGE=0, + PRECISION_ICON=16, + PRECISION_GUI=$20, + OBP_PRECISION=$84000000, + OBP_FAILIFBAD=$84000001, + PEN_EXCLUSIVE=1, + PEN_NO_SETCOLOR=2, + PENF_EXCLUSIVE=1, + PENF_NO_SETCOLOR=2, + PENB_EXCLUSIVE=0, + PENB_NO_SETCOLOR=1 + +OBJECT viewport + next:PTR TO viewport + colormap:PTR TO colormap + dspins:PTR TO coplist + sprins:PTR TO coplist + clrins:PTR TO coplist + ucopins:PTR TO ucoplist + dwidth:INT + dheight:INT + dxoffset:INT + dyoffset:INT + modes:INT -> This is unsigned + spritepriorities:CHAR + extendedmodes:CHAR + rasinfo:PTR TO rasinfo +ENDOBJECT /* SIZEOF=40 */ + +OBJECT view + viewport:PTR TO viewport + lofcprlist:PTR TO cprlist + shfcprlist:PTR TO cprlist + dyoffset:INT + dxoffset:INT + modes:INT -> This is unsigned +ENDOBJECT /* SIZEOF=18 */ + +OBJECT viewextra + xln:xln + view:PTR TO view + monitor:PTR TO monitorspec + topline:INT -> This is unsigned +ENDOBJECT /* SIZEOF=34 */ + +OBJECT viewportextra + xln:xln + viewport:PTR TO viewport + displayclip:rectangle + vectable:LONG + driverdata[2]:ARRAY OF LONG + flags:INT -> This is unsigned + origin[2]:ARRAY OF tpoint + cop1ptr:LONG + cop2ptr:LONG +ENDOBJECT /* SIZEOF=58 */ + +CONST VPXB_FREE_ME=0, + VPXF_FREE_ME=1, + VPXB_VP_LAST=1, + VPXF_VP_LAST=2, + VPXB_STRADDLES_256=4, + VPXF_STRADDLES_256=16, + VPXB_STRADDLES_512=5, + VPXF_STRADDLES_512=$20 + +OBJECT rasinfo + next:PTR TO rasinfo + bitmap:PTR TO bitmap + rxoffset:INT + ryoffset:INT +ENDOBJECT /* SIZEOF=12 */ + +CONST MVP_OK=0, + MVP_NO_MEM=1, + MVP_NO_VPE=2, + MVP_NO_DSPINS=3, + MVP_NO_DISPLAY=4, + MVP_OFF_BOTTOM=5, + MCOP_OK=0, + MCOP_NO_MEM=1, + MCOP_NOP=2 + +OBJECT dbufinfo + link1:LONG + count1:LONG + safemessage:mn + userdata1:LONG + link2:LONG + count2:LONG + dispmessage:mn + userdata2:LONG + matchlong:LONG + copptr1:LONG + copptr2:LONG + copptr3:LONG + beampos1:INT -> This is unsigned + beampos2:INT -> This is unsigned +ENDOBJECT /* SIZEOF=84 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/hardware/adkbits.e b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/adkbits.e new file mode 100644 index 0000000..6999454 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/adkbits.e @@ -0,0 +1,40 @@ +OPT MODULE +OPT EXPORT + +CONST ADKB_SETCLR=15, + ADKB_PRECOMP1=14, + ADKB_PRECOMP0=13, + ADKB_MFMPREC=12, + ADKB_UARTBRK=11, + ADKB_WORDSYNC=10, + ADKB_MSBSYNC=9, + ADKB_FAST=8, + ADKB_USE3PN=7, + ADKB_USE2P3=6, + ADKB_USE1P2=5, + ADKB_USE0P1=4, + ADKB_USE3VN=3, + ADKB_USE2V3=2, + ADKB_USE1V2=1, + ADKB_USE0V1=0, + ADKF_SETCLR=$8000, + ADKF_PRECOMP1=$4000, + ADKF_PRECOMP0=$2000, + ADKF_MFMPREC=$1000, + ADKF_UARTBRK=$800, + ADKF_WORDSYNC=$400, + ADKF_MSBSYNC=$200, + ADKF_FAST=$100, + ADKF_USE3PN=$80, + ADKF_USE2P3=$40, + ADKF_USE1P2=$20, + ADKF_USE0P1=16, + ADKF_USE3VN=8, + ADKF_USE2V3=4, + ADKF_USE1V2=2, + ADKF_USE0V1=1, + ADKF_PRE000NS=0, + ADKF_PRE140NS=$2000, + ADKF_PRE280NS=$4000, + ADKF_PRE560NS=$6000 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/hardware/blit.e b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/blit.e new file mode 100644 index 0000000..0ff107f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/blit.e @@ -0,0 +1,70 @@ +OPT MODULE +OPT EXPORT + +OBJECT bltnode + n:PTR TO bltnode + function:LONG + stat:CHAR + dummy:CHAR + blitsize:INT + beamsync:INT + cleanup:LONG +ENDOBJECT /* SIZEOF=18 */ + +CONST CLEANMEN=6, + CLEANME=$40, + CLEANUP=$40, + HSIZEBITS=6, + VSIZEBITS=10, + HSIZEMASK=$3F, + VSIZEMASK=$3FF, + MAXBYTESPERROW=$1000, + MINBYTESPERROW=$80, + MAXBYTESPERROW=$1000, + ABC=$80, + ABNC=$40, + ANBC=$20, + ANBNC=16, + NABC=8, + NABNC=4, + NANBC=2, + NANBNC=1, + BC0B_DEST=8, + BC0B_SRCC=9, + BC0B_SRCB=10, + BC0B_SRCA=11, + BC0F_DEST=$100, + BC0F_SRCC=$200, + BC0F_SRCB=$400, + BC0F_SRCA=$800, + BC1F_DESC=2, + DEST=$100, + SRCC=$200, + SRCB=$400, + SRCA=$800, + ASHIFTSHIFT=12, + BSHIFTSHIFT=12, + LINEMODE=1, + FILL_OR=8, + FILL_XOR=16, + FILL_CARRYIN=4, + ONEDOT=2, + OVFLAG=$20, + SIGNFLAG=$40, + BLITREVERSE=2, + SUD=16, + SUL=8, + AUL=4, + OCTANT8=24, + OCTANT7=4, + OCTANT6=12, + OCTANT5=28, + OCTANT4=20, + OCTANT3=8, + OCTANT2=0, + OCTANT1=16 + +CONST A_OR_B=ABC OR ANBC OR NABC OR ABNC OR ANBNC OR NABNC, + A_OR_C=ABC OR NABC OR ABNC OR ANBC OR NANBC OR ANBNC, + A_XOR_C=NABC OR ABNC OR NANBC OR ANBNC, + A_TO_D=ABC OR ANBC OR ABNC OR ANBNC diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/hardware/cia.e b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/cia.e new file mode 100644 index 0000000..3e92355 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/cia.e @@ -0,0 +1,169 @@ +OPT MODULE +OPT EXPORT + +CONST CIAA_ADDR=$bfe001, + CIAB_ADDR=$bfd000 + +OBJECT cia + ciapra:CHAR + pad0a:CHAR + pad0b[$fe]:ARRAY + ciaprb:CHAR + pad1a:CHAR + pad1b[$fe]:ARRAY + ciaddra:CHAR + pad2a:CHAR + pad2b[$fe]:ARRAY + ciaddrb:CHAR + pad3a:CHAR + pad3b[$fe]:ARRAY + ciatalo:CHAR + pad4a:CHAR + pad4b[$fe]:ARRAY + ciatahi:CHAR + pad5a:CHAR + pad5b[$fe]:ARRAY + ciatblo:CHAR + pad6a:CHAR + pad6b[$fe]:ARRAY + ciatbhi:CHAR + pad7a:CHAR + pad7b[$fe]:ARRAY + ciatodlow:CHAR + pad8a:CHAR + pad8b[$fe]:ARRAY + ciatodmid:CHAR + pad9a:CHAR + pad9b[$fe]:ARRAY + ciatodhi:CHAR + pad10a:CHAR + pad10b[$fe]:ARRAY + unusedreg:CHAR + pad11a:CHAR + pad11b[$fe]:ARRAY + ciasdr:CHAR + pad12a:CHAR + pad12b[$fe]:ARRAY + ciaicr:CHAR + pad13a:CHAR + pad13b[$fe]:ARRAY + ciacra:CHAR + pad14a:CHAR + pad14b[$fe]:ARRAY + ciacrb:CHAR +ENDOBJECT + +CONST CIAPRA=0, + CIAPRB=$100, + CIADDRA=$200, + CIADDRB=$300, + CIATALO=$400, + CIATAHI=$500, + CIATBLO=$600, + CIATBHI=$700, + CIATODLOW=$800, + CIATODMID=$900, + CIATODHI=$A00, + CIASDR=$C00, + CIAICR=$D00, + CIACRA=$E00, + CIACRB=$F00, + CIAICRB_TA=0, + CIAICRB_TB=1, + CIAICRB_ALRM=2, + CIAICRB_SP=3, + CIAICRB_FLG=4, + CIAICRB_IR=7, + CIAICRB_SETCLR=7, + CIACRAB_START=0, + CIACRAB_PBON=1, + CIACRAB_OUTMODE=2, + CIACRAB_RUNMODE=3, + CIACRAB_LOAD=4, + CIACRAB_INMODE=5, + CIACRAB_SPMODE=6, + CIACRAB_TODIN=7, + CIACRBB_START=0, + CIACRBB_PBON=1, + CIACRBB_OUTMODE=2, + CIACRBB_RUNMODE=3, + CIACRBB_LOAD=4, + CIACRBB_INMODE0=5, + CIACRBB_INMODE1=6, + CIACRBB_ALARM=7, + CIAICRF_TA=1, + CIAICRF_TB=2, + CIAICRF_ALRM=4, + CIAICRF_SP=8, + CIAICRF_FLG=16, + CIAICRF_IR=$80, + CIAICRF_SETCLR=$80, + CIACRAF_START=1, + CIACRAF_PBON=2, + CIACRAF_OUTMODE=4, + CIACRAF_RUNMODE=8, + CIACRAF_LOAD=16, + CIACRAF_INMODE=$20, + CIACRAF_SPMODE=$40, + CIACRAF_TODIN=$80, + CIACRBF_START=1, + CIACRBF_PBON=2, + CIACRBF_OUTMODE=4, + CIACRBF_RUNMODE=8, + CIACRBF_LOAD=16, + CIACRBF_INMODE0=$20, + CIACRBF_INMODE1=$40, + CIACRBF_ALARM=$80, + CIACRBF_IN_PHI2=0, + CIACRBF_IN_CNT=$20, + CIACRBF_IN_TA=$40, + CIACRBF_IN_CNT_TA=$60, + CIAB_GAMEPORT1=7, + CIAB_GAMEPORT0=6, + CIAB_DSKRDY=5, + CIAB_DSKTRACK0=4, + CIAB_DSKPROT=3, + CIAB_DSKCHANGE=2, + CIAB_LED=1, + CIAB_OVERLAY=0, + CIAB_COMDTR=7, + CIAB_COMRTS=6, + CIAB_COMCD=5, + CIAB_COMCTS=4, + CIAB_COMDSR=3, + CIAB_PRTRSEL=2, + CIAB_PRTRPOUT=1, + CIAB_PRTRBUSY=0, + CIAB_DSKMOTOR=7, + CIAB_DSKSEL3=6, + CIAB_DSKSEL2=5, + CIAB_DSKSEL1=4, + CIAB_DSKSEL0=3, + CIAB_DSKSIDE=2, + CIAB_DSKDIREC=1, + CIAB_DSKSTEP=0, + CIAF_GAMEPORT1=$80, + CIAF_GAMEPORT0=$40, + CIAF_DSKRDY=$20, + CIAF_DSKTRACK0=16, + CIAF_DSKPROT=8, + CIAF_DSKCHANGE=4, + CIAF_LED=2, + CIAF_OVERLAY=1, + CIAF_COMDTR=$80, + CIAF_COMRTS=$40, + CIAF_COMCD=$20, + CIAF_COMCTS=16, + CIAF_COMDSR=8, + CIAF_PRTRSEL=4, + CIAF_PRTRPOUT=2, + CIAF_PRTRBUSY=1, + CIAF_DSKMOTOR=$80, + CIAF_DSKSEL3=$40, + CIAF_DSKSEL2=$20, + CIAF_DSKSEL1=16, + CIAF_DSKSEL0=8, + CIAF_DSKSIDE=4, + CIAF_DSKDIREC=2, + CIAF_DSKSTEP=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/hardware/custom.e b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/custom.e new file mode 100644 index 0000000..5df7111 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/custom.e @@ -0,0 +1,269 @@ +OPT MODULE +OPT EXPORT + +CONST CUSTOMADDR=$DFF000 + +OBJECT audchannel + ptr:PTR TO INT -> Target is unsigned + len:INT -> This is unsigned + per:INT -> This is unsigned + vol:INT -> This is unsigned + dat:INT -> This is unsigned + pad[2]:ARRAY OF INT +ENDOBJECT + +OBJECT spritedef + pos:INT -> This is unsigned + ctl:INT -> This is unsigned + dataa:INT -> This is unsigned + datab:INT -> This is unsigned +ENDOBJECT + +OBJECT custom + bltdat:INT -> This is unsigned + dmaconr:INT -> This is unsigned + vposr:INT -> This is unsigned + vhposr:INT -> This is unsigned + dskdatr:INT -> This is unsigned + joy0dat:INT -> This is unsigned + joy1dat:INT -> This is unsigned + clxdat:INT -> This is unsigned + adkconr:INT -> This is unsigned + pot0dat:INT -> This is unsigned + pot1dat:INT -> This is unsigned + potinp:INT -> This is unsigned + serdatr:INT -> This is unsigned + dskbytr:INT -> This is unsigned + intenar:INT -> This is unsigned + intreqr:INT -> This is unsigned + dskpt:LONG + dsklen:INT -> This is unsigned + dskdat:INT -> This is unsigned + refptr:INT -> This is unsigned + vposw:INT -> This is unsigned + vhposw:INT -> This is unsigned + copcon:INT -> This is unsigned + serdat:INT -> This is unsigned + serper:INT -> This is unsigned + potgo:INT -> This is unsigned + joytest:INT -> This is unsigned + strequ:INT -> This is unsigned + strvbl:INT -> This is unsigned + strhor:INT -> This is unsigned + strlong:INT -> This is unsigned + bltcon0:INT -> This is unsigned + bltcon1:INT -> This is unsigned + bltafwm:INT -> This is unsigned + bltalwm:INT -> This is unsigned + bltcpt:LONG + bltbpt:LONG + bltapt:LONG + bltdpt:LONG + bltsize:INT -> This is unsigned + pad2d:CHAR + bltcon0l:CHAR + bltsizv:INT -> This is unsigned + bltsizh:INT -> This is unsigned + bltcmod:INT -> This is unsigned + bltbmod:INT -> This is unsigned + bltamod:INT -> This is unsigned + bltdmod:INT -> This is unsigned + pad34[4]:ARRAY OF INT + bltcdat:INT -> This is unsigned + bltbdat:INT -> This is unsigned + bltadat:INT -> This is unsigned + pad3b[3]:ARRAY OF INT + deniseid:INT -> This is unsigned + dsksync:INT -> This is unsigned + cop1lc:LONG + cop2lc:LONG + copjmp1:INT -> This is unsigned + copjmp2:INT -> This is unsigned + copins:INT -> This is unsigned + diwstrt:INT -> This is unsigned + diwstop:INT -> This is unsigned + ddfstrt:INT -> This is unsigned + ddfstop:INT -> This is unsigned + dmacon:INT -> This is unsigned + clxcon:INT -> This is unsigned + intena:INT -> This is unsigned + intreq:INT -> This is unsigned + adkcon:INT -> This is unsigned + aud[4]:ARRAY OF audchannel + bplpt[8]:ARRAY OF LONG + bplcon0:INT -> This is unsigned + bplcon1:INT -> This is unsigned + bplcon2:INT -> This is unsigned + bplcon3:INT -> This is unsigned + bpl1mod:INT -> This is unsigned + bpl2mod:INT -> This is unsigned + bplcon4:INT -> This is unsigned + clxcon2:INT -> This is unsigned + bpldat[8]:ARRAY OF INT -> Array is unsigned + sprpt[8]:ARRAY OF LONG + spr[8]:ARRAY OF spritedef + color[32]:ARRAY OF INT -> Array is unsigned + htotal:INT -> This is unsigned + hsstop:INT -> This is unsigned + hbstrt:INT -> This is unsigned + hbstop:INT -> This is unsigned + vtotal:INT -> This is unsigned + vsstop:INT -> This is unsigned + vbstrt:INT -> This is unsigned + vbstop:INT -> This is unsigned + sprhstrt:INT -> This is unsigned + sprhstop:INT -> This is unsigned + bplhstrt:INT -> This is unsigned + bplhstop:INT -> This is unsigned + hhposw:INT -> This is unsigned + hhposr:INT -> This is unsigned + beamcon0:INT -> This is unsigned + hsstrt:INT -> This is unsigned + vsstrt:INT -> This is unsigned + hcenter:INT -> This is unsigned + diwhigh:INT -> This is unsigned + padf3[11]:ARRAY OF INT + fmode:INT -> This is unsigned +ENDOBJECT + +CONST VARVBLANK=$1000, + LOLDIS=$800, + CSCBLANKEN=$400, + VARVSYNC=$200, + VARHSYNC=$100, + VARBEAM=$80, + DISPLAYDUAL=$40, + DISPLAYPAL=$20, + VARCSYNC=$10, + CSBLANK=8, + CSYNCTRUE=4, + VSYNCTRUE=2, + HSYNCTRUE=1, + USE_BPLCON3=1, + BPLCON2_ZDCTEN=$400, + BPLCON2_ZDBPEN=$800, + BPLCON2_ZDBPSEL0=$1000, + BPLCON2_ZDBPSEL1=$2000, + BPLCON2_ZDBPSEL2=$4000, + BPLCON3_EXTBLNKEN=1, + BPLCON3_EXTBLKZD=2, + BPLCON3_ZDCLKEN=4, + BPLCON3_BRDNTRAN=$10, + BPLCON3_BRDNBLNK=$20 + +CONST BLTDDAT=0, + DMACONR=2, + VPOSR=4, + VHPOSR=6, + DSKDATR=8, + JOY0DAT=10, + JOY1DAT=12, + CLXDAT=14, + ADKCONR=16, + POT0DAT=18, + POT1DAT=20, + POTINP=22, + SERDATR=24, + DSKBYTR=26, + INTENAR=28, + INTREQR=30, + DSKPT=$20, + DSKLEN=$24, + DSKDAT=$26, + REFPTR=$28, + VPOSW=$2A, + VHPOSW=$2C, + COPCON=$2E, + SERDAT=$30, + SERPER=$32, + POTGO=$34, + JOYTEST=$36, + STREQU=$38, + STRVBL=$3A, + STRHOR=$3C, + STRLONG=$3E, + BLTCON0=$40, + BLTCON1=$42, + BLTAFWM=$44, + BLTALWM=$46, + BLTCPT=$48, + BLTBPT=$4C, + BLTAPT=$50, + BLTDPT=$54, + BLTSIZE=$58, + BLTCON0L=$5B, + BLTSIZV=$5C, + BLTSIZH=$5E, + BLTCMOD=$60, + BLTBMOD=$62, + BLTAMOD=$64, + BLTDMOD=$66, + BLTCDAT=$70, + BLTBDAT=$72, + BLTADAT=$74, + DENISEID=$7C, + DSKSYNC=$7E, + COP1LC=$80, + COP2LC=$84, + COPJMP1=$88, + COPJMP2=$8A, + COPINS=$8C, + DIWSTRT=$8E, + DIWSTOP=$90, + DDFSTRT=$92, + DDFSTOP=$94, + DMACON=$96, + CLXCON=$98, + INTENA=$9A, + INTREQ=$9C, + ADKCON=$9E, + AUD=$A0, + AUD0=$A0, + AUD1=$B0, + AUD2=$C0, + AUD3=$D0, + AC_PTR=0, + AC_LEN=4, + AC_PER=6, + AC_VOL=8, + AC_DAT=10, + AC_SIZEOF=16, + BPLPT=$E0, + BPLCON0=$100, + BPLCON1=$102, + BPLCON2=$104, + BPLCON3=$106, + BPL1MOD=$108, + BPL2MOD=$10A, + BPLCON4=$10C, + CLXCON2=$10E, + BPLDAT=$110, + SPRPT=$120, + SPR=$140, + SD_POS=0, + SD_CTL=2, + SD_DATAA=4, + SD_DATAB=6, + SD_SIZEOF=8, + COLOR=$180, + HTOTAL=$1C0, + HSSTOP=$1C2, + HBSTRT=$1C4, + HBSTOP=$1C6, + VTOTAL=$1C8, + VSSTOP=$1CA, + VBSTRT=$1CC, + VBSTOP=$1CE, + SPRHSTRT=$1D0, + SPRHSTOP=$1D2, + BPLHSTRT=$1D4, + BPLHSTOP=$1D6, + HHPOSW=$1D8, + HHPOSR=$1DA, + BEAMCON0=$1DC, + HSSTRT=$1DE, + VSSTRT=$1E0, + HCENTER=$1E2, + DIWHIGH=$1E4, + FMODE=$1FC + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/hardware/dmabits.e b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/dmabits.e new file mode 100644 index 0000000..8a5fa0b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/dmabits.e @@ -0,0 +1,34 @@ +OPT MODULE +OPT EXPORT + +CONST DMAF_SETCLR=$8000, + DMAF_AUDIO=15, + DMAF_AUD0=1, + DMAF_AUD1=2, + DMAF_AUD2=4, + DMAF_AUD3=8, + DMAF_DISK=16, + DMAF_SPRITE=$20, + DMAF_BLITTER=$40, + DMAF_COPPER=$80, + DMAF_RASTER=$100, + DMAF_MASTER=$200, + DMAF_BLITHOG=$400, + DMAF_ALL=$1FF, + DMAF_BLTDONE=$4000, + DMAF_BLTNZERO=$2000, + DMAB_SETCLR=15, + DMAB_AUD0=0, + DMAB_AUD1=1, + DMAB_AUD2=2, + DMAB_AUD3=3, + DMAB_DISK=4, + DMAB_SPRITE=5, + DMAB_BLITTER=6, + DMAB_COPPER=7, + DMAB_RASTER=8, + DMAB_MASTER=9, + DMAB_BLITHOG=10, + DMAB_BLTDONE=14, + DMAB_BLTNZERO=13 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/hardware/intbits.e b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/intbits.e new file mode 100644 index 0000000..9b9a007 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/hardware/intbits.e @@ -0,0 +1,36 @@ +OPT MODULE +OPT EXPORT + +CONST INTB_SETCLR=15, + INTB_INTEN=14, + INTB_EXTER=13, + INTB_DSKSYNC=12, + INTB_RBF=11, + INTB_AUD3=10, + INTB_AUD2=9, + INTB_AUD1=8, + INTB_AUD0=7, + INTB_BLIT=6, + INTB_VERTB=5, + INTB_COPER=4, + INTB_PORTS=3, + INTB_SOFTINT=2, + INTB_DSKBLK=1, + INTB_TBE=0, + INTF_SETCLR=$8000, + INTF_INTEN=$4000, + INTF_EXTER=$2000, + INTF_DSKSYNC=$1000, + INTF_RBF=$800, + INTF_AUD3=$400, + INTF_AUD2=$200, + INTF_AUD1=$100, + INTF_AUD0=$80, + INTF_BLIT=$40, + INTF_VERTB=$20, + INTF_COPER=16, + INTF_PORTS=8, + INTF_SOFTINT=4, + INTF_DSKBLK=2, + INTF_TBE=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/images/led.e b/amigae33a/E_v3.3a/Src/Src/Modules/images/led.e new file mode 100644 index 0000000..282035a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/images/led.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +MODULE 'utility/tagitem' + +CONST LED_DUMMY=TAG_USER+$04000000 + +CONST LED_PAIRS=LED_DUMMY+1, + LED_VALUES=LED_DUMMY+2, + LED_COLON=LED_DUMMY+3, + LED_NEGATIVE=LED_DUMMY+4, + LED_SIGNED=LED_DUMMY+5 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/cghooks.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/cghooks.e new file mode 100644 index 0000000..2c817d7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/cghooks.e @@ -0,0 +1,29 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'graphics/clip', + 'graphics/rastport', + 'intuition/intuition', + 'intuition/screens' + +#define CUSTOM_HOOK(g) (g::gadget.mutualexclude) + +OBJECT gadgetinfo + screen:PTR TO screen + window:PTR TO window + requester:PTR TO requester + rastport:PTR TO rastport + layer:PTR TO layer + domain:ibox + detailpen:CHAR + blockpen:CHAR + drinfo:PTR TO drawinfo +ENDOBJECT /* SIZEOF=NONE !!! */ + +-> Um, this object was missing +OBJECT pgx + container:ibox + newknob:ibox +ENDOBJECT diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/classes.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/classes.e new file mode 100644 index 0000000..85e5e28 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/classes.e @@ -0,0 +1,47 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/libraries', + 'exec/nodes', + 'intuition/classusr', + 'utility/hooks' + +OBJECT iclass + dispatcher:hook + reserved:LONG + super:PTR TO iclass + id:LONG + instoffset:INT -> This is unsigned + instsize:INT -> This is unsigned + userdata:LONG + subclasscount:LONG + objectcount:LONG + flags:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST CLB_INLIST=0, + CLF_INLIST=1 + +-> instoffset and instsize are unsigned so AND with $FFFF +#define INST_DATA(cl, o) ((o)+(cl::iclass.instoffset AND $FFFF)) +#define SIZEOF_INSTANCE(cl) ((cl::iclass.instoffset AND $FFFF)+(cl::iclass.instsize AND $FFFF)+SIZEOF object) + +CONST OJ_CLASS=8 + +OBJECT object + node:mln + class:PTR TO iclass +ENDOBJECT /* SIZEOF=12 */ + +#define _OBJ(o) (o) +#define BASEOBJECT(_obj) ((_obj)+SIZEOF object) +#define _OBJECT(o) ((o)-SIZEOF object) +#define OCLASS(o) (Long(_OBJECT(o)+OJ_CLASS)) + +OBJECT classlibrary + lib:lib + pad:INT + class:PTR TO iclass +ENDOBJECT diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/classusr.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/classusr.e new file mode 100644 index 0000000..a840157 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/classusr.e @@ -0,0 +1,94 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/lists', + 'intuition/cghooks', + 'utility/tagitem' + +OBJECT msg + methodid:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +#define ROOTCLASS 'rootclass' +#define IMAGECLASS 'imageclass' +#define FRAMEICLASS 'frameiclass' +#define SYSICLASS 'sysiclass' +#define FILLRECTCLASS 'fillrectclass' +#define GADGETCLASS 'gadgetclass' +#define PROPGCLASS 'propgclass' +#define STRGCLASS 'strgclass' +#define BUTTONGCLASS 'buttongclass' +#define FRBUTTONCLASS 'frbuttonclass' +#define GROUPGCLASS 'groupgclass' +#define ICCLASS 'icclass' +#define MODELCLASS 'modelclass' +#define ITEXTICLASS 'itexticlass' +#define POINTERCLASS 'pointerclass' + +CONST OM_NEW=$101, + OM_DISPOSE=$102, + OM_SET=$103, + OM_GET=$104, + OM_ADDTAIL=$105, + OM_REMOVE=$106, + OM_NOTIFY=$107, + OM_UPDATE=$108, + OM_ADDMEMBER=$109, + OM_REMMEMBER=$10A + +OBJECT opnew + methodid:LONG + attrlist:PTR TO tagitem + ginfo:PTR TO gadgetinfo -> Always NIL +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opset + methodid:LONG + attrlist:PTR TO tagitem + ginfo:PTR TO gadgetinfo +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opupdate + methodid:LONG + attrlist:PTR TO tagitem + ginfo:PTR TO gadgetinfo + flags:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opnotify + methodid:LONG + attrlist:PTR TO tagitem + ginfo:PTR TO gadgetinfo + flags:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST OPUB_INTERIM=0, + OPUF_INTERIM=1 + +OBJECT opget + methodid:LONG + attrid:LONG + storage:PTR TO LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opaddtail + methodid:LONG + list:PTR TO lh +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opmember + methodid:LONG + object:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opaddmember + methodid:LONG + object:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opremmember + methodid:LONG + object:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/gadgetclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/gadgetclass.e new file mode 100644 index 0000000..46da255 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/gadgetclass.e @@ -0,0 +1,192 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/inputevent', + 'graphics/rastport', + 'intuition/cghooks', + 'intuition/intuition', + 'utility/tagitem' + +CONST GA_DUMMY=$80030000, + GA_LEFT=$80030001, + GA_RELRIGHT=$80030002, + GA_TOP=$80030003, + GA_RELBOTTOM=$80030004, + GA_WIDTH=$80030005, + GA_RELWIDTH=$80030006, + GA_HEIGHT=$80030007, + GA_RELHEIGHT=$80030008, + GA_TEXT=$80030009, + GA_IMAGE=$8003000A, + GA_BORDER=$8003000B, + GA_SELECTRENDER=$8003000C, + GA_HIGHLIGHT=$8003000D, + GA_DISABLED=$8003000E, + GA_GZZGADGET=$8003000F, + GA_ID=$80030010, + GA_USERDATA=$80030011, + GA_SPECIALINFO=$80030012, + GA_SELECTED=$80030013, + GA_ENDGADGET=$80030014, + GA_IMMEDIATE=$80030015, + GA_RELVERIFY=$80030016, + GA_FOLLOWMOUSE=$80030017, + GA_RIGHTBORDER=$80030018, + GA_LEFTBORDER=$80030019, + GA_TOPBORDER=$8003001A, + GA_BOTTOMBORDER=$8003001B, + GA_TOGGLESELECT=$8003001C, + GA_SYSGADGET=$8003001D, + GA_SYSGTYPE=$8003001E, + GA_PREVIOUS=$8003001F, + GA_NEXT=$80030020, + GA_DRAWINFO=$80030021, + GA_INTUITEXT=$80030022, + GA_LABELIMAGE=$80030023, + GA_TABCYCLE=$80030024, + GA_GADGETHELP=$80030025, + GA_BOUNDS=$80030026, + GA_RELSPECIAL=$80030027, + GA_TEXTATTR=$80030028, + GA_READONLY=$80030029, + PGA_DUMMY=$80031000, + PGA_FREEDOM=$80031001, + PGA_BORDERLESS=$80031002, + PGA_HORIZPOT=$80031003, + PGA_HORIZBODY=$80031004, + PGA_VERTPOT=$80031005, + PGA_VERTBODY=$80031006, + PGA_TOTAL=$80031007, + PGA_VISIBLE=$80031008, + PGA_TOP=$80031009, + PGA_NEWLOOK=$8003100A, + STRINGA_DUMMY=$80032000, + STRINGA_MAXCHARS=$80032001, + STRINGA_BUFFER=$80032002, + STRINGA_UNDOBUFFER=$80032003, + STRINGA_WORKBUFFER=$80032004, + STRINGA_BUFFERPOS=$80032005, + STRINGA_DISPPOS=$80032006, + STRINGA_ALTKEYMAP=$80032007, + STRINGA_FONT=$80032008, + STRINGA_PENS=$80032009, + STRINGA_ACTIVEPENS=$8003200A, + STRINGA_EDITHOOK=$8003200B, + STRINGA_EDITMODES=$8003200C, + STRINGA_REPLACEMODE=$8003200D, + STRINGA_FIXEDFIELDMODE=$8003200E, + STRINGA_NOFILTERMODE=$8003200F, + STRINGA_JUSTIFICATION=$80032010, + STRINGA_LONGVAL=$80032011, + STRINGA_TEXTVAL=$80032012, + STRINGA_EXITHELP=$80032013, + SG_DEFAULTMAXCHARS=$80, + LAYOUTA_DUMMY=$80038000, + LAYOUTA_LAYOUTOBJ=$80038001, + LAYOUTA_SPACING=$80038002, + LAYOUTA_ORIENTATION=$80038003, + LAYOUTA_CHILDMAXWIDTH=$80038004, + LAYOUTA_CHILDMAXHEIGHT=$80038005, + LORIENT_NONE=0, + LORIENT_HORIZ=1, + LORIENT_VERT=2, + GM_HITTEST=0, + GM_RENDER=1, + GM_GOACTIVE=2, + GM_HANDLEINPUT=3, + GM_GOINACTIVE=4, + GM_HELPTEST=5, + GM_LAYOUT=6, + GM_DOMAIN=7 + +OBJECT gphittest + methodid:LONG + ginfo:PTR TO gadgetinfo + mousex:INT + mousey:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT gphelptest + methodid:LONG + ginfo:PTR TO gadgetinfo + mousex:INT + mousey:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST GMR_GADGETHIT=4, + GMR_NOHELPHIT=0, + GMR_HELPHIT=-1, + GMR_HELPCODE=$10000 + +OBJECT gprender + methodid:LONG + ginfo:PTR TO gadgetinfo + rport:PTR TO rastport + redraw:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST GREDRAW_UPDATE=2, + GREDRAW_REDRAW=1, + GREDRAW_TOGGLE=0 + +OBJECT gpinput + methodid:LONG + ginfo:PTR TO gadgetinfo + ievent:PTR TO inputevent + termination:PTR TO LONG + mousex:INT + mousey:INT + tabletdata:PTR TO tabletdata +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT gpgoactive + methodid:LONG + ginfo:PTR TO gadgetinfo + ievent:PTR TO inputevent + termination:PTR TO LONG + mousex:INT + mousey:INT + tabletdata:PTR TO tabletdata +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST GMR_MEACTIVE=0, + GMR_NOREUSE=2, + GMR_REUSE=4, + GMR_VERIFY=8, + GMR_NEXTACTIVE=16, + GMR_PREVACTIVE=$20, + GMRB_NOREUSE=1, + GMRB_REUSE=2, + GMRB_VERIFY=3, + GMRB_NEXTACTIVE=4, + GMRB_PREVACTIVE=5, + GMRF_NOREUSE=2, + GMRF_REUSE=4, + GMRF_VERIFY=8, + GMRF_NEXTACTIVE=16, + GMRF_PREVACTIVE=$20 + +OBJECT gpgoinactive + methodid:LONG + ginfo:PTR TO gadgetinfo + abort:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT gplayout + methodid:LONG + ginfo:PTR TO gadgetinfo + initial:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT gpdomain + methodid:LONG + ginfo:PTR TO gadgetinfo + rport:PTR TO rastport + which:LONG + domain:ibox + attrs:PTR TO tagitem +ENDOBJECT + +CONST GDOMAIN_MINIMUM=0, + GDOMAIN_NOMINAL=1, + GDOMAIN_MAXIMUM=2 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/icclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/icclass.e new file mode 100644 index 0000000..251d234 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/icclass.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +CONST ICM_SETLOOP=$402, + ICM_CLEARLOOP=$403, + ICM_CHECKLOOP=$404, + ICA_DUMMY=$80040000, + ICA_TARGET=$80040001, + ICA_MAP=$80040002, + ICSPECIAL_CODE=$80040003, + ICTARGET_IDCMP=-1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/imageclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/imageclass.e new file mode 100644 index 0000000..7990e96 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/imageclass.e @@ -0,0 +1,148 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'graphics/rastport', + 'intuition/intuition', + 'intuition/screens' + +#define GADGET_BOX(g) ((g)+GD_LEFTEDGE) +#define IM_BOX(im) ((im)+IG_LEFTEDGE) +#define IM_FGPEN(im) (im::image.planepick) +#define IM_BGPEN(im) (im::image.planeonoff) + +CONST CUSTOMIMAGEDEPTH=-1, + IMAGE_ATTRIBUTES=$80020000, + IA_LEFT=$80020001, + IA_TOP=$80020002, + IA_WIDTH=$80020003, + IA_HEIGHT=$80020004, + IA_FGPEN=$80020005, + IA_BGPEN=$80020006, + IA_DATA=$80020007, + IA_LINEWIDTH=$80020008, + IA_PENS=$8002000E, + IA_RESOLUTION=$8002000F, + IA_APATTERN=$80020010, + IA_APATSIZE=$80020011, + IA_MODE=$80020012, + IA_FONT=$80020013, + IA_OUTLINE=$80020014, + IA_RECESSED=$80020015, + IA_DOUBLEEMBOSS=$80020016, + IA_EDGESONLY=$80020017, + SYSIA_SIZE=$8002000B, + SYSIA_DEPTH=$8002000C, + SYSIA_WHICH=$8002000D, + SYSIA_DRAWINFO=$80020018, + SYSIA_PENS=$8002000E, + IA_SHADOWPEN=$80020009, + IA_HIGHLIGHTPEN=$8002000A, + SYSIA_REFERENCEFONT=$80020019, + IA_SUPPORTSDISABLE=$8002001A, + IA_FRAMETYPE=$8002001B, + SYSISIZE_MEDRES=0, + SYSISIZE_LOWRES=1, + SYSISIZE_HIRES=2, + DEPTHIMAGE=0, + ZOOMIMAGE=1, + SIZEIMAGE=2, + CLOSEIMAGE=3, + SDEPTHIMAGE=5, + LEFTIMAGE=10, + UPIMAGE=11, + RIGHTIMAGE=12, + DOWNIMAGE=13, + CHECKIMAGE=14, + MXIMAGE=15, + MENUCHECK=16, + AMIGAKEY=17, + FRAME_DEFAULT=0, + FRAME_BUTTON=1, + FRAME_RIDGE=2, + FRAME_ICONDROPBOX=3, + IM_DRAW=$202, + IM_HITTEST=$203, + IM_ERASE=$204, + IM_MOVE=$205, + IM_DRAWFRAME=$206, + IM_FRAMEBOX=$207, + IM_HITFRAME=$208, + IM_ERASEFRAME=$209, + IDS_NORMAL=0, + IDS_SELECTED=1, + IDS_DISABLED=2, + IDS_BUSY=3, + IDS_INDETERMINATE=4, + IDS_INACTIVENORMAL=5, + IDS_INACTIVESELECTED=6, + IDS_INACTIVEDISABLED=7, + IDS_INDETERMINANT=4 + +OBJECT impframebox + methodid:LONG + contentsbox:PTR TO ibox + framebox:PTR TO ibox + drinfo:PTR TO drawinfo + frameflags:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST FRAMEB_SPECIFY=0, + FRAMEF_SPECIFY=1 + +OBJECT impdraw + methodid:LONG + rport:PTR TO rastport + offsetx:INT + offsety:INT + state:LONG + drinfo:PTR TO drawinfo + dimensionswidth:INT + dimensionsheight:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT impdrawframe + methodid:LONG + rport:PTR TO rastport + offsetx:INT + offsety:INT + state:LONG + drinfo:PTR TO drawinfo + dimensionswidth:INT + dimensionsheight:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT imperase + methodid:LONG + rport:PTR TO rastport + offsetx:INT + offsety:INT + dimensionswidth:INT + dimensionsheight:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT imperaseframe + methodid:LONG + rport:PTR TO rastport + offsetx:INT + offsety:INT + dimensionswidth:INT + dimensionsheight:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT imphittest + methodid:LONG + pointx:INT + pointy:INT + dimensionswidth:INT + dimensionsheight:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT imphitframe + methodid:LONG + pointx:INT + pointy:INT + dimensionswidth:INT + dimensionsheight:INT +ENDOBJECT /* SIZEOF=NONE !!! */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuition.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuition.e new file mode 100644 index 0000000..dafe114 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuition.e @@ -0,0 +1,649 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'devices/keymap', + 'exec/ports', + 'graphics/clip', + 'graphics/gfx', + 'graphics/rastport', + 'graphics/text', + 'intuition/screens', + 'intuition/sghooks', + 'utility/tagitem' + +OBJECT menu + nextmenu:PTR TO menu + leftedge:INT + topedge:INT + width:INT + height:INT + flags:INT -> This is unsigned + menuname:PTR TO CHAR + firstitem:PTR TO menuitem + jazzx:INT + jazzy:INT + beatx:INT + beaty:INT +ENDOBJECT /* SIZEOF=30 */ + +CONST MENUENABLED=1, + MIDRAWN=$100 + +OBJECT menuitem + nextitem:PTR TO menuitem + leftedge:INT + topedge:INT + width:INT + height:INT + flags:INT -> This is unsigned + mutualexclude:LONG + itemfill:LONG + selectfill:LONG + command:CHAR + subitem:PTR TO menuitem + nextselect:INT -> This is unsigned +ENDOBJECT /* SIZEOF=34 */ + +CONST CHECKIT=1, + ITEMTEXT=2, + COMMSEQ=4, + MENUTOGGLE=8, + ITEMENABLED=16, + HIGHFLAGS=$C0, + HIGHIMAGE=0, + HIGHCOMP=$40, + HIGHBOX=$80, + HIGHNONE=$C0, + CHECKED=$100, + ISDRAWN=$1000, + HIGHITEM=$2000, + MENUTOGGLED=$4000 + +OBJECT requester + olderrequest:PTR TO requester + leftedge:INT + topedge:INT + width:INT + height:INT + relleft:INT + reltop:INT + reqgadget:PTR TO gadget + reqborder:PTR TO border + reqtext:PTR TO intuitext + flags:INT -> This is unsigned + backfill:CHAR + reqlayer:PTR TO layer + reqpad1[32]:ARRAY + imagebmap:PTR TO bitmap + rwindow:PTR TO window + reqimage:PTR TO image + reqpad2[32]:ARRAY +ENDOBJECT /* SIZEOF=112 */ + +CONST POINTREL=1, + PREDRAWN=2, + NOISYREQ=4, + SIMPLEREQ=16, + USEREQIMAGE=$20, + NOREQBACKFILL=$40, + REQOFFWINDOW=$1000, + REQACTIVE=$2000, + SYSREQUEST=$4000, + DEFERREFRESH=$8000 + +CONST GD_LEFTEDGE=4 + +OBJECT gadget + nextgadget:PTR TO gadget + leftedge:INT + topedge:INT + width:INT + height:INT + flags:INT -> This is unsigned + activation:INT -> This is unsigned + gadgettype:INT -> This is unsigned + gadgetrender:LONG + selectrender:LONG + gadgettext:PTR TO intuitext + mutualexclude:LONG + specialinfo:LONG + gadgetid:INT -> This is unsigned + userdata:LONG +ENDOBJECT /* SIZEOF=44 */ + +OBJECT extgadget + nextgadget:PTR TO extgadget + leftedge:INT + topedge:INT + width:INT + height:INT + flags:INT -> This is unsigned + activation:INT -> This is unsigned + gadgettype:INT -> This is unsigned + gadgetrender:LONG + selectrender:LONG + gadgettext:PTR TO intuitext + mutualexclude:LONG + specialinfo:LONG + gadgetid:INT -> This is unsigned + userdata:LONG + moreflags:LONG + boundsleftedge:INT + boundstopedge:INT + boundswidth:INT + boundsheight:INT +ENDOBJECT /* SIZEOF=56 */ + +CONST GFLG_GADGHIGHBITS=3, + GFLG_GADGHCOMP=0, + GFLG_GADGHBOX=1, + GFLG_GADGHIMAGE=2, + GFLG_GADGHNONE=3, + GFLG_GADGIMAGE=4, + GFLG_RELBOTTOM=8, + GFLG_RELRIGHT=16, + GFLG_RELWIDTH=$20, + GFLG_RELHEIGHT=$40, + GFLG_RELSPECIAL=$4000, + GFLG_SELECTED=$80, + GFLG_DISABLED=$100, + GFLG_LABELMASK=$3000, + GFLG_LABELITEXT=0, + GFLG_LABELSTRING=$1000, + GFLG_LABELIMAGE=$2000, + GFLG_TABCYCLE=$200, + GFLG_STRINGEXTEND=$400, + GFLG_IMAGEDISABLE=$800, + GFLG_EXTENDED=$8000, + GACT_RELVERIFY=1, + GACT_IMMEDIATE=2, + GACT_ENDGADGET=4, + GACT_FOLLOWMOUSE=8, + GACT_RIGHTBORDER=16, + GACT_LEFTBORDER=$20, + GACT_TOPBORDER=$40, + GACT_BOTTOMBORDER=$80, + GACT_BORDERSNIFF=$8000, + GACT_TOGGLESELECT=$100, + GACT_BOOLEXTEND=$2000, + GACT_STRINGLEFT=0, + GACT_STRINGCENTER=$200, + GACT_STRINGRIGHT=$400, + GACT_LONGINT=$800, + GACT_ALTKEYMAP=$1000, + GACT_STRINGEXTEND=$2000, + GACT_ACTIVEGADGET=$4000, + GTYP_GADGETTYPE=$FC00, + GTYP_SYSGADGET=$8000, + GTYP_SCRGADGET=$4000, + GTYP_GZZGADGET=$2000, + GTYP_REQGADGET=$1000, + GTYP_SIZING=16, + GTYP_WDRAGGING=$20, + GTYP_SDRAGGING=$30, + GTYP_WUPFRONT=$40, + GTYP_SUPFRONT=$50, + GTYP_WDOWNBACK=$60, + GTYP_SDOWNBACK=$70, + GTYP_CLOSE=$80, + GTYP_BOOLGADGET=1, + GTYP_GADGET0002=2, + GTYP_PROPGADGET=3, + GTYP_STRGADGET=4, + GTYP_CUSTOMGADGET=5, + GTYP_GTYPEMASK=7, + GTYP_SYSTYPEMASK=$F0, + GTYP_WDEPTH=$40, + GTYP_SDEPTH=$50, + GTYP_WZOOM=$60, + GTYP_SUNUSED=$70, + GMORE_BOUNDS=1, + GMORE_GADGETHELP=2, + GMORE_SCROLLRASTER=4 + +OBJECT boolinfo + flags:INT -> This is unsigned + mask:PTR TO INT -> Target is unsigned + reserved:LONG +ENDOBJECT /* SIZEOF=10 */ + +CONST BOOLMASK=1 + +OBJECT propinfo + flags:INT -> This is unsigned + horizpot:INT -> This is unsigned + vertpot:INT -> This is unsigned + horizbody:INT -> This is unsigned + vertbody:INT -> This is unsigned + cwidth:INT -> This is unsigned + cheight:INT -> This is unsigned + hpotres:INT -> This is unsigned + vpotres:INT -> This is unsigned + leftborder:INT -> This is unsigned + topborder:INT -> This is unsigned +ENDOBJECT /* SIZEOF=22 */ + +CONST AUTOKNOB=1, + FREEHORIZ=2, + FREEVERT=4, + PROPBORDERLESS=8, + KNOBHIT=$100, + PROPNEWLOOK=16, + KNOBHMIN=6, + KNOBVMIN=4, + MAXBODY=$FFFF, + MAXPOT=$FFFF + +OBJECT stringinfo + buffer:PTR TO CHAR + undobuffer:PTR TO CHAR + bufferpos:INT + maxchars:INT + disppos:INT + undopos:INT + numchars:INT + dispcount:INT + cleft:INT + ctop:INT + extension:PTR TO stringextend + longint:LONG + altkeymap:PTR TO keymap +ENDOBJECT /* SIZEOF=36 */ + +OBJECT intuitext + frontpen:CHAR + backpen:CHAR + drawmode:CHAR + leftedge:INT + topedge:INT + itextfont:PTR TO textattr + itext:PTR TO CHAR + nexttext:PTR TO intuitext +ENDOBJECT /* SIZEOF=20 */ + +OBJECT border + leftedge:INT + topedge:INT + frontpen:CHAR + backpen:CHAR + drawmode:CHAR + count:CHAR -> This is signed + xy:PTR TO INT + nextborder:PTR TO border +ENDOBJECT /* SIZEOF=16 */ + +CONST IG_LEFTEDGE=0 + +OBJECT image + leftedge:INT + topedge:INT + width:INT + height:INT + depth:INT + imagedata:PTR TO INT -> Target is unsigned + planepick:CHAR + planeonoff:CHAR + nextimage:PTR TO image +ENDOBJECT /* SIZEOF=20 */ + +OBJECT intuimessage + execmessage:mn + class:LONG + code:INT -> This is unsigned + qualifier:INT -> This is unsigned + iaddress:LONG + mousex:INT + mousey:INT + seconds:LONG + micros:LONG + idcmpwindow:PTR TO window + speciallink:PTR TO intuimessage +ENDOBJECT /* SIZEOF=52 */ + +OBJECT extintuimessage + intuimessage:intuimessage + tabletdata:PTR TO tabletdata +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST IDCMP_SIZEVERIFY=1, + IDCMP_NEWSIZE=2, + IDCMP_REFRESHWINDOW=4, + IDCMP_MOUSEBUTTONS=8, + IDCMP_MOUSEMOVE=16, + IDCMP_GADGETDOWN=$20, + IDCMP_GADGETUP=$40, + IDCMP_REQSET=$80, + IDCMP_MENUPICK=$100, + IDCMP_CLOSEWINDOW=$200, + IDCMP_RAWKEY=$400, + IDCMP_REQVERIFY=$800, + IDCMP_REQCLEAR=$1000, + IDCMP_MENUVERIFY=$2000, + IDCMP_NEWPREFS=$4000, + IDCMP_DISKINSERTED=$8000, + IDCMP_DISKREMOVED=$10000, + IDCMP_WBENCHMESSAGE=$20000, + IDCMP_ACTIVEWINDOW=$40000, + IDCMP_INACTIVEWINDOW=$80000, + IDCMP_DELTAMOVE=$100000, + IDCMP_VANILLAKEY=$200000, + IDCMP_INTUITICKS=$400000, + IDCMP_IDCMPUPDATE=$800000, + IDCMP_MENUHELP=$1000000, + IDCMP_CHANGEWINDOW=$2000000, + IDCMP_GADGETHELP=$4000000, + IDCMP_LONELYMESSAGE=$80000000, + CWCODE_MOVESIZE=0, + CWCODE_DEPTH=1, + MENUHOT=1, + MENUCANCEL=2, + MENUWAITING=3, + OKOK=1, + OKABORT=4, + OKCANCEL=2, + WBENCHOPEN=1, + WBENCHCLOSE=2 + +OBJECT ibox + left:INT + top:INT + width:INT + height:INT +ENDOBJECT /* SIZEOF=8 */ + +OBJECT window + nextwindow:PTR TO window + leftedge:INT + topedge:INT + width:INT + height:INT + mousey:INT + mousex:INT + minwidth:INT + minheight:INT + maxwidth:INT -> This is unsigned + maxheight:INT -> This is unsigned + flags:LONG + menustrip:PTR TO menu + title:PTR TO CHAR + firstrequest:PTR TO requester + dmrequest:PTR TO requester + reqcount:INT + wscreen:PTR TO screen + rport:PTR TO rastport + borderleft:CHAR -> This is signed + bordertop:CHAR -> This is signed + borderright:CHAR -> This is signed + borderbottom:CHAR -> This is signed + borderrport:PTR TO rastport + firstgadget:PTR TO gadget + parent:PTR TO window + descendant:PTR TO window + pointer:PTR TO INT -> Target is unsigned + ptrheight:CHAR -> This is signed + ptrwidth:CHAR -> This is signed + xoffset:CHAR -> This is signed + yoffset:CHAR -> This is signed + idcmpflags:LONG + userport:PTR TO mp + windowport:PTR TO mp + messagekey:PTR TO intuimessage + detailpen:CHAR + blockpen:CHAR + checkmark:PTR TO image + screentitle:PTR TO CHAR + gzzmousex:INT + gzzmousey:INT + gzzwidth:INT + gzzheight:INT + extdata:PTR TO CHAR + userdata:PTR TO CHAR + wlayer:PTR TO layer + ifont:PTR TO textfont + moreflags:LONG +ENDOBJECT /* SIZEOF=136 */ + +CONST WFLG_SIZEGADGET=1, + WFLG_DRAGBAR=2, + WFLG_DEPTHGADGET=4, + WFLG_CLOSEGADGET=8, + WFLG_SIZEBRIGHT=16, + WFLG_SIZEBBOTTOM=$20, + WFLG_REFRESHBITS=$C0, + WFLG_SMART_REFRESH=0, + WFLG_SIMPLE_REFRESH=$40, + WFLG_SUPER_BITMAP=$80, + WFLG_OTHER_REFRESH=$C0, + WFLG_BACKDROP=$100, + WFLG_REPORTMOUSE=$200, + WFLG_GIMMEZEROZERO=$400, + WFLG_BORDERLESS=$800, + WFLG_ACTIVATE=$1000, + WFLG_RMBTRAP=$10000, + WFLG_NOCAREREFRESH=$20000, + WFLG_NW_EXTENDED=$40000, + WFLG_NEWLOOKMENUS=$200000, + WFLG_WINDOWACTIVE=$2000, + WFLG_INREQUEST=$4000, + WFLG_MENUSTATE=$8000, + WFLG_WINDOWREFRESH=$1000000, + WFLG_WBENCHWINDOW=$2000000, + WFLG_WINDOWTICKED=$4000000, + WFLG_VISITOR=$8000000, + WFLG_ZOOMED=$10000000, + WFLG_HASZOOM=$20000000, + SUPER_UNUSED=$FCFC0000, + DEFAULTMOUSEQUEUE=5 + +OBJECT nw + leftedge:INT + topedge:INT + width:INT + height:INT + detailpen:CHAR + blockpen:CHAR + idcmpflags:LONG + flags:LONG + firstgadget:PTR TO gadget + checkmark:PTR TO image + title:PTR TO CHAR + screen:PTR TO screen + bitmap:PTR TO bitmap + minwidth:INT + minheight:INT + maxwidth:INT -> This is unsigned + maxheight:INT -> This is unsigned + type:INT -> This is unsigned +ENDOBJECT /* SIZEOF=48 */ + +OBJECT extnewwindow + leftedge:INT + topedge:INT + width:INT + height:INT + detailpen:CHAR + blockpen:CHAR + idcmpflags:LONG + flags:LONG + firstgadget:PTR TO gadget + checkmark:PTR TO image + title:PTR TO CHAR + screen:PTR TO screen + bitmap:PTR TO bitmap + minwidth:INT + minheight:INT + maxwidth:INT -> This is unsigned + maxheight:INT -> This is unsigned + type:INT -> This is unsigned + extension:PTR TO tagitem +ENDOBJECT /* SIZEOF=52 */ + +CONST WA_LEFT=$80000064, + WA_TOP=$80000065, + WA_WIDTH=$80000066, + WA_HEIGHT=$80000067, + WA_DETAILPEN=$80000068, + WA_BLOCKPEN=$80000069, + WA_IDCMP=$8000006A, + WA_FLAGS=$8000006B, + WA_GADGETS=$8000006C, + WA_CHECKMARK=$8000006D, + WA_TITLE=$8000006E, + WA_SCREENTITLE=$8000006F, + WA_CUSTOMSCREEN=$80000070, + WA_SUPERBITMAP=$80000071, + WA_MINWIDTH=$80000072, + WA_MINHEIGHT=$80000073, + WA_MAXWIDTH=$80000074, + WA_MAXHEIGHT=$80000075, + WA_INNERWIDTH=$80000076, + WA_INNERHEIGHT=$80000077, + WA_PUBSCREENNAME=$80000078, + WA_PUBSCREEN=$80000079, + WA_PUBSCREENFALLBACK=$8000007A, + WA_WINDOWNAME=$8000007B, + WA_COLORS=$8000007C, + WA_ZOOM=$8000007D, + WA_MOUSEQUEUE=$8000007E, + WA_BACKFILL=$8000007F, + WA_RPTQUEUE=$80000080, + WA_SIZEGADGET=$80000081, + WA_DRAGBAR=$80000082, + WA_DEPTHGADGET=$80000083, + WA_CLOSEGADGET=$80000084, + WA_BACKDROP=$80000085, + WA_REPORTMOUSE=$80000086, + WA_NOCAREREFRESH=$80000087, + WA_BORDERLESS=$80000088, + WA_ACTIVATE=$80000089, + WA_RMBTRAP=$8000008A, + WA_WBENCHWINDOW=$8000008B, + WA_SIMPLEREFRESH=$8000008C, + WA_SMARTREFRESH=$8000008D, + WA_SIZEBRIGHT=$8000008E, + WA_SIZEBBOTTOM=$8000008F, + WA_AUTOADJUST=$80000090, + WA_GIMMEZEROZERO=$80000091, + WA_MENUHELP=$80000092, + WA_NEWLOOKMENUS=$80000093, + WA_AMIGAKEY=$80000094, + WA_NOTIFYDEPTH=$80000095, + WA_OBSOLETE=$80000096, + WA_POINTER=$80000097, + WA_BUSYPOINTER=$80000098, + WA_POINTERDELAY=$80000099, + WA_TABLETMESSAGES=$8000009A, + WA_HELPGROUP=$8000009B, + WA_HELPGROUPWINDOW=$8000009C, + HC_GADGETHELP=1 + +OBJECT remember + nextremember:PTR TO remember + remembersize:LONG + memory:PTR TO CHAR +ENDOBJECT /* SIZEOF=12 */ + +OBJECT colorspec + colorindex:INT + red:INT -> This is unsigned + green:INT -> This is unsigned + blue:INT -> This is unsigned +ENDOBJECT /* SIZEOF=8 */ + +OBJECT easystruct + structsize:LONG + flags:LONG + title:PTR TO CHAR + textformat:PTR TO CHAR + gadgetformat:PTR TO CHAR +ENDOBJECT /* SIZEOF=20 */ + +#define MENUNUM(n) ((n) AND $1F) +#define ITEMNUM(n) (Shr((n),5) AND $3F) +#define SUBNUM(n) (Shr((n),11) AND $1F) + +#define SHIFTMENU(n) ((n) AND $1F) +#define SHIFTITEM(n) (Shl((n) AND $3F,5)) +#define SHIFTSUB(n) (Shl((n) AND $1F,11)) + +#define FULLMENUNUM(menu,item,sub) (SHIFTSUB(sub) OR SHIFTITEM(item) OR \ + SHIFTMENU(menu)) + +#define SRBNUM(n) (8-Shr((n),4)) +#define SWBNUM(n) (8-((n) AND $F)) +#define SSBNUM(n) (1+Shr((n),4)) +#define SPARNUM(n) (Shr((n),4)) +#define SHAKNUM(n) ((n) AND $F) + +CONST NOMENU=31, + NOITEM=$3F, + NOSUB=31, + MENUNULL=$FFFF, + CHECKWIDTH=19, + COMMWIDTH=27, + LOWCHECKWIDTH=13, + LOWCOMMWIDTH=16, + ALERT_TYPE=$80000000, + RECOVERY_ALERT=0, + DEADEND_ALERT=$80000000, + AUTOFRONTPEN=0, + AUTOBACKPEN=1, + AUTODRAWMODE=1, + AUTOLEFTEDGE=6, + AUTOTOPEDGE=3, + AUTOITEXTFONT=0, + AUTONEXTTEXT=0, + SELECTUP=$E8, + SELECTDOWN=$68, + MENUUP=$E9, + MENUDOWN=$69, + MIDDLEUP=$EA, + MIDDLEDOWN=$6A, + ALTLEFT=16, + ALTRIGHT=$20, + AMIGALEFT=$40, + AMIGARIGHT=$80, + AMIGAKEYS=$C0, + CURSORUP=$4C, + CURSORLEFT=$4F, + CURSORRIGHT=$4E, + CURSORDOWN=$4D, + KEYCODE_Q=16, + KEYCODE_Z=$31, + KEYCODE_X=$32, + KEYCODE_V=$34, + KEYCODE_B=$35, + KEYCODE_N=$36, + KEYCODE_M=$37, + KEYCODE_LESS=$38, + KEYCODE_GREATER=$39, + TABLETA_DUMMY=$8003A000, + TABLETA_TABLETZ=$8003A001, -> Data for this tag is unsigned INT + TABLETA_RANGEZ=$8003A002, + TABLETA_ANGLEX=$8003A003, + TABLETA_ANGLEY=$8003A004, + TABLETA_ANGLEZ=$8003A005, + TABLETA_PRESSURE=$8003A006, + TABLETA_BUTTONBITS=$8003A007, + TABLETA_INPROXIMITY=$8003A008, + TABLETA_RESOLUTIONX=$8003A009, + TABLETA_RESOLUTIONY=$8003A00A + +OBJECT tabletdata + xfraction:INT -> This is unsigned + yfraction:INT -> This is unsigned + tabletx:LONG + tablety:LONG + rangex:LONG + rangey:LONG + taglist:PTR TO tagitem +ENDOBJECT /* SIZEOF=24 */ + +OBJECT tablethookdata + screen:PTR TO screen + width:LONG + height:LONG + screenchanged:LONG +ENDOBJECT /* SIZEOF=16 */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuitionbase.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuitionbase.e new file mode 100644 index 0000000..89a6270 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/intuitionbase.e @@ -0,0 +1,38 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/libraries', + 'graphics/view', + 'intuition/intuition', + 'intuition/screens' + +CONST DMODECOUNT=2, + HIRESPICK=0, + LOWRESPICK=1, + EVENTMAX=10, + RESCOUNT=2, + HIRESGADGET=0, + LOWRESGADGET=1, + GADGETCOUNT=8, + UPFRONTGADGET=0, + DOWNBACKGADGET=1, + SIZEGADGET=2, + CLOSEGADGET=3, + DRAGGADGET=4, + SUPFRONTGADGET=5, + SDOWNBACKGADGET=6, + SDRAGGADGET=7 + +OBJECT intuitionbase + libnode:lib + viewlord:view + activewindow:PTR TO window + activescreen:PTR TO screen + firstscreen:PTR TO screen + flags:LONG + mousey:INT + mousex:INT + seconds:LONG + micros:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/iobsolete.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/iobsolete.e new file mode 100644 index 0000000..e83f05e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/iobsolete.e @@ -0,0 +1,188 @@ +OPT MODULE +OPT EXPORT + +CONST GADGHIGHBITS=3, + GADGHCOMP=0, + GADGHBOX=1, + GADGHIMAGE=2, + GADGHNONE=3, + GADGIMAGE=4, + GRELBOTTOM=8, + GRELRIGHT=16, + GRELWIDTH=$20, + GRELHEIGHT=$40, + SELECTED=$80, + GADGDISABLED=$100, + LABELMASK=$3000, + LABELITEXT=0, + LABELSTRING=$1000, + LABELIMAGE=$2000, + RELVERIFY=1, + GADGIMMEDIATE=2, + ENDGADGET=4, + FOLLOWMOUSE=8, + RIGHTBORDER=16, + LEFTBORDER=$20, + TOPBORDER=$40, + BOTTOMBORDER=$80, + BORDERSNIFF=$8000, + TOGGLESELECT=$100, + BOOLEXTEND=$2000, + STRINGLEFT=0, + STRINGCENTER=$200, + STRINGRIGHT=$400, + LONGINT=$800, + ALTKEYMAP=$1000, + STRINGEXTEND=$2000, + ACTIVEGADGET=$4000, + GADGETTYPE=$FC00, + SYSGADGET=$8000, + SCRGADGET=$4000, + GZZGADGET=$2000, + REQGADGET=$1000, + SIZING=16, + WDRAGGING=$20, + SDRAGGING=$30, + WUPFRONT=$40, + SUPFRONT=$50, + WDOWNBACK=$60, + SDOWNBACK=$70, + CLOSE=$80, + BOOLGADGET=1, + GADGET0002=2, + PROPGADGET=3, + STRGADGET=4, + CUSTOMGADGET=5, + GTYPEMASK=7, + SIZEVERIFY=1, + NEWSIZE=2, + REFRESHWINDOW=4, + MOUSEBUTTONS=8, + MOUSEMOVE=16, + GADGETDOWN=$20, + GADGETUP=$40, + REQSET=$80, + MENUPICK=$100, + CLOSEWINDOW=$200, + RAWKEY=$400, + REQVERIFY=$800, + REQCLEAR=$1000, + MENUVERIFY=$2000, + NEWPREFS=$4000, + DISKINSERTED=$8000, + DISKREMOVED=$10000, + WBENCHMESSAGE=$20000, + ACTIVEWINDOW=$40000, + INACTIVEWINDOW=$80000, + DELTAMOVE=$100000, + VANILLAKEY=$200000, + INTUITICKS=$400000, + IDCMPUPDATE=$800000, + MENUHELP=$1000000, + CHANGEWINDOW=$2000000, + LONELYMESSAGE=$80000000, + WINDOWSIZING=1, + WINDOWDRAG=2, + WINDOWDEPTH=4, + WINDOWCLOSE=8, + SIZEBRIGHT=16, + SIZEBBOTTOM=$20, + REFRESHBITS=$C0, + SMART_REFRESH=0, + SIMPLE_REFRESH=$40, + SUPER_BITMAP=$80, + OTHER_REFRESH=$C0, + BACKDROP=$100, + REPORTMOUSE=$200, + GIMMEZEROZERO=$400, + BORDERLESS=$800, + ACTIVATE=$1000, + WINDOWACTIVE=$2000, + INREQUEST=$4000, + MENUSTATE=$8000, + RMBTRAP=$10000, + NOCAREREFRESH=$20000, + WINDOWREFRESH=$1000000, + WBENCHWINDOW=$2000000, + WINDOWTICKED=$4000000, + NW_EXTENDED=$40000, + VISITOR=$8000000, + ZOOMED=$10000000, + HASZOOM=$20000000, + GA_LEFT=$80030001, + GA_RELRIGHT=$80030002, + GA_TOP=$80030003, + GA_RELBOTTOM=$80030004, + GA_WIDTH=$80030005, + GA_RELWIDTH=$80030006, + GA_HEIGHT=$80030007, + GA_RELHEIGHT=$80030008, + GA_TEXT=$80030009, + GA_IMAGE=$8003000A, + GA_BORDER=$8003000B, + GA_SELECTRENDER=$8003000C, + GA_HIGHLIGHT=$8003000D, + GA_DISABLED=$8003000E, + GA_GZZGADGET=$8003000F, + GA_USERDATA=$80030011, + GA_SPECIALINFO=$80030012, + GA_SELECTED=$80030013, + GA_ENDGADGET=$80030014, + GA_IMMEDIATE=$80030015, + GA_RELVERIFY=$80030016, + GA_FOLLOWMOUSE=$80030017, + GA_RIGHTBORDER=$80030018, + GA_LEFTBORDER=$80030019, + GA_TOPBORDER=$8003001A, + GA_BOTTOMBORDER=$8003001B, + GA_TOGGLESELECT=$8003001C, + GA_SYSGADGET=$8003001D, + GA_SYSGTYPE=$8003001E, + GA_PREVIOUS=$8003001F, + GA_NEXT=$80030020, + GA_DRAWINFO=$80030021, + GA_INTUITEXT=$80030022, + GA_LABELIMAGE=$80030023, + PGA_FREEDOM=$80031001, + PGA_BORDERLESS=$80031002, + PGA_HORIZPOT=$80031003, + PGA_HORIZBODY=$80031004, + PGA_VERTPOT=$80031005, + PGA_VERTBODY=$80031006, + PGA_TOTAL=$80031007, + PGA_VISIBLE=$80031008, + PGA_TOP=$80031009, + LAYOUTA_LAYOUTOBJ=$80038001, + LAYOUTA_SPACING=$80038002, + LAYOUTA_ORIENTATION=$80038003, + IA_LEFT=$80020001, + IA_TOP=$80020002, + IA_WIDTH=$80020003, + IA_HEIGHT=$80020004, + IA_FGPEN=$80020005, + IA_BGPEN=$80020006, + IA_DATA=$80020007, + IA_LINEWIDTH=$80020008, + IA_PENS=$8002000E, + IA_RESOLUTION=$8002000F, + IA_APATTERN=$80020010, + IA_APATSIZE=$80020011, + IA_MODE=$80020012, + IA_FONT=$80020013, + IA_OUTLINE=$80020014, + IA_RECESSED=$80020015, + IA_DOUBLEEMBOSS=$80020016, + IA_EDGESONLY=$80020017, + IA_SHADOWPEN=$80020009, + IA_HIGHLIGHTPEN=$8002000A, + DETAILPEN=0, + BLOCKPEN=1, + TEXTPEN=2, + SHINEPEN=3, + SHADOWPEN=4, + HIFILLPEN=5, + HIFILLTEXTPEN=6, + BACKGROUNDPEN=7, + HILIGHTTEXTPEN=8, + NUMDRIPENS=12 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/pointerclass.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/pointerclass.e new file mode 100644 index 0000000..f89674d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/pointerclass.e @@ -0,0 +1,23 @@ +OPT MODULE +OPT EXPORT + +CONST POINTERA_DUMMY=$80039000, + POINTERA_BITMAP=$80039001, + POINTERA_XOFFSET=$80039002, + POINTERA_YOFFSET=$80039003, + POINTERA_WORDWIDTH=$80039004, + POINTERA_XRESOLUTION=$80039005, + POINTERA_YRESOLUTION=$80039006, + POINTERXRESN_DEFAULT=0, + POINTERXRESN_140NS=1, + POINTERXRESN_70NS=2, + POINTERXRESN_35NS=3, + POINTERXRESN_SCREENRES=4, + POINTERXRESN_LORES=5, + POINTERXRESN_HIRES=6, + POINTERYRESN_DEFAULT=0, + POINTERYRESN_HIGH=2, + POINTERYRESN_HIGHASPECT=3, + POINTERYRESN_SCREENRES=4, + POINTERYRESN_SCREENRESASPECT=5 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/preferences.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/preferences.e new file mode 100644 index 0000000..443df91 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/preferences.e @@ -0,0 +1,165 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/timer' + +CONST FILENAME_SIZE=30, + DEVNAME_SIZE=16, + POINTERSIZE=$24, + TOPAZ_EIGHTY=8, + TOPAZ_SIXTY=9 + +OBJECT preferences + fontheight:CHAR -> This is signed + printerport:CHAR + baudrate:INT -> This is unsigned + keyrptspeed:timeval + keyrptdelay:timeval + doubleclick:timeval + pointermatrix[$24]:ARRAY OF INT -> Array is unsigned + xoffset:CHAR -> This is signed + yoffset:CHAR -> This is signed + color17:INT -> This is unsigned + color18:INT -> This is unsigned + color19:INT -> This is unsigned + pointerticks:INT -> This is unsigned + color0:INT -> This is unsigned + color1:INT -> This is unsigned + color2:INT -> This is unsigned + color3:INT -> This is unsigned + viewxoffset:CHAR -> This is signed + viewyoffset:CHAR -> This is signed + viewinitx:INT + viewinity:INT + enablecli:INT + printertype:INT -> This is unsigned + printerfilename[30]:ARRAY + printpitch:INT -> This is unsigned + printquality:INT -> This is unsigned + printspacing:INT -> This is unsigned + printleftmargin:INT -> This is unsigned + printrightmargin:INT -> This is unsigned + printimage:INT -> This is unsigned + printaspect:INT -> This is unsigned + printshade:INT -> This is unsigned + printthreshold:INT + papersize:INT -> This is unsigned + paperlength:INT -> This is unsigned + papertype:INT -> This is unsigned + serrwbits:CHAR + serstopbuf:CHAR + serparshk:CHAR + lacewb:CHAR + pad[12]:ARRAY + prtdevname[16]:ARRAY + defaultprtunit:CHAR + defaultserunit:CHAR + rowsizechange:CHAR -> This is signed + columnsizechange:CHAR -> This is signed + printflags:INT -> This is unsigned + printmaxwidth:INT -> This is unsigned + printmaxheight:INT -> This is unsigned + printdensity:CHAR + printxoffset:CHAR + wb_width:INT -> This is unsigned + wb_height:INT -> This is unsigned + wb_depth:CHAR + ext_size:CHAR +ENDOBJECT /* SIZEOF=232 */ + +CONST LACEWB=1, + LW_RESERVED=1, + SCREEN_DRAG=$4000, + MOUSE_ACCEL=$8000, + PARALLEL_PRINTER=0, + SERIAL_PRINTER=1, + BAUD_110=0, + BAUD_300=1, + BAUD_1200=2, + BAUD_2400=3, + BAUD_4800=4, + BAUD_9600=5, + BAUD_19200=6, + BAUD_MIDI=7, + FANFOLD=0, + SINGLE=$80, + PICA=0, + ELITE=$400, + FINE=$800, + DRAFT=0, + LETTER=$100, + SIX_LPI=0, + EIGHT_LPI=$200, + IMAGE_POSITIVE=0, + IMAGE_NEGATIVE=1, + ASPECT_HORIZ=0, + ASPECT_VERT=1, + SHADE_BW=0, + SHADE_GREYSCALE=1, + SHADE_COLOR=2, + US_LETTER=0, + US_LEGAL=16, + N_TRACTOR=$20, + W_TRACTOR=$30, + CUSTOM=$40, + EURO_A0=$50, + EURO_A1=$60, + EURO_A2=$70, + EURO_A3=$80, + EURO_A4=$90, + EURO_A5=$A0, + EURO_A6=$B0, + EURO_A7=$C0, + EURO_A8=$D0, + CUSTOM_NAME=0, + ALPHA_P_101=1, + BROTHER_15XL=2, + CBM_MPS1000=3, + DIAB_630=4, + DIAB_ADV_D25=5, + DIAB_C_150=6, + EPSON=7, + EPSON_JX_80=8, + OKIMATE_20=9, + QUME_LP_20=10, + HP_LASERJET=11, + HP_LASERJET_PLUS=12, + SBUF_512=0, + SBUF_1024=1, + SBUF_2048=2, + SBUF_4096=3, + SBUF_8000=4, + SBUF_16000=5, + SREAD_BITS=$F0, + SWRITE_BITS=15, + SSTOP_BITS=$F0, + SBUFSIZE_BITS=15, + SPARITY_BITS=$F0, + SHSHAKE_BITS=15, + SPARITY_NONE=0, + SPARITY_EVEN=1, + SPARITY_ODD=2, + SPARITY_MARK=3, + SPARITY_SPACE=4, + SHSHAKE_XON=0, + SHSHAKE_RTS=1, + SHSHAKE_NONE=2, + CORRECT_RED=1, + CORRECT_GREEN=2, + CORRECT_BLUE=4, + CENTER_IMAGE=8, + IGNORE_DIMENSIONS=0, + BOUNDED_DIMENSIONS=16, + ABSOLUTE_DIMENSIONS=$20, + PIXEL_DIMENSIONS=$40, + MULTIPLY_DIMENSIONS=$80, + INTEGER_SCALING=$100, + ORDERED_DITHERING=0, + HALFTONE_DITHERING=$200, + FLOYD_DITHERING=$400, + ANTI_ALIAS=$800, + GREY_SCALE2=$1000, + CORRECT_RGB_MASK=7, + DIMENSIONS_MASK=$F0, + DITHERING_MASK=$600 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/screens.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/screens.e new file mode 100644 index 0000000..03b6ac0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/screens.e @@ -0,0 +1,222 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes', + 'exec/tasks', + 'graphics/clip', + 'graphics/gfx', + 'graphics/layers', + 'graphics/rastport', + 'graphics/text', + 'graphics/view', + 'intuition/intuition', + 'utility/tagitem' + +CONST DRI_VERSION=2 + +OBJECT drawinfo + version:INT -> This is unsigned + numpens:INT -> This is unsigned + pens:PTR TO INT -> Target is unsigned + font:PTR TO textfont + depth:INT -> This is unsigned + resolutionx:INT -> This is unsigned + resolutiony:INT -> This is unsigned + flags:LONG + checkmark:PTR TO image + amigakey:PTR TO image + longreserved[5]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST DRIF_NEWLOOK=1, + DRIB_NEWLOOK=0, + DETAILPEN=0, + BLOCKPEN=1, + TEXTPEN=2, + SHINEPEN=3, + SHADOWPEN=4, + FILLPEN=5, + FILLTEXTPEN=6, + BACKGROUNDPEN=7, + HIGHLIGHTTEXTPEN=8, + BARDETAILPEN=9, + BARBLOCKPEN=10, + BARTRIMPEN=11, + NUMDRIPENS=12, + PEN_C3=$FEFC, + PEN_C2=$FEFD, + PEN_C1=$FEFE, + PEN_C0=$FEFF + +OBJECT screen + nextscreen:PTR TO screen + firstwindow:PTR TO window + leftedge:INT + topedge:INT + width:INT + height:INT + mousey:INT + mousex:INT + flags:INT -> This is unsigned + title:PTR TO CHAR + defaulttitle:PTR TO CHAR + barheight:CHAR -> This is signed + barvborder:CHAR -> This is signed + barhborder:CHAR -> This is signed + menuvborder:CHAR -> This is signed + menuhborder:CHAR -> This is signed + wbortop:CHAR -> This is signed + wborleft:CHAR -> This is signed + wborright:CHAR -> This is signed + wborbottom:CHAR -> This is signed + font:PTR TO textattr + viewport:viewport + rastport:rastport + bitmap:bitmap + layerinfo:layer_info + firstgadget:PTR TO gadget + detailpen:CHAR + blockpen:CHAR + savecolor0:INT -> This is unsigned + barlayer:PTR TO layer + extdata:PTR TO CHAR + userdata:PTR TO CHAR +ENDOBJECT /* SIZEOF=346 */ + +CONST SCREENTYPE=15, + WBENCHSCREEN=1, + PUBLICSCREEN=2, + CUSTOMSCREEN=15, + SHOWTITLE=16, + BEEPING=$20, + CUSTOMBITMAP=$40, + SCREENBEHIND=$80, + SCREENQUIET=$100, + SCREENHIRES=$200, + STDSCREENHEIGHT=-1, + STDSCREENWIDTH=-1, + NS_EXTENDED=$1000, + AUTOSCROLL=$4000, + PENSHARED=$400, + SA_DUMMY=$80000020, + SA_LEFT=$80000021, + SA_TOP=$80000022, + SA_WIDTH=$80000023, + SA_HEIGHT=$80000024, + SA_DEPTH=$80000025, + SA_DETAILPEN=$80000026, + SA_BLOCKPEN=$80000027, + SA_TITLE=$80000028, + SA_COLORS=$80000029, + SA_ERRORCODE=$8000002A, + SA_FONT=$8000002B, + SA_SYSFONT=$8000002C, + SA_TYPE=$8000002D, + SA_BITMAP=$8000002E, + SA_PUBNAME=$8000002F, + SA_PUBSIG=$80000030, + SA_PUBTASK=$80000031, + SA_DISPLAYID=$80000032, + SA_DCLIP=$80000033, + SA_OVERSCAN=$80000034, + SA_OBSOLETE1=$80000035, + SA_SHOWTITLE=$80000036, + SA_BEHIND=$80000037, + SA_QUIET=$80000038, + SA_AUTOSCROLL=$80000039, + SA_PENS=$8000003A, + SA_FULLPALETTE=$8000003B, + SA_COLORMAPENTRIES=$8000003C, + SA_PARENT=$8000003D, + SA_DRAGGABLE=$8000003E, + SA_EXCLUSIVE=$8000003F, + SA_SHAREPENS=$80000040, + SA_BACKFILL=$80000041, + SA_INTERLEAVED=$80000042, + SA_COLORS32=$80000043, + SA_VIDEOCONTROL=$80000044, + SA_FRONTCHILD=$80000045, + SA_BACKCHILD=$80000046, + SA_LIKEWORKBENCH=$80000047, + SA_RESERVED=$80000048, + SA_MINIMIZEISG=$80000049, + OSERR_NOMONITOR=1, + OSERR_NOCHIPS=2, + OSERR_NOMEM=3, + OSERR_NOCHIPMEM=4, + OSERR_PUBNOTUNIQUE=5, + OSERR_UNKNOWNMODE=6, + OSERR_TOODEEP=7, + OSERR_ATTACHFAIL=8, + OSERR_NOTAVAILABLE=9 + +OBJECT ns + leftedge:INT + topedge:INT + width:INT + height:INT + depth:INT + detailpen:CHAR + blockpen:CHAR + viewmodes:INT -> This is unsigned + type:INT -> This is unsigned + font:PTR TO textattr + defaulttitle:PTR TO CHAR + gadgets:PTR TO gadget + custombitmap:PTR TO bitmap +ENDOBJECT /* SIZEOF=32 */ + +OBJECT extnewscreen + leftedge:INT + topedge:INT + width:INT + height:INT + depth:INT + detailpen:CHAR + blockpen:CHAR + viewmodes:INT -> This is unsigned + type:INT -> This is unsigned + font:PTR TO textattr + defaulttitle:PTR TO CHAR + gadgets:PTR TO gadget + custombitmap:PTR TO bitmap + extension:PTR TO tagitem +ENDOBJECT /* SIZEOF=36 */ + +CONST OSCAN_TEXT=1, + OSCAN_STANDARD=2, + OSCAN_MAX=3, + OSCAN_VIDEO=4 + +OBJECT pubscreennode + ln:ln + screen:PTR TO screen + flags:INT -> This is unsigned + size:INT + visitorcount:INT + sigtask:PTR TO tc + sigbit:CHAR + pad1:CHAR +ENDOBJECT /* SIZEOF=30 */ + +CONST PSNF_PRIVATE=1, + MAXPUBSCREENNAME=$8B, + SHANGHAI=1, + POPPUBSCREEN=2, + SDEPTH_TOFRONT=0, + SDEPTH_TOBACK=1, + SDEPTH_INFAMILY=2, + SDEPTH_CHILDONLY=2, + SPOS_RELATIVE=0, + SPOS_ABSOLUTE=1, + SPOS_MAKEVISIBLE=2, + SPOS_FORCEDRAG=4 + +OBJECT screenbuffer + bitmap:PTR TO bitmap + dbufinfo:PTR TO dbufinfo +ENDOBJECT /* SIZEOF=8 */ + +CONST SB_SCREEN_BITMAP=1, + SB_COPY_BITMAP=2 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/intuition/sghooks.e b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/sghooks.e new file mode 100644 index 0000000..1611d20 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/intuition/sghooks.e @@ -0,0 +1,84 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/inputevent', + 'graphics/text', + 'intuition/cghooks', + 'intuition/intuition', + 'utility/hooks' + +OBJECT stringextend + font:PTR TO textfont + pens[2]:ARRAY + activepens[2]:ARRAY + initialmodes:LONG + edithook:PTR TO hook + workbuffer:PTR TO CHAR + reserved[4]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=36 */ + +OBJECT sgwork + gadget:PTR TO gadget + stringinfo:PTR TO stringinfo + workbuffer:PTR TO CHAR + prevbuffer:PTR TO CHAR + modes:LONG + ievent:PTR TO inputevent + code:INT -> This is unsigned + bufferpos:INT + numchars:INT + actions:LONG + longint:LONG + gadgetinfo:PTR TO gadgetinfo + editop:INT -> This is unsigned +ENDOBJECT /* SIZEOF=44 */ + +CONST EO_NOOP=1, + EO_DELBACKWARD=2, + EO_DELFORWARD=3, + EO_MOVECURSOR=4, + EO_ENTER=5, + EO_RESET=6, + EO_REPLACECHAR=7, + EO_INSERTCHAR=8, + EO_BADFORMAT=9, + EO_BIGCHANGE=10, + EO_UNDO=11, + EO_CLEAR=12, + EO_SPECIAL=13, + SGM_REPLACE=1, + SGMB_REPLACE=0, + SGMF_REPLACE=1, + SGM_FIXEDFIELD=2, + SGMB_FIXEDFIELD=1, + SGMF_FIXEDFIELD=2, + SGM_NOFILTER=4, + SGMB_NOFILTER=2, + SGMF_NOFILTER=4, + SGM_EXITHELP=$80, + SGMB_EXITHELP=7, + SGMF_EXITHELP=$80, + SGA_USE=1, + SGAB_USE=0, + SGAF_USE=1, + SGA_END=2, + SGAB_END=1, + SGAF_END=2, + SGA_BEEP=4, + SGAB_BEEP=2, + SGAF_BEEP=4, + SGA_REUSE=8, + SGAB_REUSE=3, + SGAF_REUSE=8, + SGA_REDISPLAY=16, + SGAB_REDISPLAY=4, + SGAF_REDISPLAY=16, + SGA_NEXTACTIVE=$20, + SGAB_NEXTACTIVE=5, + SGAF_NEXTACTIVE=$20, + SGA_PREVACTIVE=$40, + SGAB_PREVACTIVE=6, + SGAF_PREVACTIVE=$40, + SGH_KEY=1, + SGH_CLICK=2 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/amigaguide.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/amigaguide.e new file mode 100644 index 0000000..f229dda --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/amigaguide.e @@ -0,0 +1,156 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes', + 'exec/ports', + 'intuition/screens', + 'utility/hooks', + 'utility/tagitem' + +CONST APSH_TOOL_ID=$2AF8, + STARTUPMSGID=$2AF9, + LOGINTOOLID=$2AFA, + LOGOUTTOOLID=$2AFB, + SHUTDOWNMSGID=$2AFC, + ACTIVATETOOLID=$2AFD, + DEACTIVATETOOLID=$2AFE, + ACTIVETOOLID=$2AFF, + INACTIVETOOLID=$2B00, + TOOLSTATUSID=$2B01, + TOOLCMDID=$2B02, + TOOLCMDREPLYID=$2B03, + SHUTDOWNTOOLID=$2B04, + AGA_DUMMY=$80000000, + AGA_PATH=$80000001, + AGA_XREFLIST=$80000002, + AGA_ACTIVATE=$80000003, + AGA_CONTEXT=$80000004, + AGA_HELPGROUP=$80000005, + AGA_RESERVED1=$80000006, + AGA_RESERVED2=$80000007, + AGA_RESERVED3=$80000008, + AGA_AREXXPORT=$80000009, + AGA_AREXXPORTNAME=$8000000A, + AGA_WORKPATH=$8000000B, + AGA_WORKNODE=$8000000C + +OBJECT amigaguidemsg + msg:mn + type:LONG + data:LONG + dsize:LONG + dtype:LONG + pri_ret:LONG + sec_ret:LONG + system1:LONG + system2:LONG +ENDOBJECT /* SIZEOF=52 */ + +OBJECT newamigaguide + lock:LONG + name:PTR TO CHAR + screen:PTR TO screen + pubscreen:PTR TO CHAR + hostport:PTR TO CHAR + clientport:PTR TO CHAR + basename:PTR TO CHAR + flags:LONG + context:PTR TO LONG + node:PTR TO CHAR + line:LONG + extens:PTR TO tagitem + client:LONG +ENDOBJECT /* SIZEOF=52 */ + +CONST HTF_LOAD_INDEX=1, + HTF_LOAD_ALL=2, + HTF_CACHE_NODE=4, + HTF_CACHE_DB=8, + HTF_UNIQUE=16, + HTF_NOACTIVATE=$20, + HTFC_SYSGADS=$80000000, + HTH_OPEN=0, + HTH_CLOSE=1, + HTERR_NOT_ENOUGH_MEMORY=$64, + HTERR_CANT_OPEN_DATABASE=$65, + HTERR_CANT_FIND_NODE=$66, + HTERR_CANT_OPEN_NODE=$67, + HTERR_CANT_OPEN_WINDOW=$68, + HTERR_INVALID_COMMAND=$69, + HTERR_CANT_COMPLETE=$6A, + HTERR_PORT_CLOSED=$6B, + HTERR_CANT_CREATE_PORT=$6C, + HTERR_KEYWORD_NOT_FOUND=$71 + +OBJECT xref + node:ln + pad:INT -> This is unsigned +-> Umm, should be 'PTR TO docfile', but 'docfile' not defined + df:LONG + file:PTR TO CHAR + name:PTR TO CHAR + line:LONG +ENDOBJECT /* SIZEOF=32 */ + +CONST XR_GENERIC=0, + XR_FUNCTION=1, + XR_COMMAND=2, + XR_INCLUDE=3, + XR_MACRO=4, + XR_STRUCT=5, + XR_FIELD=6, + XR_TYPEDEF=7, + XR_DEFINE=8 + +OBJECT amigaguidehost + dispatcher:hook + reserved:LONG + flags:LONG + usecnt:LONG + systemdata:LONG + userdata:LONG +ENDOBJECT /* SIZEOF=40 */ + +CONST HM_FINDNODE=1, + HM_OPENNODE=2, + HM_CLOSENODE=3, + HM_EXPUNGE=10 + +-> Um, methodid's were all missing +OBJECT opfindhost + methodid:LONG + attrs:PTR TO tagitem + node:PTR TO CHAR + toc:PTR TO CHAR + title:PTR TO CHAR + next:PTR TO CHAR + prev:PTR TO CHAR +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT opnodeio + methodid:LONG + attrs:PTR TO tagitem + node:PTR TO CHAR + filename:PTR TO CHAR + docbuffer:PTR TO CHAR + bufflen:LONG + flags:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST HTNF_KEEP=1, + HTNF_RESERVED1=2, + HTNF_RESERVED2=4, + HTNF_ASCII=8, + HTNF_RESERVED3=16, + HTNF_CLEAN=$20, + HTNF_DONE=$40, + HTNA_DUMMY=$80000000, + HTNA_SCREEN=$80000001, + HTNA_PENS=$80000002, + HTNA_RECTANGLE=$80000003, + HTNA_HELPGROUP=$80000005 + +OBJECT opexpungenode + methodid:LONG + attrs:PTR TO tagitem +ENDOBJECT /* SIZEOF=NONE !!! */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/asl.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/asl.e new file mode 100644 index 0000000..83f1116 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/asl.e @@ -0,0 +1,302 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/lists', + 'exec/nodes', + 'graphics/displayinfo', + 'graphics/text', + 'workbench/startup' + +#define ASLNAME 'asl.library' + +CONST ASL_TB=$80080000, + ASL_FILEREQUEST=0, + ASL_FONTREQUEST=1, + ASL_SCREENMODEREQUEST=2 + +OBJECT filerequester + reserved0[4]:ARRAY + file:LONG + drawer:LONG + reserved1[10]:ARRAY + leftedge:INT + topedge:INT + width:INT + height:INT + reserved2[2]:ARRAY + numargs:LONG + arglist:PTR TO wbarg + userdata:LONG + reserved3[8]:ARRAY + pattern:PTR TO CHAR +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST ASLFR_WINDOW=$80080002, + ASLFR_SCREEN=$80080028, + ASLFR_PUBSCREENNAME=$80080029, + ASLFR_PRIVATEIDCMP=$8008002A, + ASLFR_INTUIMSGFUNC=$80080046, + ASLFR_SLEEPWINDOW=$8008002B, + ASLFR_USERDATA=$80080034, + ASLFR_TEXTATTR=$80080033, + ASLFR_LOCALE=$80080032, + ASLFR_TITLETEXT=$80080001, + ASLFR_POSITIVETEXT=$80080012, + ASLFR_NEGATIVETEXT=$80080013, + ASLFR_INITIALLEFTEDGE=$80080003, + ASLFR_INITIALTOPEDGE=$80080004, + ASLFR_INITIALWIDTH=$80080005, + ASLFR_INITIALHEIGHT=$80080006, + ASLFR_INITIALFILE=$80080008, + ASLFR_INITIALDRAWER=$80080009, + ASLFR_INITIALPATTERN=$8008000A, + ASLFR_FLAGS1=$80080014, + ASLFR_FLAGS2=$80080016, + ASLFR_DOSAVEMODE=$8008002C, + ASLFR_DOMULTISELECT=$8008002D, + ASLFR_DOPATTERNS=$8008002E, + ASLFR_DRAWERSONLY=$8008002F, + ASLFR_FILTERFUNC=$80080031, + ASLFR_REJECTICONS=$8008003C, + ASLFR_REJECTPATTERN=$8008003D, + ASLFR_ACCEPTPATTERN=$8008003E, + ASLFR_FILTERDRAWERS=$8008003F, + ASLFR_HOOKFUNC=$80080007, + FRF_DOWILDFUNC=$80, -> Obsolete + FRB_FILTERFUNC=7, + FRF_FILTERFUNC=$80, + FRF_DOMSGFUNC=$40, -> Obsolete + FRB_INTUIFUNC=6, + FRF_INTUIFUNC=$40, + FRB_DOSAVEMODE=5, + FRF_DOSAVEMODE=$20, + FRB_PRIVATEIDCMP=4, + FRF_PRIVATEIDCMP=16, + FRB_DOMULTISELECT=3, + FRF_DOMULTISELECT=8, + FRB_DOPATTERNS=0, + FRF_DOPATTERNS=1, + FRB_DRAWERSONLY=0, + FRF_DRAWERSONLY=1, + FRB_FILTERDRAWERS=1, + FRF_FILTERDRAWERS=2, + FRB_REJECTICONS=2, + FRF_REJECTICONS=4 + +OBJECT fontrequester + reserved0[8]:ARRAY + attr:textattr + frontpen:CHAR + backpen:CHAR + drawmode:CHAR + reserved1:CHAR + userdata:LONG + leftedge:INT + topedge:INT + width:INT + height:INT + tattr:ttextattr +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST ASLFO_WINDOW=$80080002, + ASLFO_SCREEN=$80080028, + ASLFO_PUBSCREENNAME=$80080029, + ASLFO_PRIVATEIDCMP=$8008002A, + ASLFO_INTUIMSGFUNC=$80080046, + ASLFO_SLEEPWINDOW=$8008002B, + ASLFO_USERDATA=$80080034, + ASLFO_TEXTATTR=$80080033, + ASLFO_LOCALE=$80080032, + ASLFO_TITLETEXT=$80080001, + ASLFO_POSITIVETEXT=$80080012, + ASLFO_NEGATIVETEXT=$80080013, + ASLFO_INITIALLEFTEDGE=$80080003, + ASLFO_INITIALTOPEDGE=$80080004, + ASLFO_INITIALWIDTH=$80080005, + ASLFO_INITIALHEIGHT=$80080006, + ASLFO_INITIALNAME=$8008000A, + ASLFO_INITIALSIZE=$8008000B, + ASLFO_INITIALSTYLE=$8008000C, + ASLFO_INITIALFLAGS=$8008000D, + ASLFO_INITIALFRONTPEN=$8008000E, + ASLFO_INITIALBACKPEN=$8008000F, + ASLFO_INITIALDRAWMODE=$8008003B, + ASLFO_FLAGS=$80080014, + ASLFO_DOFRONTPEN=$8008002C, + ASLFO_DOBACKPEN=$8008002D, + ASLFO_DOSTYLE=$8008002E, + ASLFO_DODRAWMODE=$8008002F, + ASLFO_FIXEDWIDTHONLY=$80080030, + ASLFO_MINHEIGHT=$80080010, + ASLFO_MAXHEIGHT=$80080011, + ASLFO_FILTERFUNC=$80080031, + ASLFO_HOOKFUNC=$80080007, + ASLFO_MODELIST=$80080015, + ASLFO_FRONTPENS=$80080040, + ASLFO_BACKPENS=$80080041, + ASLFO_MAXFRONTPEN=$80080042, + ASLFO_MAXBACKPEN=$80080043, + FOB_DOFRONTPEN=0, + FOB_DOBACKPEN=1, + FOB_DOFONTSTYLE=2, + FOB_DODRAWMODE=3, + FOB_FIXEDWIDTHONLY=4, + FOB_PRIVATEIDCMP=5, + FOB_INTUIFUNC=6, + FOB_FILTERFUNC=7, + FOF_DOFRONTPEN=1, + FOF_DOBACKPEN=2, + FOF_DOFONTSTYLE=4, + FOF_DODRAWMODE=8, + FOF_FIXEDWIDTHONLY=16, + FOF_PRIVATE=$20, -> Obsolete + FOF_PRIVATEIDCMP=$20, + FOF_DOMSGFUNC=$40, -> Obsolete + FOF_INTUIFUNC=$40, + FOF_DOWILDFUNC=$80, -> Obsolete + FOF_FILTERFUNC=$80 + +OBJECT screenmoderequester + displayid:LONG + displaywidth:LONG + displayheight:LONG + displaydepth:INT -> This is unsigned + overscantype:INT -> This is unsigned + autoscroll:INT + bitmapwidth:LONG + bitmapheight:LONG + leftedge:INT + topedge:INT + width:INT + height:INT + infoopened:INT + infoleftedge:INT + infotopedge:INT + infowidth:INT + infoheight:INT + userdata:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT displaymode + ln:ln + dimensioninfo:dimensioninfo + propertyflags:LONG +ENDOBJECT /* SIZEOF=106 */ + +CONST ASLSM_WINDOW=$80080002, + ASLSM_SCREEN=$80080028, + ASLSM_PUBSCREENNAME=$80080029, + ASLSM_PRIVATEIDCMP=$8008002A, + ASLSM_INTUIMSGFUNC=$80080046, + ASLSM_SLEEPWINDOW=$8008002B, + ASLSM_USERDATA=$80080034, + ASLSM_TEXTATTR=$80080033, + ASLSM_LOCALE=$80080032, + ASLSM_TITLETEXT=$80080001, + ASLSM_POSITIVETEXT=$80080012, + ASLSM_NEGATIVETEXT=$80080013, + ASLSM_INITIALLEFTEDGE=$80080003, + ASLSM_INITIALTOPEDGE=$80080004, + ASLSM_INITIALWIDTH=$80080005, + ASLSM_INITIALHEIGHT=$80080006, + ASLSM_INITIALDISPLAYID=$80080064, + ASLSM_INITIALDISPLAYWIDTH=$80080065, + ASLSM_INITIALDISPLAYHEIGHT=$80080066, + ASLSM_INITIALDISPLAYDEPTH=$80080067, + ASLSM_INITIALOVERSCANTYPE=$80080068, + ASLSM_INITIALAUTOSCROLL=$80080069, + ASLSM_INITIALINFOOPENED=$8008006A, + ASLSM_INITIALINFOLEFTEDGE=$8008006B, + ASLSM_INITIALINFOTOPEDGE=$8008006C, + ASLSM_DOWIDTH=$8008006D, + ASLSM_DOHEIGHT=$8008006E, + ASLSM_DODEPTH=$8008006F, + ASLSM_DOOVERSCANTYPE=$80080070, + ASLSM_DOAUTOSCROLL=$80080071, + ASLSM_PROPERTYFLAGS=$80080072, + ASLSM_PROPERTYMASK=$80080073, + ASLSM_MINWIDTH=$80080074, + ASLSM_MAXWIDTH=$80080075, + ASLSM_MINHEIGHT=$80080076, + ASLSM_MAXHEIGHT=$80080077, + ASLSM_MINDEPTH=$80080078, + ASLSM_MAXDEPTH=$80080079, + ASLSM_FILTERFUNC=$8008007A, + ASLSM_CUSTOMSMLIST=$8008007B + + -> Obsolete +CONST RF_FILE=4, + RF_DIR=8, + RF_LEFTEDGE=22, + RF_TOPEDGE=24, + RF_WIDTH=26, + RF_HEIGHT=28, + RF_NUMARGS=$20, + RF_ARGLIST=$24, + RF_USERDATA=$28, + RF_PAT=$34, + ASL_DUMMY=$80080000, + ASL_HAIL=$80080001, + ASL_WINDOW=$80080002, + ASL_LEFTEDGE=$80080003, + ASL_TOPEDGE=$80080004, + ASL_WIDTH=$80080005, + ASL_HEIGHT=$80080006, + ASL_HOOKFUNC=$80080007, + ASL_FILE=$80080008, + ASL_DIR=$80080009, + ASL_PATTERN=$8008000A, + ASL_FONTNAME=$8008000A, + ASL_FONTHEIGHT=$8008000B, + ASL_FONTSTYLES=$8008000C, + ASL_FONTFLAGS=$8008000D, + ASL_FRONTPEN=$8008000E, + ASL_BACKPEN=$8008000F, + ASL_MINHEIGHT=$80080010, + ASL_MAXHEIGHT=$80080011, + ASL_OKTEXT=$80080012, + ASL_CANCELTEXT=$80080013, + ASL_FUNCFLAGS=$80080014, + ASL_MODELIST=$80080015, + ASL_EXTFLAGS1=$80080016, + FILB_PATGAD=0, + FILB_MULTISELECT=3, + FILB_NEWIDCMP=4, + FILB_SAVE=5, + FILB_DOMSGFUNC=6, + FILB_DOWILDFUNC=7, + FILF_PATGAD=1, + FILF_MULTISELECT=8, + FILF_NEWIDCMP=16, + FILF_SAVE=$20, + FILF_DOMSGFUNC=$40, + FILF_DOWILDFUNC=$80, + FIL1B_NOFILES=0, + FIL1B_MATCHDIRS=1, + FIL1F_NOFILES=1, + FIL1F_MATCHDIRS=2, + RFF_DOWILDFUNC=$80, + RFF_DOMSGFUNC=$40, + RFF_DOCOLOR=$20, + RFF_NEWIDCMP=16, + RFF_MULTISELECT=8, + RFF_PATGAD=1, + FONB_FRONTCOLOR=0, + FONB_BACKCOLOR=1, + FONB_STYLES=2, + FONB_DRAWMODE=3, + FONB_FIXEDWIDTH=4, + FONB_NEWIDCMP=5, + FONB_DOMSGFUNC=6, + FONB_DOWILDFUNC=7, + FONF_FRONTCOLOR=1, + FONF_BACKCOLOR=2, + FONF_STYLES=4, + FONF_DRAWMODE=8, + FONF_FIXEDWIDTH=16, + FONF_NEWIDCMP=$20, + FONF_DOMSGFUNC=$40, + FONF_DOWILDFUNC=$80 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/commodities.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/commodities.e new file mode 100644 index 0000000..b7fb96e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/commodities.e @@ -0,0 +1,85 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/ports' + +#define CxFilter(d) CreateCxObj(CX_FILTER, (d), 0) +#define CxSender(port, id) CreateCxObj(CX_SEND, (port), (id)) +#define CxSignal(task, sig) CreateCxObj(CX_SIGNAL, (task), (sig)) +#define CxTranslate(ie) CreateCxObj(CX_TRANSLATE, (ie), 0) +#define CxDebug(id) CreateCxObj(CX_DEBUG, (id), 0) +#define CxCustom(action, id) CreateCxObj(CX_CUSTOM, (action), id) + +OBJECT newbroker + version:CHAR + reserve1:CHAR + name:PTR TO CHAR + title:PTR TO CHAR + descr:PTR TO CHAR + unique:INT + flags:INT + pri:CHAR -> This is signed + reserve2:CHAR + port:PTR TO mp + reservedchannel:INT +ENDOBJECT /* SIZEOF=26 */ + +CONST NB_VERSION=5, + CBD_NAMELEN=24, + CBD_TITLELEN=$28, + CBD_DESCRLEN=$28, + NBU_DUPLICATE=0, + NBU_UNIQUE=1, + NBU_NOTIFY=2, + COF_SHOW_HIDE=4, + CX_INVALID=0, + CX_FILTER=1, + CX_TYPEFILTER=2, + CX_SEND=3, + CX_SIGNAL=4, + CX_TRANSLATE=5, + CX_BROKER=6, + CX_DEBUG=7, + CX_CUSTOM=8, + CX_ZERO=9, + CXM_IEVENT=$20, + CXM_COMMAND=$40, + CXCMD_DISABLE=15, + CXCMD_ENABLE=17, + CXCMD_APPEAR=19, + CXCMD_DISAPPEAR=21, + CXCMD_KILL=23, + CXCMD_LIST_CHG=27, + CXCMD_UNIQUE=25 + +OBJECT inputxpression + version:CHAR + class:CHAR + code:INT -> This is unsigned + codemask:INT -> This is unsigned + qualifier:INT -> This is unsigned + qualmask:INT -> This is unsigned + qualsame:INT -> This is unsigned +ENDOBJECT /* SIZEOF=12 */ + +#define NULL_IX(ix) (ix::inputxpression.class=IECLASS_NULL) + +CONST IX_VERSION=2, + IXSYM_SHIFT=1, + IXSYM_CAPS=2, + IXSYM_ALT=4, + IXSYM_SHIFTMASK=3, + IXSYM_CAPSMASK=7, + IXSYM_ALTMASK=$30, + IX_NORMALQUALS=$7FFF, + CBERR_OK=0, + CBERR_SYSERR=1, + CBERR_DUP=2, + CBERR_VERSION=3, + COERR_ISNULL=1, + COERR_NULLATTACH=2, + COERR_BADFILTER=4, + COERR_BADTYPE=8 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/configregs.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/configregs.e new file mode 100644 index 0000000..ad99a3f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/configregs.e @@ -0,0 +1,114 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +OBJECT expansionrom + type:CHAR + product:CHAR + flags:CHAR + reserved03:CHAR + manufacturer:INT -> This is unsigned + serialnumber:LONG + initdiagvec:INT -> This is unsigned + reserved0c:CHAR + reserved0d:CHAR + reserved0e:CHAR + reserved0f:CHAR +ENDOBJECT /* SIZEOF=16 */ + +OBJECT expansioncontrol + interrupt:CHAR + z3_highbase:CHAR + baseaddress:CHAR + shutup:CHAR + reserved14:CHAR + reserved15:CHAR + reserved16:CHAR + reserved17:CHAR + reserved18:CHAR + reserved19:CHAR + reserved1a:CHAR + reserved1b:CHAR + reserved1c:CHAR + reserved1d:CHAR + reserved1e:CHAR + reserved1f:CHAR +ENDOBJECT /* SIZEOF=16 */ + +CONST E_SLOTSIZE=$10000, + E_SLOTMASK=$FFFF, + E_SLOTSHIFT=16, + E_EXPANSIONBASE=$E80000, + EZ3_EXPANSIONBASE=$FF000000, + E_EXPANSIONSIZE=$80000, + E_EXPANSIONSLOTS=8, + E_MEMORYBASE=$200000, + E_MEMORYSIZE=$800000, + E_MEMORYSLOTS=$80, + EZ3_CONFIGAREA=$40000000, + EZ3_CONFIGAREAEND=$7FFFFFFF, + EZ3_SIZEGRANULARITY=$80000, + ERT_TYPEMASK=$C0, + ERT_TYPEBIT=6, + ERT_TYPESIZE=2, + ERT_NEWBOARD=$C0, + ERT_ZORROII=$C0, + ERT_ZORROIII=$80, + ERTB_MEMLIST=5, + ERTB_DIAGVALID=4, + ERTB_CHAINEDCONFIG=3, + ERTF_MEMLIST=$20, + ERTF_DIAGVALID=16, + ERTF_CHAINEDCONFIG=8, + ERT_MEMMASK=7, + ERT_MEMBIT=0, + ERT_MEMSIZE=3, + ERFB_MEMSPACE=7, + ERFB_NOSHUTUP=6, + ERFB_EXTENDED=5, + ERFB_ZORRO_III=4, + ERFF_MEMSPACE=$80, + ERFF_NOSHUTUP=$40, + ERFF_EXTENDED=$20, + ERFF_ZORRO_III=16, + ERT_Z3_SSMASK=15, + ERT_Z3_SSBIT=0, + ERT_Z3_SSSIZE=4, + ECIB_INTENA=1, + ECIB_RESET=3, + ECIB_INT2PEND=4, + ECIB_INT6PEND=5, + ECIB_INT7PEND=6, + ECIB_INTERRUPTING=7, + ECIF_INTENA=2, + ECIF_RESET=8, + ECIF_INT2PEND=16, + ECIF_INT6PEND=$20, + ECIF_INT7PEND=$40, + ECIF_INTERRUPTING=$80 + +#define ERT_MEMNEEDED(t) (IF (t) AND ERT_MEMMASK THEN Shl($10000, ((t) AND ERT_MEMMASK)-1) ELSE $800000) +#define ERT_SLOTSNEEDED(t) (IF (t) AND ERT_MEMMASK THEN Shl(1, ((t) AND ERT_MEMMASK)-1) ELSE $80) +#define EC_MEMADDR(slot) (Shl((slot), E_SLOTSHIFT)) + +OBJECT diagarea + config:CHAR + flags:CHAR + size:INT -> This is unsigned + diagpoint:INT -> This is unsigned + bootpoint:INT -> This is unsigned + name:INT -> This is unsigned + reserved01:INT + reserved02:INT +ENDOBJECT /* SIZEOF=14 */ + +CONST DAC_BUSWIDTH=$C0, + DAC_NIBBLEWIDE=0, + DAC_BYTEWIDE=$40, + DAC_WORDWIDE=$80, + DAC_BOOTTIME=$30, + DAC_NEVER=0, + DAC_CONFIGTIME=16, + DAC_BINDTIME=$20 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/configvars.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/configvars.e new file mode 100644 index 0000000..8079db2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/configvars.e @@ -0,0 +1,36 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes', + 'libraries/configregs' + +OBJECT configdev + node:ln + flags:CHAR + pad:CHAR + rom:expansionrom + boardaddr:LONG + boardsize:LONG + slotaddr:INT -> This is unsigned + slotsize:INT -> This is unsigned + driver:LONG + nextcd:PTR TO configdev + unused[4]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=68 */ + +CONST CDB_SHUTUP=0, + CDB_CONFIGME=1, + CDB_BADMEMORY=2, + CDB_PROCESSED=3, + CDF_SHUTUP=1, + CDF_CONFIGME=2, + CDF_BADMEMORY=4, + CDF_PROCESSED=8 + +OBJECT currentbinding + configdev:PTR TO configdev + filename:PTR TO CHAR + productstring:PTR TO CHAR + tooltypes:PTR TO LONG +ENDOBJECT /* SIZEOF=16 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/diskfont.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/diskfont.e new file mode 100644 index 0000000..5d10156 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/diskfont.e @@ -0,0 +1,71 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes', + 'graphics/text' + +CONST MAXFONTPATH=$100 + +OBJECT fc + filename[$100]:ARRAY + ysize:INT -> This is unsigned + style:CHAR + flags:CHAR +ENDOBJECT /* SIZEOF=260 */ + +OBJECT tfc + filename[$fe]:ARRAY + tagcount:INT -> This is unsigned + ysize:INT -> This is unsigned + style:CHAR + flags:CHAR +ENDOBJECT /* SIZEOF=260 */ + +CONST FCH_ID=$F00, + TFCH_ID=$F02, + OFCH_ID=$F03 + +OBJECT fch + fileid:INT -> This is unsigned + numentries:INT -> This is unsigned +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST DFH_ID=$F80, + MAXFONTNAME=$20 + +OBJECT diskfontheader + df:ln + fileid:INT -> This is unsigned + revision:INT -> This is unsigned + segment:LONG + name[$20]:ARRAY + tf:textfont +ENDOBJECT /* SIZEOF=106 */ + +CONST DFH_TAGLIST=18, + AFB_MEMORY=0, + AFF_MEMORY=1, + AFB_DISK=1, + AFF_DISK=2, + AFB_SCALED=2, + AFF_SCALED=4, + AFB_BITMAP=3, + AFF_BITMAP=8, + AFB_TAGGED=16, + AFF_TAGGED=$10000, + AFF_TTATTR=$10000 + +OBJECT af + type:INT -> This is unsigned + attr:textattr +ENDOBJECT /* SIZEOF=10 */ + +OBJECT taf + type:INT -> This is unsigned + attr:ttextattr +ENDOBJECT /* SIZEOF=14 */ + +OBJECT afh + numentries:INT -> This is unsigned +ENDOBJECT /* SIZEOF=NONE !!! */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansion.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansion.e new file mode 100644 index 0000000..5d83b3b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansion.e @@ -0,0 +1,10 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define EXPANSIONNAME 'expansion.library' + +CONST ADNB_STARTPROC=0, + ADNF_STARTPROC=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansionbase.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansionbase.e new file mode 100644 index 0000000..5a36da0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/expansionbase.e @@ -0,0 +1,48 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/libraries', + 'exec/lists', + 'exec/nodes', + 'libraries/configvars' + +OBJECT bootnode + ln:ln + flags:INT + devicenode:LONG +ENDOBJECT /* SIZEOF=20 */ + +OBJECT expansionbase + lib:lib + flags:CHAR + private01:CHAR + private02:LONG + private03:LONG + private04:currentbinding + private05:lh + mountlist:lh +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST EE_OK=0, + EE_LASTBOARD=$28, + EE_NOEXPANSION=$29, + EE_NOMEMORY=$2A, + EE_NOBOARD=$2B, + EE_BADMEM=$2C, + EBB_CLOGGED=0, + EBF_CLOGGED=1, + EBB_SHORTMEM=1, + EBF_SHORTMEM=2, + EBB_BADMEM=2, + EBF_BADMEM=4, + EBB_DOSFLAG=3, + EBF_DOSFLAG=8, + EBB_KICKBACK33=4, + EBF_KICKBACK33=16, + EBB_KICKBACK36=5, + EBF_KICKBACK36=$20, + EBB_SILENTSTART=6, + EBF_SILENTSTART=$40, + EBB_START_CC0=7, + EBF_START_CC0=$80 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/gadtools.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/gadtools.e new file mode 100644 index 0000000..e402b6b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/gadtools.e @@ -0,0 +1,201 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'graphics/gfx', + 'graphics/rastport', + 'graphics/text', + 'intuition/screens' + +CONST GENERIC_KIND=0, + BUTTON_KIND=1, + CHECKBOX_KIND=2, + INTEGER_KIND=3, + LISTVIEW_KIND=4, + MX_KIND=5, + NUMBER_KIND=6, + CYCLE_KIND=7, + PALETTE_KIND=8, + SCROLLER_KIND=9, + SLIDER_KIND=11, + STRING_KIND=12, + TEXT_KIND=13, + NUM_KINDS=14, + ARROWIDCMP=$400068, + BUTTONIDCMP=$40, + CHECKBOXIDCMP=$40, + INTEGERIDCMP=$40, + LISTVIEWIDCMP=$400078, + MXIDCMP=$20, + NUMBERIDCMP=0, + CYCLEIDCMP=$40, + PALETTEIDCMP=$40, + SCROLLERIDCMP=$70, + SLIDERIDCMP=$70, + STRINGIDCMP=$40, + TEXTIDCMP=0 + +OBJECT newgadget + leftedge:INT + topedge:INT + width:INT + height:INT + gadgettext:PTR TO CHAR + textattr:PTR TO textattr + gadgetid:INT -> This is unsigned + flags:LONG + visualinfo:LONG + userdata:LONG +ENDOBJECT /* SIZEOF=30 */ + +CONST PLACETEXT_LEFT=1, + PLACETEXT_RIGHT=2, + PLACETEXT_ABOVE=4, + PLACETEXT_BELOW=8, + PLACETEXT_IN=16, + NG_HIGHLABEL=$20 + +OBJECT newmenu + type:CHAR + pad:CHAR + label:PTR TO CHAR + commkey:PTR TO CHAR + flags:INT -> This is unsigned + mutualexclude:LONG + userdata:LONG +ENDOBJECT /* SIZEOF=20 */ + +#define GTMENU_USERDATA(m) (Long((m)+SIZEOF menu)) +#define GTMENUITEM_USERDATA(mi) (Long((mi)+SIZEOF menuitem)) +#define MENU_USERDATA(mi) (GTMENUITEM_USERDATA(mi)) + +CONST MENU_IMAGE=$80, + NM_TITLE=1, + NM_ITEM=2, + NM_SUB=3, + IM_ITEM=$82, + IM_SUB=$83, + NM_END=0, + NM_IGNORE=$40, + NM_BARLABEL=-1, + NM_MENUDISABLED=1, + NM_ITEMDISABLED=16, + NM_COMMANDSTRING=4, + NM_FLAGMASK=$FFFFFF39, + NM_FLAGMASK_V39=$FFFFFF3D, + GTMENU_TRIMMED=1, + GTMENU_INVALID=2, + GTMENU_NOMEM=3, + MX_WIDTH=17, + MX_HEIGHT=9, + CHECKBOX_WIDTH=26, + CHECKBOX_HEIGHT=11, + GT_TAGBASE=$80080000, + GTVI_NEWWINDOW=$80080001, + GTVI_NWTAGS=$80080002, + GT_PRIVATE0=$80080003, + GTCB_CHECKED=$80080004, + GTLV_TOP=$80080005, + GTLV_LABELS=$80080006, + GTLV_READONLY=$80080007, + GTLV_SCROLLWIDTH=$80080008, + GTMX_LABELS=$80080009, + GTMX_ACTIVE=$8008000A, + GTTX_TEXT=$8008000B, + GTTX_COPYTEXT=$8008000C, + GTNM_NUMBER=$8008000D, + GTCY_LABELS=$8008000E, + GTCY_ACTIVE=$8008000F, + GTPA_DEPTH=$80080010, + GTPA_COLOR=$80080011, + GTPA_COLOROFFSET=$80080012, + GTPA_INDICATORWIDTH=$80080013, + GTPA_INDICATORHEIGHT=$80080014, + GTSC_TOP=$80080015, + GTSC_TOTAL=$80080016, + GTSC_VISIBLE=$80080017, + GTSC_OVERLAP=$80080018, + GTSL_MIN=$80080026, + GTSL_MAX=$80080027, + GTSL_LEVEL=$80080028, + GTSL_MAXLEVELLEN=$80080029, + GTSL_LEVELFORMAT=$8008002A, + GTSL_LEVELPLACE=$8008002B, + GTSL_DISPFUNC=$8008002C, + GTST_STRING=$8008002D, + GTST_MAXCHARS=$8008002E, + GTIN_NUMBER=$8008002F, + GTIN_MAXCHARS=$80080030, + GTMN_TEXTATTR=$80080031, + GTMN_FRONTPEN=$80080032, + GTBB_RECESSED=$80080033, + GT_VISUALINFO=$80080034, + GTLV_SHOWSELECTED=$80080035, + GTLV_SELECTED=$80080036, + GT_RESERVED1=$80080038, + GTTX_BORDER=$80080039, + GTNM_BORDER=$8008003A, + GTSC_ARROWS=$8008003B, + GTMN_MENU=$8008003C, + GTMX_SPACING=$8008003D, + GTMN_FULLMENU=$8008003E, + GTMN_SECONDARYERROR=$8008003F, + GT_UNDERSCORE=$80080040, + GTST_EDITHOOK=$80080037, + GTIN_EDITHOOK=$80080037, + GTMN_CHECKMARK=$80080041, + GTMN_AMIGAKEY=$80080042, + GTMN_NEWLOOKMENUS=$80080043, + GTCB_SCALED=$80080044, + GTMX_SCALED=$80080045, + GTPA_NUMCOLORS=$80080046, + GTMX_TITLEPLACE=$80080047, + GTTX_FRONTPEN=$80080048, + GTTX_BACKPEN=$80080049, + GTTX_JUSTIFICATION=$8008004A, + GTNM_FRONTPEN=$80080048, + GTNM_BACKPEN=$80080049, + GTNM_JUSTIFICATION=$8008004A, + GTNM_FORMAT=$8008004B, + GTNM_MAXNUMBERLEN=$8008004C, + GTBB_FRAMETYPE=$8008004D, + GTLV_MAKEVISIBLE=$8008004E, + GTLV_ITEMHEIGHT=$8008004F, + GTSL_MAXPIXELLEN=$80080050, + GTSL_JUSTIFICATION=$80080051, + GTPA_COLORTABLE=$80080052, + GTLV_CALLBACK=$80080053, + GTLV_MAXPEN=$80080054, + GTTX_CLIPPED=$80080055, + GTNM_CLIPPED=$80080055, + GT_RESERVED0=$80080037, + GTJ_LEFT=0, + GTJ_RIGHT=1, + GTJ_CENTER=2, + BBFT_BUTTON=1, + BBFT_RIDGE=2, + BBFT_ICONDROPBOX=3, + INTERWIDTH=8, + INTERHEIGHT=4, + NWAY_KIND=7, + NWAYIDCMP=$40, + GTNW_LABELS=$8008000E, + GTNW_ACTIVE=$8008000F, + GADTOOLBIT=$8000, + GADTOOLMASK=$FFFF7FFF, + LV_DRAW=$202, + LVCB_OK=0, + LVCB_UNKNOWN=1, + LVR_NORMAL=0, + LVR_SELECTED=1, + LVR_NORMALDISABLED=2, + LVR_SELECTEDDISABLED=8 + +OBJECT lvdrawmsg + methodid:LONG + rastport:PTR TO rastport + drawinfo:PTR TO drawinfo + bounds:rectangle + state:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/iffparse.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/iffparse.e new file mode 100644 index 0000000..4ed3ed4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/iffparse.e @@ -0,0 +1,100 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/clipboard', + 'exec/nodes', + 'exec/ports' + +OBJECT iffhandle + stream:LONG + flags:LONG + depth:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST IFFF_READ=0, + IFFF_WRITE=1, + IFFF_RWBITS=1, + IFFF_FSEEK=2, + IFFF_RSEEK=4, + IFFF_RESERVED=$FFFF0000 + +OBJECT iffstreamcmd + command:LONG + buf:PTR TO CHAR + nbytes:LONG +ENDOBJECT /* SIZEOF=12 */ + +OBJECT contextnode + mln:mln + id:LONG + type:LONG + size:LONG + scan:LONG +ENDOBJECT /* SIZEOF=24 */ + +OBJECT localcontextitem + mln:mln + id:LONG + type:LONG + ident:LONG +ENDOBJECT /* SIZEOF=20 */ + +OBJECT storedproperty + size:LONG + data:LONG +ENDOBJECT /* SIZEOF=8 */ + +OBJECT collectionitem + next:PTR TO collectionitem + size:LONG + data:LONG +ENDOBJECT /* SIZEOF=12 */ + +OBJECT clipboardhandle + iocr:ioclipreq + cbport:mp + satisfyport:mp +ENDOBJECT /* SIZEOF=120 */ + +CONST IFFERR_EOF=-1, + IFFERR_EOC=-2, + IFFERR_NOSCOPE=-3, + IFFERR_NOMEM=-4, + IFFERR_READ=-5, + IFFERR_WRITE=-6, + IFFERR_SEEK=-7, + IFFERR_MANGLED=-8, + IFFERR_SYNTAX=-9, + IFFERR_NOTIFF=-10, + IFFERR_NOHOOK=-11, + IFF_RETURN2CLIENT=-12, + ID_FORM=$464F524D, + ID_LIST=$4C495354, + ID_CAT=$43415420, + ID_PROP=$50524F50, + ID_NULL=$20202020, + IFFLCI_PROP=$70726F70, + IFFLCI_COLLECTION=$636F6C6C, + IFFLCI_ENTRYHANDLER=$656E6864, + IFFLCI_EXITHANDLER=$65786864, + IFFPARSE_SCAN=0, + IFFPARSE_STEP=1, + IFFPARSE_RAWSTEP=2, + IFFSLI_ROOT=1, + IFFSLI_TOP=2, + IFFSLI_PROP=3, + IFFSIZE_UNKNOWN=-1, + IFFCMD_INIT=0, + IFFCMD_CLEANUP=1, + IFFCMD_READ=2, + IFFCMD_WRITE=3, + IFFCMD_SEEK=4, + IFFCMD_ENTRY=5, + IFFCMD_EXIT=6, + IFFCMD_PURGELCI=7, + IFFSCC_INIT=0, + IFFSCC_CLEANUP=1, + IFFSCC_READ=2, + IFFSCC_WRITE=3, + IFFSCC_SEEK=4 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/locale.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/locale.e new file mode 100644 index 0000000..d6b6149 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/locale.e @@ -0,0 +1,147 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/libraries', + 'exec/nodes' + +CONST DAY_1=1, + DAY_2=2, + DAY_3=3, + DAY_4=4, + DAY_5=5, + DAY_6=6, + DAY_7=7, + ABDAY_1=8, + ABDAY_2=9, + ABDAY_3=10, + ABDAY_4=11, + ABDAY_5=12, + ABDAY_6=13, + ABDAY_7=14, + MON_1=15, + MON_2=16, + MON_3=17, + MON_4=18, + MON_5=19, + MON_6=20, + MON_7=21, + MON_8=22, + MON_9=23, + MON_10=24, + MON_11=25, + MON_12=26, + ABMON_1=27, + ABMON_2=28, + ABMON_3=29, + ABMON_4=30, + ABMON_5=31, + ABMON_6=$20, + ABMON_7=$21, + ABMON_8=$22, + ABMON_9=$23, + ABMON_10=$24, + ABMON_11=$25, + ABMON_12=$26, + YESSTR=$27, + NOSTR=$28, + AM_STR=$29, + PM_STR=$2A, + SOFTHYPHEN=$2B, + HARDHYPHEN=$2C, + OPENQUOTE=$2D, + CLOSEQUOTE=$2E, + YESTERDAYSTR=$2F, + TODAYSTR=$30, + TOMORROWSTR=$31, + FUTURESTR=$32, + MAXSTRMSG=$33 + +OBJECT localebase + lib:lib + syspatches:INT +ENDOBJECT /* SIZEOF=NONE !!! */ + +OBJECT locale + localename:PTR TO CHAR + languagename:PTR TO CHAR + preflanguages[10]:ARRAY OF LONG + flags:LONG + codeset:LONG + countrycode:LONG + telephonecode:LONG + gmtoffset:LONG + measuringsystem:CHAR + calendartype:CHAR + reserved0[2]:ARRAY + datetimeformat:PTR TO CHAR + dateformat:PTR TO CHAR + timeformat:PTR TO CHAR + shortdatetimeformat:PTR TO CHAR + shortdateformat:PTR TO CHAR + shorttimeformat:PTR TO CHAR + decimalpoint:PTR TO CHAR + groupseparator:PTR TO CHAR + fracgroupseparator:PTR TO CHAR + grouping:PTR TO CHAR + fracgrouping:PTR TO CHAR + mondecimalpoint:PTR TO CHAR + mongroupseparator:PTR TO CHAR + monfracgroupseparator:PTR TO CHAR + mongrouping:PTR TO CHAR + monfracgrouping:PTR TO CHAR + monfracdigits:CHAR + monintfracdigits:CHAR + reserved1[2]:ARRAY + moncs:PTR TO CHAR + monsmallcs:PTR TO CHAR + monintcs:PTR TO CHAR + monpositivesign:PTR TO CHAR + monpositivespacesep:CHAR + monpositivesignpos:CHAR + monpositivecspos:CHAR + reserved2:CHAR + monnegativesign:PTR TO CHAR + monnegativespacesep:CHAR + monnegativesignpos:CHAR + monnegativecspos:CHAR + reserved3:CHAR +ENDOBJECT /* SIZEOF=168 */ + +CONST MS_ISO=0, + MS_AMERICAN=1, + MS_IMPERIAL=2, + MS_BRITISH=3, + CT_7SUN=0, + CT_7MON=1, + CT_7TUE=2, + CT_7WED=3, + CT_7THU=4, + CT_7FRI=5, + CT_7SAT=6, + SS_NOSPACE=0, + SS_SPACE=1, + SP_PARENS=0, + SP_PREC_ALL=1, + SP_SUCC_ALL=2, + SP_PREC_CURR=3, + SP_SUCC_CURR=4, + CSP_PRECEDES=0, + CSP_SUCCEEDS=1, + OC_TAGBASE=$80090000, + OC_BUILTINLANGUAGE=$80090001, + OC_BUILTINCODESET=$80090002, + OC_VERSION=$80090003, + OC_LANGUAGE=$80090004, + SC_ASCII=0, + SC_COLLATE1=1, + SC_COLLATE2=2 + +OBJECT catalog + ln:ln + pad:INT + language:PTR TO CHAR + codeset:LONG + version:INT -> This is unsigned + revision:INT -> This is unsigned +ENDOBJECT /* SIZEOF=28 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/lowlevel.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/lowlevel.e new file mode 100644 index 0000000..1e627fa --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/lowlevel.e @@ -0,0 +1,161 @@ +OPT MODULE +OPT EXPORT + +OBJECT keyquery + keycode:INT -> This is unsigned + pressed:INT -> This is unsigned +ENDOBJECT + +CONST LLKF_LSHIFT=$10000, + LLKF_RSHIFT=$20000, + LLKF_CAPSLOCK=$40000, + LLKF_CONTROL=$80000, + LLKF_LALT=$100000, + LLKF_RALT=$200000, + LLKF_LAMIGA=$400000, + LLKF_RAMIGA=$800000, + LLKB_LSHIFT=16, + LLKB_RSHIFT=17, + LLKB_CAPSLOCK=18, + LLKB_CONTROL=19, + LLKB_LALT=20, + LLKB_RALT=21, + LLKB_LAMIGA=22, + LLKB_RAMIGA=23, + SJA_DUMMY=$80C00100, + SJA_TYPE=$80C00101, + SJA_REINITIALIZE=$80C00102, + SJA_TYPE_AUTOSENSE=0, + SJA_TYPE_GAMECTLR=1, + SJA_TYPE_MOUSE=2, + SJA_TYPE_JOYSTK=3, + JP_TYPE_NOTAVAIL=0, + JP_TYPE_GAMECTLR=$10000000, + JP_TYPE_MOUSE=$20000000, + JP_TYPE_JOYSTK=$30000000, + JP_TYPE_UNKNOWN=$40000000, + JP_TYPE_MASK=$F0000000, + JPF_BUTTON_BLUE=$800000, + JPF_BUTTON_RED=$400000, + JPF_BUTTON_YELLOW=$200000, + JPF_BUTTON_GREEN=$100000, + JPF_BUTTON_FORWARD=$80000, + JPF_BUTTON_REVERSE=$40000, + JPF_BUTTON_PLAY=$20000, + JPB_BUTTON_BLUE=23, + JPB_BUTTON_RED=22, + JPB_BUTTON_YELLOW=21, + JPB_BUTTON_GREEN=20, + JPB_BUTTON_FORWARD=19, + JPB_BUTTON_REVERSE=18, + JPB_BUTTON_PLAY=17, + JP_BUTTON_MASK=$FE0000, + JPF_JOY_UP=8, + JPF_JOY_DOWN=4, + JPF_JOY_LEFT=2, + JPF_JOY_RIGHT=1, + JPB_JOY_UP=3, + JPB_JOY_DOWN=2, + JPB_JOY_LEFT=1, + JPB_JOY_RIGHT=0, + JP_DIRECTION_MASK=15, + JP_MHORZ_MASK=$FF, + JP_MVERT_MASK=$FF00, + JP_MOUSE_MASK=$FFFF, + JPB_BTN1=23, + JPF_BTN1=$800000, + JPB_BTN2=22, + JPF_BTN2=$400000, + JPB_BTN3=21, + JPF_BTN3=$200000, + JPB_BTN4=20, + JPF_BTN4=$100000, + JPB_BTN5=19, + JPF_BTN5=$80000, + JPB_BTN6=18, + JPF_BTN6=$40000, + JPB_BTN7=17, + JPF_BTN7=$20000, + JPB_UP=3, + JPF_UP=8, + JPB_DOWN=2, + JPF_DOWN=4, + JPB_LEFT=1, + JPF_LEFT=2, + JPB_RIGHT=0, + JPF_RIGHT=1, + SCON_DUMMY=$80C00000, + SCON_DUMMY=$80C00000, + SCON_TAKEOVERSYS=$80C00000, + SCON_KILLREQ=$80C00001, + SCON_CDREBOOT=$80C00002, + SCON_STOPINPUT=$80C00003, + SCON_ADDCREATEKEYS=$80C00004, + SCON_REMCREATEKEYS=$80C00005, + CDREBOOT_ON=1, + CDREBOOT_OFF=0, + CDREBOOT_DEFAULT=2, + RAWKEY_PORT0_BUTTON_BLUE=$72, + RAWKEY_PORT0_BUTTON_RED=$78, + RAWKEY_PORT0_BUTTON_YELLOW=$77, + RAWKEY_PORT0_BUTTON_GREEN=$76, + RAWKEY_PORT0_BUTTON_FORWARD=$75, + RAWKEY_PORT0_BUTTON_REVERSE=$74, + RAWKEY_PORT0_BUTTON_PLAY=$73, + RAWKEY_PORT0_JOY_UP=$79, + RAWKEY_PORT0_JOY_DOWN=$7A, + RAWKEY_PORT0_JOY_LEFT=$7C, + RAWKEY_PORT0_JOY_RIGHT=$7B, + RAWKEY_PORT1_BUTTON_BLUE=$172, + RAWKEY_PORT1_BUTTON_RED=$178, + RAWKEY_PORT1_BUTTON_YELLOW=$177, + RAWKEY_PORT1_BUTTON_GREEN=$176, + RAWKEY_PORT1_BUTTON_FORWARD=$175, + RAWKEY_PORT1_BUTTON_REVERSE=$174, + RAWKEY_PORT1_BUTTON_PLAY=$173, + RAWKEY_PORT1_JOY_UP=$179, + RAWKEY_PORT1_JOY_DOWN=$17A, + RAWKEY_PORT1_JOY_LEFT=$17C, + RAWKEY_PORT1_JOY_RIGHT=$17B, + RAWKEY_PORT2_BUTTON_BLUE=$272, + RAWKEY_PORT2_BUTTON_RED=$278, + RAWKEY_PORT2_BUTTON_YELLOW=$277, + RAWKEY_PORT2_BUTTON_GREEN=$276, + RAWKEY_PORT2_BUTTON_FORWARD=$275, + RAWKEY_PORT2_BUTTON_REVERSE=$274, + RAWKEY_PORT2_BUTTON_PLAY=$273, + RAWKEY_PORT2_JOY_UP=$279, + RAWKEY_PORT2_JOY_DOWN=$27A, + RAWKEY_PORT2_JOY_LEFT=$27C, + RAWKEY_PORT2_JOY_RIGHT=$27B, + RAWKEY_PORT3_BUTTON_BLUE=$372, + RAWKEY_PORT3_BUTTON_RED=$378, + RAWKEY_PORT3_BUTTON_YELLOW=$377, + RAWKEY_PORT3_BUTTON_GREEN=$376, + RAWKEY_PORT3_BUTTON_FORWARD=$375, + RAWKEY_PORT3_BUTTON_REVERSE=$374, + RAWKEY_PORT3_BUTTON_PLAY=$373, + RAWKEY_PORT3_JOY_UP=$379, + RAWKEY_PORT3_JOY_DOWN=$37A, + RAWKEY_PORT3_JOY_LEFT=$37C, + RAWKEY_PORT3_JOY_RIGHT=$37B, + LANG_UNKNOWN=0, + LANG_AMERICAN=1, + LANG_ENGLISH=2, + LANG_GERMAN=3, + LANG_FRENCH=4, + LANG_SPANISH=5, + LANG_ITALIAN=6, + LANG_PORTUGUESE=7, + LANG_DANISH=8, + LANG_DUTCH=9, + LANG_NORWEGIAN=10, + LANG_FINNISH=11, + LANG_SWEDISH=12, + LANG_JAPANESE=13, + LANG_CHINESE=14, + LANG_ARABIC=15, + LANG_GREEK=16, + LANG_HEBREW=17, + LANG_KOREAN=18 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathieeesp.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathieeesp.e new file mode 100644 index 0000000..ca0b384 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathieeesp.e @@ -0,0 +1,21 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define PI (3.14159265) +#define TWO_PI (!2*PI) +#define PI2 (!PI/2) +#define PI4 (!PI/4) + +#define E (2.71828183) + +#define LOG10 (2.30258509) +#define FPTEN (10.0) +#define FPONE (1.0) +#define FPHALF (0.5) +#define FPZERO (0.0) + +#define Trunc(x) (Ffloor(x)) +#define Round(x) (!(x)!) +#define ItoF(i) ((x)!) diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathlibrary.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathlibrary.e new file mode 100644 index 0000000..fcce0cd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathlibrary.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/libraries' + +OBJECT mathieeebase + libnode:lib + reserved[18]:ARRAY + taskopenlib:LONG + taskcloselib:LONG +ENDOBJECT /* SIZEOF=60 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathresource.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathresource.e new file mode 100644 index 0000000..c0511cb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/mathresource.e @@ -0,0 +1,24 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +OBJECT mathieeeresource + node:ln + flags:INT -> This is unsigned + baseaddr:PTR TO INT -> The target is unsigned + dblbasinit:LONG + dbltransinit:LONG + sglbasinit:LONG + sgltransinit:LONG + extbasinit:LONG + exttransinit:LONG +ENDOBJECT /* SIZEOF=44 */ + +CONST MATHIEEERESOURCEF_DBLBAS=1, + MATHIEEERESOURCEF_DBLTRANS=2, + MATHIEEERESOURCEF_SGLBAS=4, + MATHIEEERESOURCEF_SGLTRANS=8, + MATHIEEERESOURCEF_EXTBAS=16, + MATHIEEERESOURCEF_EXTTRANS=$20 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/nonvolatile.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/nonvolatile.e new file mode 100644 index 0000000..56d867b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/nonvolatile.e @@ -0,0 +1,30 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/nodes' + +OBJECT nvinfo + maxstorage:LONG + freestorage:LONG +ENDOBJECT + +OBJECT nventry + node:mln + name:PTR TO CHAR + size:LONG + protection:LONG +ENDOBJECT + +#define SizeNVData(dataptr) (Long((dataptr)-4)-4) + +CONST NVEB_DELETE=0, + NVEF_DELETE=1, + NVEB_APPNAME=31, + NVEF_APPNAME=$80000000, + NVERR_BADNAME=1, + NVERR_WRITEPROT=2, + NVERR_FAIL=3, + NVERR_FATAL=4 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/realtime.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/realtime.e new file mode 100644 index 0000000..c3f654e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/realtime.e @@ -0,0 +1,114 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/libraries', + 'exec/lists', + 'exec/nodes', + 'exec/tasks', + 'utility/hooks' + +CONST TICK_FREQ=$4B0 + +OBJECT conductor + ln:ln + reserved0:INT + players:mlh + clocktime:LONG + starttime:LONG + externaltime:LONG + maxexternaltime:LONG + metronome:LONG + reserved1:INT + flags:INT -> This is unsigned + state:CHAR +ENDOBJECT + +CONST CONDUCTF_EXTERNAL=1, + CONDUCTF_GOTTICK=2, + CONDUCTF_METROSET=4, + CONDUCTF_PRIVATE=8, + CONDUCTB_EXTERNAL=0, + CONDUCTB_GOTTICK=1, + CONDUCTB_METROSET=2, + CONDUCTB_PRIVATE=3, + CONDSTATE_STOPPED=0, + CONDSTATE_PAUSED=1, + CONDSTATE_LOCATE=2, + CONDSTATE_RUNNING=3, + CONDSTATE_METRIC=-1, + CONDSTATE_SHUTTLE=-2, + CONDSTATE_LOCATE_SET=-3 + +OBJECT player + ln:ln + reserved0:CHAR + reserved1:CHAR + hook:PTR TO hook + source:PTR TO conductor + task:PTR TO tc + metrictime:LONG + alarmtime:LONG + userdata:LONG + playerid:INT -> This is unsigned + flags:INT -> This is unsigned +ENDOBJECT + +CONST PLAYERF_READY=1, + PLAYERF_ALARMSET=2, + PLAYERF_QUIET=4, + PLAYERF_CONDUCTED=8, + PLAYERF_EXTSYNC=16, + PLAYERB_READY=0, + PLAYERB_ALARMSET=1, + PLAYERB_QUIET=2, + PLAYERB_CONDUCTED=3, + PLAYERB_EXTSYNC=4, + PLAYER_BASE=$80000040, + PLAYER_HOOK=$80000041, + PLAYER_NAME=$80000042, + PLAYER_PRIORITY=$80000043, + PLAYER_CONDUCTOR=$80000044, + PLAYER_READY=$80000045, + PLAYER_ALARMTIME=$8000004c, + PLAYER_ALARM=$8000004d, + PLAYER_ALARMSIGTASK=$80000046, + PLAYER_ALARMSIGBIT=$80000048, + PLAYER_CONDUCTED=$80000047, + PLAYER_QUIET=$80000049, + PLAYER_USERDATA=$8000004A, + PLAYER_ID=$8000004B, + PLAYER_EXTSYNC=$8000004E, + PLAYER_ERRORCODE=$8000004F, + PM_TICK=0, + PM_STATE=1, + PM_POSITION=2, + PM_SHUTTLE=3 + +OBJECT pmtime + method:LONG + time:LONG +ENDOBJECT + +OBJECT pmstate + method:LONG + oldstate:LONG +ENDOBJECT + +CONST RT_CONDUCTORS=0, + RTE_NOMEMORY=$321, + RTE_NOCONDUCTOR=$322, + RTE_NOTIMER=$323, + RTE_PLAYING=$324 + +OBJECT realtimebase + lib:lib + reserved0[2]:ARRAY + time:LONG + timefrac:LONG + reserved1:INT + tickerr:INT +ENDOBJECT + +CONST REALTIME_TICKERR_MIN=-$2C1, + REALTIME_TICKERR_MAX=$2C1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/libraries/translator.e b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/translator.e new file mode 100644 index 0000000..6e8a3b4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/libraries/translator.e @@ -0,0 +1,7 @@ +OPT MODULE +OPT EXPORT + +CONST TR_NOTUSED=-1, + TR_NOMEM=-2, + TR_MAKEBAD=-4 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/font.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/font.e new file mode 100644 index 0000000..34f5376 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/font.e @@ -0,0 +1,23 @@ +OPT MODULE +OPT EXPORT + +MODULE 'graphics/text' + +CONST ID_FONT=$464F4E54, + FONTNAMESIZE=$80 + +OBJECT fontprefs + reserved[3]:ARRAY OF LONG + reserved2:INT + type:INT -> This is unsigned + frontpen:CHAR + backpen:CHAR + drawmode:CHAR + textattr:textattr + name[$80]:ARRAY +ENDOBJECT /* SIZEOF=155 */ + +CONST FP_WBFONT=0, + FP_SYSFONT=1, + FP_SCREENFONT=2 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/icontrol.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/icontrol.e new file mode 100644 index 0000000..8d885ef --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/icontrol.e @@ -0,0 +1,27 @@ +OPT MODULE +OPT EXPORT + +CONST ID_ICTL=$4943544C + +OBJECT icontrolprefs + reserved[4]:ARRAY OF LONG + timeout:INT -> This is unsigned + metadrag:INT + flags:LONG + wbtofront:CHAR + fronttoback:CHAR + reqtrue:CHAR + reqfalse:CHAR +ENDOBJECT /* SIZEOF=28 */ + +CONST ICB_COERCE_COLORS=0, + ICB_COERCE_LACE=1, + ICB_STRGAD_FILTER=2, + ICB_MENUSNAP=3, + ICB_MODEPROMOTE=4, + ICF_COERCE_COLORS=1, + ICF_COERCE_LACE=2, + ICF_STRGAD_FILTER=4, + ICF_MENUSNAP=8, + ICF_MODEPROMOTE=16 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/input.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/input.e new file mode 100644 index 0000000..4bf8fa7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/input.e @@ -0,0 +1,16 @@ +OPT MODULE +OPT EXPORT + +MODULE 'devices/timer' + +CONST ID_INPT=$494E5054 + +OBJECT inputprefs + keymap[16]:ARRAY + pointerticks:INT -> This is unsigned + doubleclick:timeval + keyrptdelay:timeval + keyrptspeed:timeval + mouseaccel:INT +ENDOBJECT /* SIZEOF=44 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/locale.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/locale.e new file mode 100644 index 0000000..ab5c294 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/locale.e @@ -0,0 +1,53 @@ +OPT MODULE +OPT EXPORT + +CONST ID_LCLE=$4C434C45, + ID_CTRY=$43545259 + +OBJECT countryprefs + reserved[4]:ARRAY OF LONG + countrycode:LONG + telephonecode:LONG + measuringsystem:CHAR +-> Um, have to fiddle alignment in .m file + datetimeformat[80]:ARRAY + dateformat[40]:ARRAY + timeformat[40]:ARRAY + shortdatetimeformat[80]:ARRAY + shortdateformat[40]:ARRAY + shorttimeformat[40]:ARRAY + decimalpoint[10]:ARRAY + groupseparator[10]:ARRAY + fracgroupseparator[10]:ARRAY + grouping[10]:ARRAY + fracgrouping[10]:ARRAY + mondecimalpoint[10]:ARRAY + mongroupseparator[10]:ARRAY + monfracgroupseparator[10]:ARRAY + mongrouping[10]:ARRAY + monfracgrouping[10]:ARRAY + monfracdigits:CHAR + monintfracdigits:CHAR + moncs[10]:ARRAY + monsmallcs[10]:ARRAY + monintcs[10]:ARRAY + monpositivesign[10]:ARRAY + monpositivespacesep:CHAR + monpositivesignpos:CHAR + monpositivecspos:CHAR +-> Um, have to fiddle alignment in .m file + monnegativesign[10]:ARRAY + monnegativespacesep:CHAR + monnegativesignpos:CHAR + monnegativecspos:CHAR + calendartype:CHAR +ENDOBJECT /* SIZEOF=504 */ + +OBJECT localeprefs + reserved[4]:ARRAY OF LONG + countryname[32]:ARRAY + preferredlanguages[300]:ARRAY + gmtoffset:LONG + flags:LONG + countrydata:countryprefs +ENDOBJECT /* SIZEOF=860 */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/overscan.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/overscan.e new file mode 100644 index 0000000..6159e62 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/overscan.e @@ -0,0 +1,21 @@ +OPT MODULE +OPT EXPORT + +MODULE 'graphics/gfx' + +CONST ID_OSCN=$4F53434E, + OSCAN_MAGIC=$FEDCBA89 + +OBJECT overscanprefs + reserved:LONG + magic:LONG + hstart:INT -> This is unsigned + hstop:INT -> This is unsigned + vstart:INT -> This is unsigned + vstop:INT -> This is unsigned + displayid:LONG + viewpos:tpoint + text:tpoint + standard:rectangle +ENDOBJECT /* SIZEOF=36 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/palette.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/palette.e new file mode 100644 index 0000000..a8707ec --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/palette.e @@ -0,0 +1,15 @@ +OPT MODULE +OPT EXPORT + +MODULE 'intuition/intuition' + +CONST ID_PALT=$50414C54 + +OBJECT paletteprefs + reserved[4]:ARRAY OF LONG +-> Um, these had illegal names + x4colorpens[32]:ARRAY OF INT + x8colorpens[32]:ARRAY OF INT + colors[32]:ARRAY OF colorspec +ENDOBJECT /* SIZEOF=400 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/pointer.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/pointer.e new file mode 100644 index 0000000..54891d7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/pointer.e @@ -0,0 +1,25 @@ +OPT MODULE +OPT EXPORT + +CONST ID_PNTR=$504E5452 + +OBJECT pointerprefs +-> Um, this was wrong + reserved[4]:ARRAY OF LONG + which:INT -> This is unsigned + size:INT -> This is unsigned + width:INT -> This is unsigned + ieight:INT -> This is unsigned + depth:INT -> This is unsigned + ysize:INT -> This is unsigned + x:INT -> This is unsigned +ENDOBJECT /* SIZEOF=18 */ + +CONST WBP_NORMAL=0, + WBP_BUSY=1 + +OBJECT rgbtable + red:CHAR + green:CHAR + blue:CHAR +ENDOBJECT /* SIZEOF=3 */ diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/prefhdr.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/prefhdr.e new file mode 100644 index 0000000..23a9e5b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/prefhdr.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +CONST ID_PREF=$50524546, + ID_PRHD=$50524844 + +OBJECT prefheader + version:CHAR + type:CHAR + flags:LONG +ENDOBJECT /* SIZEOF=6 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printergfx.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printergfx.e new file mode 100644 index 0000000..e18e08e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printergfx.e @@ -0,0 +1,50 @@ +OPT MODULE +OPT EXPORT + +CONST ID_PGFX=$50474658 + +OBJECT printergfxprefs + reserved[4]:ARRAY OF LONG + aspect:INT -> This is unsigned + shade:INT -> This is unsigned + image:INT -> This is unsigned + threshold:INT + colorcorrect:CHAR + dimensions:CHAR + dithering:CHAR + graphicflags:INT -> This is unsigned + printdensity:CHAR + printmaxwidth:INT -> This is unsigned + printmaxheight:INT -> This is unsigned + printxoffset:CHAR + printyoffset:CHAR +ENDOBJECT /* SIZEOF=36 */ + +CONST PA_HORIZONTAL=0, + PA_VERTICAL=1, + PS_BW=0, + PS_GREYSCALE=1, + PS_COLOR=2, + PS_GREY_SCALE2=3, + PI_POSITIVE=0, + PI_NEGATIVE=1, + PCCB_RED=0, + PCCB_GREEN=1, + PCCB_BLUE=2, + PCCF_RED=1, + PCCF_GREEN=2, + PCCF_BLUE=4, + PD_IGNORE=0, + PD_BOUNDED=1, + PD_ABSOLUTE=2, + PD_PIXEL=3, + PD_MULTIPLY=4, + PD_ORDERED=0, + PD_HALFTONE=1, + PD_FLOYD=2, + PGFB_CENTER_IMAGE=0, + PGFB_INTEGER_SCALING=1, + PGFB_ANTI_ALIAS=2, + PGFF_CENTER_IMAGE=1, + PGFF_INTEGER_SCALING=2, + PGFF_ANTI_ALIAS=4 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printerps.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printerps.e new file mode 100644 index 0000000..5c664d5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printerps.e @@ -0,0 +1,92 @@ +OPT MODULE +OPT EXPORT + +CONST ID_POST=$50535044 + +OBJECT printerpsprefs + reserved[4]:ARRAY OF LONG + drivermode:CHAR + paperformat:CHAR + reserved1[2]:ARRAY + copies:LONG + paperwidth:LONG + paperheight:LONG + horizontaldpi:LONG + verticaldpi:LONG + font:CHAR + pitch:CHAR + orientation:CHAR + tab:CHAR + reserved2[8]:ARRAY + leftmargin:LONG + rightmargin:LONG + topmargin:LONG + bottommargin:LONG + fontpointsize:LONG + leading:LONG + reserved3[8]:ARRAY + leftedge:LONG + topedge:LONG + width:LONG + height:LONG + image:CHAR + shading:CHAR + dithering:CHAR + reserved4a:CHAR + reserved4[8]:ARRAY + aspect:CHAR + scalingtype:CHAR + reserved5:CHAR + centering:CHAR + reserved6[8]:ARRAY +ENDOBJECT /* SIZEOF=124 */ + +CONST DM_POSTSCRIPT=0, + DM_PASSTHROUGH=1, + PF_USLETTER=0, + PF_USLEGAL=1, + PF_A4=2, + PF_CUSTOM=3, + FONT_COURIER=0, + FONT_TIMES=1, + FONT_HELVETICA=2, + FONT_HELV_NARROW=3, + FONT_AVANTGARDE=4, + FONT_BOOKMAN=5, + FONT_NEWCENT=6, + FONT_PALATINO=7, + FONT_ZAPFCHANCERY=8, + PITCH_NORMAL=0, + PITCH_COMPRESSED=1, + PITCH_EXPANDED=2, + ORIENT_PORTRAIT=0, + ORIENT_LANDSCAPE=1, + TAB_4=0, + TAB_8=1, + TAB_QUART=2, + TAB_HALF=3, + TAB_INCH=4, + IM_POSITIVE=0, + IM_NEGATIVE=1, + SHAD_BW=0, + SHAD_GREYSCALE=1, + SHAD_COLOR=2, + DITH_DEFAULT=0, + DITH_DOTTY=1, + DITH_VERT=2, + DITH_HORIZ=3, + DITH_DIAG=4, + ASP_HORIZ=0, + ASP_VERT=1, + ST_ASPECT_ASIS=0, + ST_ASPECT_WIDE=1, + ST_ASPECT_TALL=2, + ST_ASPECT_BOTH=3, + ST_FITS_WIDE=4, + ST_FITS_TALL=5, + ST_FITS_BOTH=6, + CENT_NONE=0, + CENT_HORIZ=1, + CENT_VERT=2, + CENT_BOTH=3 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printertxt.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printertxt.e new file mode 100644 index 0000000..42d20d6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/printertxt.e @@ -0,0 +1,56 @@ +OPT MODULE +OPT EXPORT + +CONST ID_PTXT=$50545854, + ID_PUNT=$50554E54, + DRIVERNAMESIZE=30, + DEVICENAMESIZE=$20 + +OBJECT printertxtprefs + reserved[4]:ARRAY OF LONG + driver[30]:ARRAY + port:CHAR + papertype:INT -> This is unsigned + papersize:INT -> This is unsigned + paperlength:INT -> This is unsigned + pitch:INT -> This is unsigned + spacing:INT -> This is unsigned + leftmargin:INT -> This is unsigned + rightmargin:INT -> This is unsigned + quality:INT -> This is unsigned +ENDOBJECT /* SIZEOF=63 */ + +CONST PP_PARALLEL=0, + PP_SERIAL=1, + PT_FANFOLD=0, + PT_SINGLE=1, + PS_US_LETTER=0, + PS_US_LEGAL=1, + PS_N_TRACTOR=2, + PS_W_TRACTOR=3, + PS_CUSTOM=4, + PS_EURO_A0=5, + PS_EURO_A1=6, + PS_EURO_A2=7, + PS_EURO_A3=8, + PS_EURO_A4=9, + PS_EURO_A5=10, + PS_EURO_A6=11, + PS_EURO_A7=12, + PS_EURO_A8=13, + PP_PICA=0, + PP_ELITE=1, + PP_FINE=2, + PS_SIX_LPI=0, + PS_EIGHT_LPI=1, + PQ_DRAFT=0, + PQ_LETTER=1 + +OBJECT printerunitprefs +-> Um, this was wrong + reserved[4]:ARRAY OF LONG + unitnum:LONG + opendeviceflags:LONG + devicename[$20]:ARRAY +ENDOBJECT /* SIZEOF=44 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/screenmode.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/screenmode.e new file mode 100644 index 0000000..d42e83d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/screenmode.e @@ -0,0 +1,17 @@ +OPT MODULE +OPT EXPORT + +CONST ID_SCRM=$5343524D + +OBJECT screenmodeprefs + reserved[4]:ARRAY OF LONG + displayid:LONG + width:INT -> This is unsigned + height:INT -> This is unsigned + depth:INT -> This is unsigned + control:INT -> This is unsigned +ENDOBJECT /* SIZEOF=28 */ + +CONST SMB_AUTOSCROLL=0, + SMF_AUTOSCROLL=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/serial.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/serial.e new file mode 100644 index 0000000..52a4bef --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/serial.e @@ -0,0 +1,27 @@ +OPT MODULE +OPT EXPORT + +CONST ID_SERL=$5345524C + +OBJECT serialprefs + reserved[3]:ARRAY OF LONG + unit0map:LONG + baudrate:LONG + inputbuffer:LONG + outputbuffer:LONG + inputhandshake:CHAR + outputhandshake:CHAR + parity:CHAR + bitsperchar:CHAR + stopbits:CHAR +ENDOBJECT /* SIZEOF=33 */ + +CONST PARITY_NONE=0, + PARITY_EVEN=1, + PARITY_ODD=2, + PARITY_MARK=3, + PARITY_SPACE=4, + HSHAKE_XON=0, + HSHAKE_RTS=1, + HSHAKE_NONE=2 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/sound.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/sound.e new file mode 100644 index 0000000..c7970d0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/sound.e @@ -0,0 +1,19 @@ +OPT MODULE +OPT EXPORT + +CONST ID_SOND=$534F4E44 + +OBJECT soundprefs + reserved[4]:ARRAY OF LONG + displayqueue:INT + audioqueue:INT + audiotype:INT -> This is unsigned + audiovolume:INT -> This is unsigned + audioperiod:INT -> This is unsigned + audioduration:INT -> This is unsigned + audiofilename[256]:ARRAY +ENDOBJECT /* SIZEOF=284 */ + +CONST SPTYPE_BEEP=0, + SPTYPE_SAMPLE=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/prefs/wbpattern.e b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/wbpattern.e new file mode 100644 index 0000000..5da2097 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/prefs/wbpattern.e @@ -0,0 +1,24 @@ +OPT MODULE +OPT EXPORT + +CONST ID_PTRN=$5054524E + +OBJECT wbpatternprefs + reserved[4]:ARRAY OF LONG + which:INT -> This is unsigned + flags:INT -> This is unsigned + revision:CHAR + depth:CHAR + datalength:INT -> This is unsigned +ENDOBJECT /* SIZEOF=24 */ + +CONST WBP_ROOT=0, + WBP_DRAWER=1, + WBP_SCREEN=2, + WBPF_PATTERN=1, + WBPF_NOREMAP=16, + MAXDEPTH=3, + DEFPATDEPTH=2, + PAT_WIDTH=16, + PAT_HEIGHT=16 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/battclock.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battclock.e new file mode 100644 index 0000000..04c566b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battclock.e @@ -0,0 +1,6 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define BATTCLOCKNAME 'battclock.resource' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmem.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmem.e new file mode 100644 index 0000000..0d4ee6d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmem.e @@ -0,0 +1,6 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define BATTMEMNAME 'battmem.resource' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsamiga.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsamiga.e new file mode 100644 index 0000000..35ec375 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsamiga.e @@ -0,0 +1,10 @@ +OPT MODULE +OPT EXPORT + +CONST BATTMEM_AMIGA_AMNESIA_ADDR=0, + BATTMEM_AMIGA_AMNESIA_LEN=1, + BATTMEM_SCSI_TIMEOUT_ADDR=1, + BATTMEM_SCSI_TIMEOUT_LEN=1, + BATTMEM_SCSI_LUNS_ADDR=2, + BATTMEM_SCSI_LUNS_LEN=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsshared.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsshared.e new file mode 100644 index 0000000..5ee5942 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/battmembitsshared.e @@ -0,0 +1,14 @@ +OPT MODULE +OPT EXPORT + +CONST BATTMEM_SHARED_AMNESIA_ADDR=$40, + BATTMEM_SHARED_AMNESIA_LEN=1, + BATTMEM_SCSI_HOST_ID_ADDR=$41, + BATTMEM_SCSI_HOST_ID_LEN=3, + BATTMEM_SCSI_SYNC_XFER_ADDR=$44, + BATTMEM_SCSI_SYNC_XFER_LEN=1, + BATTMEM_SCSI_FAST_SYNC_ADDR=$45, + BATTMEM_SCSI_FAST_SYNC_LEN=1, + BATTMEM_SCSI_TAG_QUEUES_ADDR=$46, + BATTMEM_SCSI_TAG_QUEUES_LEN=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/card.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/card.e new file mode 100644 index 0000000..8ddf10b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/card.e @@ -0,0 +1,96 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/interrupts', + 'exec/nodes' + +#define CARDRESNAME 'card.resource' + +OBJECT cardhandle + cardnode:ln + cardremoved:PTR TO is + cardinserted:PTR TO is + cardstatus:PTR TO is + cardflags:CHAR +ENDOBJECT /* SIZEOF=27 */ + +OBJECT devicetdata + dtsize:LONG + dtspeed:LONG + dttype:CHAR + dtflags:CHAR +ENDOBJECT /* SIZEOF=10 */ + +OBJECT cardmemorymap + commonmemory:PTR TO CHAR + attributememory:PTR TO CHAR + iomemory:PTR TO CHAR + commonmemsize:LONG + attributememsize:LONG + iomemsize:LONG +ENDOBJECT /* SIZEOF=12 */ + +CONST CARDB_RESETREMOVE=0, + CARDF_RESETREMOVE=1, + CARDB_IFAVAILABLE=1, + CARDF_IFAVAILABLE=2, + CARDB_DELAYOWNERSHIP=2, + CARDF_DELAYOWNERSHIP=4, + CARDB_POSTSTATUS=3, + CARDF_POSTSTATUS=8, + CARDB_REMOVEHANDLE=0, + CARDF_REMOVEHANDLE=1, + CARD_STATUSB_CCDET=6, + CARD_STATUSF_CCDET=$40, + CARD_STATUSB_BVD1=5, + CARD_STATUSF_BVD1=$20, + CARD_STATUSB_SC=5, + CARD_STATUSF_SC=$20, + CARD_STATUSB_BVD2=4, + CARD_STATUSF_BVD2=16, + CARD_STATUSB_DA=4, + CARD_STATUSF_DA=16, + CARD_STATUSB_WR=3, + CARD_STATUSF_WR=8, + CARD_STATUSB_BSY=2, + CARD_STATUSF_BSY=4, + CARD_STATUSB_IRQ=2, + CARD_STATUSF_IRQ=4, + CARD_VOLTAGE_0V=0, + CARD_VOLTAGE_5V=1, + CARD_VOLTAGE_12V=2, + CARD_ENABLEB_DIGAUDIO=1, + CARD_ENABLEF_DIGAUDIO=2, + CARD_DISABLEB_WP=3, + CARD_DISABLEF_WP=8, + CARD_INTERFACE_AMIGA_0=0, + CARD_INTB_SETCLR=7, + CARD_INTF_SETCLR=128, + CARD_INTB_BVD1=5, + CARD_INTF_BVD1=32, + CARD_INTB_SC=5, + CARD_INTF_SC=32, + CARD_INTB_BVD2=4, + CARD_INTF_BVD2=16, + CARD_INTB_DA=4, + CARD_INTF_DA=16, + CARD_INTB_BSY=2, + CARD_INTF_BSY=4, + CARD_INTB_IRQ=2, + CARD_INTF_IRQ=4, + CISTPL_AMIGAXIP=$91 + +OBJECT amigaxip +-> Um, this was all wrong + code:CHAR + link:CHAR + xiploc[4]:ARRAY + xipflags:CHAR + xipresrv:CHAR +ENDOBJECT /* SIZEOF=8 */ + +CONST XIPFLAGB_AUTORUN=0, + XIPFLAGF_AUTORUN=1 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/cia.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/cia.e new file mode 100644 index 0000000..0191e55 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/cia.e @@ -0,0 +1,7 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +#define CIAANAME 'ciaa.resource' +#define CIABNAME 'ciab.resource' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/disk.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/disk.e new file mode 100644 index 0000000..0007153 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/disk.e @@ -0,0 +1,57 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/interrupts', + 'exec/libraries', + 'exec/lists', + 'exec/ports', + 'exec/tasks' + +OBJECT discresourceunit + mn:mn + discblock:is + discsync:is + index:is +ENDOBJECT /* SIZEOF=86 */ + +OBJECT discresource + lib:lib + current:PTR TO discresourceunit + flags:CHAR + pad:CHAR + syslib:PTR TO lib + ciaresource:PTR TO lib + unitid[4]:ARRAY OF LONG + waiting:lh + discblock:is + discsync:is + index:is + currtask:PTR TO tc +ENDOBJECT /* SIZEOF=148 */ + +#define DISKNAME 'disk.resource' + +CONST DRB_ALLOC0=0, + DRB_ALLOC1=1, + DRB_ALLOC2=2, + DRB_ALLOC3=3, + DRB_ACTIVE=7, + DRF_ALLOC0=1, + DRF_ALLOC1=2, + DRF_ALLOC2=4, + DRF_ALLOC3=8, + DRF_ACTIVE=$80, + DSKDMAOFF=$4000, + DR_ALLOCUNIT=-6, + DR_FREEUNIT=-$c, + DR_GETUNIT=-$12, + DR_GIVEUNIT=-$18, + DR_GETUNITID=-$1e, + DR_READUNITID=-$24, + DR_LASTCOMM=$FFFFFFDC, + DRT_AMIGA=0, + DRT_37422D2S=$55555555, + DRT_EMPTY=-1, + DRT_150RPM=$AAAAAAAA diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/filesysres.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/filesysres.e new file mode 100644 index 0000000..c00a4df --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/filesysres.e @@ -0,0 +1,32 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/lists', + 'exec/nodes', + 'exec/tasks' + +OBJECT filesysresource + ln:ln + creator:PTR TO CHAR + filesysentries:lh +ENDOBJECT /* SIZEOF=32 */ + +OBJECT filesysentry + ln:ln + dostype:LONG + version:LONG + patchflags:LONG + type:LONG + task:PTR TO tc + lock:LONG + handler:PTR TO CHAR + stacksize:LONG + priority:LONG + startup:LONG + seglist:LONG + globalvec:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +#define FSRNAME 'FileSystem.resource' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/mathresource.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/mathresource.e new file mode 100644 index 0000000..89b84b6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/mathresource.e @@ -0,0 +1,24 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +OBJECT mathieeeresourceresource + node:ln + flags:INT -> This is unsigned + baseaddr:PTR TO INT -> The target is unsigned + dblbasinit:LONG + dbltransinit:LONG + sglbasinit:LONG + sgltransinit:LONG + extbasinit:LONG + exttransinit:LONG +ENDOBJECT /* SIZEOF=44 */ + +CONST MATHIEEERESOURCEF_DBLBAS=1, + MATHIEEERESOURCEF_DBLTRANS=2, + MATHIEEERESOURCEF_SGLBAS=4, + MATHIEEERESOURCEF_SGLTRANS=8, + MATHIEEERESOURCEF_EXTBAS=16, + MATHIEEERESOURCEF_EXTTRANS=$20 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/misc.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/misc.e new file mode 100644 index 0000000..6a96ae7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/misc.e @@ -0,0 +1,13 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +CONST MR_SERIALPORT=0, + MR_SERIALBITS=1, + MR_PARALLELPORT=2, + MR_PARALLELBITS=3, + MR_ALLOCMISCRESOURCE=-6, + MR_FREEMISCRESOURCE=-$c + +#define MISCNAME 'misc.resource' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/resources/potgo.e b/amigae33a/E_v3.3a/Src/Src/Modules/resources/potgo.e new file mode 100644 index 0000000..519ae3b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/resources/potgo.e @@ -0,0 +1,8 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +CONST RESOURCES_POTGO_I=1 + +#define POTGONAME 'potgo.resource' diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/rexx/errors.e b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/errors.e new file mode 100644 index 0000000..d19b988 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/errors.e @@ -0,0 +1,55 @@ +OPT MODULE +OPT EXPORT + +CONST ERRC_MSG=0, + ERR10_001=1, + ERR10_002=2, + ERR10_003=3, + ERR10_005=5, + ERR10_006=6, + ERR10_008=8, + ERR10_009=9, + ERR10_010=10, + ERR10_011=11, + ERR10_012=12, + ERR10_013=13, + ERR10_014=14, + ERR10_015=15, + ERR10_016=16, + ERR10_017=17, + ERR10_018=18, + ERR10_019=19, + ERR10_020=20, + ERR10_021=21, + ERR10_022=22, + ERR10_023=23, + ERR10_024=24, + ERR10_025=25, + ERR10_026=26, + ERR10_027=27, + ERR10_028=28, + ERR10_029=29, + ERR10_030=30, + ERR10_031=31, + ERR10_032=$20, + ERR10_033=$21, + ERR10_034=$22, + ERR10_035=$23, + ERR10_036=$24, + ERR10_037=$25, + ERR10_039=$27, + ERR10_040=$28, + ERR10_041=$29, + ERR10_042=$2A, + ERR10_043=$2B, + ERR10_044=$2C, + ERR10_045=$2D, + ERR10_046=$2E, + ERR10_047=$2F, + ERR10_048=$30, + RC_FAIL=-1, + RC_OK=0, + RC_WARN=5, + RC_ERROR=10, + RC_FATAL=20 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/rexx/rexxio.e b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/rexxio.e new file mode 100644 index 0000000..2bfc06e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/rexxio.e @@ -0,0 +1,52 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/lists', + 'exec/ports', + 'rexx/storage' + +CONST RXBUFFSZ=$CC + +OBJECT iobuff +-> Um, this was all wrong + node:rexxrsrc + rpt:LONG + rct:LONG + dfh:LONG + lock:LONG + bct:LONG + area[$CC]:ARRAY +ENDOBJECT /* SIZEOF=256 */ + +CONST IOBNAME=10, + IOBMODE=24, + IOBEOF=25, + IOBPOS=28, + RXIO_EXIST=-1, + RXIO_STRF=0, + RXIO_READ=1, + RXIO_WRITE=2, + RXIO_APPEND=3, + RXIO_BEGIN=-1, + RXIO_CURR=0, + RXIO_END=1 + +#define LLOFFSET(rrp) (rrp::rexxrsrc.arg1) +#define LLVERS(rrp) (rrp::rexxrsrc.arg2) +#define CLVALUE(rrp) (rrp::rexxrsrc.arg1) + +OBJECT rexxmsgport +-> Um, this was all wrong + rrsizeof:rexxrsrc + port:mp + replylist:lh +ENDOBJECT /* SIZEOF=80 */ + +CONST DT_DEV=0, + DT_DIR=1, + DT_VOL=2, + ACTION_STACK=$7D2, + ACTION_QUEUE=$7D3 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/rexx/rxslib.e b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/rxslib.e new file mode 100644 index 0000000..fd54ae4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/rxslib.e @@ -0,0 +1,85 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/libraries', + 'exec/lists', + 'exec/ports', + 'rexx/storage' + +#define RXSNAME 'rexxsyslib.library' +#define RXSDIR 'REXX' +#define RXSTNAME 'ARexx' + +OBJECT rxslib + lib:lib + flags:CHAR + shadow:CHAR + sysbase:LONG + dosbase:LONG + ieeedpbase:LONG + seglist:LONG + nil:LONG + chunk:LONG + maxnest:LONG + null:PTR TO nexxstr + false:PTR TO nexxstr + true:PTR TO nexxstr + rexx:PTR TO nexxstr + command:PTR TO nexxstr + stdin:PTR TO nexxstr + stdout:PTR TO nexxstr + stderr:PTR TO nexxstr + version:PTR TO CHAR + taskname:PTR TO CHAR + taskpri:LONG + taskseg:LONG + stacksize:LONG + rexxdir:PTR TO CHAR + ctable:PTR TO CHAR + notice:PTR TO CHAR + rexxport:mp + readlock:INT -> This is unsigned + tracefh:LONG + tasklist:lh + numtask:INT + liblist:lh + numlib:INT + cliplist:lh + numclip:INT + msglist:lh + nummsg:INT + pgmlist:lh + numpgm:INT + tracecnt:INT -> This is unsigned + avail:INT +ENDOBJECT /* SIZEOF=252 */ + +CONST RLFB_TRACE=0, + RLFB_HALT=1, + RLFB_SUSP=2, + RLFB_STOP=6, + RLFB_CLOSE=7, + RLFMASK=7, + RXSCHUNK=$400, + RXSNEST=$20, + RXSTPRI=0, + RXSSTACK=$1000, + CTB_SPACE=0, + CTB_DIGIT=1, + CTB_ALPHA=2, + CTB_REXXSYM=3, + CTB_REXXOPR=4, + CTB_REXXSPC=5, + CTB_UPPER=6, + CTB_LOWER=7, + CTF_SPACE=1, + CTF_DIGIT=2, + CTF_ALPHA=4, + CTF_REXXSYM=8, + CTF_REXXOPR=16, + CTF_REXXSPC=$20, + CTF_UPPER=$40, + CTF_LOWER=$80 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/rexx/storage.e b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/storage.e new file mode 100644 index 0000000..1d7278f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/rexx/storage.e @@ -0,0 +1,160 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/lists', + 'exec/nodes', + 'exec/ports' + +OBJECT nexxstr + ivalue:LONG + length:INT -> This is unsigned + flags:CHAR + hash:CHAR + buff[8]:ARRAY +ENDOBJECT /* SIZEOF=16 */ + +#define IVALUE(nsptr) (nsptr::nexxstr.ivalue) + +CONST NXADDLEN=9, + NSB_KEEP=0, + NSB_STRING=1, + NSB_NOTNUM=2, + NSB_NUMBER=3, + NSB_BINARY=4, + NSB_FLOAT=5, + NSB_EXT=6, + NSB_SOURCE=7, + NSF_KEEP=1, + NSF_STRING=2, + NSF_NOTNUM=4, + NSF_NUMBER=8, + NSF_BINARY=16, + NSF_FLOAT=$20, + NSF_EXT=$40, + NSF_SOURCE=$80, + NSF_INTNUM=26, + NSF_DPNUM=$28, + NSF_ALPHA=6, + NSF_OWNED=$C1, + KEEPSTR=$86, + KEEPNUM=$9A + +OBJECT rexxarg + size:LONG + length:INT -> This is unsigned + flags:CHAR + hash:CHAR + buff[8]:ARRAY +ENDOBJECT /* SIZEOF=16 */ + +OBJECT rexxmsg + mn:mn + taskblock:LONG + libbase:LONG + action:LONG + result1:LONG + result2:LONG + args[16]:ARRAY OF LONG + passport:PTR TO mp + commaddr:PTR TO CHAR + fileext:PTR TO CHAR + stdin:LONG + stdout:LONG + avail:LONG +ENDOBJECT /* SIZEOF=128 */ + +#define ARG0(rmp) (rmp::rexxmsg.args[0]) +#define ARG1(rmp) (rmp::rexxmsg.args[1]) +#define ARG2(rmp) (rmp::rexxmsg.args[2]) + +CONST ACTION=28, + RESULT1=$20, + RESULT2=$24, + MAXRMARG=15, + RXCOMM=$1000000, + RXFUNC=$2000000, + RXCLOSE=$3000000, + RXQUERY=$4000000, + RXADDFH=$7000000, + RXADDLIB=$8000000, + RXREMLIB=$9000000, + RXADDCON=$A000000, + RXREMCON=$B000000, + RXTCOPN=$C000000, + RXTCCLS=$D000000, + RXFB_NOIO=16, + RXFB_RESULT=17, + RXFB_STRING=18, + RXFB_TOKEN=19, + RXFB_NONRET=20, + RXFF_RESULT=$20000, + RXFF_STRING=$40000, + RXFF_TOKEN=$80000, + RXFF_NONRET=$100000, + RXCODEMASK=$FF000000, + RXARGMASK=15 + +OBJECT rexxrsrc + ln:ln + func:INT + base:LONG + size:LONG + arg1:PTR TO CHAR + arg2:LONG +ENDOBJECT /* SIZEOF=32 */ + +CONST RRTYPE=8, + RRNAME=10, + RRSIZE=20, + RRT_ANY=0, + RRT_LIB=1, + RRT_PORT=2, + RRT_FILE=3, + RRT_HOST=4, + RRT_CLIP=5, + GLOBALSZ=$C8 + +OBJECT rexxtask + global[$C8]:ARRAY + msgport:mp + flags:CHAR + sigbit:CHAR -> This is signed + clientid:LONG + msgpkt:LONG + taskid:LONG + port:LONG + errtrap:LONG + stackptr:LONG + header1:lh + header2:lh + header3:lh + header4:lh + header5:lh +ENDOBJECT /* SIZEOF=330 */ + +CONST ENVLIST=$104, + FREELIST=$112, + MEMLIST=$120, + FILELIST=$12E, + PORTLIST=$13C, + NUMLISTS=5, + RTFB_TRACE=0, + RTFB_HALT=1, + RTFB_SUSP=2, + RTFB_TCUSE=3, + RTFB_WAIT=6, + RTFB_CLOSE=7, + MEMQUANT=16, + MEMMASK=-16, + MEMQUICK=1, + MEMCLEAR=$10000 + +OBJECT srcnode + succ:PTR TO srcnode + pred:PTR TO srcnode + ptr:LONG + size:LONG +ENDOBJECT /* SIZEOF=16 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/utility/date.e b/amigae33a/E_v3.3a/Src/Src/Modules/utility/date.e new file mode 100644 index 0000000..76b4f4a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/utility/date.e @@ -0,0 +1,13 @@ +OPT MODULE +OPT EXPORT + +OBJECT clockdata + sec:INT -> This is unsigned + min:INT -> This is unsigned + hour:INT -> This is unsigned + mday:INT -> This is unsigned + month:INT -> This is unsigned + year:INT -> This is unsigned + wday:INT -> This is unsigned +ENDOBJECT /* SIZEOF=14 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/utility/hooks.e b/amigae33a/E_v3.3a/Src/Src/Modules/utility/hooks.e new file mode 100644 index 0000000..3075e6c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/utility/hooks.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/nodes' + +OBJECT hook + mln:mln + entry:LONG + subentry:LONG + data:LONG +ENDOBJECT /* SIZEOF=20 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/utility/name.e b/amigae33a/E_v3.3a/Src/Src/Modules/utility/name.e new file mode 100644 index 0000000..125d258 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/utility/name.e @@ -0,0 +1,18 @@ +OPT MODULE +OPT EXPORT + +CONST UTILITY_NAME_I=1 + +OBJECT namedobject + object:LONG +ENDOBJECT /* SIZEOF=NONE !!! */ + +CONST ANO_NAMESPACE=$FA0, + ANO_USERSPACE=$FA1, + ANO_PRIORITY=$FA2, + ANO_FLAGS=$FA3, + NSB_NODUPS=0, + NSB_CASE=1, + NSF_NODUPS=1, + NSF_CASE=2 + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/utility/pack.e b/amigae33a/E_v3.3a/Src/Src/Modules/utility/pack.e new file mode 100644 index 0000000..58a9703 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/utility/pack.e @@ -0,0 +1,23 @@ +OPT MODULE +OPT EXPORT + +CONST UTILITY_PACK_I=1, + PSTB_SIGNED=31, + PSTB_UNPACK=30, + PSTB_PACK=29, + PSTB_EXISTS=26, + PSTF_SIGNED=$80000000, + PSTF_UNPACK=$40000000, + PSTF_PACK=$20000000, + PSTF_EXISTS=$4000000, + PKCTRL_PACKUNPACK=0, + PKCTRL_PACKONLY=$40000000, + PKCTRL_UNPACKONLY=$20000000, + PKCTRL_BYTE=$80000000, + PKCTRL_WORD=$88000000, + PKCTRL_LONG=$90000000, + PKCTRL_UBYTE=0, + PKCTRL_UWORD=$8000000, + PKCTRL_ULONG=$10000000, + PKCTRL_BIT=$18000000, + PKCTRL_FLIPBIT=$98000000 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/utility/tagitem.e b/amigae33a/E_v3.3a/Src/Src/Modules/utility/tagitem.e new file mode 100644 index 0000000..1a80ee4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/utility/tagitem.e @@ -0,0 +1,18 @@ +OPT MODULE +OPT EXPORT + +OBJECT tagitem + tag:LONG + data:LONG +ENDOBJECT /* SIZEOF=8 */ + +CONST TAG_DONE=0, + TAG_END=0, + TAG_IGNORE=1, + TAG_MORE=2, + TAG_SKIP=3, + TAG_USER=$80000000, + TAGFILTER_AND=0, + TAGFILTER_NOT=1, + MAP_REMOVE_NOT_FOUND=0, + MAP_KEEP_NOT_FOUND=1 diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/utility/utility.e b/amigae33a/E_v3.3a/Src/Src/Modules/utility/utility.e new file mode 100644 index 0000000..6b96049 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/utility/utility.e @@ -0,0 +1,15 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/libraries' + +#define UTILITYNAME 'utility.library' + +OBJECT utilitybase + lib:lib + language:CHAR + reserved:CHAR +ENDOBJECT /* SIZEOF=NONE !!! */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/workbench/startup.e b/amigae33a/E_v3.3a/Src/Src/Modules/workbench/startup.e new file mode 100644 index 0000000..29bb6f0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/workbench/startup.e @@ -0,0 +1,21 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/ports' + +CONST WORKBENCH_STARTUP_I=1 + +OBJECT wbstartup + message:mn + process:PTR TO mp + segment:LONG + numargs:LONG + toolwindow:PTR TO CHAR + arglist:PTR TO wbarg +ENDOBJECT /* SIZEOF=40 */ + +OBJECT wbarg + lock:LONG + name:PTR TO CHAR +ENDOBJECT /* SIZEOF=8 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Modules/workbench/workbench.e b/amigae33a/E_v3.3a/Src/Src/Modules/workbench/workbench.e new file mode 100644 index 0000000..58248f2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Modules/workbench/workbench.e @@ -0,0 +1,102 @@ +OPT MODULE +OPT EXPORT + +OPT PREPROCESS + +MODULE 'exec/lists', + 'exec/ports', + 'intuition/intuition', + 'workbench/startup' + +CONST WORKBENCH_WORKBENCH_I=1, + WBDISK=1, + WBDRAWER=2, + WBTOOL=3, + WBPROJECT=4, + WBGARBAGE=5, + WBDEVICE=6, + WBKICK=7, + WBAPPICON=8 + +-> Um, this object was missing +OBJECT olddrawerdata + newwindow:nw + currentx:LONG + currenty:LONG +ENDOBJECT + +CONST OLDDRAWERDATAFILESIZE=$38 + +OBJECT drawerdata + newwindow:nw + currentx:LONG + currenty:LONG + flags:LONG + viewmodes:INT -> This is unsigned +ENDOBJECT /* SIZEOF=62 */ + +CONST DRAWERDATAFILESIZE=$3E + +OBJECT diskobject + magic:INT -> This is unsigned + version:INT -> This is unsigned + gadget:gadget + type:CHAR + pad_byte:CHAR + defaulttool:PTR TO CHAR + tooltypes:PTR TO LONG + currentx:LONG + currenty:LONG + drawerdata:PTR TO drawerdata + toolwindow:PTR TO CHAR + stacksize:LONG +ENDOBJECT /* SIZEOF=78 */ + +CONST WB_DISKMAGIC=$E310, + WB_DISKVERSION=1, + WB_DISKREVISION=1, + WB_DISKREVISIONMASK=$FF + +OBJECT freelist + numfree:INT + memlist:lh +ENDOBJECT /* SIZEOF=16 */ + +CONST GFLG_GADGBACKFILL=1, + GADGBACKFILL=1, + NO_ICON_POSITION=$80000000, + AM_VERSION=1, + AMTYPE_APPWINDOW=7, + AMTYPE_APPICON=8, + AMTYPE_APPMENUITEM=9 + +#define WORKBENCH_NAME 'workbench.library' + +OBJECT appmessage + message:mn + type:INT -> This is unsigned + userdata:LONG + id:LONG + numargs:LONG + arglist:PTR TO wbarg + version:INT -> This is unsigned + class:INT -> This is unsigned + mousex:INT + mousey:INT + seconds:LONG + micros:LONG + reserved[8]:ARRAY OF LONG +ENDOBJECT /* SIZEOF=62 */ + +OBJECT appwindow + private:LONG +ENDOBJECT /* SIZEOF=0 */ + +OBJECT appicon + private:LONG +ENDOBJECT /* SIZEOF=0 */ + +OBJECT appmenuitem + private:LONG +ENDOBJECT /* SIZEOF=0 */ + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/er.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/er.e new file mode 100644 index 0000000..9803fac --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/er.e @@ -0,0 +1,72 @@ +/* + +Just opens a tiny window and rotates a line. Use it to see if your +kite's still running :) + +*/ + +OPT PREPROCESS + +MODULE 'oomodules/coordinate/line', 'oomodules/coordinate', 'intuition/intuition', + 'oomodules/sort/numbers/float' + +#define NULL_X (30) +#define NULL_Y (15) + +DEF hauptwin:PTR TO window, /* Hauptfenster */ + meineintmessage:PTR TO intuimessage /* Kopie der intmsg */ + + + +PROC main() +DEF coo:PTR TO coordinate,co2:PTR TO coordinate, + line:PTR TO line,flt:PTR TO float + + NEW coo.new(["set",0.0,0.0,0.0]) + NEW co2.new(["set",30.0,30.0,0.0]) + + NEW flt.new() + flt.set(2.0) + + NEW line.new() + + line.setStart(coo) + + line.setEnd(coo) + line.end.shift(co2) + + co2.x.neg() + co2.y.neg() + co2.z.neg() + line.shift(co2) + + hauptwin := OpenWindowTagList(NIL, + [WA_TITLE,'ER', + WA_IDCMP,IDCMP_RAWKEY OR IDCMP_CLOSEWINDOW OR IDCMP_MOUSEMOVE OR IDCMP_GADGETUP OR IDCMP_GADGETDOWN OR IDCMP_MOUSEBUTTONS OR IDCMP_MENUPICK OR IDCMP_REFRESHWINDOW, + WA_FLAGS,WFLG_ACTIVATE+WFLG_CLOSEGADGET+WFLG_DRAGBAR+WFLG_DEPTHGADGET, + WA_INNERWIDTH, 90, WA_INNERHEIGHT, 50, + WA_REPORTMOUSE,TRUE,WA_GIMMEZEROZERO,TRUE,NIL]) + + SetStdRast(hauptwin.rport) + + REPEAT + meineintmessage := GetMsg(hauptwin.userport) + + line.rotateZ(3.0) + + line.x.add(flt) +-> line.y.substract(flt) + + Line(NULL_X+(!line.getX()!/2),NULL_Y+(!line.getY()!/4), + NULL_X+(!line.end.getX()!/2) ,NULL_Y+(!line.end.getY()!/4)) + WaitTOF() + Line(NULL_X+(!line.getX()!/2),NULL_Y+(!line.getY()!/4), + NULL_X+(!line.end.getX()!/2) ,NULL_Y+(!line.end.getY()!/4),0) + + UNTIL (meineintmessage.class = IDCMP_CLOSEWINDOW) + + CloseWindow(hauptwin) + + CleanUp(0) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/line.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/line.e new file mode 100644 index 0000000..36fedf3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/line.e @@ -0,0 +1,100 @@ +/* + +This is a 'reducing' way to implement the Line: the attributes x, y and z +are used as starting values, they may be used. Therefore, start is removed + +Look at the rotate procs and see the powerful way of coding oo :) +*/ + +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/coordinate','oomodules/sort/numbers/float' + +OBJECT line OF coordinate + end:PTR TO coordinate +ENDOBJECT + +PROC name() OF line IS 'Line' + +PROC init() OF line +DEF coo:PTR TO coordinate, + float_x:PTR TO float, + float_y:PTR TO float, + float_z:PTR TO float + + NEW float_x.new() + self.x := float_x + + NEW float_y.new() + self.y := float_y + + NEW float_z.new() + self.z := float_z + + NEW coo.new() + self.end := coo + +ENDPROC + +PROC end() OF line +DEF coo:PTR TO coordinate,flt:PTR TO float + + flt := self.x + END flt + + flt := self.y + END flt + + flt := self.z + END flt + + coo := self.end + END coo + +ENDPROC + + +PROC select(optionlist,index) OF line +/* + +TODO: error check: len-o'-list! + + +DEF item, value + + item := ListItem(optionlist, index) + + SELECT item + CASE "set" + + INC index + ENDSELECT +*/ +ENDPROC index + + +PROC setStart(coo:PTR TO coordinate) OF line + + self.setX( coo.getX() ) + self.setY( coo.getY() ) + self.setZ( coo.getZ() ) + +ENDPROC + +PROC setEnd(coo:PTR TO coordinate) OF line IS coo.copy(self.end) + +PROC rotateZ(angle, at=NIL:PTR TO coordinate) OF line + self.end.rotateZ(angle,at) + SUPER self.rotateZ(angle,at) +ENDPROC + +PROC rotateY(angle, at=NIL:PTR TO coordinate) OF line + self.end.rotateY(angle,at) + SUPER self.rotateY(angle,at) +ENDPROC + +PROC rotateX(angle, at=NIL:PTR TO coordinate) OF line + self.end.rotateX(angle,at) + SUPER self.rotateX(angle,at) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polyline.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polyline.e new file mode 100644 index 0000000..43df477 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polyline.e @@ -0,0 +1,34 @@ +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/coordinate', + 'other/queuestack' + +OBJECT polyline OF coordinate + coordinates:PTR TO queuestack +ENDOBJECT + +PROC init() OF polyline +DEF q:PTR TO queuestack + + NEW q.new() + + self.coordinates := q + +ENDPROC + +PROC end() OF polyline +DEF q:PTR TO queuestack + + q:=self.coordinates + + END q +ENDPROC + +PROC name() OF polyline IS 'Polyline' + +PROC add(coo:PTR TO coordinate) OF polyline + + self.coordinates.addLast(coo) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polylinewin.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polylinewin.e new file mode 100644 index 0000000..ec1be37 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/Coordinate/polylinewin.e @@ -0,0 +1,94 @@ +/* + +Just draws some circle. Remove the Delay() and the second Plot() to +see its speed :) + +*/ + +OPT PREPROCESS + +MODULE 'oomodules/coordinate', 'oomodules/coordinate/polyline' + +#define NULL_X (200) +#define NULL_Y (100) + +DEF lastx=0,lasty=0,firstelement,polycolour + +PROC main() +DEF win, coo:PTR TO coordinate,count,co2:PTR TO coordinate, + polyline:PTR TO polyline, co3:PTR TO coordinate, + co4:PTR TO coordinate + + NEW coo.new(["set",50.0,50.0,0.0]) + NEW co2.new(["set",0.0,-50.0,25.0]) + NEW co3.new(["set",-35.0,35.0,0.0]) + NEW co4.new(["set",50.0,50.0,0.0]) + + NEW polyline.new() + + polyline.add(coo) + polyline.add(co2) + polyline.add(co3) + polyline.add(co4) + + win := OpenW(0,0,400,200,0,$F,'ui',0,1,0,0) + + + Line(NULL_X-100, NULL_Y, NULL_X+100, NULL_Y) + Line(NULL_X, NULL_Y-50, NULL_X, NULL_Y+50) + + + FOR count:=0 TO 180*5 + + firstelement:=TRUE + + polycolour:=1 + polyline.coordinates.do({draw}) -> draw it + + Delay(1) + WaitTOF() + polycolour:=0 + polyline.coordinates.do({draw}) -> delete it + + polyline.coordinates.do({rotate}) -> rotate it + ENDFOR + + Delay(150) + + CloseW(win) + +ENDPROC + +PROC drawline (x,y,x2,y2,colour=1) + + Line(NULL_X+(x/2),NULL_Y+(y/4), + NULL_X+(x2/2) ,NULL_Y+(y2/4),colour) + +ENDPROC + + +PROC draw(obj:PTR TO coordinate) +DEF nux,nuy + + nux:=!obj.getX()! + nuy:=!obj.getY()! + + /* + * The flag is deleted when we process the first element. Since each + * line begins where the last line ended we can't draw the first one... + */ + + IF firstelement=TRUE + firstelement := FALSE + ELSE + drawline(lastx,lasty, nux, nuy,polycolour) + ENDIF + + lastx:=nux + lasty:=nuy +ENDPROC + +PROC rotate(obj:PTR TO coordinate) + + obj.rotateY(2.0) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/README b/amigae33a/E_v3.3a/Src/Src/OOmodules/README new file mode 100644 index 0000000..61f660e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/README @@ -0,0 +1,15 @@ +This is a small but still useable part of the object oriented e project +(ooep). The programs in this archive demonstrate some features of the objects +that are included. To get an idea of the ooep go to the oodoc/ directory and +read the files in the guides/ folder. To browse through the examples, use +Multiview or Amigaguide on the Examples file there. + +The ooep needs you to grow. Ask me how you can contribute (my address can +be found in the registration site section of e.guide). + +Gregor Goldbach, April 1997 + +[Note: I moved everything but the modules to the Src/ hierarchy. for +some test programs this may mean editing the MODULE declarations +from '*mod' to 'oomodules/../mod'. This may also have broken some +amigaguide links -- Wouter] diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/application.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/application.e new file mode 100644 index 0000000..f142de9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/application.e @@ -0,0 +1,66 @@ +OPT MODULE + +/* + +Application object. Features: arexx port, commodity + + NAME + application + + PURPOSE + A basic application object. By now it's totally undefined what will + find it's way in here. Any ideas are welcome. Here's a list of things + That could be part of this object in the future: + + - locale support + - arexx support + - commodity + - gui engine (easygui and/or MUI via compiler switch) + +*/ + +MODULE 'oomodules/object', + 'oomodules/commodity', + 'oomodules/library/exec/port/arexxport', + 'oomodules/library/exec/port/portlist' + +OBJECT application OF object + commodity:PTR TO commodity + ports:PTR TO portList +ENDOBJECT + +PROC init() OF application + + NEW ports.new() + +ENDPROC + +PROC select(opts,i) OF application +DEF item, + arexx:PTR TO arexxPort, + cx:PTR TO commodity + + item:=ListItem(opts,i) + + + SELECT item + + CASE "rexx" + + INC i + NEW arexx.new(ListItem(opts,i)) + self.ports.add(arexx,"rexx") + + CASE "cx" + + NEW cx.new(ListItem(opts,i)) + self.commodity := cx + + ENDSELECT + +ENDPROC i + +/*EE folds +-1 +32 3 35 22 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/commodity.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/commodity.e new file mode 100644 index 0000000..9dc7487 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/commodity.e @@ -0,0 +1,466 @@ +OPT MODULE +OPT OSVERSION=37 + +MODULE 'oomodules/library/commodities', + 'oomodules/object', + + 'commodities', + 'libraries/commodities', + 'exec/ports' + + +DEF nb:PTR TO newbroker, + hotkey, hotkeyID, + + cxlib:PTR TO commodities + +EXPORT OBJECT commodity OF object +/****** object/commodity ****************************** + + NAME + commodity of object -- Commodity object. Installs a commodity in the + system. + + PURPOSE + Add commodity facilities to your application. + + ATTRIBUTES + broker:LONG -- Pointer to broker structure as returned and used + by the commodities.library + + messagePort:PTR TO mp -- Message port of the commodity. Messages + arrive here when we press the hotkey, enable the commodity and + so on. + + openGUIProc:LONG -- Address of the proc to call when the commodity is + told to open the gui (via hotkey or exchange program). No + arguments. + + closeGUIProc:LONG -- The opposite of the open gui proc. + + killProc:LONG -- Address of proc to call when the commodity is told + to quit. If left NIL a standard proc is called that removes the + commodity from the system, frees the message port and other + allocated resources. That standard proc is removeFromSystem(). + You may put your own proc here and call removeFromSystem() when + you're finished. See autodoc of that proc. + + NOTES + A quick & dirty implementation from one of my old sources. I'm sure it + isn't finished. + + SEE ALSO + object + +********/ + broker + messagePort:PTR TO mp + openGUIProc + closeGUIProc + killProc +ENDOBJECT + +PROC init() OF commodity +/****** commodity/init ****************************** + + NAME + init() of commodity -- Initialization of the object. + + SYNOPSIS + commodity.init() + + FUNCTION + Opens commodities library if needed and creates message port. Some + flags are set. The commodity is set to be unique. + + SEE ALSO + commodity + +********/ + + NEW cxlib.new() + + self.messagePort := CreateMsgPort() + NEW nb + + nb.unique := NBU_UNIQUE OR NBU_NOTIFY + nb.flags := COF_SHOW_HIDE + nb.port := self.messagePort + + hotkeyID := 1 + + SUPER self.init() + +ENDPROC + +PROC select(opts,i) OF commodity +/****** commodity/select ****************************** + + NAME + select() of commodity -- Selection of action. + + SYNOPSIS + commodity.select(LONG, LONG) + + commodity.select(opts, i) + + FUNCTION + The following tags are recognized: + "name" -- Name of cx. + + "title" -- Title of cx. Some simple line that says who did it. + + "desc" -- Short description line ('OS3 version', 'Testversion') + + "vers" -- Version byte + + "hotk" -- Hotkey string, e.g. 'control alt d' + + "open" -- Pointer to proc that will be called if the cx is told + to open the gui. No arguments are passed. + + "clos" -- Pointer to proc that will be called if the cx is told + to close the gui. No arguments are passed. + + "kill" -- Pointer to proc that will be called if the cx is told + to kill the gui. No arguments are passed. If you use this tag + be sure to call removeFromSystem(). + + "now" -- If this tag is found in the list the cx is added to the + system at once. Do *NOT* provide any more tags, this one has + to be the last one in the list. If you do, behaviour is + undefined. + + The tags "name", "titl", "desc" and "hotkey" have to be provided. + However, this is not checked. If you forget one, behaviour is + undefined. + + INPUTS + opts:LONG -- Option list. + + i:LONG -- Index of optionlist. + + RESULT + LONG -- Current index we are at. + + EXAMPLE + NEW cx.new(["name", 'DevEnv', + "titl", 'DevEnv 0.5ß © 1995,6 Gregor Goldbach', + "desc", 'E Development Environment', + "vers", 5, + "hotk", 'control alt d', + "open", {showMainWindow}, + "now"]) + SEE ALSO + commodity + +********/ +DEF item + + item:=ListItem(opts,i) + + + SELECT item + + CASE "name" + + INC i + nb.name := ListItem(opts,i) + + CASE "titl" + + INC i + nb.title := ListItem(opts,i) + + CASE "desc" + + INC i + nb.descr := ListItem(opts,i) + + CASE "hotk" + + INC i + hotkey := ListItem(opts,i) + + CASE "vers" + + INC i + nb.version := ListItem(opts,i) + + CASE "now" + + self.addToSystem() + END nb + + CASE "open" + + INC i + self.openGUIProc := ListItem(opts,i) + + CASE "clos" + + INC i + self.closeGUIProc := ListItem(opts,i) + + CASE "kill" + + INC i + self.killProc := ListItem(opts,i) + + ENDSELECT + +ENDPROC i + +EXPORT PROC addToSystem() OF commodity +/****** commodity/addToSystem ****************************** + + NAME + addToSystem() of commodity -- Adds commodity to the system. + + SYNOPSIS + commodity.addToSystem() + + FUNCTION + The commodity is installed by the commodities library, arguments set + in select() will be used. Check self.broker to know if the creation + was successful or not. There may be an exception for this in the + future. + + SEE ALSO + commodity + +********/ +DEF filter, sender, translate + + IF nb + + self.broker:=CxBroker(nb,0) -> Create broker with the filled nb structure + + IF self.broker + + + /* Create a filter which checks * + * input events for our hotkey. */ + IF filter:=CreateCxObj(CX_FILTER,hotkey,0) + /* We have to attach the filter to * + * our broker. */ + AttachCxObj(self.broker,filter) + /* Create a sender which sends us * + * hotkey/data info to our port */ + IF sender:=CreateCxObj(CX_SEND,self.messagePort,hotkeyID) + /* Attach the sender to the filter */ + AttachCxObj(filter,sender) + /* Create a translator which 'eats' * + * the input event if it was ours. */ + IF translate:=CreateCxObj(CX_TRANSLATE,0,0) + /* Attach also the translator to the filter */ + AttachCxObj(filter,translate) + /* Global error-check on our filter */ + IF (CxObjError(filter)=0) + /* No errors. Let's go! */ + ActivateCxObj(self.broker,TRUE) + /* We use a subroutine now * + * (only to have a cleaner source) */ + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF + +ENDPROC + +PROC removeFromSystem() OF commodity +/****** commodity/removeFromSystem ****************************** + + NAME + removeFromSystem() of commodity -- + + SYNOPSIS + commodity.removeFromSystem() + + FUNCTION + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + commodity + +********/ + + DeleteCxObjAll(self.broker) + DeleteMsgPort(self.messagePort) + + END cxlib + +ENDPROC + +EXPORT PROC handleInputs() OF commodity +/****** commodity/handleInputs ****************************** + + NAME + handleInputs() of commodity -- + + SYNOPSIS + commodity.handleInputs() + + FUNCTION + Handles general inputs for the commodity. These are the things + you can do with Exchange or any clone of that program. When you + tell the cx to pop up (via hotkey or the Exchange button) the + proc you provided at init() is called. + + When the cx is told to commit suicide the 'close GUI' proc is called + (if provided) and then the cx is removed from the system. Note that + this is the case only if you didn't provide your own kill proc. + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + commodity + +********/ +DEF msg,msgid,msgtype,rcode, + proc + + REPEAT + rcode:=0 /* reset main LOOP RETURN code */ + + /* Wait for any message at our port */ + + WaitPort(self.messagePort) + + + /* Get the message :) */ + + IF msg:=GetMsg(self.messagePort) + + /* Get more data from message for CX */ + + msgid:=CxMsgID(msg) + msgtype:=CxMsgType(msg) + + /* Reply (here OR later but important!) */ + + ReplyMsg(msg) + + /* Check for CXM_IEVENT (Hotkey) */ + + IF msgtype=CXM_IEVENT + + /* Was it our hotkey? */ + + IF msgid=hotkeyID + + /*** Here the hotkey action takes place! ***/ + + proc := self.openGUIProc + IF proc THEN proc() + + ENDIF + + /* Check for CXM_COMMAND (Exchange, ...) */ + + ELSEIF msgtype=CXM_COMMAND + + /* Exchange command Disable */ + + IF msgid=CXCMD_DISABLE + + /*** Remove patches / stop cx-action here ***/ + + ActivateCxObj(self.broker,FALSE) + + /* Exchange command Enable */ + + ELSEIF msgid=CXCMD_ENABLE + + /*** Install patches / start our cx-action here ***/ + + ActivateCxObj(self.broker,TRUE) + + /* Exchange command Show (if COF_SHOW_HIDE flag is SET) */ + + ELSEIF msgid=CXCMD_APPEAR + + /*** Open our GUI/window here ***/ + + proc := self.openGUIProc + IF proc THEN proc() + + /* Exchange command Hide (see CMD_APPEAR) */ + + ELSEIF msgid=CXCMD_DISAPPEAR + + /*** Close our GUI/window here ***/ + + + /* We were started again by a stupid user, * + * so we tell him and ask to quit. * + * (CXCMD_UNIQUE if nb.unique filled) * + * rcode becomes 1 if user wants to quit */ + + proc := self.closeGUIProc + IF proc THEN proc() + + ELSEIF msgid=CXCMD_UNIQUE + + rcode:=EasyRequestArgs(0,[20,0,'CX 37.0','CX already works.\nQuit it now?','Quit|Cancel'],0,0) + + /* Exchange Killer command */ + + ELSEIF msgid=CXCMD_KILL + + proc := self.killProc + IF proc + + proc() + + ELSE + + proc := self.closeGUIProc + IF proc THEN proc() + + + ENDIF + + rcode:=1 + + /* COMMAND check end */ + + ENDIF + + /* COMMAND & IEVENT check end */ + + ENDIF + + /* message scanned & replied */ + + ENDIF + + /* get the next message from our master */ + + UNTIL rcode + +ENDPROC + +/*EE folds +-1 +17 44 19 30 22 115 25 56 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/coordinate.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/coordinate.e new file mode 100644 index 0000000..a74505f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/coordinate.e @@ -0,0 +1,734 @@ +/* + +rotating + +seems to work +*/ + +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/sort/numbers/float','oomodules/object' + +OBJECT coordinate OF object +/****** coordinate/--coordinate-- ****************************************** + + NAME + coordinate of object + + PURPOSE + Unfinished object for three dimensional coordinates. + +****************************************************************************** + +History + + +*/ + x:PTR TO float, + y:PTR TO float, + z:PTR TO float +ENDOBJECT + +PROC name() OF coordinate IS 'coordinate' +/****** coordinate/name ****************************************** + + NAME + name() -- Get name of object. + + SYNOPSIS + coordinate.name() + + FUNCTION + Returns 'Coordinate' + + RESULTS + see above +****************************************************************************** + +History + + +*/ + +PROC init() OF coordinate +/****** coordinate/init ****************************************** + + NAME + init() -- Initialization of the object. + + SYNOPSIS + coordinate.init() + + FUNCTION + Initializes the floats in the object. + + SEE ALSO + float/new() +****************************************************************************** + +History + + +*/ +DEF float_x:PTR TO float, + float_y:PTR TO float, + float_z:PTR TO float + + NEW float_x.new() + self.x := float_x + + NEW float_y.new() + self.y := float_y + + NEW float_z.new() + self.z := float_z + +ENDPROC + + +PROC end() OF coordinate +/****** coordinate/end ****************************************** + + NAME + end() -- Destructor. + + SYNOPSIS + coordinate.end() + + FUNCTION + ENDs the Floats. + + SEE ALSO + float/end() +****************************************************************************** + +History + + +*/ +DEF float:PTR TO float + + float := self.x + END float + + float := self.y + END float + + float := self.y + END float + +ENDPROC + + +PROC getX() OF coordinate IS self.x.get() +/****** coordinate/getX ****************************************** + + NAME + getX() -- Get x part of coordinate. + + SYNOPSIS + coordinate.getX() + + FUNCTION + Returns the value of the x Float of the coordinate. + + RESULT + see float/get() +****************************************************************************** + +History + + +*/ +PROC getY() OF coordinate IS self.y.get() +/****** coordinate/getY ****************************************** + + NAME + getY() -- Get y part of coordinate. + + SYNOPSIS + coordinate.getY() + + FUNCTION + Returns the value of the y Float of the coordinate. + + RESULT + see float/get() +**************************************************************************** +History + + +*/ +PROC getZ() OF coordinate IS self.z.get() +/****** coordinate/getZ ****************************************** + + NAME + getZ() -- Get z part of coordinate. + + SYNOPSIS + coordinate.getZ() + + FUNCTION + Returns the value of the z Float of the coordinate. + + RESULT + see float/get() +****************************************************************************** + +History + + +*/ + +PROC setX(v) OF coordinate IS self.x.set(v) +/****** coordinate/setX ****************************************** + + NAME + setX() -- Set x part of coordinate. + + SYNOPSIS + coordinate.setX(v) + + FUNCTION + Sets the value of the x Float of the coordinate. + + INPUTS + parameter for float/set() +****************************************************************************** + +History + + +*/ + +PROC setY(v) OF coordinate IS self.y.set(v) +/****** coordinate/setY ****************************************** + + NAME + setY() -- Set y part of coordinate. + + SYNOPSIS + coordinate.setY(v) + + FUNCTION + Sets the value of the y Float of the coordinate. + + INPUTS + parameter for float/set() +****************************************************************************** + +History + + +*/ +PROC setZ(v) OF coordinate IS self.z.set(v) +/****** coordinate/setZ ****************************************** + + NAME + setZ() -- Set z part of coordinate. + + SYNOPSIS + coordinate.setZ(v) + + FUNCTION + Sets the value of the z Float of the coordinate. + + INPUTS + parameter for float/set() +****************************************************************************** + +History + + +*/ + + + +/* returns an array with a normal compare to all three dims? +PROC cmp(item:PTR TO integer) OF integer + IF self.number < item.number THEN RETURN -1 + RETURN IF self.number > item.number THEN 1 ELSE 0 +ENDPROC + +*/ + +PROC select(optionlist,index) OF coordinate +/****** coordinate/select ****************************************** + + NAME + select() -- Selection of action on initialization. + + SYNOPSIS + coordinate.select(optionlist, index) + + FUNCTION + Recognizes the following items: + "set" -- The following three items have to be of the type + that set() expects. + + INPUTS + optionlist -- The optionlist + + index -- the index of the optionlist + + SEE ALSO + object/select() +****************************************************************************** + +History + + +*/ +/* + +TODO: error check: len-o'-list! + +*/ +DEF item, value + + item := ListItem(optionlist, index) + + SELECT item + CASE "set" + INC index + self.x.set(ListItem(optionlist,index)) + + INC index + self.y.set(ListItem(optionlist,index)) + + INC index + self.z.set( ListItem(optionlist,index)) + + ENDSELECT + +ENDPROC index + + +PROC write() OF coordinate +/****** coordinate/write ****************************************** + + NAME + write() -- Get string with printable coordinate. + + SYNOPSIS + coordinate.write() + + FUNCTION + Returns a string with the printable coordinate. It looks like this: + + [ ; ; ] + + RESULT + String above. + + NOTES + The string has a maximum legth of 100 characters. + +****************************************************************************** + +History + + +*/ +DEF out + + out:=String(100) + + StrAdd(out,'[ ') + StrAdd(out, self.x.write()) + StrAdd(out,' ; ') + StrAdd(out, self.y.write()) + StrAdd(out,' ; ') + StrAdd(out, self.z.write()) + StrAdd(out,' ]') + + RETURN out +ENDPROC + + +PROC copy(to=NIL:PTR TO coordinate) OF coordinate +/****** coordinate/copy ****************************************** + + NAME + copy() -- Copy a coordinate + + SYNOPSIS + coordinate.copy(destination=NIL) + + FUNCTION + Copies a coordinate. + + INPUTS + destination=NIL:PTR TO coordinate -- Coordinate that is the + destination of the copy. IF NIL, a new coordinate will be + created. + + RESULT + PTR TO coordinate -- If the incoming coordinate object was + NIL a freshly created coordinated will be returned. + + NOTES + May raise extension on NEWing the coordinate when the incoming object + is NIL. + +****************************************************************************** + +History + + +*/ +DEF destination:PTR TO coordinate + + IF to=NIL THEN NEW destination.new() ELSE destination := to + + self.x.copy( destination.x ) + self.y.copy( destination.y ) + self.z.copy( destination.z ) + +ENDPROC destination + + +PROC shift(by:PTR TO coordinate) OF coordinate +/****** coordinate/shift ****************************************** + + NAME + shift() -- Shift a coordinate. + + SYNOPSIS + coordinate.shift(PTR TO coordinate) + + FUNCTION + Shifts a coordinate by another. + + INPUTS + PTR TO coordinate -- Coordinate to shift by. + + EXAMPLE + Be baseCoordinate [ 1.0 ; 0.0 ; 2.0 ] + Be secondCoordinate [ 0.0 ; 1.0 ; 1.0 ] + + baseCoordinate.shift(secondCoordinate) would result in + baseCoordinate being [ 1.0 ; 1.0 ; 3.0 ] + +****************************************************************************** + +History + + +*/ + + self.x.add(by.x) + self.y.add(by.y) + self.z.add(by.z) + +ENDPROC + + +-> turns 0-360 to 0-2*pi +PROC angle2radians(angle) OF coordinate +/****** coordinate/angle2radians ****************************************** + + NAME + angle2radians() -- Turn angle to radians. + + SYNOPSIS + coordinate.angle2radians(angle) + + FUNCTION + Turns an angle into it's radians equivalent. 360 degree would result + in 2*PI. + + INPUTS + angle -- Normal angle between 0 and 360 degree. HAS to be an e-float! + + RESULT + radians -- The according radians + +****************************************************************************** + +History + + +*/ +/* + +Seems to work only with angles>0 +NOTE: only float angles, please! + +*/ +DEF out[80]:STRING + + IF angle<0 THEN angle := angle+360 + + angle := angle/180.0 + angle := angle*3.14159265 + +-> RealF(out,angle,8) +-> WriteF('\s\n', out) + + RETURN angle +ENDPROC + + +PROC rotateZ(angle,coordinate=NIL:PTR TO coordinate) OF coordinate +/****** coordinate/rotateZ ****************************************** + + NAME + rotateZ() -- Rotate around the z axis. + + SYNOPSIS + coordinate.rotateZ(e-float,PTR TO coordinate) + + FUNCTION + If the second parameter is NIL the coordinate is rotated around the + z axis by the given angle. If a coordinate is specified, however, + the object will be rotated around the z axis that goes through that + point. + + INPUTS + angle -- Angle to rotate by. HAS to be an e-float! + + coordinate=NIL:PTR TO coordinate -- If provided the object won't be + rotated around [ 0.0 ; 0.0 ; 0.0 ] but around this coordinate. + + SEE ALSO + rotateY(), rotateX() +****************************************************************************** + +History + + +*/ +/* + +This method rotates the point by the given angle around the given coordinate. +If no coordinate is specified, we rotate aroung 0;0;0 + +*/ + +DEF fltangle, nux, nuy, out[80]:STRING, + fltx,flty, resulta, resultb + + /* + * To rotate around a point we do this: substract the coordinate's values, + * i.e. shift it to 0;0;0, rotate it, and add the coordinate's values + * to the result. + */ + + IF coordinate + self.x.substract(coordinate.x) + self.y.substract(coordinate.y) + self.z.substract(coordinate.z) + ENDIF + + + fltangle := self.angle2radians(angle) + + fltx := self.x.get() + flty := self.y.get() + + resulta := !fltx * Fcos(fltangle) + resultb := !flty * Fsin(fltangle) + + nux := !resulta - resultb + + resulta := !fltx * Fsin(fltangle) + resultb := !flty * Fcos(fltangle) + + nuy := !resulta + resultb + + /* + * Now let's shift it back to where it came from (see above) + */ + + self.x.set(nux) + self.y.set(nuy) + + IF coordinate + self.x.add(coordinate.x) + self.y.add(coordinate.y) + self.z.add(coordinate.z) + ENDIF + +ENDPROC + + +PROC rotateY(angle,coordinate=NIL:PTR TO coordinate) OF coordinate +/****** coordinate/rotateY ****************************************** + + NAME + rotateY() -- Rotate around the y axis. + + SYNOPSIS + coordinate.rotateY(e-float,PTR TO coordinate) + + FUNCTION + If the second parameter is NIL the coordinate is rotated around the + y axis by the given angle. If a coordinate is specified, however, + the object will be rotated around the y axis that goes through that + point. + + INPUTS + angle -- Angle to rotate by. HAS to be an e-float! + + coordinate=NIL:PTR TO coordinate -- If provided the object won't be + rotated around [ 0.0 ; 0.0 ; 0.0 ] but around this coordinate. + + SEE ALSO + rotateZ(), rotateX() +****************************************************************************** + +History + + +*/ +/* + + note: + + to rotate 90 degree (mathematical) one has to provide -90 + (wrong formula?) +*/ + +DEF fltangle, nux, nuz, out[80]:STRING, + fltx,fltz, resulta, resultb + + + IF coordinate + self.x.substract(coordinate.x) + self.y.substract(coordinate.y) + self.z.substract(coordinate.z) + ENDIF + + + fltangle := self.angle2radians(angle) + + fltx := self.x.get() + fltz := self.z.get() + + resulta := !fltz * Fcos(fltangle) + resultb := !fltx * Fsin(fltangle) + + nuz := !resulta - resultb + + resulta := !fltz * Fsin(fltangle) + resultb := !fltx * Fcos(fltangle) + + nux := !resulta + resultb + + self.x.set(nux) + self.z.set(nuz) + + IF coordinate + self.x.add(coordinate.x) + self.y.add(coordinate.y) + self.z.add(coordinate.z) + ENDIF + +ENDPROC + + +PROC rotateX(angle,coordinate=NIL:PTR TO coordinate) OF coordinate +/****** coordinate/rotateX ****************************************** + + NAME + rotateX() -- Rotate around the x axis. + + SYNOPSIS + coordinate.rotateX(e-float,PTR TO coordinate) + + FUNCTION + If the second parameter is NIL the coordinate is rotated around the + x axis by the given angle. If a coordinate is specified, however, + the object will be rotated around the x axis that goes through that + point. + + INPUTS + angle -- Angle to rotate by. HAS to be an e-float! + + coordinate=NIL:PTR TO coordinate -- If provided the object won't be + rotated around [ 0.0 ; 0.0 ; 0.0 ] but around this coordinate. + + SEE ALSO + rotateY(), rotateZ() +****************************************************************************** + +History + + +*/ +/* + + note: + + to rotate 90 degree (mathematical) one has to provide -90 + (wrong formula?) +*/ + +DEF fltangle, nuy, nuz, out[80]:STRING, + fltz,flty, resulta, resultb + + IF coordinate + self.x.substract(coordinate.x) + self.y.substract(coordinate.y) + self.z.substract(coordinate.z) + ENDIF + + + fltangle := self.angle2radians(angle) + + fltz := self.z.get() + flty := self.y.get() + + resulta := !flty * Fcos(fltangle) + resultb := !fltz * Fsin(fltangle) + + nuy := !resulta - resultb + + resulta := !flty * Fsin(fltangle) + resultb := !fltz * Fcos(fltangle) + + nuz := !resulta + resultb + + self.y.set(nuy) + self.z.set(nuz) + + IF coordinate + self.x.add(coordinate.x) + self.y.add(coordinate.y) + self.z.add(coordinate.z) + ENDIF + +ENDPROC + + +PROC neg() OF coordinate +/****** cordinate/neg ****************************************** + + NAME + neg() -- Negate cordinate. + + SYNOPSIS + coordinate.neg() + + FUNCTION + Negates the x, y and z value of the coordinate. + + SEE ALSO + float/neg() +****************************************************************************** + +History + + +*/ + self.x.neg() + self.y.neg() + self.z.neg() +ENDPROC + +/*EE folds +1 +54 34 56 32 190 50 192 40 194 40 196 34 199 43 201 81 203 73 205 72 207 24 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library.e new file mode 100644 index 0000000..492ae6b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library.e @@ -0,0 +1,183 @@ +/****** library/--background-- ****************************************** + + PURPOSE + Basic implementation of the Library object. + + CREATION + back in Februaray of 1995 by Gregor Goldbach + + HISTORY + Joseph E. van Riper III overworked everything a bit. + + SEE ALSO + library/device + +****************************************************************************** + +History + + +*/ +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/object' + +OBJECT library OF object +/****** library/--library-- ****************************************** + + NAME + library + + ATTRIBUTES + libName -- the name of the library + + version -- version of the library. 33 is v1.2 of the AmigaOS, + 37 is OS2.04, 39 is OS3.0, 40 is OS3.1 + + CREATION + back in February of 1995 by Gregor Goldbach + + HISTORY + JEVR3 changes; removed 'base', included 'name' and 'version', + now included in the 'oomodules' hierarchy. +****************************************************************************** + +History + + +*/ + identifier + version +ENDOBJECT + +PROC select(opts,i) OF library +/****** library/select ****************************************** + + NAME + select -- selection of actions via taglist + + SYNOPSIS + library.select() + + FUNCTION + Select an action for this object upon initialization. See + documentation of Object's new() and select. + + These items are recognized: + "name" -- next item is library name. Note that the identifier + is set to the string of characters you pass -- it is NOT + copied, so you have to keep the string. + + "ver" -- next item is library version to open. + + INPUTS + opts -- Optionslist + + i -- index of optionlist + + EXAMPLE + + /* + * create an instance of the library class and open gadtools + * version 37. + */ + + NEW library.new(["name", 'gadtools.library', "ver",37]) + +****************************************************************************** + +History + + +*/ +DEF item + + item:=ListItem(opts,i) + + SELECT item + + CASE "name" + + INC i + self.identifier:=ListItem(opts,i) + + CASE "ver" + + INC i + self.version:=ListItem(opts,i) + + ENDSELECT + +ENDPROC i + +PROC open() OF library IS self.derivedClassResponse() +/****** library/open ****************************************** + + NAME + open() -- Open the library + + SYNOPSIS + library.open() + + FUNCTION + + Open the library. Not functional in this basic object, the + derived objects have to take care of that. + +****************************************************************************** + +History + + +*/ + +PROC close() OF library IS self.derivedClassResponse() +/****** library/close ****************************************** + + NAME + close() -- Close the library + + SYNOPSIS + library.close() + + FUNCTION + Close the library. Not functional in this basic object, the + derived objects have to take care of that. + +****************************************************************************** + +History + + +*/ + +PROC end() OF library +/****** library/end ****************************************** + + NAME + end() -- Free resources. + + SYNOPSIS + library.end() + + FUNCTION + Frees all resources used by this object. Automatically called + when ENDing the object. + + NOTES + JEVR3 addition; seemed logical to make 'end()' close() the library. + +****************************************************************************** + +History + + +*/ + + self.close() +ENDPROC +/*EE folds +-1 +154 23 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/Examples new file mode 100644 index 0000000..78d9cdb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/Examples @@ -0,0 +1,39 @@ +@database library_example + +@node main "Introduction to Library" + +The library is an essential object in the Amiga system. Basically it's a +collection of functions. Refer to standard Amiga documentation (ROM Kernel +Reference Manuals or the Guru Book) for a more detailed explanation. + +The library object of the oomodules/ hierarchy doesn't enhance the usage +of libraries very much - at least not at this basic level. There are +derived objects that use this object as a 'foundation'. + + + + +The library object template @{" anylibrary " alink EMODULES:oomodules/library/anylibrary.e/main} may serve as an example for +own libraries. + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/library/main} file available or this object. + +@endnode + +@node initilisation "Allocation and initilisation of ..." + +Select takes some arguments. + +@endnode + +@node where "Where to use this object" + +Anywhere you want to use a library. + +@endnode + +@node see_also "See also" + +Library derived objects. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/anylibrary.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/anylibrary.e new file mode 100644 index 0000000..5d9b6d1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/anylibrary.e @@ -0,0 +1,142 @@ +/* + +Library template for any library. This object can be used to open other +libraries. See it as an example how to build own library derived objects. + +*/ + +OPT MODULE + + + +/* + +Export everything defined in here. + +*/ +OPT EXPORT + + + +/* + +Include the basic library object and normal E modules of the library to +implement. + +*/ + +MODULE 'oomodules/library', 'anylibrary', 'libraries/anylibrary' + + + +OBJECT anylibrary OF library +/****** anylibrary/--background-- ****************************************** + + NAME + anylibrary of library + + PURPOSE + Basic implementation of a simple library module. + + ATTRIBUTES + No special attributes since it's used for demonstration. + + CREATION + September 9 1996 Gregor Goldbach + +****************************************************************************** + +History + + +*/ +ENDOBJECT + + + +PROC init() OF anylibrary +/****** anylibrary/init ****************************************** + + NAME + init() -- Initialization of the object. + + SYNOPSIS + anylibrary.init() + + FUNCTION + Sets the library's name and the version to 0. After that the library + is opened. + + This menas that any version found be opened if the version isn't + changed in select(). + + SEE ALSO + open() +****************************************************************************** + +The object attributes identifier and version are set to initial values. +The version attribute may very well be changed by the "vers" tag of select() +if you want to open a specific version of the library. + +*/ + self.identifier:='anylibrary.library' + self.version:=0 + self.open() +ENDPROC + + + +PROC open() OF anylibrary +/****** anylibrary/open ****************************************** + + NAME + open() -- Open anylibrary.library + + SYNOPSIS + anylibrary.open() + + FUNCTION + Opens the anylibrary.library and sets the global library base to + the value returned by OpenLibrary(). + + EXCEPTIONS + "lib",{anylibOpen} will be raised if the opening fails. You should + provide at least one exception handler to receive the exception and + act on it. + +****************************************************************************** + +History + + +*/ + IF (anylibrarybase:=OpenLibrary(self.identifier,self.version)) = NIL THEN Throw("lib",{reqtoolOpen}) +ENDPROC + + +PROC close() OF anylibrary +/****** anylibrary/close ****************************************** + + NAME + close() -- Close the library. + + SYNOPSIS + anylibrary.close() + + FUNCTION + Closes the library. + + SEE ALSO + open() +****************************************************************************** + +History + + +*/ + CloseLibrary(anylibrarybase) +ENDPROC + + +anylibOpen: + CHAR 'Unable to open anylibrary.library.',0 diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/asl.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/asl.e new file mode 100644 index 0000000..65fa014 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/asl.e @@ -0,0 +1,309 @@ +OPT MODULE + +MODULE 'oomodules/library', + + 'asl', + 'libraries/asl', + + 'other/ecode', + 'dos/dos', + 'dos/dosasl', + 'utility/hooks' + +CONST MAXPATTERNLENGTH=80, + MAXFILELENGTH=30, + MAXDIRLENGTH=255 + +DEF patbuffer, + +/* + * The patbuffer variable is used in hookFunc and getFileWithPattern. It holds + * the pattern the files should match. + */ + + temporaryBuffer:PTR TO CHAR -> contains temporary data + +/* + * the temporary buffer contains the absolute file name of the file name + * that was chosen in the last requester. + */ + +EXPORT OBJECT asl OF library +/****** asl/asl ****************************** + + NAME + asl of library + + PURPOSE + Object for handling the asl.library. + + ATTRIBUTES + patbuffer[MAXPATTERNLENGTH]:ARRAY OF CHAR -- buffer to store the file + pattern in. + + lastFileChosen[MAXFILELENGTH]:ARRAY OF CHAR -- buffer to store the name + of the file that was chosen in the last requester. + + lastDirChosen[MAXDIRLENGTH]:ARRAY OF CHAR -- buffer to store the name + of the directory that was chosen in the last requester. + + NOTES + Not all functions of the asl.library are implemented. + + SEE ALSO + library + +********/ + patbuffer[MAXPATTERNLENGTH]:ARRAY OF CHAR, + lastFileChosen[MAXFILELENGTH]:ARRAY OF CHAR + lastDirChosen[MAXDIRLENGTH]:ARRAY OF CHAR +ENDOBJECT + +PROC init() OF asl +/****** reqtools/init ****************************************** + + NAME + init() -- Initialization of the object. + + SYNOPSIS + asl.init() + + FUNCTION + Copies 'SYS:' to the lastDirChosen attribute. + Sets the library's name and the version to 0. After that the library + is opened. + + SEE ALSO + open() +****************************************************************************** + +History + + +*/ + temporaryBuffer := String(255) + + AstrCopy(self.lastDirChosen, 'SYS:') + + self.identifier:='asl.library' + self.version:=0 + self.open() +ENDPROC + +EXPORT PROC open() OF asl +/****** asl/open ****************************** + + NAME + open() of asl -- Open the asl.library. + + SYNOPSIS + asl.open() + + FUNCTION + Open the asl.library. The version to open can be specified in the + option list you pass to new(). + + EXCEPTION + As with all libraries, the exception "lib" is raised when the opening + failed. The exceptioninfo contains a string that tells this. + + NOTES + The string may be localized in the future. + + SEE ALSO + asl + +********/ + + IF (aslbase:=OpenLibrary(self.identifier,self.version)) = NIL THEN Throw("lib",{aslOpen}) + +ENDPROC + +EXPORT PROC close() OF asl +/****** asl/close ****************************** + + NAME + close() of asl -- Close the library. + + SYNOPSIS + asl.close() + + FUNCTION + Closes the library if it is open. + + SEE ALSO + asl + +********/ + + IF aslbase THEN CloseLibrary(aslbase) + +ENDPROC + +PROC end() OF asl +/****** asl/end ****************************** + + NAME + end() of asl -- Global destructor. + + SYNOPSIS + asl.end() + + FUNCTION + Frees allocated resources and closes the library. + + SEE ALSO + asl + +********/ + + DisposeLink(temporaryBuffer) + self.close() + +ENDPROC + +PROC hookFunc(type, obj:PTR TO anchorpath, fr) +/****** /hookFunc ****************************** + + NAME + hookFunc() -- Hook function for requesters. + + SYNOPSIS + hookFunc(LONG, PTR TO anchorpath, LONG) + + hookFunc(type, obj, fr) + + FUNCTION + Used when displaying the file requesters. + + NOTES + Stolen from JRH's rkrm examples. Dunno how it works, so this autodoc + lacks the input description :-( + + SEE ALSO + getFileWithPattern(), rkrm examples +********/ + DEF returnvalue + SELECT type + CASE FILF_DOMSGFUNC + -> We got a message meant for the window + RETURN obj + CASE FILF_DOWILDFUNC + -> We got an AnchorPath structure, should the requester display this file? + + -> MatchPattern() is a dos.library function that compares a matching + -> pattern (parsed by the ParsePattern() DOS function) to a string and + -> returns TRUE if they match. + returnvalue:=MatchPattern(patbuffer, obj.info.filename) + + -> We have to negate MatchPattern()'s return value because the file + -> requester expects a zero for a match not a TRUE value + RETURN returnvalue=FALSE + ENDSELECT +ENDPROC + +EXPORT PROC getFileWithPattern(pattern:PTR TO CHAR, taglist=NIL) OF asl +/****** asl/getFileWithPattern ****************************** + + NAME + getFileWithPattern() of asl -- Get a file that matches the pattern. + + SYNOPSIS + asl.getFileWithPattern(PTR TO CHAR, LONG=NIL) + + asl.getFileWithPattern(pattern, taglist) + + FUNCTION + Opens a file requester that displays the files that match the pattern + provided. + + INPUTS + pattern:PTR TO CHAR -- The pattern of the files that should appear in + the file list. The usual dos.library wildcards are allowed. + + taglist:LONG -- asl tags. See CBM's asl.doc for those. + + RESULT + PTR TO CHAR -- The chosen file or NIL if the user aborted. + + NOTES + The attributes lastFileChosen and lastDirChosen are set by this proc. + + Stolen from JRH's rkrm examples. + + KNOWN BUGS + Tries to add a file name even if no file was chosen. Fixed this bug + (May 26 1996 Gregor Goldbach). + + SEE ALSO + asl/asl, CBM's asl.doc, JRH's rkrm examples + +********/ +DEF fr:PTR TO filerequester, + myFunc, + nulist + + ParsePattern(pattern, self.patbuffer, MAXPATTERNLENGTH) + + patbuffer := self.patbuffer + + fr:=AllocFileRequest() + -> E-Note: eCodeASLHook() sets up an E PROC for use as an ASL hook function + myFunc:=eCodeASLHook({hookFunc}) + + IF myFunc + + /* + * now we have myFunc. we're able to set up the tag list + */ + + nulist := List(255) + ListCopy(nulist, taglist) + ListAdd(nulist, [ASL_HOOKFUNC, myFunc, ASL_FUNCFLAGS, FILF_DOWILDFUNC OR FILF_DOMSGFUNC OR FILF_SAVE]) + + +/* + IF AslRequest(fr, [ASL_DIR, 'SYS:Utilities', +-> ASL_WINDOW, window, + ASL_TOPEDGE, 0, + ASL_HEIGHT, 200, + ASL_HAIL, 'Pick an icon, select save', + -> E-Note: use the value returned from aslhook() + ASL_HOOKFUNC, myFunc, + ASL_FUNCFLAGS, FILF_DOWILDFUNC OR FILF_DOMSGFUNC + ASL_OKTEXT, 'Save', + NIL]) +*/ + + IF AslRequest(fr, nulist) + + AstrCopy(self.lastDirChosen,fr.drawer, IF StrLen(fr.drawer) the size of the biggest device block + LONGEST_NAME=40 + +-> JEVR3 modification; moved 'name' to object 'library'. + + +OBJECT device OF library +/****** device/--device-- ****************************************** + + NAME + device + + ATTRIBUTES + unit -- The unit of the device you want to use. If you don't know + of a special unit to specify when you work with a device, set + it to 0. Otherwise, as with the trackdisk.device for example, + set it to the unit you want to operate on. Think of a unit as + a 'sub-system' of that device. + + io -- Pointer to the io request structure used for this device. + + flags -- Special flags you set. + + lasterror -- You for convenience, this entry contains the last + error as in io.error. + +****************************************************************************** + +History + + +*/ + unit + io:PTR TO io + flags + lasterror +ENDOBJECT + +-> JEVR3 addition; select() handles 'unit' and 'flag' options. + +PROC select(opts,i) OF device +/****** device/select ****************************************** + + NAME + select() -- Select action via taglist + + SYNOPSIS + device.select() + + FUNCTION + Select an action upon initialization of the object. See + object/new() and object/select() for more information. + + Recognizes these items: + "unit" -- set unit of device + + "flag" -- set flags of device + + INPUTS + opts -- Optionlist + + i -- index of optionlist + + SEE ALSO + object/select() +****************************************************************************** + +History + + +*/ + +DEF item + + item:=ListItem(opts,i) + + SELECT item + + CASE "unit" + INC i + self.unit := ListItem(opts,i) + + CASE "flag" + INC i + self.flags := ListItem(opts,i) + + DEFAULT + i:=SUPER self.select(opts,i) + + ENDSELECT +ENDPROC i + +-> JEVR3 modification; no more options (new() handles that). Changed the +-> error handling a little bit. + +PROC open() OF device HANDLE +/****** device/open ****************************************** + + NAME + open() -- Open a device with given attributes. + + SYNOPSIS + device.open() + + FUNCTION + Open a device with the attributes set. + + RETURNS + TRUE if the device could be opened. + + EXCEPTIONS + May raise "dev" with exceptioninfo + + {msgportfail} - CreateMsgPort() failed + {ioreqfail} - CreateIORequest() failed + {opendev} - OpenDevice() failed + + SEE ALSO + close(), select() +****************************************************************************** + +History + + +*/ +DEF ioreq=0:PTR TO io, + meinport:PTR TO mp, + fehler=0 + + IF self.io THEN RETURN TRUE -> JEVR3 modification.. reduce redundancy + +->try to open a no-name message port + + meinport := CreateMsgPort() + IF (meinport = NIL) THEN Throw("dev",{msgportfail}) + +->try to create an iorequest + + ioreq := CreateIORequest(meinport, SIZE_OF_BIGGEST_DEVICE_BLOCK) + IF (ioreq = NIL) THEN Throw("dev",{ioreqfail}) + +->try to open the device + + fehler := OpenDevice(self.identifier,self.unit,ioreq,self.flags) + IF(fehler) + Throw("dev",{opendev}) + ELSE + self.io := ioreq + RETURN TRUE + ENDIF + +-> EXCEPT handling by JEVR3 + +EXCEPT DO + IF ioreq THEN DeleteIORequest(ioreq) + IF meinport THEN DeleteMsgPort(meinport) + ReThrow() +ENDPROC FALSE + +-> JEVR3 modification; added IF statement + +PROC close() OF device +/****** device/close ****************************************** + + NAME + close() -- Close a device if open. + + SYNOPSIS + device.close() + + FUNCTION + Closes the device and frees allocated resources. + + SEE ALSO + open() +****************************************************************************** + +History + + +*/ + IF self.io + CloseDevice(self.io) + DeleteIORequest(self.io) + DeleteMsgPort(self.io.mn::mn.replyport) + ENDIF +ENDPROC + +PROC end() OF device +/****** device/end ***************************************** + + NAME + end() -- Frees allocated resources. + + SYNOPSIS + device.end() + + FUNCTION + Frees allocated resources of the object, that includes closing it. + Automatically called when ENDing the object. + +****************************************************************************** + +History + + +*/ + self.close() +ENDPROC + +PROC doio() OF device +/****** device/doio ****************************************** + + NAME + doio() -- Perform a DoIO(). + + SYNOPSIS + device.doio() + + FUNCTION + Perform exec.library's DoIO() on the io request. + + SEE ALSO + exec/DoIO() +****************************************************************************** + +History + + +*/ + IF self.io THEN DoIO(self.io) +ENDPROC + +PROC sendio() OF device +/****** device/sendio ****************************************** + + NAME + sendio() -- Perform a SendIO(). + + SYNOPSIS + device.sendio() + + FUNCTION + Perform exec.library's SendIO() on the io request. + + SEE ALSO + exec/SendIO() +****************************************************************************** + +History + + +*/ + IF self.io THEN SendIO(self.io) +ENDPROC + +PROC abortio() OF device +/****** device/abortio ****************************************** + + NAME + abortio() -- Perform a AbortIO(). + + SYNOPSIS + device.abortio() + + FUNCTION + Perform exec.library's AbortIO() on the io request. + + SEE ALSO + exec/AbortIO() +****************************************************************************** + +History + + +*/ + IF self.io THEN AbortIO(self.io) +ENDPROC + +PROC reset() OF device +/****** device/reset ****************************************** + + NAME + reset() -- Reset the device. + + SYNOPSIS + device.reset() + + FUNCTION + reset the device by sending the according command. + +****************************************************************************** + +History + + +*/ + IF self.io + self.io::iostd.command := CMD_RESET + DoIO(self.io) + ENDIF +ENDPROC + +-> JEVR3 addition: strings for error messages. These should change +-> in the future whenever we develop a fairly comprehensive locale +-> handling object for all our devices. Sorry it's English for now. + +msgportfail: + CHAR 'Couldn''t create message port.',0 +ioreqfail: + CHAR 'Couldn''t create i/o request.',0 +opendev: + CHAR 'Couldn''t open the device.',0 +/*EE folds +-1 +41 30 45 49 117 24 120 19 123 20 126 20 129 20 132 21 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/keyboard.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/keyboard.e new file mode 100644 index 0000000..f88d2a9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/keyboard.e @@ -0,0 +1,48 @@ +/* + +A first version of the keyboard object. By now only one command is +available: read(). Is reads from the keyboard. The pressed key(s) can +be read out of ivent:inputevent. + + V2.0 12.4.95 made it fit to 'Object' + should work +*/ + +OPT OSVERSION=37 +OPT MODULE +OPT EXPORT + +MODULE 'devices/keyboard','exec/io', 'devices/inputevent', + 'oomodules/library/device' + +OBJECT keyboard OF device + ievent:inputevent +ENDOBJECT + +PROC name() OF keyboard IS 'Keyboard' + +PROC init() OF keyboard + self.name := 'keyboard.device' +ENDPROC + +PROC read() OF keyboard + + IF self.io = NIL THEN self.open('keyboard.device',0,0) + + self.io::iostd.data := self.ievent + self.io::iostd.length := SIZEOF inputevent + self.io::iostd.command := KBD_READEVENT + + DoIO(self.io) + +ENDPROC + +PROC end() OF keyboard + self.close() +ENDPROC + +PROC openIfClosed() OF keyboard + + IF self.io = NIL THEN self.new(["name",'keyboard.device']) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer.e new file mode 100644 index 0000000..61894f0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer.e @@ -0,0 +1,238 @@ +OPT MODULE +OPT OSVERSION=37 +OPT EXPORT + +-> NOTE: some modifications to this by JEVR3 +-> All 'self.open()' statements changed to reflect use of 'new()' + +MODULE 'devices/printer', 'exec/devices', 'exec/io', 'exec/nodes', + 'exec/ports','exec/devices', + 'oomodules/library/device' + +OBJECT printer OF device +/****** printer/--printer-- ****************************************** + + NAME + printer of device + + PURPOSE + To provide basic means to control every printer. + + CREATION + Back in February of 1995 by Gregor Goldbach + + HISTORY + some minor modifications by Trey +****************************************************************************** + +History + + +*/ +ENDOBJECT + +-> JEVR3 addition: init() sets default name and unit for printer.device. + +PROC init() OF printer +/****** printer/init ****************************************** + + NAME + init() -- Initialization of the object. + + SYNOPSIS + printer.init() + + FUNCTION + Set default name and unit. +****************************************************************************** + +History + + +*/ + self.identifier:={defaultPrinter} + self.unit:=0 +ENDPROC + +PROC rawwrite(zkette,laenge) OF printer +/****** printer/rawwrite ****************************************** + + NAME + rawwrite() -- Printing chars without esc substitution. + SYNOPSIS + printer.rawwrite(PTR TO CHAR, LONG) + + FUNCTION + Sends the characters to the printer. Esc-sequences will not be + substituted. Opens the printer.device if necessary. + + INPUTS + PTR TO CHAR -- The characters to print + + LONG -- The number of characters to print + +****************************************************************************** + +History + + +*/ + +-> JEVR3 modification; removed surrounding IF/ENDIF; now in open() itself +-> Also tests to insure device opened. + + IF self.open() + + self.io::iostd.data := zkette + self.io::iostd.length := laenge + self.io::iostd.command := PRD_RAWWRITE + + self.doio() + + self.lasterror := self.io.error + ENDIF +ENDPROC + +PROC write(zkette,laenge) OF printer +/****** printer/write ****************************************** + + NAME + write() -- Printing chars with esc substitution. + SYNOPSIS + printer.write(PTR TO CHAR, LONG) + + FUNCTION + Sends the characters to the printer. Esc-sequences will be + substituted. Opens the printer.device if necessary. + + INPUTS + PTR TO CHAR -- The characters to print + + LONG -- The number of characters to print + +****************************************************************************** + +History + + +*/ +-> JEVR3 modification; removed surrounding IF/ENDIF; now in open() itself +-> Added test to see if it actually opened. + + IF self.open() + + + self.io::iostd.data := zkette + self.io::iostd.length := laenge + + self.io::iostd.command := CMD_WRITE + + self.doio() + + self.lasterror := self.io.error + ENDIF +ENDPROC + +PROC xcommand(kommando,p0=NIL,p1=NIL,p2=NIL,p3=NIL) OF printer +/****** printer/xcommand ****************************************** + + NAME + xcommand() -- execute printer command. + + SYNOPSIS + printer.xcommand(LONG, LONG=NIL, LONG=NIL, LONG=NIL, LONG=NIL) + + FUNCTION + Executes a printer command with the given parameters such as setting + left and right border, justification etc. + Opens the printer.device if necessary. + + INPUTS + command:LONG -- the printer command to be executed + param0-3:LONG -- command parameters + +****************************************************************************** + +History + +DESCRIPTION + + +*/ + +-> JEVR3 modification; removed surrounding IF/ENDIF; now in open() itself +-> Added test to see if it actually opened. + + IF self.open() + + self.io::ioprtcmdreq.prtcommand := kommando + self.io::ioprtcmdreq.parm0 := p0 + self.io::ioprtcmdreq.parm1 := p1 + self.io::ioprtcmdreq.parm2 := p2 + self.io::ioprtcmdreq.parm3 := p3 + self.io.command := PRD_PRTCOMMAND + self.doio() + + ENDIF + +ENDPROC + +PROC graphicdump(rport,cmap,vmodes,srcx,srcy,srcwidth,srcheight,destcols,destrows,special) OF printer +/****** printer/graphicdump ****************************************** + + NAME + graphicdump() -- Print a part of a rastport. + + SYNOPSIS + printer.graphicdump(10 LONGs) + + FUNCTION + It prints a part of a rastport. + + INPUTS + rport -- the RastPort containing the image to print + cmap -- screen's ColorMap + vmodes -- ViewModes of the screen + srcx,srcy, + srcwidth, + srcheight -- source dimensions: start point & width & height + destcols, + destrows - dimensions on the printer in points + Special - special flags + +****************************************************************************** + +History + + +*/ + +-> JEVR3 modification; removed surrounding IF/ENDIF; now in open() itself +-> Added test to make sure device was opened. + + IF self.open() + self.io::iodrpreq.rastport := rport + self.io::iodrpreq.colormap := cmap + self.io::iodrpreq.modes := vmodes + self.io::iodrpreq.srcx := srcx + self.io::iodrpreq.srcy := srcy + self.io::iodrpreq.srcwidth := srcwidth + self.io::iodrpreq.srcheight := srcheight + self.io::iodrpreq.destcols := destcols + self.io::iodrpreq.destrows := destrows + self.io::iodrpreq.special := special + + self.io.command := PRD_DUMPRPORT + self.doio() + ENDIF + +ENDPROC + +-> JEVR3 addition: strings for the default printer. + +defaultPrinter: + CHAR 'printer.device',0 +/*EE folds +-1 +12 20 16 18 19 36 22 37 25 41 28 48 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test.e new file mode 100644 index 0000000..62ea145 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test.e @@ -0,0 +1,11 @@ +MODULE 'oomodules/library/device/printer/printer' + +PROC main() +DEF drucker:PTR TO printer + + NEW drucker.new() + drucker.write('Hallo',5) + + END drucker + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test2.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test2.e new file mode 100644 index 0000000..2285c7c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/printer/test2.e @@ -0,0 +1,44 @@ +/* + * this tests the printer object. NOTE: those vars are only needed + * for the graphic dump :) + */ + +-> NOTE: one modification to reflect enhancement by JEVR3 + +OPT OSVERSION=37 + +MODULE 'oomodules/library/device','exec/io','devices/printer', + 'oomodules/library/device/printer', + 'intuition/intuition', 'intuition/intuitionbase','graphics/gfxbase','graphics/view', + 'graphics/rastport' + +PROC main() +DEF drucker:PTR TO printer, + ibase:PTR TO intuitionbase, + gbase:PTR TO gfxbase, + vp:PTR TO viewport, + rp:PTR TO rastport + + ibase:=intuitionbase + gbase:=gfxbase + rp := ibase.activewindow::window.rport + vp := gbase.actiview::view.viewport + +-> JEVR3: added new() to set defaults. + + NEW drucker.new() + + drucker.graphicdump( rp, + vp.colormap, + vp.modes, + 0,0,100,100,100,100,0) + + drucker.rawwrite('Hallo', 5) + drucker.xcommand(27) -> superscript on + drucker.write('Hallo', 5) + + WriteF('Fehler:\d\n',drucker.io.error) + + + END drucker +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk.e new file mode 100644 index 0000000..2e69aad --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk.e @@ -0,0 +1,117 @@ +/* + +Second module for the trackdisk.device. Uses my E-PROCs from 1993 which were +adapted to use the device object. + +Gregor Goldbach 1st April 1995 + +VISION: + + - procs to read/write non-dos tracks + - open device if not opened already + + V2.0 12.4.95 made it fit to 'Object' + works +*/ + + +OPT MODULE +OPT OSVERSION=37 +OPT EXPORT + +MODULE 'exec/devices', 'exec/io', 'exec/nodes', + 'exec/ports','exec/devices', 'devices/trackdisk', + 'oomodules/library/device' + +OBJECT trackdisk OF device + label[16]:ARRAY OF CHAR + buffer[512]:ARRAY OF CHAR +ENDOBJECT + +PROC name() OF trackdisk IS 'Trackdisk' + +PROC init() OF trackdisk + self.name := 'trackdisk.device' +ENDPROC + +PROC motor(flag=FALSE,drive=0) OF trackdisk +DEF wert + + IF self.io = NIL THEN self.open('trackdisk.device',drive) + + IF flag THEN wert := 1 ELSE wert := 0 + /* ior.iostd.length := 1 -> Motor an */ + /* ior.iostd.length := 0 -> Motor aus */ + + self.io::iostd.length := wert + self.io::iostd.command := TD_MOTOR + self.doio() + +ENDPROC + +PROC getchangenum() OF trackdisk + + IF self.io = NIL THEN self.open('trackdisk.device') + + self.io::iostd.command := TD_CHANGENUM + self.doio() + RETURN self.io::iostd.actual /* ior.iostd.actual hier steht nach DoIO die Nummer drin */ +ENDPROC + +PROC readblock(nummer,drive=0) OF trackdisk + + IF self.io=NIL THEN self.open('trackdisk.device', drive, 0) + + self.io::ioexttd.count := self.getchangenum() + self.io::iostd.offset := nummer*512 -> der Offset wird in Bytes angegeben, ein Block = 512 Bytes + self.io::iostd.data := self.buffer + self.io::iostd.length := TD_SECTOR + self.io::ioexttd.seclabel := self.label -> vor jedem Block stehen noch 16 Bytes, sog. Label + self.io::iostd.command := ETD_READ + self.doio() + +ENDPROC self.io::iostd.error + +PROC writeblock(nummer,drive=0) OF trackdisk +DEF laufvar + + IF self.io=NIL THEN self.open('trackdisk.device',drive) + + -> set the block's label to 0 + FOR laufvar := 0 TO 15 DO self.label[laufvar]:=0 + + self.io::ioexttd.count := self.getchangenum() + self.io::iostd.offset := nummer*512 + self.io::iostd.data := self.buffer + self.io::iostd.length := TD_SECTOR + self.io::ioexttd.seclabel := self.label + self.io::iostd.command := ETD_WRITE + self.doio() + self.io::iostd.command := ETD_UPDATE ->nicht nur in den internen Puffer schreiben, sondern sofort abspeichern + self.doio() + +ENDPROC self.io::iostd.error + +PROC diskindrive(drive=0) OF trackdisk +-> disk in drive? + + IF self.io=NIL THEN self.open('trackdisk.device', drive) + + self.io::iostd.command := TD_CHANGESTATE + self.doio() + IF(self.io::iostd.actual = 0) THEN RETURN(TRUE) ELSE RETURN(FALSE) + /* wenn eine Diskette drin ist, ist ioreq.iostd.actual == 0! */ + +ENDPROC + + +PROC diskprotected(drive=0) OF trackdisk +-> disk write protected? + + IF self.io=NIL THEN self.open('trackdisk.device', drive) + + self.io::iostd.command := TD_PROTSTATUS + self.doio() + RETURN(self.io::iostd.actual) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk/test.e new file mode 100644 index 0000000..5fd0ed5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/device/trackdisk/test.e @@ -0,0 +1,23 @@ +MODULE 'oomodules/library/device/trackdisk/trackdisk' + +PROC main() +DEF diskette:PTR TO trackdisk, count + + NEW diskette.new() + + IF diskette.diskindrive() + + diskette.readblock(0) + + FOR count := 0 TO 15 DO WriteF(' \z\h[2] ', diskette.buffer[count]) + WriteF('\n') + FOR count := 0 TO 15 DO IF diskette.buffer[count] THEN WriteF(' \c ', diskette.buffer[count]) ELSE WriteF(' ') + WriteF('\n') + IF diskette.diskprotected() THEN WriteF('The disk is write protected.\n') + ELSE + WriteF('Please insert a disk in drive zero.\n') + ENDIF + diskette.motor(FALSE) + + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec.e new file mode 100644 index 0000000..b7251a2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec.e @@ -0,0 +1,14 @@ +OPT MODULE + +MODULE 'oomodules/library' + +OBJECT exec OF library +ENDOBJECT + +PROC name() OF exec IS 'Exec' + +PROC open(no_1=NIL,no_2=NIL,no_3=NIL) OF exec IS NIL + +PROC close() OF exec IS NIL + +PROC end() OF exec IS NIL diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/Examples new file mode 100644 index 0000000..7ca3d58 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/Examples @@ -0,0 +1,8 @@ +@database exec_example + +@node main "Introduction to Exec" + +This object does nothing and is a basic object. Not all objects in this +directory inherit from it, though. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port.e new file mode 100644 index 0000000..45e3b8e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port.e @@ -0,0 +1,433 @@ +OPT MODULE + +MODULE 'oomodules/object', + + 'exec/ports', + 'exec/nodes', + + 'gadtools' + +EXPORT OBJECT port OF object +/****** object/port ****************************** + + NAME + port of object -- Message port object. + + FUNCTION + + ATTRIBUTES + mp:PTR TO mp -- Pointer to message port. Ready to use after new(). + + lastMessage:PTR TO mn -- Pointer to last message received. The usual + restrictions about messages apply here, too -- don't access it + when you've replied. + + SEE ALSO + object, exec.library system documentation + +********/ + mp:PTR TO mp + lastMessage:PTR TO mn +ENDOBJECT + +PROC init() OF port +/****** port/init ****************************** + + NAME + init() of port -- Initialization of the object. + + SYNOPSIS + port.init() + + FUNCTION + Creates an unnamed message port. Note that the name can be + set with the "name" tag in select(). + + EXCEPTIONS + Raises "port", text when creation failed. + + EXAMPLE + + /* + * Add a port named 'testport' to the system + */ + + NEW port.new(["name", 'testport', "add"]) + + + + SEE ALSO + port + +********/ + + self.mp := CreateMsgPort() + + IF self.mp = NIL THEN Throw("port",'Unable to create message port.') + +ENDPROC + +PROC select(opts,i) OF port +/****** port/select ****************************** + + NAME + select() of port -- Selection of action upon initialization. + + SYNOPSIS + port.select(LONG, LONG) + + port.select(opts, i) + + FUNCTION + Recognized tags are: + "name" -- set port's name + "add" -- add the port to the system + + INPUTS + opts:LONG -- List of options + + i:LONG -- Index of option list + + SEE ALSO + port + +********/ +DEF item + + item:=ListItem(opts,i) + + + SELECT item + + CASE "name" + + INC i + self.mp::ln.name := ListItem(opts,i) + + CASE "add" + + self.addToSystem() + + ENDSELECT + +ENDPROC i + +PROC getSignalMask() OF port IS Shl(1,self.mp.sigbit) +/****** port/getSignalMask ****************************** + + NAME + getSignalMask() of port -- Get signal mask for Wait() + + SYNOPSIS + port.getSignalMask() + + FUNCTION + Gets the signal mask from an existing port. This mask is used + in Wait(). + + RESULT + LONG -- Signal mask of the port. + + EXAMPLE + + /* + * Wait for a message to arrive + */ + + mask := port.getSignalMask() + port.waitForSignalMask() + + SEE ALSO + port, exec/Wait(), waitForSignalMask() + +********/ + +PROC getMsg(mode="exec") OF port +/****** port/getMsg ****************************** + + NAME + getMsg() of port -- Get message from port. + + SYNOPSIS + port.getMsg(LONG="exec") + + port.getMsg(mode) + + FUNCTION + Get a message from the port. This message can either be one of + exec's or a gadtools message, the only argument sets this mode. + + INPUTS + mode:LONG -- "exec" for exec, "gadt" for gadtools message. Default + is "exec" + + RESULT + PTR TO mn -- Message pointer or NIL if no message was at the port. + + EXAMPLE + + /* + * Wait for a message to arrive at exec's port. + */ + + mask := port.getSignalMask() + IF (port.waitForSignalMask() AND mask) + + /* + * Get it. + */ + + message := port.getMsg() + + ENDIF + + SEE ALSO + port, getSignalMask(), exec/Wait() + +********/ + + SELECT mode + + CASE "gadt" + + IF gadtoolsbase + + self.lastMessage := Gt_GetIMsg(self.mp) + RETURN self.lastMessage + + ENDIF + + DEFAULT + + self.lastMessage := GetMsg(self.mp) + RETURN self.lastMessage + + ENDSELECT + +ENDPROC + +PROC replyMsg(mode="exec") OF port +/****** port/replyMsg ****************************** + + NAME + replyMsg() of port -- Reply a message. + + SYNOPSIS + port.replyMsg(LONG="exec") + + port.replyMsg(mode) + + FUNCTION + Reply a message that was received at the port. For multi-tasking + reasons this has to be done as soon as possible after receiving it. + + INPUTS + mode:LONG -- "exec" for exec message or "gadt" for gadtools. + + EXAMPLE + + /* + * Wait for a message to arrive at exec's port. + */ + + mask := port.getSignalMask() + IF (port.waitForSignalMask() AND mask) + + + + /* + * Get it. + */ + + message := port.getMsg() + + + + /* + * Copy the important data so we can reply at once. + */ + + port.replyMsg() + + ENDIF + + + SEE ALSO + port, exec/Wait(), exec.library system documentation about messages + +********/ + + IF self.lastMessage = NIL THEN RETURN + + SELECT mode + + CASE "gadt" + + IF gadtoolsbase THEN Gt_ReplyIMsg(self.lastMessage) + + DEFAULT + + ReplyMsg(self.lastMessage) + + ENDSELECT + +ENDPROC + +PROC waitForSignalMask(mask) OF port IS Wait(mask) +/****** port/waitForSignalMask ****************************** + + NAME + waitForSignalMask() of port -- Wait for signal mask. + + SYNOPSIS + port.waitForSignalMask(LONG) + + port.waitForSignalMask(mask) + + FUNCTION + Wait until a signal according to the mask is sent to the port. + + INPUTS + mask:LONG -- Mask to wait for. The should be the one from + getSignalMask(). + + RESULT + LONG -- Signal mask received. + + SEE ALSO + port, getSignalMask() + +********/ + +PROC wait() OF port IS Wait(self.getSignalMask()) +/****** port/wait ****************************** + + NAME + wait() of port -- Wait for a message to arrive. + + SYNOPSIS + port.wait() + + FUNCTION + Waits until a message arrives at the port. Use this function when + there is only one port in your program. + + RESULT + LONG -- Signal mask received. + + NOTES + See portList for waiting on any number of ports. + + SEE ALSO + port, portList + +********/ + +PROC end() OF port +/****** port/end ****************************** + + NAME + end() of port -- Global destructor. + + SYNOPSIS + port.end() + + FUNCTION + Removes the message port from the system and deletes it. Be sure you + have received all your messages. + + SEE ALSO + port + +********/ + + IF self.mp = NIL THEN RETURN + + self.removeFromSystem() + DeleteMsgPort(self.mp) + +ENDPROC + +PROC addToSystem() OF port +/****** port/addToSystem ****************************** + + NAME + addToSystem() of port -- Add port to the system. + + SYNOPSIS + port.addToSystem() + + FUNCTION + Adds the port to the system, i. e. you can receive messages from + other programs if they know the name of your port. Provide the + "add" tag when newing the port object and it will be added when + it's initialized. + + SEE ALSO + port + +********/ + + AddPort(self.mp) + +ENDPROC + +PROC removeFromSystem() OF port +/****** port/removeFromSystem ****************************** + + NAME + removeFromSystem() of port -- Remove port. + + SYNOPSIS + port.removeFromSystem() + + FUNCTION + Removes the port from the system. No other task will be able to send + you messages any more. Called in END automatically, DO NOT call it + unless you know what you do. + + SEE ALSO + port + +********/ + + RemPort(self.mp) + +ENDPROC + +EXPORT PROC wrapPort(p:PTR TO mp) +/****** port/wrapPort ****************************** + + NAME + wrapPort() -- Wrap a port system structure in an object. + + SYNOPSIS + wrapPort(PTR TO mp) + + wrapPort(p) + + FUNCTION + Wraps the system structure port in an object of that type. When + you have a port from, say, a window this can be quite useful. The + window port can then be used as if it was a normal port object. + + INPUTS + p:PTR TO mp -- Port to wrap. + + RESULT + PTR TO port -- Port object that was just created. + + SEE ALSO + portList + +********/ +DEF port:PTR TO port + + NEW port.new() + DeleteMsgPort(port.mp) + port.mp := p + + RETURN port + +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/Examples new file mode 100644 index 0000000..f8f5b10 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/Examples @@ -0,0 +1,24 @@ +@database port_example + +@node main "Introduction to Port" + +Port is another 'wrapper' object for a system structure - exec.library's +message port. This is used in inter-task communication such as intuition +or arexx. + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/port/main} file available or this object. + +To know more about message ports read the RKRM or take a look at the @{" AEE " link "AEE:exec/message ports.guide/main"} guide about it. +@endnode + +@node where "Where to use this object" + +Wherever you need a port. + +@endnode + +@node see_also "See also" + +Port derived objects and Amiga system documentation about message ports. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxPort/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxPort/test.e new file mode 100644 index 0000000..d003566 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxPort/test.e @@ -0,0 +1,31 @@ +/* + +Open ARexx port and get messages. Print the text that was sent to stdout. +Exit on message 'QUIT' + +*/ + +MODULE 'oomodules/library/exec/port/arexxport' + +PROC main() +DEF a:PTR TO arexxPort, + quit=FALSE + + NEW a.new(["name", 'gregor', "add"]) + + REPEAT + + a.wait() + a.getMsg() + + WriteF('\s\n', a.getArgStr(0)) + + IF OstrCmp(a.getArgStr(0), 'QUIT')=0 THEN quit := TRUE + + a.replyMsg() + + UNTIL quit + + END a + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxport.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxport.e new file mode 100644 index 0000000..00be495 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/arexxport.e @@ -0,0 +1,168 @@ +OPT MODULE + +MODULE 'oomodules/library/exec/port', + + 'exec/ports', + 'exec/nodes', + + 'rexx/storage', + + 'rexxsyslib', + 'gadtools' + +EXPORT OBJECT arexxPort OF port +/****** port/arexxPort ****************************** + + NAME + arexxPort() of port -- + + SYNOPSIS + port.arexxPort(LONG, LONG) + + port.arexxPort(result1, result2) + + FUNCTION + + INPUTS + result1:LONG -- + + result2:LONG -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + port + +********/ + result1 + result2 +ENDOBJECT + +PROC replyMsg(mode="exec") OF arexxPort +/****** arexxPort/replyMsg ****************************** + + NAME + replyMsg() of arexxPort -- + + SYNOPSIS + arexxPort.replyMsg(LONG="exec") + + arexxPort.replyMsg(mode) + + FUNCTION + + INPUTS + mode:LONG -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + arexxPort + +********/ +DEF msg:PTR TO rexxmsg + + IF self.lastMessage = NIL THEN RETURN + + msg := self.lastMessage + + msg.result1:= self.result1 + msg.result2:= self.result2 + + IF msg.action AND RXFF_RESULT AND (self.result1=0) AND (self.result2<>NIL) + msg.result2:=CreateArgstring(self.result2,StrLen(self.result2)) + ENDIF + + ReplyMsg(msg) + +ENDPROC + +PROC setResults(result1, result2) OF arexxPort +/****** arexxPort/setResults ****************************** + + NAME + setResults() of arexxPort -- + + SYNOPSIS + arexxPort.setResults(LONG, LONG) + + arexxPort.setResults(result1, result2) + + FUNCTION + + INPUTS + result1:LONG -- + + result2:LONG -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + arexxPort + +********/ + + self.result1 := result1 + self.result2 := result2 + +ENDPROC + +PROC getArgStr(number) OF arexxPort +/****** arexxPort/getArgStr ****************************** + + NAME + getArgStr() of arexxPort -- + + SYNOPSIS + arexxPort.getArgStr(LONG) + + arexxPort.getArgStr(number) + + FUNCTION + + INPUTS + number:LONG -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + arexxPort + +********/ + + RETURN self.lastMessage::rexxmsg.args[number] + +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portList/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portList/test.e new file mode 100644 index 0000000..500d3b6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portList/test.e @@ -0,0 +1,309 @@ +/* + +Old program that builds a frame for own programs that use more than one +window. + +Created back in 1993 where 2.1b was the available version of EC :) + +The REPEAT...UNTIL loop in the *huge* main proc shows the usage of portList +and port procs. + +es, the program looks ugly. I just browsed through my sources looking for +a program that works with multiple windows and that was easy to modify... + +*/ + +/* + * Windowgrundgerüst.e + * + * Ein kleines Proggy, das ein Haupt- und Nebenfenster öffnet und in das + * Hauptfenster ein Menü hängt. Samt Abfrage der Inputevents. Flagge für + * gedrückte linke Maustaste. IntuiMessage wird kopiert in + * ·meineintmessage· und dann sofort zurückgegeben. Bei Betätigung des + * Close-Gadgets werden im Hafen liegende Nachrichten abgeholt, jedoch + * nicht bearbeitet. + * + * V1.3 von Gregor Goldbach. 'Placed in the Public Domain.' + * compilierbar mit v2.1b/v3.0a/v3.0b + */ + + +MODULE 'intuition/intuition','intuition/screens','gadtools', + 'libraries/gadtools', 'graphics/text','exec/ports','graphics/scale', + 'graphics/rastport','graphics/gfx','exec/memory', 'exec/nodes', + 'exec/lists', + + 'oomodules/library/exec/port/portList', + 'oomodules/library/exec/port' + + +ENUM FEHLER_NOGADTOOLS,FEHLER_NOVISUAL,FEHLER_NOMENUS, FEHLER_GADGET, FEHLER_CONTEXT + +DEF hauptwin:PTR TO window, /* Hauptfenster */ + nebenwin:PTR TO window, /* Nebenfenster */ + uport:PTR TO mp, /* UserPort: für Signal */ + pscreen:PTR TO screen, /* für LockPubScreen() */ + lmbdown=FALSE, /* Flagge: gesetzt, wenn linke Maustaste gedrückt */ + intmsg:PTR TO intuimessage, /* von GetMsg() */ + meineintmessage:PTR TO intuimessage, /* Kopie der intmsg */ + zahl1,zahl2, + zkette_x[80]:STRING, adresse_x, + + vinfo=NIL, /* VisualInfo, muß 0 sein */ + menu=NIL, /* für LayoutMenus(), muß 0 sein */ + + listv:PTR TO LONG, + gadgetliste=NIL, + g:PTR TO gadget + +PROC main() HANDLE + +DEF meineklasse,meincode,x,y,x2,y2,laufvar, + + ports:PTR TO portList, + port:PTR TO port, + portKey + + NEW ports.new() + + IF(meineintmessage := AllocMem(SIZEOF intuimessage, MEMF_CLEAR OR MEMF_PUBLIC))=NIL + WriteF('Kein Speicher (\d Bytes) für Kopie der intuimessage!\n', SIZEOF intuimessage) + CleanUp(20) + ENDIF + + gadtoolsbase := OpenLibrary('gadtools.library', 37) + IF gadtoolsbase=NIL THEN Raise(FEHLER_NOGADTOOLS+4) + + pscreen := LockPubScreen(NIL) + IF(vinfo := GetVisualInfoA(pscreen, NIL)) = NIL THEN Raise(FEHLER_NOVISUAL) + IF(g:=CreateContext( {gadgetliste} ))=NIL THEN Raise(FEHLER_CONTEXT) + + listv:=[0,0,0,0]; listv[0]:=listv+4; listv[2]:=listv /* listenheader?*/ + AddTail(listv,[0,0,0,0,'eins']:ln) + AddTail(listv,[0,0,0,0,'zwei']:ln) + AddTail(listv,[0,0,0,0,'drei']:ln) + AddTail(listv,[0,0,0,0,'vier']:ln) + AddTail(listv,[0,0,0,0,'fünf']:ln) + + IF (g:=CreateGadgetA(LISTVIEW_KIND,g, + [8,4,155,40,NIL,NIL,2,0,vinfo,0]:newgadget, + [GTLV_LABELS,listv, + GTLV_SHOWSELECTED,0, + 0,0]))=NIL THEN Raise(FEHLER_GADGET) + + hauptwin := OpenWindowTagList(NIL, + [WA_TITLE,'Hauptfenster', + WA_IDCMP,IDCMP_RAWKEY OR IDCMP_CLOSEWINDOW OR IDCMP_MOUSEMOVE OR IDCMP_GADGETUP OR IDCMP_GADGETDOWN OR IDCMP_MOUSEBUTTONS OR IDCMP_MENUPICK OR IDCMP_REFRESHWINDOW, + WA_FLAGS,WFLG_ACTIVATE+WFLG_CLOSEGADGET, + WA_GADGETS, gadgetliste, + WA_INNERHEIGHT,120, WA_DEPTHGADGET, TRUE, + WA_DRAGBAR, TRUE, + WA_REPORTMOUSE,TRUE,WA_GIMMEZEROZERO,TRUE,NIL]) + + Gt_RefreshWindow(hauptwin,NIL) + + SetAPen(hauptwin.rport,1) + SetBPen(hauptwin.rport,0) + SetDrMd(hauptwin.rport,RP_JAM2) + + nebenwin := OpenWindowTagList(NIL, + [WA_TITLE,'Nebenfenster',WA_IDCMP,IDCMP_RAWKEY+IDCMP_CLOSEWINDOW+IDCMP_MOUSEMOVE+IDCMP_GADGETUP+IDCMP_MOUSEBUTTONS+IDCMP_MENUPICK OR IDCMP_REFRESHWINDOW, + WA_FLAGS,WFLG_ACTIVATE+WFLG_CLOSEGADGET, + WA_TOP,120, + WA_INNERHEIGHT,60,WA_DEPTHGADGET,TRUE, + WA_DRAGBAR, TRUE, + WA_REPORTMOUSE,TRUE,WA_GIMMEZEROZERO,TRUE,NIL]) + + + /* + * Add port to the list and use window pointers as keys. We get the + * according key when a message arrives at that port. + */ + + ports.add(hauptwin.userport, hauptwin) + ports.add(nebenwin.userport, nebenwin) + + + + REPEAT + + /* + * Get message, port key and port from the list. + */ + + intmsg, portKey, port := ports.waitAndGet("gadt") + + + /* + * Check portKey for matching window pointer + */ + + IF(portKey = hauptwin) + REPEAT + + kopiere_intmessage(intmsg,meineintmessage) + + port.replyMsg("gadt") + + meineklasse := meineintmessage.class + meincode := meineintmessage.code + + SELECT meineklasse + CASE IDCMP_CLOSEWINDOW + /* + * Nach Betätigung des Close-Gadgets werden alle eingelaufenen + * Nachrichten entfernt. + */ + WHILE(intmsg := port.getMsg("gadt")) DO port.replyMsg("gadt") + + CASE IDCMP_MENUPICK + handle_menus(meincode) + CASE IDCMP_MOUSEBUTTONS + IF meincode = 104 + lmbdown:=TRUE + tete(hauptwin,'Hi! and Welcome', 12,10,40,10) + tete(hauptwin,'The Amiga E Encyclopedia', 12,20,40,10) + + ELSEIF meincode = 232 + lmbdown:=FALSE + ENDIF + CASE IDCMP_GADGETUP + StringF(zkette_x, 'Eintrag Nummer \d.', meincode) + Move(hauptwin.rport, 100, 100) + Text(hauptwin.rport, zkette_x, StrLen(zkette_x)) + + CASE IDCMP_REFRESHWINDOW + Gt_BeginRefresh(hauptwin) + Gt_EndRefresh(hauptwin, TRUE) + + ENDSELECT + UNTIL (intmsg := port.getMsg("gadt")=NIL) + + ELSEIF(portKey = nebenwin) + + /* + * Here we have the more 'traditional' way of message processing. + */ + + WHILE(intmsg := Gt_GetIMsg(nebenwin.userport)) + kopiere_intmessage(intmsg,meineintmessage) + Gt_ReplyIMsg(intmsg) + + meineklasse := meineintmessage.class + meincode := meineintmessage.code + + SELECT meineklasse + CASE IDCMP_CLOSEWINDOW + /* + * Nach Betätigung des Close-Gadgets werden alle eingelaufenen + * Nachrichten entfernt. + */ + WHILE(intmsg := GetMsg(hauptwin.userport)) DO ReplyMsg(intmsg) + + CASE IDCMP_MOUSEBUTTONS + IF meincode = 104 + lmbdown:=TRUE + + ELSEIF meincode = 232 + lmbdown:=FALSE + ENDIF + + CASE IDCMP_REFRESHWINDOW + Gt_BeginRefresh(hauptwin) + Gt_EndRefresh(hauptwin, TRUE) + + ENDSELECT + ENDWHILE + ENDIF + + UNTIL ((meineklasse=IDCMP_CLOSEWINDOW) AND (portKey AND hauptwin)) + + ClearMenuStrip(hauptwin) + FreeMenus(menu) + CloseWindow(hauptwin) + IF nebenwin THEN CloseWindow(nebenwin) + IF gadgetliste THEN FreeGadgets(gadgetliste) + FreeVisualInfo(vinfo) + UnlockPubScreen(NIL,pscreen) + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + FreeMem(meineintmessage, SIZEOF intuimessage) + WriteF('Einen schönen Tag noch!\n') + CleanUp(0) +EXCEPT + IF hauptwin THEN ClearMenuStrip(hauptwin) + IF menu THEN FreeMenus(menu) + IF vinfo THEN FreeVisualInfo(vinfo) + IF(hauptwin) THEN CloseWindow(hauptwin) + IF nebenwin THEN CloseWindow(nebenwin) + IF gadgetliste THEN FreeGadgets(gadgetliste) + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + WriteF('Fehler Nummer \d\n',exception) + CleanUp(20) + +ENDPROC + + +PROC handle_menus(code) +DEF titel,item,subitem,gadnummer,zkette[50]:STRING,fenster:PTR TO window, + laufvar + + titel := (code AND %11111) /* Bits 0-4 */ + item := ((code/32) AND %111111) /* Bits 5-11 */ + subitem := ((code/2048) AND %11111) /* Bits 11-15 */ + + IF (code < 65535) + SELECT titel + CASE 1 + SELECT item + CASE 0 + NOP + CASE 1 + NOP + CASE 2 + NOP + CASE 3 + NOP + ENDSELECT + ENDSELECT + ENDIF +ENDPROC + + +PROC kopiere_intmessage(i1,i2) +/* kopiert die inhalte von i1 nach i2 */ +DEF int1:PTR TO intuimessage,int2:PTR TO intuimessage + + int1 := i1 + int2 := i2 + +/* + int2.execmessage := int1.execmessage +*/ + int2.class := int1.class + int2.code := int1.code + int2.class := int1.class + int2.qualifier := int1.qualifier + int2.iaddress := int1.iaddress + int2.mousex := int1.mousex + int2.mousey := int1.mousey + int2.seconds := int1.seconds + int2.micros := int1.micros + int2.idcmpwindow := int1.idcmpwindow + int2.speciallink := int1.speciallink + +ENDPROC + +PROC tete(win:PTR TO window, zkette, x_start,y_start, x_end,y_end) +DEF zaehler + + FOR zaehler := x_start TO x_end + Move(win.rport,zaehler,y_start) + SetAPen(win.rport,1) + Text(win.rport,zkette, StrLen(zkette)) + WaitTOF() + SetAPen(win.rport,0) + Text(win.rport,zkette, StrLen(zkette)) + ENDFOR + +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portlist.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portlist.e new file mode 100644 index 0000000..4255739 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/exec/port/portlist.e @@ -0,0 +1,196 @@ +OPT MODULE + +MODULE 'oomodules/list/associativeArray', + 'oomodules/library/exec/port', + + 'exec/ports' + +EXPORT OBJECT portList OF associativeArray +/****** associativeArray/portList ****************************** + + NAME + portList() of associativeArray -- + + SYNOPSIS + associativeArray.portList(LONG) + + associativeArray.portList(signalMask) + + FUNCTION + + INPUTS + signalMask:LONG -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + associativeArray + +********/ + signalMask +ENDOBJECT + +PROC add(p:PTR TO mp,key) OF portList +/****** portList/add ****************************** + + NAME + add() of portList -- + + SYNOPSIS + portList.add(PTR TO mp, LONG) + + portList.add(p, key) + + FUNCTION + + INPUTS + p:PTR TO mp -- + + key:LONG -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + portList + +********/ +DEF port:PTR TO port + + port := wrapPort(p) + + SUPER self.set(key, port) + self.signalMask := self.signalMask OR port.getSignalMask() + +ENDPROC + +PROC delete(port:PTR TO port) OF portList +/****** portList/delete ****************************** + + NAME + delete() of portList -- + + SYNOPSIS + portList.delete(PTR TO port) + + portList.delete(port) + + FUNCTION + + INPUTS + port:PTR TO port -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + portList + +********/ + + IF port = NIL THEN RETURN + + self.remove(port) + END port + +ENDPROC + +PROC wait() OF portList IS Wait(self.signalMask) +/****** portList/wait ****************************** + + NAME + wait() of portList -- + + SYNOPSIS + portList.wait() + + FUNCTION + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + portList + +********/ + +PROC waitAndGet(mode="exec") OF portList +/****** portList/waitAndGet ****************************** + + NAME + waitAndGet() of portList -- + + SYNOPSIS + portList.waitAndGet(LONG="exec") + + portList.waitAndGet(mode) + + FUNCTION + + INPUTS + mode:LONG -- + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + portList + +********/ +DEF signal, + port:PTR TO port, + index=-1 + + IF self.tail = 0 THEN RETURN + + signal := self.wait() + + REPEAT + + INC index + port := self.val[index] + + UNTIL (signal AND port.getSignalMask()) + +-> WriteF('Message arrived at port \d.\n', port) + + RETURN port.getMsg(mode), self.key[index], port + +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/gadtools.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/gadtools.e new file mode 100644 index 0000000..30c7d5d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/gadtools.e @@ -0,0 +1,94 @@ +OPT MODULE + +MODULE 'oomodules/library', + 'oomodules/object', + + 'gadtools', + 'libraries/gadtools' + +EXPORT OBJECT gadtools OF library +ENDOBJECT + +EXPORT PROC init() OF gadtools + + self.version:=0 + self.open() + +ENDPROC + +PROC open() OF gadtools + + IF gadtoolsbase THEN RETURN + + IF (gadtoolsbase := OpenLibrary('gadtools.library', self.version))=NIL THEN Throw("lib", 'Unable to open gadtools.library') + +ENDPROC + +PROC close() OF gadtools +/****** locale/close ****************************** + + NAME + close() of locale -- + + SYNOPSIS + locale.close() + + FUNCTION + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + locale + +********/ + + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + +ENDPROC + + +PROC end() OF gadtools +/****** locale/end ****************************** + + NAME + end() of locale -- + + SYNOPSIS + locale.end() + + FUNCTION + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + locale + +********/ + + self.close() + +ENDPROC + + + +PROC name() OF gadtools IS 'Gadtools' +/*EE folds +-1 +12 4 15 5 18 27 22 27 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale.e new file mode 100644 index 0000000..e110757 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale.e @@ -0,0 +1,392 @@ +OPT MODULE + +MODULE 'oomodules/library', + 'oomodules/object', + 'oomodules/sort/string', + + 'locale', + 'libraries/locale' + +EXPORT OBJECT locale OF library +/****** library/locale ****************************** + + NAME + locale of library + + PURPOSE + Object wrapper for the locale.library + + ATTRIBUTES + catalog:LONG -- Catalog as returned from OpenCatalog() + + builtinLanguage:LONG -- String that says which language we want. + NIL is for english. + + SEE ALSO + library + +********/ + catalog -> the current catalog + builtinLanguage -> if NIL it's english +ENDOBJECT + +EXPORT PROC init() OF locale +/****** locale/init ****************************** + + NAME + init() of locale -- Initilization of the object. + + SYNOPSIS + locale.init() + + FUNCTION + Opens any version of the library. + + SEE ALSO + locale + +********/ + + self.version:=0 + self.open() + +ENDPROC + +PROC open() OF locale +/****** locale/open ****************************** + + NAME + open() of locale -- Open locale. + + SYNOPSIS + locale.open() + + FUNCTION + Opens the locale.library and throws an exceptions if opening failed. + + SEE ALSO + locale, library/open + +********/ + + IF localebase THEN RETURN + + IF (localebase := OpenLibrary('locale.library', self.version))=NIL THEN Throw("lib", 'Unable to open locale.library') + +ENDPROC + +PROC close() OF locale +/****** locale/close ****************************** + + NAME + close() of locale -- Close locale.library + + SYNOPSIS + locale.close() + + FUNCTION + Closes the library if it was open. + + SEE ALSO + locale, library/close + +********/ + + IF localebase THEN CloseLibrary(localebase) + +ENDPROC + +PROC openCatalog(locale, name:PTR TO CHAR, builtinLanguage=NIL:PTR TO CHAR) OF locale +/****** locale/openCatalog ****************************** + + NAME + openCatalog() of locale -- Open catalog. + + SYNOPSIS + locale.openCatalog(LONG, PTR TO CHAR, PTR TO CHAR=NIL:PTR TO CHAR) + + locale.openCatalog(locale, name, builtinLanguage) + + FUNCTION + Opens the specified catalog. If the catalog of this object is open + when you call this function it is closed first. + + INPUTS + locale:LONG -- Pointer to locale structure, normally left NIL. + + name:PTR TO CHAR -- Name o catalog to open. + + builtinLanguage:PTR TO CHAR -- 'Native' language of your program. + Used if the desired catalog couldn't be opened. If NIL, your + program speaks english. + + RESULT + LONG -- Opended catalog or NIL if opening failed. + + EXAMPLE + /* + * Try to open term's catalog. + */ + + NEW locale.new(["ctlg", 'term.catalog']) + + + + /* + * Success? + */ + + IF locale.catalog + + /* + * do anything with it + */ + + ENDIF + + + + /* + * Try to open the Prefs catalog. If term.catalog is still open, + * it will be closed first. + */ + + locale.openCatalog(NIL, 'prefs.catalog', NIL) + + /* + * do anything with it + */ + + SEE ALSO + locale + +********/ + + IF self.catalog -> if there's a catalog open + + self.closeCatalog(self.catalog) + + self.catalog := NIL + + ENDIF + + self.builtinLanguage := builtinLanguage + + self.catalog := OpenCatalogA(locale,name, IF self.builtinLanguage=NIL THEN 'english' ELSE self.builtinLanguage) + + RETURN self.catalog + +ENDPROC + +PROC closeCatalog(catalog) OF locale +/****** locale/closeCatalog ****************************** + + NAME + closeCatalog() of locale -- Close catalog. + + SYNOPSIS + locale.closeCatalog(LONG) + + locale.closeCatalog(catalog) + + FUNCTION + Closes a catalog that was opened with openCatalog(). + + INPUTS + catalog:LONG -- Catalog to close. + + SEE ALSO + locale + +********/ + + IF catalog THEN CloseCatalog(catalog) + +ENDPROC + +PROC getString(number, default=NIL:PTR TO CHAR) OF locale +/****** locale/getString ****************************** + + NAME + getString() of locale -- Get string from open catalog. + + SYNOPSIS + locale.getString(LONG, PTR TO CHAR=NIL:PTR TO CHAR) + + locale.getString(number, default) + + FUNCTION + Gets a string from an opened catalog and returns it. If it fails, + the passed default string will be returned. + + INPUTS + number:LONG -- Number of string to get from the catalog. + + default:PTR TO CHAR -- Default string to return on failure. + + RESULT + PTR TO CHAR -- string from catalog or default string. + LONG -- "NoCa" if no catalog is open. + + SEE ALSO + locale + +********/ +-> gets a string from the current catalog +-> if no catalog is open returns "NoCa" (no catalog) + + IF self.catalog THEN RETURN GetCatalogStr(self.catalog,number,default) ELSE RETURN "NoCa" + +ENDPROC + +PROC end() OF locale +/****** locale/end ****************************** + + NAME + end() of locale -- Global destructor. + + SYNOPSIS + locale.end() + + FUNCTION + Closes open catalog and locale.library. + + SEE ALSO + locale + +********/ + + self.closeCatalog(self.catalog) + + self.close() + +ENDPROC + +PROC select(optionlist, index) OF locale +/****** locale/select ****************************** + + NAME + select() of locale -- Selection of action upon initialisation. + + SYNOPSIS + locale.select(LONG, LONG) + + locale.select(optionlist, index) + + FUNCTION + The following tags are recognized: + "ctlg" -- Name of catalog to open. The catalog will be opened + at once via openCatalog(). + "lang" -- Sets the builtin language. Any string or NIL for + 'english' + + INPUTS + optionlist:LONG -- List of options. + + index:LONG -- Index of optionlist. + + SEE ALSO + locale + +********/ +DEF item + + item:=ListItem(optionlist,index) + + SELECT item + + CASE "ctlg" -> open catalog + + INC index + self.openCatalog(NIL, ListItem(optionlist,index), self.builtinLanguage) + + CASE "lang" -> set builtin language + + INC index + self.builtinLanguage := ListItem(optionlist,index) + + ENDSELECT + +ENDPROC index + +PROC getObjectString(object:PTR TO object, container:PTR TO string,number, default=NIL:PTR TO CHAR) OF locale +/****** locale/getObjectString ****************************************** + + NAME + getLocalizedObjectString() -- Get string from object catalog + + SYNOPSIS + locale.getObjectString(PTR TO object, PTR TO string, LONG, PTR TO CHAR=NIL:PTR TO CHAR) + + locale.getObjectString(object, container, number, default) + + FUNCTION + Gets a string from the object's catalog. + + INPUTS + object:PTR TO object -- Object to get the string for + + container:PTR TO string -- String object to store the string in + + number:LONG -- Number of string to get + + default=NIL:PTR TOF CHAR -- The default string to return if there is no string + of that number. + + RESULT + "NoCa" if the locale.library couldn't be opened. + The default string if there's no entry of that number in the catalog, + otherwise the requested string. + + NOTES + The returned string from the catalog is READ-ONLY. + +******************************************************************************/ + +DEF string:PTR TO string, + oldCatalog, + stringToReturn:PTR TO CHAR + + END container + NEW container.new() + + NEW string.new() + string.cat('oomodules/') + string.cat(object.name()) + string.cat('.catalog') + + /* + * 'save' the old catalog + */ + + oldCatalog := self.catalog + + /* + * Set it to NIL so self.openCatalog() won't close it + */ + + self.catalog:=NIL + + /* + * Open the object's catalog + */ + + self.openCatalog(NIL, string.write(), self.builtinLanguage) + + stringToReturn := self.getString(number,default) + container.cat(stringToReturn) + + self.closeCatalog(self.catalog) + + /* + * Restore the old catalog + */ + + self.catalog := oldCatalog + + END string + +ENDPROC + + +PROC name() OF locale IS 'Locale' diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/Examples new file mode 100644 index 0000000..7d4441e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/Examples @@ -0,0 +1,19 @@ +@database locale_example + +@node main "Introduction to locale" + +Locale is the wrapping object for the locale library, the library that +'localizes' programs, i.e. more than one language is available. + +The locale object of the oomodules/ hierarchy doesn't enhance the usage +of libraries very much - at least not at this basic level. There are +derived objects that use this object as a 'foundation', e.g. the catalogList +object. + + +There are two examples, the first @{" example " link EMODULES:oomodules/library/locale/test.e/main} shows the basic functions +and the @{" second " link EMODULES:oomodules/library/locale/testObjectString.e/main} gets strings from one of ooep's object catalogs. + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/locale/main} file available or this object. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList.e new file mode 100644 index 0000000..d6d57e9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList.e @@ -0,0 +1,375 @@ +OPT MODULE + +MODULE 'oomodules/sort/string', + 'oomodules/list/associativeArray', + 'oomodules/library/locale' + +OBJECT nuArray OF associativeArray +/****** nuArray/nuArray ****************************** + + NAME + nuArray() of associativeArray + + PURPOSE + Just to override the testKey() method. This array has strings as + keys. The strings are the names of the catalogs. When ENDing this + object the values (catalogs) are disposed (closed) automatically. + + ATTRIBUTES + cl:PTR TO catalogList -- The catalogList I am in. Just for + convenience with disposeVal(). + + SEE ALSO + associativeArray + +********/ + cl:PTR TO catalogList +ENDOBJECT + + + +EXPORT OBJECT catalogList OF locale +/****** catalogList/catalogList ****************************** + + NAME + catalogList of locale + + PURPOSE + This object holds any number of catalogs at the same time. Use it + to make your application use more than one catalog. + + catalogList is needed for the localization of the ooep: each object + has it's own catalog. Therefore it is necessary to hold any number + of objects open simultaneously. + + ATTRIBUTES + catalogArray:PTR TO nuArray -- a slightly modified associativeArray. + The keys aren't numbers but the names of the catalogs. + + SEE ALSO + associativeArray/associativeArray + +********/ + catalogArray:PTR TO nuArray +ENDOBJECT + + + + +/****************** + + methods of nuArray + +******************/ + +PROC testKey(string1, string2) OF nuArray IS OstrCmp(string1, string2) +/****** nuArray/testKey ****************************** + + NAME + testKey() of nuArray -- Compare two keys. + + SYNOPSIS + nuArray.testKey(LONG, LONG) + + nuArray.testKey(string1, string2) + + FUNCTION + Compares two keys. See associativeArray/testKey(). + In this object the keys are strings. Comparing is done with E's + builtin OstrCmp(). + + INPUTS + string1:LONG -- First string to compare. + + string2:LONG -- Second string to compare. + + RESULT + See E.doc/OstrCmp() for the return values. + + SEE ALSO + nuArray + +********/ + +PROC disposeVal(catalog) OF nuArray +/****** nuArray/disposeVal ****************************** + + NAME + disposeVal() of nuArray -- Dispose the value. + + SYNOPSIS + nuArray.disposeVal(LONG) + + nuArray.disposeVal(catalog) + + FUNCTION + Disposes the value stored in the nuArray. This is a catalog, the + disposing means that it's closed. + + INPUTS + catalog:LONG -- Catalog to be closed. + + SEE ALSO + nuArray/nuArray, associativeArray/associativeArray + +********/ +DEF cl:PTR TO catalogList + + cl := self.cl + cl.closeCatalog(catalog) + +ENDPROC + + + +/****************** + + methods of catalogList + +******************/ + + + +PROC init() OF catalogList +/****** catalogList/init ****************************** + + NAME + init() of catalogList -- Initialization of the object. + + SYNOPSIS + catalogList.init() + + FUNCTION + The nuArray is NEWed and SUPER init() is called. + + SEE ALSO + catalogList/catalogList + +********/ + + NEW self.catalogArray.new() + + self.catalogArray.cl := self + + SUPER self.init() -> locale.init() + +ENDPROC + +PROC setCurrentCatalog(locale, name:PTR TO CHAR, builtinLanguage=NIL:PTR TO CHAR) OF catalogList HANDLE +/****** catalogList/setCurrentCatalog ****************************** + + NAME + setCurrentCatalog() of catalogList -- Set the catalog to work with + + SYNOPSIS + catalogList.setCurrentCatalog(LONG, PTR TO CHAR, PTR TO CHAR=NIL) + + catalogList.setCurrentCatalog(locale, name, builtinLanguage) + + FUNCTION + Sets the 'current' catalog, i.e. all procs that work with a catalog + will work with this one. If the catalog isn't open it will be opened. + + INPUTS + locale:LONG -- locale structure as needed by the locale.library. + Usually this can be left NIL. + + name:PTR TO CHAR -- name of the catalog. + + builtinLanguage=NIL:PTR TO CHAR -- the language the strings in the + source are written in. NIL means that English is builtin. + + RESULT + the catalog + + EXAMPLE + cl.setCurrentCatalog(NIL,'oomodules/object') + + SEE ALSO + catalogList + +********/ +DEF catalog + +-> WriteF('Setting the new catalog .\s.\n',name) + + catalog := self.catalogArray.get(name) + + self.catalog := catalog + RETURN catalog + +EXCEPT + +-> WriteF('have to open it.\n\n') + + catalog := self.openCatalog(locale,name,builtinLanguage) + + IF catalog + + self.catalogArray.set(name, catalog) + + self.catalog := catalog + + ENDIF + + RETURN catalog + +ENDPROC + +PROC removeCurrentCatalog() OF catalogList HANDLE +/****** catalogList/removeCurrentCatalog ****************************** + + NAME + removeCurrentCatalog() of catalogList -- Remove catalog from list. + + SYNOPSIS + catalogList.removeCurrentCatalog() + + FUNCTION + Removes the current catalog from the internal list. It is *not* + closed, you have to do that. + + RESULT + the current catalog + + SEE ALSO + catalogList + +********/ + + IF self.catalog THEN self.catalogArray.remove(self.catalog) + RETURN self.catalog + +EXCEPT + +ENDPROC + +PROC end() OF catalogList +/****** catalogList/end ****************************** + + NAME + end() of catalogList -- Global destructor. + + SYNOPSIS + catalogList.end() + + FUNCTION + ENDs the nuArray and calls SUPER end(). + + SEE ALSO + catalogList, locale/end() + +********/ + + END self.catalogArray + + SUPER self.end() + +ENDPROC + +PROC select(optionlist, index) OF catalogList +/****** catalogList/select ****************************** + + NAME + select() of catalogList -- Selection of action. + + SYNOPSIS + catalogList.select(LONG, LONG) + + catalogList.select(optionlist, index) + + FUNCTION + Supports the following tags: + + "ctlg" -- Name of catalog to open at once. + + "lang" -- Bultin language to set. NIL means English. Set this + before you open any catalog. + + INPUTS + optionlist:LONG -- elist of options + + index:LONG -- index of option list + + RESULT + index after processing one tag. + + SEE ALSO + catalogList, object/select() + +********/ +DEF item + + item:=ListItem(optionlist,index) + + SELECT item + + CASE "ctlg" -> open catalog + + INC index + self.setCurrentCatalog(NIL, ListItem(optionlist,index), self.builtinLanguage) + + CASE "lang" -> set builtin language + + INC index + self.builtinLanguage := ListItem(optionlist,index) + + ENDSELECT + +ENDPROC index + + + +PROC name() OF catalogList IS 'CatalogList' +/****** catalogList/name ****************************** + + NAME + name() of catalogList -- Return object's name. + + SYNOPSIS + catalogList.name() + + FUNCTION + Returns the name of the object. + + RESULT + 'CatalogList' + + SEE ALSO + catalogList + +********/ + +PROC length() OF catalogList IS self.catalogArray.tail-1 +/****** catalogList/length ****************************** + + NAME + length() of catalogList -- Get number of catalogs open. + + SYNOPSIS + catalogList.length() + + FUNCTION + Gets you the number of catalogs open. + + RESULT + LONG -- tail entry of nuArray minus 1. + + SEE ALSO + catalogList, nuArray/nuArray + +********/ + +/* +PROC write(index) OF catalogList + WriteF('key\d=\d val\d=$\h\n', index, self.catalogArray.key[index], index, self.catalogArray.val[index]) + +ENDPROC + +*/ + + +/*EE folds +-1 +133 22 136 58 139 25 142 20 145 48 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/Examples new file mode 100644 index 0000000..acaac06 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/Examples @@ -0,0 +1,26 @@ +@database catalogList_example + +@node main "Introduction to catalogList" + +The catalogList object is exactly what its name suggests - a list of +catalogs. It was developed for internal use of the oomodules hierarchy. +Since each object can have it's own catalog and an application can use +many objects there has to be a way to deal with any number of catalogs +open at any time. + +This is were the catalogList object comes in handy. By using the +setCurrentCatalog() method one can switch between catalogs. It doesn't +matter if this catalog is open or not, if this function returns non-NIL +access is granted. + +There is an @{" example " link EMODULES:oomodules/library/locale/catalogList/test.e/main} available + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/catalogList/main} file available or this object. + + + +Again, this object was developed for internal use. Yes, you can use it +in your applications, but normally there should be no need for it for +an application has only one catalog. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/test.e new file mode 100644 index 0000000..c57d5d5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/catalogList/test.e @@ -0,0 +1,72 @@ +/* + +Example program for the catalogList object. + +*/ + + + +MODULE 'oomodules/library/locale/catalogList' + +PROC main() +DEF cl:PTR TO catalogList, index + + /* + * Open the catalogs with builtin language english + */ + + NEW cl.new(["ctlg", 'term.catalog', "ctlg", 'oomodules/object.catalog']) + WriteF('number of catalogs open: \d\n', cl.length()) + + + + /* + * Set the current catalog. If the catalog attribute is non-NIL the + * setting was successful. + */ + + cl.setCurrentCatalog(NIL,'term.catalog') + IF cl.catalog + + WriteF('\s\n\s\n\s\n', cl.getString(1,'bla'), + cl.getString(2,'bla'), + cl.getString(3,'bla')) + + ENDIF + + + + /* + * Switch to the other catalog. Note that if we hadn't opened the + * object.catalog yet this proc would open it now. + */ + + cl.setCurrentCatalog(NIL,'oomodules/object.catalog') + IF cl.catalog + + WriteF('\s\n\s\n\s\n', cl.getString(1,'bla'), + cl.getString(2,'bla'), + cl.getString(3,'bla')) + + ENDIF + + + + /* + * Switch back to term + */ + + cl.setCurrentCatalog(NIL,'term.catalog') + IF cl.catalog + + WriteF('\s\n\s\n\s\n', cl.getString(1,'bla'), + cl.getString(2,'bla'), + cl.getString(3,'bla')) + + ENDIF + + + + END cl + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/cataloglist.m b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/cataloglist.m new file mode 100644 index 0000000000000000000000000000000000000000..c5db9521525b81bcb6b101b7ee8d812cb538e934 GIT binary patch literal 2222 zcmc&!&u<$=6#mvW?owHisjSF{N^GqNC2Csd5TOeB;9!FcxQ^8Z$RTaIu_w-!&91e( zPSe66{{e&(C&V!aD&^1%QvVk&2#(y4Wf_)lW_SIol@O<{Jf4|1-}~O1_rBea?rzud z7UJi-WN}q3()|Cu^?5kH*$BtwTgY+fjngn}{em>U-u@H0)`Ql7h#?U}-+9eD1);Y16K4P@uYn-B}cuse}mB<@a6pX6zGf-v>z;KaK-kZu>H*SSvi8GE+ zP*}-s1LWUmolm%BCga8*@1ndOUUIzPxLDf`FSkb6TWf?b*6xNE2~SyP zkkRCQWL7!3UfUuzy6Jd{QClr!uc9zFflB12*O(mt_zE+#c-~AufJh;?uM(#eR{^I?@gns7479|eVcK8Wo>z~aI?a~KJ{uYF=wGyB5PIM zrPw+*zAUxN@2CzxX{!!@c)<=&yGG1h*M>>`l+ObyMwd!5DxJXYT|N)Thd|}tbE!aT zBv#`T%h-|r^3h7=u^V-OHN0(9Y|}}249W8~c1r=JMVw_GRL=VH9v=Xst#7+7{-IZc*tVD^;b677W;x8-@}Q-G0lXAp0AZ|ni- zO-aHvu#0QH2xc^kSdoL+Dg?=>`$?}=dh;IZfg z_XE#zsPs(Cr=fwXJWcGWiM@`cj_vwll7c$X!1vtk3uj_ZGSg5&R(V8$HQYf~A}4ul zvYz4z$dlY<16j+lf(c?BS>JjVRb1j$B}3rzJn~q9?hBjOpoM*-)j(Ewp6f+>;5xFC zo=MswGQ#P~l|&b?+!da6BDyu(^!>A;j|f#N(*x7u_nD78$$cd#5`{tj z#NJS7qBe@J#P%*>*doEp97?=+TBgY5v}q)l2Ott{>I^`fGXopiGgv9m@sJ;;LFAbbRr2qf` literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/test.e new file mode 100644 index 0000000..d31d11d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/test.e @@ -0,0 +1,37 @@ +/* + +Example program for the locale object. Very simple, really. It opens an +existing catalog and displays a message. + +*/ + + + +MODULE 'oomodules/library/locale' + +PROC main() +DEF locale:PTR TO locale + + /* + * Open the term catalog with builtin language english + */ + + NEW locale.new(["ctlg", 'term.catalog']) + + + + /* + * If it's open get some strings and write the result. + */ + + IF locale.catalog + + WriteF('\s\n\s\n\s\n', locale.getString(1,'bla'), + locale.getString(2,'bla'), + locale.getString(3,'bla')) + + ENDIF + + + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/testObjectString.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/testObjectString.e new file mode 100644 index 0000000..a2dac7d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/locale/testObjectString.e @@ -0,0 +1,86 @@ +/* + +Short sample program for the locale object. + +*/ + + + +MODULE 'oomodules/library/locale', + 'oomodules/object', + 'oomodules/sort/string' + + + +PROC main() +DEF locale:PTR TO locale, + object:PTR TO object, + string:PTR TO string + + + /* + * Allocate objects. The string object is needed in getObjectString() + */ + + NEW string.new() + NEW object.new() + + + + /* + * Open the term catalog with builtin language english + */ + + NEW locale.new(["ctlg", 'term.catalog']) + IF locale.catalog + + + + /* + * Get the frist three strings and print them. + */ + + WriteF('Here are some strings from term\as catalog:\n\n') + WriteF('\s\n\s\n\s\n', locale.getString(1,'bla'), + locale.getString(2,'bla'), + locale.getString(3,'bla')) + + + + ELSE + + RETURN + + ENDIF + + + + WriteF('\n\n') + WriteF('Now you\all get a string from the object\as catalog:\n\n') + + + + /* + * Get a string from the object's catalog and set the string object to it. + * Currently that string is retrieved from the catalog + * oomodules/object.catalog. + */ + + locale.getObjectString(object,string, 1,'bla') + WriteF('\s\n', string.write()) + + + + /* + * Get back to term's catalog. + */ + + WriteF('\n\n') + WriteF('Here are some strings from term\as catalog again:\n\n') + WriteF('\s\n\s\n\s\n', locale.getString(1,'bla'), + locale.getString(2,'bla'), + locale.getString(3,'bla')) + + + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools.e new file mode 100644 index 0000000..f7126d3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools.e @@ -0,0 +1,274 @@ +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/library', 'reqtools', 'libraries/reqtools' + +CONST FILEREQ=0 + +-> NOTE: some modifications by JEVR3 here and there. + +OBJECT reqtools OF library +/****** library/--library-- ****************************************** + + NAME + library of object + + PURPOSE + Basic implementation of a simple library module. + + ATTRIBUTES + stringbuf -- Address of the buffer for the last character input. + + filebuf -- Address of the buffer for the last file choice. + + dirbuf -- Address of the buffer for the last directory choice. + + number -- Address of the variable that contains the last number + entered. + + CREATION + Back in February of 1995 by Gregor Goldbach + + HISTORY + +****************************************************************************** + +History + + +*/ + stringbuf + filebuf + dirbuf + number +ENDOBJECT + +-> JEVR3 addition: init() sets 'reqtools.library' and no version. + +PROC init() OF reqtools +/****** reqtools/init ****************************************** + + NAME + init() -- Initialization of the object. + + SYNOPSIS + reqtools.init() + + FUNCTION + Sets the library's name and the version to 0. After that the library + is opened. + + SEE ALSO + open() +****************************************************************************** + +History + + +*/ + self.identifier:='reqtools.library' + self.version:=0 + self.open() +ENDPROC + +-> JEVR3 modification: made it one-line (I'm demented) + +PROC open() OF reqtools +/****** reqtools/open ****************************************** + + NAME + open() -- Open reqtools.library + + SYNOPSIS + reqtools.open() + + FUNCTION + Opens the reqtools.library. + + EXCEPTIONS + "lib",{reqtoolOpen} will be raised if the opening fails. + +****************************************************************************** + +History + + +*/ + IF (reqtoolsbase:=OpenLibrary(self.identifier,self.version)) = NIL THEN Throw("lib",{reqtoolOpen}) +ENDPROC + +PROC ez(body,gadgets,dunno=NIL,arglist=NIL,taglist=NIL) OF reqtools +/****** reqtools/ez ****************************************** + + NAME + ez() -- Display an eazy requester. + + SYNOPSIS + reqtools.ez(LONG,LONG,LONG=NIL,LONG=NIL,LONG=NIL) + + FUNCTION + Displays one of those nice ez requesters. Refer to the reqtools + documentation for input details. + +****************************************************************************** + +History + + +*/ + + IF reqtoolsbase + RETURN RtEZRequestA(body,gadgets,dunno,arglist,taglist) + ENDIF +ENDPROC + +-> JEVR3 modification; string() returns stringbuf, New() now String() + +PROC string(title=NIL,maxlen=200,dunno=NIL,dunno2=NIL) OF reqtools +/****** reqtools/string ****************************************** + + NAME + string() -- Asks for a character input. + + SYNOPSIS + reqtools.string(LONG=NIL,LONG=NIL,LONG=NIL,LONG=NIL) + + FUNCTION + Asks for a string input. For further documentation refer to the + reqtools document. + + RESULT + PTR TO CHAR -- Address of the string entered. + +****************************************************************************** + +History + + +*/ + IF self.stringbuf THEN Dispose(self.stringbuf) + self.stringbuf := String(maxlen) + + RtGetStringA(self.stringbuf,maxlen,title,dunno,dunno2) +ENDPROC self.stringbuf + +-> JEVR3 modification; changed 'end()' to 'close()'. 'end()' still works, +-> since it calls 'self.close()' + +PROC close() OF reqtools +/****** reqtools/close ****************************************** + + NAME + close() -- Close the library. + + SYNOPSIS + reqtools.close() + + FUNCTION + Closes the library. + + SEE ALSO + open() +****************************************************************************** + +History + + +*/ + IF self.stringbuf THEN DisposeLink(self.stringbuf) + CloseLibrary(reqtoolsbase) +ENDPROC + +PROC palette(title,dunno=NIL,dunno2=NIL) OF reqtools +/****** reqtools/palette ****************************************** + + NAME + palette() -- Pop up palette requester. + + SYNOPSIS + reqtools.palette(LONG,LONG=NIL,LONG=NIL) + + FUNCTION + Display reqtools' palette requester. + + RESULT + number of colour chosen. + +****************************************************************************** + +History + + +*/ + self.number := RtPaletteRequestA(title,dunno,dunno2) +ENDPROC self.number + +PROC long(title,number=NIL,dunno=NIL,dunno2=NIL) OF reqtools +/****** reqtools/long ****************************************** + + NAME + long() -- Pop up long integer requester. + + SYNOPSIS + reqtools.long(LONG,LONG=NIL,LONG=NIL,LONG=NIL) + + FUNCTION + Display a requester that asks for a long integer to be entered. + For more documentation refer to the reqtools manual. + +****************************************************************************** + +History + + +*/ + RtGetLongA({number}, title, dunno, dunno2) + self.number := number +ENDPROC self.number + +PROC file(title,maxlen=200,tags=NIL) OF reqtools HANDLE +/****** reqtools/file ****************************************** + + NAME + file() -- Get file via requester. + + SYNOPSIS + reqtools.file(PTR TO CHAR,LONG) + + RESULT + TRUE if a file was selected, FALSE otherwise. See reqtools.doc + for more info. + + FUNCTION + Select a file via file requester. The file and directory choices + are copied to the according attributes. + +****************************************************************************** + +History + + +*/ +DEF req:PTR TO rtfilerequester, + result + + IF req:=RtAllocRequestA(FILEREQ,0) + + IF self.filebuf THEN Dispose(self.filebuf) + IF self.dirbuf THEN Dispose(self.dirbuf) + self.filebuf := NewR(maxlen) + self.dirbuf := NewR(maxlen) + + result := RtFileRequestA(req,self.filebuf,title,tags) + AstrCopy(self.dirbuf,req.dir,maxlen) + RtFreeRequest(req) + ENDIF + + RETURN result + +EXCEPT + NOP +ENDPROC + +reqtoolOpen: + CHAR 'Unable to open reqtools.library.',0 diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools/test.e new file mode 100644 index 0000000..0378cb8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools/test.e @@ -0,0 +1,28 @@ +MODULE 'oomodules/library/reqtools', + 'reqtools','libraries/reqtools' + +PROC main() HANDLE +DEF req:PTR TO reqtools + + NEW req.new(["name",'reqtools.library',"vers",37]) + + req.ez('Nice to see ya!','Ah.|So what?',0,0,[RTEZ_REQTITLE,'Just a test',RT_REQPOS,REQPOS_POINTER]) + req.string('Just enter a string:') + WriteF('\s\n',req.stringbuf) + req.string('Just enter a string:') + WriteF('\s\n',req.stringbuf) + + req.long('just enter a number:') + WriteF('\d\n', req.number) + + req.palette('just choose a colour:') + WriteF('\d\n', req.number) + + req.file('FILE?') + WriteF('\s\n', req.filebuf) + WriteF('\s\n', req.dirbuf) + + +EXCEPT + WriteF('no lib, sorry (base=\d).\n',reqtoolsbase) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools_test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools_test.e new file mode 100644 index 0000000..91633e7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/library/reqtools_test.e @@ -0,0 +1,33 @@ +MODULE '*reqtools','libraries/reqtools' + +-> Only need 'libraries/reqtools' for the CONST now. + +-> NOTE: Some modifications by JEVR3 to reflect enhancements + +PROC main() +DEF req:PTR TO reqtools + +-> JEVR3: Now uses 'new()' to set up library. + + NEW req.new() + +-> JEVR3: uncommented this part. + + req.ez('Nice to see ya!','Ah.|So what?',0,0,[RTEZ_REQTITLE,'Just a test',RT_REQPOS,REQPOS_POINTER,0]) + +-> JEVR3: compressed some lines a little bit. + + WriteF('\s\n',req.string('Just enter a string:')) + WriteF('\s\n',req.string('Just enter a string:')) + + WriteF('\d\n', req.long('Just enter a number:')) + + + WriteF('\d\n', req.palette('just choose a colour:')) + + req.file('FILE?') + WriteF('\s\n', req.filebuf) + WriteF('\s\n', req.dirbuf) + END req + -> automatically closes the library! +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/Examples new file mode 100644 index 0000000..578c059 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/Examples @@ -0,0 +1,12 @@ +@database list_example + +@node main "Introduction to list" + +list is the place where you can find all the objects that fiddle around +with lists. + +There are objects for E's own lists (the object is called @{" elist " link EMODULES:oomodules/list/elist/Examples/main}), lists +of the exec.library (@{" execlist " link EMODULES:oomodules/list/execlist/Examples/main}) and some more advanced lists like the +@{" associative array " link EMODULES:oomodules/list/associativeArray/Examples/main}. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray.e new file mode 100644 index 0000000..a1a7eae --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray.e @@ -0,0 +1,566 @@ +OPT MODULE +OPT REG=5, + PREPROCESS + +MODULE 'oomodules/object' + +-> #define NO_SAFE_STACK 1 -> Uncomment if you don't want to watch the stack. +#define PIVOT(l,u) ((l)+(Div(((u)-(l)),(2)))) + +/* + * Exceptions. + * + * ASAR_EXCEPTION identifies this module as the origin of the exception. The + * remaining constants identify the reason for an exception raised by this + * module, eg: + * + * Throw(ASAR_EXCEPTION, ASAR_KEYNOTFOUND) + */ +EXPORT CONST ASAR_EXCEPTION="AsAr" +EXPORT CONST ASAR_KEYNOTFOUND="key", + ASAR_STACKOVERFLOW="stak" + +CONST DEFAULT_LENGTH=64 + +EXPORT OBJECT associativeArray OF object +/****** object/associativeArray ****************************** + + NAME + associativeArray of object -- Dynamic, one-dimensional, ordered + array + + PURPOSE + Dynamic, one-dimensional, ordered array for storing things whose + indices fit any of these criteria: 1) are non-numeric (most + popular index type is a string), 2) are not consecutive and/or + have big gaps between values (commonly known as sparse arrays), + 3) order cannot be simply determined by builtin E arithmetic + operators (=<>). Basically any index type that is not the typical + positive integer from 0 to MAXLONG. + + ATTRIBUTES + len:LONG -- current max length of the array + + tail:LONG -- first empty place after the last element + + key:PTR TO LONG -- array stores the keys in ordered sequence + + val:PTR TO LONG -- array stores the values associated with each key + in array key + + EXCEPTIONS + ASAR_EXCEPTION identifies this module as the origin of the exception. + The remaining constants identify the reason for an exception raised + by this module. These are: + + ASAR_KEYNOTFOUND -- there is no such key in the array + + ASAR_STACKOVERFLOW -- stack overflow. Should not be raised if the + stack watch is enabled. + + NOTES + disposeKey(key) + disposeVal(val) + + These are the default actions for disposal of keys and vals of type + LONG, which is "do nothing", since they require no special cleanup. + Override them if key and/or val requires cleanup, (ie, dynamically + allocated, else your storage WILL NOT be freed when you set() or end()!!!) + + EXAMPLE: + + PROC disposeVal(val) OF myAsAr IS DisposeLink(val) + + Storage for new elements is automatically allocated, increased by 32 + each time the array's limits are exceeded. + + No duplicate keys will ever exist, values are simply overwritten. + + Inserting and removing from the front of the array is SLOW with large + arrays. This can't be helped, however it's often worth the sacrifice + for the efficient lookup of binary searches and the handiness of + sparse, non-numeric indexed arrays. + + The binary search function uses recursion and has a FreeStack() check. + 4096 should be plenty for most applications since the algorithm is + amazingly efficient. + + Changing any of the PUBLIC (READ-ONLY) values in the object isn't + recommended, but hey, who's to stop ya besides the guru? :) + + SEE ALSO + object + +********/ + len: LONG + tail: LONG + key: PTR TO LONG + val: PTR TO LONG +ENDOBJECT + + +/* Local. */ +CONST LT=-1, + EQ=0, + GT=1 + +/*===========================================================================*/ +/*=== Con/Destructors =======================================================*/ +/*===========================================================================*/ + +/* + * original new() contents: + * self.end() + * self.key:=NewR(Mul(length, 4)) + * self.val:=NewR(Mul(length, 4)) + * self.len:=length + * self.tail:=0 + * + * length is the initial number of empty elements in the array + */ + +PROC init() OF associativeArray +/****** associativeArray/init ****************************** + + NAME + init() of associativeArray -- Initialization of the object. + + SYNOPSIS + associativeArray.init() + + FUNCTION + Initializes the object. The list will initially contain + DEFAULT_LENGTH elements. + + EXCEPTION + May raise "MEM". + + SEE ALSO + associativeArray + +********/ + + self.key:=NewR(Mul(DEFAULT_LENGTH, 4)) + self.val:=NewR(Mul(DEFAULT_LENGTH, 4)) + self.len:=DEFAULT_LENGTH + self.tail:=0 + +ENDPROC + + +PROC end() OF associativeArray +/****** associativeArray/end ****************************** + + NAME + end() of associativeArray -- Global destructor. + + SYNOPSIS + associativeArray.end() + + FUNCTION + Cleans up keys and values using methods disposeKey() and disposeVal(), + so if your keys and values are dynamically allocated, you must + override these if you want this method to free them. NOTE: this + method was written to be very safe! It may be called directly at any + time (even multiple times) to free resources. 'myobj.end()' doesn't + free the object, only its contents. Just don't be so silly as to + call -any- methods after an 'END myobj'. :) + + SEE ALSO + associativeArray + +********/ + DEF i, last, ar:PTR TO LONG + last:=self.tail-1 + IF ar:=self.key + FOR i:=0 TO last DO self.disposeKey(ar[i]) + Dispose(ar) + self.key:=NIL + ENDIF + IF ar:=self.val + FOR i:=0 TO last DO self.disposeVal(ar[i]) + Dispose(ar) + self.val:=NIL + ENDIF + self.tail:=0 +ENDPROC + +/*===========================================================================*/ +/*=== Tell-me-about-myself Methods ==========================================*/ +/*===========================================================================*/ + +PROC disposeKey(key) OF associativeArray IS EMPTY +/****** associativeArray/disposeKey ****************************** + + NAME + disposeKey() of associativeArray -- Call destructor of key. + + SYNOPSIS + associativeArray.disposeKey(LONG) + + associativeArray.disposeKey(key) + + FUNCTION + Empty method. Special action to take when calling the destructor for + an array whose keys are dynamically allocated. Default for type LONG + is NO ACTION. + + INPUTS + key:LONG -- Pointer to key. + + SEE ALSO + associativeArray, disposeVal() + +********/ + +PROC disposeVal(val) OF associativeArray IS EMPTY +/****** associativeArray/disposeVal ****************************** + + NAME + disposeVal() of associativeArray -- Call destructor of value. + + SYNOPSIS + associativeArray.disposeVal(LONG) + + associativeArray.disposeVal(val) + + FUNCTION + Empty method. Special action to take when calling the destructor, + or overwriting a value for a key that already exists, for an array + whose keys are dynamically allocated. Default for type LONG is + NO ACTION. + + INPUTS + val:LONG -- Pointer to value. + + SEE ALSO + associativeArray, disposeKey() + +********/ + +PROC testKey(left, right) OF associativeArray IS IF (right>left) THEN 1 ELSE (right0 + pos:=binarySearch(self, 0, self.tail-1, key, PIVOT(0,self.tail-1)) + rel:=self.testKey(self.key[pos], key) + ENDIF + IF rel=EQ + self.disposeVal(self.val[pos]) + ELSE + IF rel=GT THEN INC pos + makeRoom(self, pos) + self.tail:=self.tail+1 + ENDIF + self.key[pos]:=key + self.val[pos]:=val +ENDPROC + +PROC get(searchKey) OF associativeArray +/****** associativeArray/get ****************************** + + NAME + get() of associativeArray -- + + SYNOPSIS + associativeArray.get(LONG) + + associativeArray.get(searchKey) + + FUNCTION + Perform binary search for matching key and return its associated + value. + + INPUTS + searchKey:LONG -- the associated key used to identify a value + + RESULT + val:LONG -- value associated with key + + pos:LONG -- the position of the element in the array. + + EXCEPTIONS + Throws ASAR_EXCEPTION, ASAR_KEYNOTFOUND or + ASAR_EXCEPTION, ASAR_STACKOVERFLOW + + SEE ALSO + associativeArray + +********/ + DEF pos + pos:=binarySearch(self, 0, self.tail-1, searchKey, PIVOT(0,self.tail-1)) + IF self.testKey(self.key[pos], searchKey) THEN Throw(ASAR_EXCEPTION, ASAR_KEYNOTFOUND) +ENDPROC self.val[pos],pos + +PROC remove(searchKey) OF associativeArray +/****** associativeArray/remove ****************************** + + NAME + remove() of associativeArray -- + + SYNOPSIS + associativeArray.remove(LONG) + + associativeArray.remove(searchKey) + + FUNCTION + Remove the key and value from the array and return them. + + INPUTS + searchKey:LONG -- the key of the element to be removed + + RESULT + key:LONG -- the key you passed + + val:LONG -- value associated with key + + EXCEPTIONS + Throws ASAR_EXCEPTION, ASAR_KEYNOTFOUND or + ASAR_EXCEPTION, ASAR_STACKOVERFLOW + + SEE ALSO + associativeArray + +********/ + DEF pos, last, i, k:PTR TO LONG, v:PTR TO LONG, key, val + pos:=binarySearch(self, 0, self.tail-1, searchKey, PIVOT(0,self.tail-1)) + IF self.testKey(self.key[pos], searchKey) THEN Throw(ASAR_EXCEPTION, ASAR_KEYNOTFOUND) + last:=self.tail-1 + k:=self.key + v:=self.val + key:=k[pos] + val:=v[pos] + FOR i:=pos TO last + k[i]:=k[i+1] + v[i]:=v[i+1] + ENDFOR + k[i]:=0 + v[i]:=0 + self.tail:=self.tail-1 +ENDPROC key,val + +/*===========================================================================*/ +/*=== Private Support Functions =============================================*/ +/*===========================================================================*/ + +PROC binarySearch(ar:PTR TO associativeArray, l, u, key, pivot) +/****** /binarySearch ****************************** + + NAME + binarySearch() -- + + SYNOPSIS + binarySearch(PTR TO associativeArray, LONG, LONG, LONG, LONG) + + binarySearch(ar, l, u, key, pivot) + + FUNCTION + Recursive binary search of array ar.key. Returns pos when + ar.key[pos] equals key, or when l=u. + + INPUTS + ar:PTR TO associativeArray -- array to work on + + l:LONG -- + + u:LONG -- + + key:LONG -- + + pivot:LONG -- + + RESULT + LONG -- index + + EXCEPTION + Throws ASAR_EXCEPTION, ASAR_STACKOVERFLOW + +********/ + DEF rel +#ifndef NO_SAFE_STACK + IF FreeStack()<1000 THEN Throw(ASAR_EXCEPTION, ASAR_STACKOVERFLOW) +#endif + IF l=u THEN RETURN pivot + rel:=ar.testKey(ar.key[pivot], key) + IF rel=GT + IF l=pivot THEN RETURN pivot+1 + l:=pivot + ELSEIF rel=LT + u:=pivot + ELSE + RETURN pivot + ENDIF +ENDPROC binarySearch(ar, l, u, key, PIVOT(l,u)) + +PROC makeRoom(ar:PTR TO associativeArray, pos) HANDLE +/****** /makeRoom ****************************** + + NAME + makeRoom() -- Make room for an element. + + SYNOPSIS + makeRoom(PTR TO associativeArray, LONG) + + makeRoom(ar, pos) + + FUNCTION + Make a blank element at position pos (for an insert operation). + Expand the length of the array by 32 elements if necessary. + + INPUTS + ar:PTR TO associativeArray -- array to work on + + pos:LONG -- position to insert an element + +********/ + DEF toKey=NIL:PTR TO LONG, toVal=NIL:PTR TO LONG + DEF fromKey:PTR TO LONG, fromVal:PTR TO LONG, i, last + fromKey:=ar.key + fromVal:=ar.val + /* Expand array if necessary and copy elements BEFORE pos, setup so that + * upper half of array is copied. Else setup so that upper half of array + * is shifted right. **/ + IF ar.tail=ar.len + toKey:=NewR(ar.len+32*4) + toVal:=NewR(ar.len+32*4) + last:=pos-1 + FOR i:=0 TO last + toKey[i]:=fromKey[i] + toVal[i]:=fromVal[i] + ENDFOR + ELSE + toKey:=fromKey + toVal:=fromVal + ENDIF + /* Shift upper half of array one position to the right. */ + INC pos + last:=ar.tail + FOR i:=last TO pos STEP -1 + toKey[i]:=fromKey[i-1] + toVal[i]:=fromVal[i-1] + ENDFOR + /* Cleanup if the array was expanded. */ + IF toKey<>fromKey + Dispose(fromKey) + Dispose(fromVal) + ar.key:=toKey + ar.val:=toVal + ar.len:=ar.len+32 + ENDIF +EXCEPT + /* The only recovery required is if toVal:=NewR(ar.len+32*4) raises "MEM". */ + IF toKey THEN Dispose(toKey) + ReThrow() +ENDPROC + +PROC asList() OF associativeArray +DEF valueList:PTR TO LONG, + keyList:PTR TO LONG, + index, + numberOfItems + + numberOfItems := self.tail + + valueList := List(numberOfItems) + keyList := List(numberOfItems) + + IF (valueList AND keyList) + + FOR index := 0 TO numberOfItems-1 + + valueList[index] := self.val[index] + keyList[index] := self.key[index] + +-> WriteF('key: \d, value: $\h\n',self.key[index],self.val[index]) +-> WriteF('key: \d, value: $\h\n\n',keyList[index],valueList[index]) + ENDFOR +-> WriteF('\n') + + SetList(keyList,numberOfItems) + SetList(valueList,numberOfItems) + ENDIF + + RETURN keyList,valueList + +ENDPROC +/*EE folds +-1 +151 34 247 52 250 33 253 44 260 46 263 58 266 28 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/Examples new file mode 100644 index 0000000..f8a6e39 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/Examples @@ -0,0 +1,21 @@ +@database associativeArray_example + +@node main "Introduction to associativeArray" + +Dynamic, one-dimensional, ordered array for storing things whose indices +fit any of these criteria: 1) are non-numeric (most popular index type is +a string), 2) are not consecutive and/or have big gaps between values +(commonly known as sparse arrays), 3) order cannot be simply determined by +builtin E arithmetic operators (=<>). Basically any index type that is not +the typical positive integer from 0 to MAXLONG. + +There is are three examples, they are practically like those provided by +Barry Wills. + + @{" ar " link EMODULES:oomodules/list/associativeArray/ar.e/main} + @{" ar2 " link EMODULES:oomodules/list/associativeArray/ar2.e/main} + @{" listTest " link EMODULES:oomodules/list/associativeArray/listTest.e/main} + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/associativeArray/main} file available or this object. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar.e new file mode 100644 index 0000000..73e59f7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar.e @@ -0,0 +1,147 @@ +/* + * ar.e - yer very basic test suite to make sure numbers go in the right place + * when inserted/removed in various orders. + * + * December 24 1995 Gregor Goldbach + * This is the original test program by Barry with these exceptions: I removed + * the initial size argument from new() and added NEW end END to each test. + * + */ + +OPT REG=5, + PREPROCESS + +MODULE 'oomodules/list/associativeArray' + +#define TEST1 +#define TEST2 +#define TEST3 +#define TEST4 +#define TEST5 +#define TEST6 +#define TEST7 +#define TEST8 + +OBJECT aa OF associativeArray +ENDOBJECT + +PROC printAll() OF aa + DEF i, last + last:=self.tail-1 + FOR i:=0 TO last DO self.print(i) + WriteF('\n') +ENDPROC + /* printAll */ + +PROC print(i) OF aa + WriteF('key\d=\d val\d=$\h\n', i, self.key[i], i, self.val[i]) +ENDPROC + /* print */ + +PROC main() HANDLE + DEF ar:PTR TO aa, i + NEW ar.new() +/*---------------------------------------------------------------------------*/ +/*--- test order of insert --------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +#ifdef TEST1 + WriteF('/*** TEST 1 ***/\n') + ar.set(1, $1111); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(5, $5555); ar.printAll() + END ar +#endif +#ifdef TEST2 + NEW ar.new() + WriteF('/*** TEST 2 ***/\n') + ar.set(5, $5555); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(1, $1111); ar.printAll() + END ar +#endif +#ifdef TEST3 + NEW ar.new() + WriteF('/*** TEST 3 ***/\n') + ar.set(5, $5555); ar.printAll() + ar.set(1, $1111); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(3, $3333); ar.printAll() + END ar + +#endif +#ifdef TEST4 + NEW ar.new() + WriteF('/*** TEST 4 ***/\n') + ar.set(3, $3333); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(5, $5555); ar.printAll() + ar.set(1, $1111); ar.printAll() + END ar +#endif +#ifdef TEST5 + NEW ar.new() + WriteF('/*** TEST 5 ***/\n') + ar.set(1, $1111); ar.printAll() + ar.set(5, $5555); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(4, $4444); ar.printAll() + END ar +#endif + +/*---------------------------------------------------------------------------*/ +/*--- test overwrite --------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +#ifdef TEST6 + NEW ar.new() + WriteF('/*** TEST 6 ***/\n') + ar.set(1, $1111); ar.printAll() + ar.set(5, $5555); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(2, $2222); ar.printAll() + + ar.set(1, $5555); ar.printAll() + ar.set(2, $4444); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(4, $2222); ar.printAll() + ar.set(5, $1111); ar.printAll() + END ar +#endif +/*---------------------------------------------------------------------------*/ +/*--- test get() and remove() -----------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +#ifdef TEST7 + NEW ar.new() + WriteF('/*** TEST 7 ***/\n') + ar.set(3, $3333); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(1, $1111); ar.printAll() + ar.set(5, $5555); ar.printAll() + + FOR i:=1 TO 5 DO WriteF('get(\d)=$\h\n', i, ar.get(i)) + WriteF('\n') + + ar.remove(3); ar.printAll() + ar.remove(1); ar.printAll() + ar.remove(5); ar.printAll() + ar.remove(4); ar.printAll() + ar.remove(2); ar.printAll() + END ar +#endif +#ifdef TEST8 + NEW ar.new() + WriteF('/*** TEST 8 (should raise exception) ***/\n') + ar.remove("blah") ->should raise exception +#endif +EXCEPT DO + IF exception THEN WriteF('BOOM!\n') + CleanUp() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar2.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar2.e new file mode 100644 index 0000000..3529638 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/ar2.e @@ -0,0 +1,163 @@ +/* + * ar2.e - yer very basic dumb program that reads a text file and counts the + * number of times each unique word occurs. Words are used as the array index + * (key) in an associative array. This is not -really- an E parser, so it's + * easier to follow if you use it on plain text, else you'll see some weird + * "words" and have to THINK to figure out where they're coming from. :) + * + * December 24 1995 Gregor Goldbach + * This is the original test program by Barry. I just removed the initial size + * value from the call to new(). + * I ran it over my guided dos autodoc (nearly 205Kb). It swallows nearly + * 800Kb :) + */ + +MODULE 'exec/strings' +MODULE 'oomodules/list/associativeArray' + +RAISE "OPEN" IF Open()=NIL, + "MEM" IF String()=NIL, + "^C" IF CtrlC()=TRUE + +CONST SPACE=" ", + TAB=9 + +/* + * Derived class. + */ + +OBJECT myAsAr OF associativeArray + /* key will store pointers to strings */ + /* val will store a count of the string's occurence */ +ENDOBJECT + /* myAsAr */ + +PROC disposeKey(key) OF myAsAr IS DisposeLink(key) +PROC testKey(string1, string2) OF myAsAr IS OstrCmp(string1, string2) + +/*---------------------------------------------------------------------------*/ + +/* + * TEST FUNCTIONS. + */ + +PROC isWhite(c) + SELECT c + CASE SPACE; RETURN TRUE + CASE TAB; RETURN TRUE + CASE LF; RETURN TRUE + ENDSELECT +ENDPROC FALSE + /* isWhite */ + +PROC isPunct(c) IS (-1<>InStr('.,;:()/?-''"!@#$%^&*=+\\|[]{}<>`~', [c,0]:CHAR)) + /* note: left out "_" for my test since identifiers can have them */ + +PROC skipSeparator(s) + DEF c + WHILE (isWhite(c:=s[]) OR isPunct(c)) DO INC s +ENDPROC s + /* skipSeparator */ + +/*---------------------------------------------------------------------------*/ + +/* + * Add word to array and tally. + */ +PROC tallyWord(ar:PTR TO myAsAr, key) HANDLE + DEF val=0 + val:=ar.get(key) +EXCEPT DO + val:=val+1 + ar.set(key, val) +ENDPROC + /* tallyWord */ + +/* + * Make key from word. + */ +PROC makeKey(w) + DEF key + key:=String(EstrLen(w)) + StrCopy(key, w) +ENDPROC key + /* makeKey */ + +/* + * Pickup a word. + */ +PROC getWord(ar, s, w) + DEF key + SetStr(w, 0) + WHILE (isWhite(s[]) OR isPunct(s[])=FALSE) AND (s[]<>EOS) + StrAdd(w, s, 1) + INC s + ENDWHILE + IF EstrLen(w) + key:=makeKey(w) + tallyWord(ar, key) + ENDIF +ENDPROC s + /* getWord */ + +/* + * Pickup all words in a line. + */ +PROC getWords(ar:PTR TO myAsAr, s, w) + LOOP + s:=skipSeparator(s) + IF s[]=EOS THEN RETURN + s:=getWord(ar, s, w) + ENDLOOP +ENDPROC + /* getWords */ + +/*---------------------------------------------------------------------------*/ + +/* + * Print entire contents of array. + */ +PROC printEmAll(ar:PTR TO myAsAr) + DEF i, last, key:PTR TO LONG, val:PTR TO LONG + key:=ar.key + val:=ar.val + last:=ar.tail-1 + FOR i:=0 TO last DO WriteF(' \s == \d\n', key[i], val[i]) +ENDPROC + /* printEmAll */ + +/*---------------------------------------------------------------------------*/ + +/* + * MAIN. + */ +PROC main() HANDLE + DEF ar=NIL:PTR TO myAsAr + DEF fh=NIL, s=NIL, w=NIL + IF arg[]=EOS THEN Raise("ARGS") + fh:=Open(arg, OLDFILE) + s:=String(100) + w:=String(100) + NEW ar.new() + /* process the whole file, tallying word occurences into ar */ + WHILE Fgets(fh, s, 100) DO getWords(ar, s, w) + /* print out the entire array */ + printEmAll(ar) +EXCEPT DO + IF fh THEN Close(fh) + SELECT exception + CASE ASAR_EXCEPTION + SELECT exceptioninfo + CASE ASAR_KEYNOTFOUND; WriteF('bad key request\n') + CASE ASAR_STACKOVERFLOW; WriteF('stack overflow\n') + ENDSELECT + CASE "MEM"; WriteF('out of mem\n') + CASE "ARGS"; WriteF('examine which file?\n') + CASE "OPEN"; WriteF('can''t open file\n') + CASE "^C"; WriteF('interrupted\n') + CASE 0; + DEFAULT; WriteF('unknow exception \d/\d\n', exception, exceptioninfo) + ENDSELECT + CleanUp() +ENDPROC + /* main */ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/associativeStringArray.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/associativeStringArray.e new file mode 100644 index 0000000..94f10c7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/associativeStringArray.e @@ -0,0 +1,10 @@ +OPT MODULE + +MODULE 'oomodules/list/associativeArray' + +EXPORT OBJECT associativeStringArray OF associativeArray + /* key will store pointers to strings */ +ENDOBJECT + +-> crashes sometimes PROC disposeKey(key) OF associativeStringArray IS DisposeLink(key) +PROC testKey(string1, string2) OF associativeStringArray IS OstrCmp(string1, string2) diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/associativestringarray.m b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/associativestringarray.m new file mode 100644 index 0000000000000000000000000000000000000000..fefddbf9874efe189d256cd9c43550aa215ef4d8 GIT binary patch literal 662 zcmYjOO>fgc5PfcqF_l$CRTSmGp+!9)Q3wYP2ytlDQU$fR6%=k9R`s;3aO`N;311if z77{0BZrPa$nEix7Uw`?e*X>GOl#^ zwQciXSjCT%zsT~B`Gg*A^EbEd{=fEW>os=s3GUL5egZwL5d1;EZE{Q-0 z&Q_Ou&Y5py#`={~5h5W@8)Hj#!b$d7ND3TuriKSGPr5kc{y<6SBf=?CW(SG4-?bLC2oI6edbD72 z9+Polnpq#i`&t_AQR@^tY;iFu#lNWQIU1B4!{FAmjn4TA1(|!}R(vsk)!Yts5&Q>o C<$T%z literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/listTest.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/listTest.e new file mode 100644 index 0000000..f99f5a9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/associativeArray/listTest.e @@ -0,0 +1,149 @@ +/* + +This is nearly the same test program like the one that was written by Barry. +The only difference is the function printAll(): it creates elists of +keys and values with the method asList(). + + January 28 1996 Gregor Goldbach + +*/ + +OPT REG=5, + PREPROCESS + +MODULE 'oomodules/list/associativeArray' + +#define TEST1 +#define TEST2 +#define TEST3 +#define TEST4 +#define TEST5 +#define TEST6 +#define TEST7 +#define TEST8 + +OBJECT aa OF associativeArray +ENDOBJECT + +PROC printAll() OF aa +DEF values:PTR TO LONG, + keys:PTR TO LONG, + index, + numberOfItems + + keys, values := self.asList() + numberOfItems := ListLen(keys) + + FOR index:=0 TO numberOfItems-1 DO WriteF('key\d=\d \tval\d=$\h\n', index, keys[index], index, values[index]) + + WriteF('\n') + +ENDPROC + +PROC main() HANDLE + DEF ar:PTR TO aa, i + NEW ar.new() +/*---------------------------------------------------------------------------*/ +/*--- test order of insert --------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +#ifdef TEST1 + WriteF('/*** TEST 1 ***/\n') + ar.set(1, $1111); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(5, $5555); ar.printAll() + END ar +#endif +#ifdef TEST2 + NEW ar.new() + WriteF('/*** TEST 2 ***/\n') + ar.set(5, $5555); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(1, $1111); ar.printAll() + END ar +#endif +#ifdef TEST3 + NEW ar.new() + WriteF('/*** TEST 3 ***/\n') + ar.set(5, $5555); ar.printAll() + ar.set(1, $1111); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(3, $3333); ar.printAll() + END ar + +#endif +#ifdef TEST4 + NEW ar.new() + WriteF('/*** TEST 4 ***/\n') + ar.set(3, $3333); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(5, $5555); ar.printAll() + ar.set(1, $1111); ar.printAll() + END ar +#endif +#ifdef TEST5 + NEW ar.new() + WriteF('/*** TEST 5 ***/\n') + ar.set(1, $1111); ar.printAll() + ar.set(5, $5555); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(4, $4444); ar.printAll() + END ar +#endif + +/*---------------------------------------------------------------------------*/ +/*--- test overwrite --------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +#ifdef TEST6 + NEW ar.new() + WriteF('/*** TEST 6 ***/\n') + ar.set(1, $1111); ar.printAll() + ar.set(5, $5555); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(2, $2222); ar.printAll() + + ar.set(1, $5555); ar.printAll() + ar.set(2, $4444); ar.printAll() + ar.set(3, $3333); ar.printAll() + ar.set(4, $2222); ar.printAll() + ar.set(5, $1111); ar.printAll() + END ar +#endif +/*---------------------------------------------------------------------------*/ +/*--- test get() and remove() -----------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +#ifdef TEST7 + NEW ar.new() + WriteF('/*** TEST 7 ***/\n') + ar.set(3, $3333); ar.printAll() + ar.set(2, $2222); ar.printAll() + ar.set(4, $4444); ar.printAll() + ar.set(1, $1111); ar.printAll() + ar.set(5, $5555); ar.printAll() + + FOR i:=1 TO 5 DO WriteF('get(\d)=$\h\n', i, ar.get(i)) + WriteF('\n') + + ar.remove(3); ar.printAll() + ar.remove(1); ar.printAll() + ar.remove(5); ar.printAll() + ar.remove(4); ar.printAll() + ar.remove(2); ar.printAll() + END ar +#endif +#ifdef TEST8 + NEW ar.new() + WriteF('/*** TEST 8 (should raise exception) ***/\n') + ar.remove("blah") ->should raise exception +#endif +EXCEPT DO + IF exception THEN WriteF('BOOM!\n') + CleanUp() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked.e new file mode 100644 index 0000000..73c0b81 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked.e @@ -0,0 +1,666 @@ +/****** doublylinked/--background-- ****************************************** + + PURPOSE + no hassle, flexible, doubly-linked list base class + + NOTES + + 1. head and tail are dummy nodes which are part of the list header. + They cannot be removed, nor can your data be stored in them! + Crashes will occur if you attempt to circumvent the methods. All + your data nodes are stored AFTER list.head and BEFORE list.tail. + This is to simplify the algorithms. + + 2. The following macros are provided for speed and work precisely + the same as their OO counterparts, except they require the argument + 'list': LISTISEMPTY(list), FIRSTNODE(list), LASTNODE(list). + + 3. (Gregor Goldbach) Ported the module to the OOEP of the AEE. + Thus I had to add the methods select(), init() and end(). Made a + minor change to the dllh object, the attributes are now pointers. + + For additional information about modification read the doc of every + proc. + + CREATION + early September 1995 Gregor Goldbach + + HISTORY + September 10 1995 Gregor Goldbach + Added length() to dllh. + +****************************************************************************** + +History + + +*/ + new() + - constructor. ALWAYS call it when NEWing the object! + + isEmpty() + - test if list is empty + + firstNode() + - return first node, list.tail if list is empty + + lastNode() + - return last node, list.head if list is empty + + insert(node:PTR TO dlln, listNode:PTR TO dlln) + - insert node after listnode + + addHead(node:PTR TO dlln) + - add node to front of list + + addTail(node:PTR TO dlln) + - add node to end of list + + remove(node:PTR TO dlln) + - remove node from list, return node + + remHead() + - remove first node from list, return node + + remTail() + - remove last node from list, return node + + end() + + - automatically called when you END the object. Frees alls resources + allocated. + + +*----------------------------------------------------------------------------*/ + +OPT MODULE +OPT EXPORT, + REG=5, + PREPROCESS + +MODULE 'oomodules/object' + +OBJECT dlln OF object +/****** dlln/--dlln-- ****************************************** + + NAME + dlln -- doubly linked list node + + ATTRIBUTES + pred:PTR TO dlln -- Predecessor + + succ:PTR TO dlln -- Successor + + SEE ALSO + doublylinked/--dllh-- +****************************************************************************** + +History + + +*/ + pred:PTR TO dlln + succ:PTR TO dlln +ENDOBJECT + +PROC name() OF dlln IS 'doubly linked list node' +/****** dlln/name ****************************************** + + NAME + name() -- Return 'doubly linked list node' + + SYNOPSIS + dlln.name() + + FUNCTION + Returns name of object. + +****************************************************************************** + +History + + +*/ +PROC size() OF dlln IS 12 +/****** dlln/size ****************************************** + + NAME + size() -- Return size of dlln + + SYNOPSIS + dlln.size() + + FUNCTION + Gets you the size of the object. + +****************************************************************************** + +History + + +*/ + +PROC select(optionlist,index) OF dlln +/****** dlln/select ****************************************** + + NAME + select() -- Selection of action on initialization + + SYNOPSIS + dlln.select(otionslist,index) + + FUNCTION + Recognizes the following items: + "pred" -- next item is predecessor + + "succ" -- next item is successor + + INPUTS + optionlist -- optionlist + + index -- index of optionlist + + SEE ALSO + object/select() +****************************************************************************** + +History + + +*/ +-> TODO: error check: len-o'-list! +DEF item, value + + item := ListItem(optionlist, index) + + SELECT item + CASE "pred" + INC index + self.pred := ListItem(optionlist,index) + + CASE "succ" + INC index + self.succ := ListItem(optionlist,index) + + ENDSELECT + +ENDPROC index + +OBJECT dllh OF object +/****** dllh/--dllh-- ****************************************** + + NAME + dllh -- doubly linked list header + + ATTRIBUTES + head:PTR TO dlln -- The head of the list + + tail:PTR TO dlln -- The tail of the list + + SEE ALSO + doublylinked/--dlln-- +****************************************************************************** + +History + + +*/ + head:PTR TO dlln + tail:PTR TO dlln +ENDOBJECT + +PROC name() OF dllh IS 'doubly linked list header' +/****** dllh/name ****************************************** + + NAME + name() -- Return 'doubly linked list header' + + SYNOPSIS + dllh.name() + + FUNCTION + Returns the name of the object. + +****************************************************************************** + +History + + +*/ +PROC size() OF dllh IS 28 ->12+12+4 +/****** dllh/size ****************************************** + + NAME + size() -- Get size of object + + SYNOPSIS + dllh.size() + + FUNCTION + Gets you the size of the object. + +****************************************************************************** + +History + + +*/ + +PROC select(optionlist,index) OF dllh +/****** dllh/select ****************************************** + + NAME + select() -- Select actionon initialization. + + SYNOPSIS + dllh.select() + + FUNCTION + Recognizes no items. + +****************************************************************************** + +History + + +*/ +-> TODO: error check: len-o'-list! +DEF item, value + +-> item := ListItem(optionlist, index) + +ENDPROC index + +PROC init() OF dllh +/****** dllh/init ****************************************** + + NAME + init() -- Initialization of object. + + SYNOPSIS + dllh.init() + + FUNCTION + Initializes the object that way that an empty list is created. +****************************************************************************** + +History + + +*/ +DEF n:PTR TO dlln + + NEW n.new() + self.head := n + + NEW n.new() + self.tail := n + + self.head.succ:=self.tail + self.tail.pred:=self.head + self.head.pred:=NIL + self.tail.succ:=NIL +ENDPROC + +PROC end() OF dllh +/****** dllh/end ****************************************** + + NAME + end() -- Global destructor. + + SYNOPSIS + dllh.end() + + FUNCTION + Frees allocated resources. This does NOT mean that the list is + automatically cleared. + +****************************************************************************** + +History + + +*/ +DEF n + + n := self.tail + Dispose(n) + + n := self.head + Dispose(n) + +ENDPROC + + +#define LISTISEMPTY(list) (list::dllh.head.succ=list::dllh.tail) +/****** dllh/LISTISEMPTY ****************************************** + + NAME + LISTISEMPTY + + SYNOPSIS + LISTISEMPTY(list:PTR TO dllh) + + FUNCTION + Test if the list is empty. + + INPUTS + list:PTR TO dllh -- The list to test + + RESULT + TRUE if the list is empty, FALSE otherwise + +****************************************************************************** + +History + + +*/ +#define FIRSTNODE(list) (list::dllh.head.succ) +/****** dllh/FIRSTNODE ****************************************** + + NAME + FIRSTNODE -- Get first node of list. + + SYNOPSIS + FIRSTNODE(list:PTR TO dllh) + + FUNCTION + Get the first node of the list. + + INPUTS + list:PTR TO dllh -- The list to get the first node of. + + RESULT + PTR TO dlln -- The first node of the list + +****************************************************************************** + +History + + +*/ +#define LASTNODE(list) (list::dllh.tail.pred) +/****** dllh/LASTNODE ****************************************** + + NAME + LASTNODE -- Get first node of list. + + SYNOPSIS + LASTNODE(list:PTR TO dllh) + + FUNCTION + Get the last node of the list. + + INPUTS + list:PTR TO dllh -- The list to get the last node of. + + RESULT + PTR TO dlln -- The last node of the list + +****************************************************************************** + +History + + +*/ + +PROC isEmpty() OF dllh IS self.head.succ=self.tail +/****** dllh/isEmpty ****************************************** + + NAME + isEmpty() -- Is the list empty? + + SYNOPSIS + dllh.isEmpty() + + FUNCTION + Test if the list is empty. + + RESULT + TRUE if the list is empty, FALSE otherwise + +****************************************************************************** + +History + + +*/ +PROC firstNode() OF dllh IS self.head.succ +/****** dllh/firstNode ****************************************** + + NAME + firstNode() -- Get first node of list. + + SYNOPSIS + dllh.firstNode() + + FUNCTION + Get the first node of the list. + + RESULT + PTR TO dlln -- The first node of the list + +****************************************************************************** + +History + + +*/ +PROC lastNode() OF dllh IS self.tail.pred +/****** dllh/lastNode ****************************************** + + NAME + lastNode() -- Get first node of list. + + SYNOPSIS + dllh.lastNode() + + FUNCTION + Get the last node of the list. + + RESULT + PTR TO dlln -- The last node of the list + +****************************************************************************** + +History + + +*/ + +PROC insert(node:PTR TO dlln, listNode:PTR TO dlln) OF dllh +/****** dllh/insert ****************************************** + + NAME + insert() -- Insert node in list. + + SYNOPSIS + dllh.insert(node:PTR TO dlln, listNode:PTR TO dlln) + + FUNCTION + Inserts a node after another. + + INPUTS + node:PTR TO dlln -- Node to insert. + + listNode:PTR TO dlln -- Node after which the first node will be + inserted. + +****************************************************************************** + +History + + +*/ + node.pred:=listNode + node.succ:=listNode.succ + listNode.succ:=node + listNode:=node.succ + listNode.pred:=node +ENDPROC + +PROC addHead(node:PTR TO dlln) OF dllh +/****** dllh/addHead ****************************************** + + NAME + addHead() -- Insert node at the head of the list. + + SYNOPSIS + dllh.addHead(node:PTR TO dlln) + + FUNCTION + Inserts a node at the head of the list. + + INPUTS + node:PTR TO dlln -- Node to insert. + +****************************************************************************** + +History + + +*/ + self.insert(node, self.head) +ENDPROC + +PROC addTail(node:PTR TO dlln) OF dllh +/****** dllh/addTail ****************************************** + + NAME + addTail() -- Insert a node at the tail of the list. + + SYNOPSIS + dllh.addTail(node:PTR TO dlln) + + FUNCTION + Inserts a node at the tail of the list. + + INPUTS + node:PTR TO dlln -- Node to insert. + +****************************************************************************** + +History + + +*/ + self.insert(node, self.tail.pred) +ENDPROC + +PROC remove(node:PTR TO dlln) OF dllh +/****** dllh/remove ****************************************** + + NAME + remove() -- Removes a node from the list. + + SYNOPSIS + dllh.remove(node:PTR TO dlln) + + FUNCTION + Removes a node from the list it's in. + + INPUTS + node:PTR TO dlln -- Node to remove. + + RESULT + PTR TO dlln -- The node that was removed. + +****************************************************************************** + +History + + +*/ + IF self.head.succ=self.tail THEN RETURN NIL + node.pred.succ:=node.succ + node.succ.pred:=node.pred + node.succ:=NIL + node.pred:=NIL +ENDPROC node + +PROC remHead() OF dllh IS self.remove(self.head.succ) +/****** dllh/remHead ****************************************** + + NAME + remHead() -- Remove the head of the list. + + SYNOPSIS + dllh.remHead() + + FUNCTION + Removes it's head. + + RESULTS + PTR TO dlln -- The ex-head. + +****************************************************************************** + +History + + +*/ + +PROC remTail() OF dllh IS self.remove(self.tail.succ) +/****** dllh/remTail ****************************************** + + NAME + remTail() -- Remove the tail of the list. + + SYNOPSIS + dllh.remTail() + + FUNCTION + Removes it's tail. + + RESULT + PTR TO dlln -- The ex-tail. + +****************************************************************************** + +History + + +*/ + +PROC length() OF dllh +/****** dllh/length ****************************************** + + NAME + length() -- Get the length of the list. + + SYNOPSIS + dllh.length() + + FUNCTION + Gets the number of nodes in this list. 0 means the list is empty. + + RESULT + The number of nodes in this list. + +****************************************************************************** + +History + + +*/ +DEF actualNode:PTR TO dlln, + lastNode:PTR TO dlln, + count=1 + + IF self.isEmpty() THEN RETURN 0 + + actualNode := self.firstNode() + lastNode := self.lastNode() + + + WHILE (actualNode<>lastNode) + actualNode := actualNode.succ + count++ + ENDWHILE + +ENDPROC count +/*EE folds +-1 +83 21 122 43 125 21 164 22 167 28 170 26 311 28 314 21 317 21 320 28 367 35 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/Examples new file mode 100644 index 0000000..0e53a0a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/Examples @@ -0,0 +1,16 @@ +@database doublylinked_example + +@node main "Introduction to doublylinked" + +The doublylinked object provides a doubly linked list object. Each item +of such a list has a link to its successor and predecessor. The object +can be seen as an example for exec's list. + +This object was designed by Barry Wills and ported to the ooep by Gregor +Goldbach. + +There is an @{" example " link EMODULES:oomodules/list/doublylinked/test.e/main} available. + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/doublylinked/main} file available or this object. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist.e new file mode 100644 index 0000000..b7c4d2a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist.e @@ -0,0 +1,214 @@ +/* + +This module contains the code of the original example program of Barry's +doubly linked list module. + +Gregor Goldbach September 10 1995 + + +Just added a new method. It takes an elist and builds a alpha sorted string +list from it. The elist's entries are copied. Named the proc after queuestack's +asQueuestack() asStringList(). + +Gregor Goldbach September 29 1995 + + + April 10 1996 Gregor Goldbach + Removed the method asExecList for we have the execList object to convert + an elist. To get an execList from a stringList do this: + + /* + * A stringList has already been built, set elist to stringList' + * contents: + */ + + elist.set(stringList.asList()) + + + /* + * Get execList from elist: + */ + + NEW execList.new(["list", elist.list]) + + + Renamed asStringList() to fromList(). + +*/ + +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/list/doublylinked' + +OBJECT stringNode OF dlln + string +ENDOBJECT + +OBJECT stringList OF dllh +ENDOBJECT + + +PROC select(optionlist,index) OF stringNode +-> TODO: error check: len-o'-list! +DEF item, value, + len + + item := ListItem(optionlist, index) + + SELECT item + CASE "set" + INC index + + self.string:=StrCopy(String(len:=StrLen(ListItem(optionlist,index))), ListItem(optionlist,index), len) + + ENDSELECT + +ENDPROC index + +PROC end() OF stringNode + DisposeLink(self.string) +ENDPROC + +PROC clear() OF stringList + DEF node:PTR TO stringNode + WHILE self.isEmpty()=FALSE + node:=self.remHead() + END node + ENDWHILE +ENDPROC + +PROC insertAlphaSorted(node:PTR TO stringNode) OF stringList + DEF listnode:PTR TO stringNode, done=FALSE + listnode:=self.firstNode() ->returns lastnode or tail + REPEAT + IF listnode=self.tail + done:=TRUE + ELSEIF OstrCmp(node.string, listnode.string)>=0 + done:=TRUE + ELSE + listnode:=listnode.succ + ENDIF + UNTIL done + self.insert(node, listnode.pred) +ENDPROC + +PROC printAll() OF stringList + DEF node:PTR TO stringNode + IF self.isEmpty() + WriteF('*** List is empty\n') + RETURN + ENDIF + node:=self.firstNode() + WHILE node<>self.tail + WriteF('\s\n', node.string) + node:=node.succ + ENDWHILE +ENDPROC + + +PROC asList() OF stringList +/* + + NAME + + asList() of stringList + + FUNCTION + + Returns an elist with the names as items. + +*/ + +DEF index, + list:PTR TO LONG, + len, + actualNode:PTR TO stringNode + + len := self.length() + IF len=0 THEN RETURN + IF (list := List(len)) = NIL THEN RETURN + + + actualNode := self.firstNode() + + + FOR index := 0 TO len-1 + list[index] := actualNode.string + actualNode := actualNode.succ + ENDFOR + + SetList(list,len) + + RETURN list + +ENDPROC + +EXPORT PROC fromList(list) OF stringList +DEF n:PTR TO stringNode, + index + + FOR index := 0 TO ListLen(list)-1 + + self.insertAlphaSorted(NEW n.new(["set",ListItem(list,index)])) + + ENDFOR + +ENDPROC + +/* + +the following method asExecList() is removed from this object because of +the execList object. To get an execList from a stringList one has to do +this: + + /* a stringList has already been built */ + + elist.set(stringList.asList()) + NEW execList.new(["list", elist.list]) + + + +PROC asExecList() OF stringList +/* + + NAME + + asExecList() of stringList + + FUNCTION + + Returns an execlist with the names as items. Note that the + names are NOT copied. + +*/ + +DEF index, + list:PTR TO LONG, + len, + actualNode:PTR TO stringNode, + + execlist:PTR TO lh, + execnode:PTR TO ln + + execlist := newlist() + + len := self.length() + IF len=0 THEN RETURN + IF (list := List(len)) = NIL THEN RETURN + + + actualNode := self.firstNode() + + + FOR index := 0 TO len-1 + execnode := newnode(NIL, actualNode.string) + AddTail(execlist,execnode) + actualNode := actualNode.succ + ENDFOR + + RETURN execlist + +ENDPROC + +*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/Examples new file mode 100644 index 0000000..058041d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/Examples @@ -0,0 +1,18 @@ +@database stringList_example + +@node main "Introduction to stringList" + +stringList is an extension of the doublylinked list object by Barry Wills. +It handles strings in such a list, you can insert alphanumerically-sorted. + +There are methods to export the sorted list to other objects (elist). + +This object was designed by Barry Wills and ported to the ooep by Gregor +Goldbach. + +There are two examples, the @{" first example " link EMODULES:oomodules/list/doublylinked/stringList/test.e/main} just inserts some items, +the @{" second " link EMODULES:oomodules/list/doublylinked/stringList/execTest.e/main} converts a list between stringList, @{" elist " link EMODULES:oomodules/list/elist/Examples/Main} and @{" execList " link EMODULES:oomodules/list/execList/Examples/main}. + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/stringList/main} file available or this object. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/test.e new file mode 100644 index 0000000..8d1dc66 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/test.e @@ -0,0 +1,61 @@ +/* + +Small test program for the stringList object. + +Allocate a stringList, insert some strings alpha-sorted and print it. + +*/ + +MODULE 'oomodules/list/doublylinked/stringlist' + +PROC main() + +/* + * These are the vars we need: the stringList object, a var to hold the + * list we want to have and the index counter for the list. + */ + +DEF stringList:PTR TO stringList, + sortedList, + index + + + /* + * Allocate and initialize the object + */ + + NEW stringList.new() + + + + /* + * Insert some words and get an list. The elist will contain pointers + * to the alpha-sorted strings. + */ + + stringList.fromList(['fire','walk','with','me']) + sortedList := stringList.asList() + + + + /* + * Dump the list. + */ + + FOR index := 0 TO ListLen(sortedList)-1 + + WriteF('\s\n', ListItem(sortedList,index)) + + ENDFOR + + + + /* + * We have to dispose the sorted list we got from asList() since that + * method allocated it. E's runtime system would free that memory at the + * end of the program but it is good style... + */ + + Dispose(sortedList) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/testExec.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/testExec.e new file mode 100644 index 0000000..61fe9c7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/stringlist/testExec.e @@ -0,0 +1,46 @@ +MODULE 'oomodules/list/doublylinked/stringlist', + 'oomodules/list/execList', + 'oomodules/list/eList', + 'exec/lists', + 'exec/nodes' + + + +PROC main() +DEF stringList:PTR TO stringList, + sortedList, + index, + execlist:PTR TO execlist, + elist:PTR TO elist + + + NEW stringList.new() + + stringList.fromList(['fire','walk','with','me']) + + NEW elist.new() + + elist.set(stringList.asList()) + NEW execlist.new(["list", elist.list]) + + dumpExeclist(execlist.list) + +ENDPROC + +PROC dumpExeclist(list:PTR TO lh) +DEF node:PTR TO ln, + nextnode:PTR TO ln + + node := list.head + + WHILE node.succ + + WriteF('\s\n', node.name) + + nextnode := node.succ + + node := nextnode + + ENDWHILE + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/test.e new file mode 100644 index 0000000..134699c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/doublylinked/test.e @@ -0,0 +1,87 @@ +/* + +This is the original example program of the module that is now +oomodules/list/doublylinked. I didn't change a single byte. + +Gregor Goldbach 95/7/3 + +Added WriteF() of length. + +Gregor Goldbach 95/9/10 + +*/ + +/*=== EXAMPLE PROGRAM ===*/ + +MODULE 'oomodules/list/doublylinked' + +OBJECT mynode OF dlln + string +ENDOBJECT + +OBJECT mylist OF dllh +ENDOBJECT + +PROC new(string) OF mynode + DEF len + self.string:=StrCopy(String(len:=StrLen(string)), string, len) +ENDPROC + +PROC end() OF mynode + DisposeLink(self.string) +ENDPROC + +PROC clear() OF mylist + DEF node:PTR TO mynode + WHILE self.isEmpty()=FALSE + node:=self.remHead() + END node + ENDWHILE +ENDPROC + +PROC insertAlphaSorted(node:PTR TO mynode) OF mylist + DEF listnode:PTR TO mynode, done=FALSE + listnode:=self.firstNode() ->returns lastnode or tail + REPEAT + IF listnode=self.tail + done:=TRUE + ELSEIF OstrCmp(node.string, listnode.string)>=0 + done:=TRUE + ELSE + listnode:=listnode.succ + ENDIF + UNTIL done + self.insert(node, listnode.pred) +ENDPROC + +PROC printAll() OF mylist + DEF node:PTR TO mynode + IF self.isEmpty() + WriteF('*** List is empty\n') + RETURN + ENDIF + node:=self.firstNode() + WHILE node<>self.tail + WriteF('\s\n', node.string) + node:=node.succ + ENDWHILE +ENDPROC + + +PROC main() HANDLE + DEF l:PTR TO mylist, n:PTR TO mynode + NEW l.new() + l.insertAlphaSorted(NEW n.new('AC/DC')) + l.insertAlphaSorted(NEW n.new('Megadeth')) + l.insertAlphaSorted(NEW n.new('Alice in Chains')) + l.insertAlphaSorted(NEW n.new('Metallica')) + +EXCEPT DO + IF exception THEN WriteF('Error occurred during initialization\n') + IF l + l.printAll() + WriteF('\nThe list contains \d items.\n', l.length()) + l.clear() + END l + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist.e new file mode 100644 index 0000000..0453d3f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist.e @@ -0,0 +1,513 @@ +OPT MODULE + +MODULE 'oomodules/object' + +EXPORT OBJECT elist OF object +/****** elist/elist ****************************** + + NAME + elist of object + + PURPOSE + Handles E's own lists in a more dynamic manner. When the limit of + items is reached the list is simply expanded. + + ATTRIBUTES + list:PTR TO LONG -- Normal E list. + + itemCount:LONG -- How many items actually are in the list. Note that + this is NOT the length of the list. This attribute points at the + next free slot to put a value in. + + hunkSize:LONG -- The number of items the list is expanded by if + necessary. + + SEE ALSO + object/object +********/ + list:PTR TO LONG + itemCount + hunkSize +ENDOBJECT + +PROC init() OF elist +/****** elist/init ****************************** + + NAME + init() of elist -- Initialization of the object. + + SYNOPSIS + elist.init() + + FUNCTION + Sets the hunk size to the initial value (currently this is 16, that + may change) and allocates a list that can holg that much items. + + SEE ALSO + elist + +********/ + + self.hunkSize := 16 + self.list := List(self.hunkSize) + SetList(self.list, self.hunkSize) + +ENDPROC + +PROC select(optionlist, index) OF elist +/****** elist/select ****************************** + + NAME + select() of elist -- Selection of action via tag list. + + SYNOPSIS + elist.select(LONG, LONG) + + elist.select(optionlist, index) + + FUNCTION + Recognized tags are: + "set" -- next item is a normal E list. The object is set to + hold that list. See elist/set(). + + INPUTS + optionlist:LONG -- list of options + + index:LONG -- index of option list + + EXAMPLE + see object/select for an example of how select() works in general. + + SEE ALSO + elist/set() + +********/ +DEF item + + item:=ListItem(optionlist,index) + + SELECT item + + CASE "set" + + INC index + self.set(ListItem(optionlist,index)) + + ENDSELECT + +ENDPROC index + +PROC set(elist) OF elist +/****** elist/set ****************************** + + NAME + set() of elist -- Sets the contents of the list. + + SYNOPSIS + elist.set(LONG) + + elist.set(elist) + + FUNCTION + The object is set to point to the list that is given to the function. + By calling this function you hand the list over to the object. That + means that you may not free it unless you remove it from the object + first. Note that the list is automatically freed when ENDing this + object. + + If the object already holds a list that one is freed first. So if + you want to remove a list from the object safely after you have passed + it you may call this function with NIL. + + INPUTS + elist:LONG -- normal E list. May be NIL. + + EXAMPLE + + -> First allocate it + + NEW elist.new() + + -> set it + + elist.set([1,2,3,42]) + + -> now free it + elist.set(NIL) + + NOTES + This function is called when you provide the tag "list" in the option + list for method new() + + SEE ALSO + elist, new() + +********/ + + IF self.list THEN DisposeLink(self.list) + self.list := elist + IF elist THEN self.itemCount := ListLen(self.list) ELSE self.itemCount := 0 + +ENDPROC + +PROC get() OF elist IS self.list, IF self.list THEN ListLen(self.list) ELSE -1 +/****** elist/get ****************************** + + NAME + get() of elist -- Get the list and it's length. + + SYNOPSIS + elist.get() + + FUNCTION + Gets you the actual E list and it's length. The list may not have all + it's items set if it was expanded. + + RESULT + PTR TO LONG -- The E list. NIL if no list is there. + + LONG -- The length of the E list. -1 if no list is there. + + SEE ALSO + elist + +********/ + +PROC grow() OF elist +/****** elist/grow ****************************** + + NAME + grow() of elist -- Expand a list. + + SYNOPSIS + elist.grow() + + FUNCTION + Expands the list by the number of items that is put in the hunkSize + attribute. + + RESULT + LONG -- -1 if the list could not be expanded. The current list stays + valid. + + EXAMPLE + + NEW list.new() + + WriteF('Actual lenght of the list is \d.\n', ListLen(list.list)) + list.grow() + WriteF('Actual lenght of the list is \d.\n', ListLen(list.list)) + + SEE ALSO + elist, add() + +********/ +DEF tempList:PTR TO LONG, + nuSize + + nuSize := ListLen(self.list)+self.hunkSize + tempList := List(nuSize) + + IF tempList = NIL THEN RETURN -1 + + ListCopy(tempList, self.list, ALL) + DisposeLink(self.list) + self.list := tempList + SetList(self.list,nuSize) + +ENDPROC + +PROC add(item) OF elist +/****** elist/add ****************************** + + NAME + add() of elist -- Add an item to the list. + + SYNOPSIS + elist.add(LONG) + + elist.add(item) + + FUNCTION + Adds an item to the list and expands the list if necessary. + + INPUTS + item:LONG -- Item to add to the list. + + RESULT + LONG -- -1 if expansion of the list failed. The current list stays + valid. + + SEE ALSO + elist, grow() + +********/ +DEF list:PTR TO LONG, + res + + list := self.list + + res := Mod(self.itemCount+1, self.hunkSize) +-> WriteF('-- \d\n', res) + IF (res = 0) + +-> WriteF('hafta grow at \d\n', self.itemCount) + IF self.grow()=-1 THEN RETURN -1 +-> WriteF('grown at \n', self.itemCount) + list := self.list + ENDIF + + list[self.itemCount] := item + self.itemCount := self.itemCount+1 + +ENDPROC + +PROC putAt(item,position) OF elist HANDLE +/****** elist/putAt ****************************** + + NAME + putAt() of elist -- Puts an item at a specific position in the list. + + SYNOPSIS + elist.putAt(LONG, LONG) + + elist.putAt(item, position) + + FUNCTION + Puts an item in the list at a certain position. Any value that is at + that position will be overwritten. The list is expanded if necessary. + + INPUTS + item:LONG -- Item to put in the list. + + position:LONG -- Position to put it at. + + RESULT + LONG -- -1 if the list could not be expanded. The current list stays + valid. + + SEE ALSO + elist, grow() + +********/ + + WHILE (position>=ListLen(self.list)) -> while position is out of range + + IF (self.grow()=-1) THEN Raise("MEM") -> exit if no memory + + ENDWHILE + + self.list[position] := item + +-> WriteF('put \d at \d.\n', item, position) + + +EXCEPT + + RETURN -1 + +ENDPROC + +PROC getFrom(position) OF elist +/****** elist/getFrom ****************************** + + NAME + getFrom() of elist -- Get item from a specific position. + + SYNOPSIS + elist.getFrom(LONG) + + elist.getFrom(position) + + FUNCTION + Gets the item that's at position in the list. + + INPUTS + position:LONG -- Position to get the item from. + + RESULT + LONG, LONG -- 0, "rnge" if the position was out of range, i.e. if it + exceeded the list's length. + + SEE ALSO + elist + +********/ + + IF position >= ListLen(self.list) THEN RETURN 0,"rnge" + + RETURN self.list[position] + +ENDPROC + +PROC end() OF elist +/****** elist/end ****************************** + + NAME + end() of elist -- Global destructor. + + SYNOPSIS + elist.end() + + FUNCTION + Disposes the list. + + SEE ALSO + elist + +********/ + + IF self.list THEN DisposeLink(self.list) + +ENDPROC + +PROC kill() OF elist +/****** elist/kill ****************************** + + NAME + kill() of elist -- END all items and the object. + + SYNOPSIS + elist.kill() + + FUNCTION + Goes through the list and does an END on each if the item is not NIL. + After that the object itself is ENDed. + + NOTES + Only call this function when you really know what is in the list. + + SEE ALSO + elist + +********/ +DEF index, + item + + IF self.list = NIL THEN RETURN + + FOR index := 0 TO self.itemCount + + item := self.list[index] + IF item THEN END item + + ENDFOR + + END self + +ENDPROC + +PROC strip() OF elist +/****** elist/strip ****************************** + + NAME + strip() of elist -- Strip existing list from object. + + SYNOPSIS + elist.strip() + + FUNCTION + Gets you the existing list and initializes the object. The list you + get can be used ater the object was ENDed. Useful in procs + when you want to work with the elist object but don't want to return + this object. + + EXAMPLE + + PROC passMeAList(passedList) + DEF elist:PTR TO elist, + list, + anyVar + + NEW elist.new() + + ForAll({anyVar}, passedList, 'IF anyVar=42 THEN elist.add('blue-footed boobie')) + + /* + * We strip the list from the object for outside of this proc + * nobody should know what object we'rr working with :) + */ + + list := elist.strip() + END elist + + ENDPROC list + + SEE ALSO + elist, init() + +********/ +DEF list + + list := self.list + SetList(list, self.itemCount) + + self.list := NIL + self.itemCount := 0 + + self.init() + + RETURN list + +ENDPROC + +PROC find(item) OF elist +DEF index=-1 + + REPEAT + + INC index + + UNTIL (self.list[index]=item) OR (index=self.itemCount) + + /* WriteF('found at \d.\n', index) */ + IF index = self.itemCount THEN Throw("elis",'item not found') ELSE RETURN index + +ENDPROC + +PROC removeFrom(number) OF elist + + IF self.list = NIL THEN RETURN + + IF self.itemCount + + self.list[number] := self.list[self.itemCount-1] + self.list[self.itemCount-1] := NIL + + self.itemCount := self.itemCount-1 + + ELSE + + self.list[0] := NIL + self.itemCount := 0 + + ENDIF + +ENDPROC + +PROC remove(item) OF elist HANDLE + + self.removeFrom(self.find(item)) + +EXCEPT + + /* WriteF('Unable to remove item - not in list.\n')*/ +ENDPROC + +PROC setNextFreeSlotAt(position) OF elist HANDLE + + WHILE (position>=ListLen(self.list)) -> while position is out of range + + IF (self.grow()=-1) THEN Raise("MEM") -> exit if no memory + + ENDWHILE + + self.itemCount := position + +EXCEPT + +ENDPROC +/*EE folds +-1 +5 26 7 21 10 40 13 50 39 41 42 42 91 29 94 18 97 33 100 51 103 11 106 17 109 6 112 11 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/examples new file mode 100644 index 0000000..047f3bf --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/examples @@ -0,0 +1,48 @@ +@database elist_example + +@node main "Introduction to elist" + +The elist object is some kind of 'object oriented object wrapper' for E's +lists. Is as easy to use as the normal lists but provides some powerful +features, for example it increases the size of the list automatically +when this is necessary. + +The list attribute of elist holds the currently active list. Currently +active means that this list may not be valid in the future. + +This is because of the dynamic handling of lists implemented in this object. +The list can't be full as normal E lists can. (Actually it can, but only if +there's no memory left). You can add items to the list and the object +expands itself if necessary. + + + +Currently there's only @{" one example " link EMODULES:oomodules/list/elist/test.e/main} that fiddles around with the elist +features. + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/elist/main} file available or this object. + +@endnode + +@node initilisation "Allocation and initilisation of elist" + +Only one argument can be passed to new - "set". The following tag is a list. +The list attribute is set to this list. If you get a normal E list and you +want to use the advantages of the elist object simply pass the list to NEW. + +@endnode + +@node where "Where to use this object" + +The elist can be used when you have an unknown number of item you want to +collect in a list. When allocating one of E's lists the size is fixed. The +kill() method may come in handy, too. + +@endnode + +@node see_also "See also" + +Associated objects are the objects of the list hierarchy - queuestack +(big but useful), execlist (doubly linked system list) and the others. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/test.e new file mode 100644 index 0000000..58683db --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/elist/test.e @@ -0,0 +1,116 @@ +/* + +Small example to test the elist features. + +*/ + +MODULE 'oomodules/list/elist' + +PROC main() +DEF l:PTR TO elist, + index + + + /* + * Allocate the object and initialize it. + */ + + NEW l.new() + + + + /* + * Dump some information on the list. It should have the size of the + * initial hunk size that is defined as a constant in the elist module. + */ + + WriteF('Created an elist; ') + WriteF('list at \d, ', l.list) + WriteF('hunk size is \d\n', l.hunkSize) + + WriteF('list size is \d\n', ListLen(l.list)) + WriteF('count is \d\n', l.itemCount) + + + + /* + * Add twenty items and set it to anything (in this case the number of + * the element. The add() method takes anything and put it in the list. + */ + + WriteF('\nAdding twenty items.\n') + FOR index := 0 TO 20 + l.add(index) + ENDFOR + + + + /* + * If the hunk size is smaller than twenty the list should be grown now. + */ + + WriteF('list size is \d\n', ListLen(l.list)) + + + + /* + * Play around with the items. The itemCount attribute points to the next + * free slot of the list, i.e. when we want to get rid of the last 10 + * elements of the list we can set this attribute to itemCount-10. The + * items will be overwritten. + */ + + WriteF('\nPut 26 at slot 24.\n') + l.putAt(26,24) + WriteF('count is \d\n', l.itemCount) + l.setNextFreeSlotAt(25) + WriteF('count is \d\n', l.itemCount) + + WriteF('list size is \d\n', ListLen(l.list)) + + + + /* + * Dump the contents of the list. + */ + + WriteF('\nDump all items.\n') + FOR index := 0 TO l.itemCount-1 + WriteF('\d\n', l.getFrom(index)) + ENDFOR + + + + /* + * Remove some items. + */ + + WriteF('\nRemove items 10 and 19.\n') + l.remove(10) + l.remove(19) + + WriteF('list size is \d\n', ListLen(l.list)) + WriteF('count is \d\n', l.itemCount) + + + + /* + * Dump it again to see if removing was successful. + */ + + WriteF('\nDump all items.\n') + FOR index := 0 TO l.itemCount-1 + WriteF('\d\n', l.getFrom(index)) + ENDFOR + + + /* + * END the object and free allocated resources. This does *not* include + * the elements in the list. If you collect allocated objects in such a + * list you would have to call the kill() method to END them as well. + * This END does only free the list, not it's contents. + */ + + END l + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist.e new file mode 100644 index 0000000..def8d41 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist.e @@ -0,0 +1,176 @@ +OPT MODULE + +MODULE 'oomodules/object', + + 'tools/constructors', + + 'exec/lists', + 'exec/nodes' + +EXPORT OBJECT execlist OF object +/****** object/execlist ****************************** + + NAME + execlist of object -- List as used in the exec.library + + PURPOSE + Just a quick and small implementation of exec's list. Only useable + for converting from an elist (for listviews etc.) + + ATTRIBUTES + list:PTR TO lh -- exec's list header + + len:LONG -- number of nodes in the list + + SEE ALSO + object, exec + +********/ + list:PTR TO lh, + len +ENDOBJECT + +PROC init() OF execlist IS EMPTY +/****** execlist/init ****************************** + + NAME + init() of execlist -- Initialization of the object. + + SYNOPSIS + execlist.init() + + FUNCTION + Empty by now. + + SEE ALSO + execlist + +********/ + +PROC select(optionlist, index) OF execlist +/****** execlist/select ****************************** + + NAME + select() of execlist -- Selection of action. + + SYNOPSIS + execlist.select(LONG, LONG) + + execlist.select(optionlist, index) + + FUNCTION + Recognized tags are: + "list" -- take items as node names. See fromList(). + INPUTS + optionlist:LONG -- list of options + + index:LONG -- index of option list + + SEE ALSO + execlist, fromList() + +********/ +DEF item + + item:=ListItem(optionlist,index) + + SELECT item + + CASE "list" + + INC index + self.fromList(ListItem(optionlist,index)) + + ENDSELECT + +ENDPROC index + +PROC fromList(list:PTR TO LONG) OF execlist +/****** execlist/fromList ****************************** + + NAME + fromList() of execlist -- Take items of elist as node names. + + SYNOPSIS + execlist.fromList(LONG) + + execlist.fromList(list) + + FUNCTION + Creates a list. The items of the passed elist are taken as names of + the nodes. Therefore you may free the elist but not the items. + + INPUTS + list:LONG -- E list of strings. + + SEE ALSO + execlist + +********/ +DEF execlist:PTR TO lh, + execnode:PTR TO ln, + nextNode:PTR TO ln, + str, + item, + index + + IF list=NIL THEN RETURN + + self.list := newlist() + + FOR index := 0 TO ListLen(list)-1 + + execnode := newnode(NIL, ListItem(list,index)) + AddTail(self.list,execnode) + + ENDFOR + + self.len := ListLen(list) + +ENDPROC + +PROC end() OF execlist +/****** execlist/end ****************************** + + NAME + end() of execlist -- Global destructor. + + SYNOPSIS + execlist.end() + + FUNCTION + Disposes all nodes and the list. If the nodes have names you have to + dispose them. + + SEE ALSO + execlist + +********/ +DEF execnode:PTR TO ln, + index, + nextNode:PTR TO ln + + execnode := self.list.head + + WriteF('ending exec list with \d nodes.\n', self.len) + + FOR index:=1 TO self.len + + nextNode := execnode.succ + WriteF('ending node at \d, next node is \d.\n', execnode, nextNode) + Dispose(execnode) + execnode := nextNode + + ENDFOR + + WriteF('ending list header at \d.\n') + Dispose(self.list) + + WriteF('all resources of object freed, returning.\n') + +ENDPROC + +/*EE folds +-1 +10 21 29 35 32 41 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/Examples new file mode 100644 index 0000000..a9262f1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/Examples @@ -0,0 +1,35 @@ +@database execlist_example + +@node main "Introduction to execlist" + +The execlist object is some kind of 'object oriented object wrapper' for +exec.library's lists. Those lists are used in listview gadgets for example +and in many other places of the Amiga OS. + +Currently there's only @{" one example " link EMODULES:oomodules/list/execlist/test.e/main} that fiddles around with the execlist +features. + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/execlist/main} file available or this object. + +@endnode + +@node initilisation "Allocation and initilisation of execlist" + +The most important argument that can be passed to new is "list". The +following tag is an E list the object is set to. Listviews and other +system objects can be initialised quickly using this feature. + +@endnode + +@node where "Where to use this object" + +Anywhere you want to use exec lists. + +@endnode + +@node see_also "See also" + +Associated objects are the objects of the list hierarchy - queuestack +(big but useful), elist (object wrapper of E's list) and the others. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/test.e new file mode 100644 index 0000000..3caa6ac --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/execlist/test.e @@ -0,0 +1,64 @@ +/* + +Sample program for the execlist object. It allocates an execlist and +displays its contents in a Listview gadgets via EasyGUI. + +*/ + +MODULE 'oomodules/list/execlist', + 'tools/easygui' + +PROC main() HANDLE + + /* + * Call the proc that opens a windows with the title 'huhu' + */ + + showList(NIL,'huhu') + + + + /* + * If something went wrong we are here + */ + +EXCEPT + WriteF('exception raised\n') +ENDPROC + + + +PROC showList(list, title) +DEF execlist:PTR TO execlist + + /* + * Allocate the object and set the list two the four entries. + * Since the "list" tag takes any E list we could use the elist + * object when we want to have a dynamic list (see there). + */ + + NEW execlist.new(["list", ['1','two','tres','vier']]) + + + + /* + * Tell EasyGUI to open a window with a listview gadget. A listview + * gadget takes the entries to display from an exec list - each node + * of the list is an entry. That exec list can be retrieved from the + * execlist object be specifying the list attribute. + */ + + easygui(title, + [EQROWS, + [LISTV,NIL,NIL,30,10,execlist.list,0,0,0], + [BUTTON,NIL,'None'] + ]) + + + /* + * Be friendly and END the object. + */ + + END execlist + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/list/queuestack.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/queuestack.e new file mode 100644 index 0000000..9be25a7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/list/queuestack.e @@ -0,0 +1,381 @@ +OPT MODULE + +MODULE 'oomodules/object' + +EXPORT OBJECT qsnode OF object + right:PTR TO qsnode + left:PTR TO qsnode + item +ENDOBJECT + +EXPORT OBJECT queuestack OF object + baditem + mysize + last:PTR TO qsnode + first:PTR TO qsnode +ENDOBJECT + +DEF tmp:PTR TO qsnode,moo:PTR TO LONG +EXPORT DEF ctrlc + +EXPORT PROC name() OF qsnode IS 'QSNode' + +EXPORT PROC size() OF qsnode IS 16 + +EXPORT PROC select(opts,i) OF qsnode + DEF item + item:=ListItem(opts,i) + SELECT item + CASE "set" + INC i + self.item:=ListItem(opts,i) + ENDSELECT +ENDPROC i + +EXPORT PROC inject(proc,item) OF qsnode + self.item:=proc(self.item,item) + IF ctrlc AND CtrlC() THEN Raise("^C") + IF self.right THEN self.right.inject(proc,self.item) +ENDPROC + +EXPORT PROC injectBackwards(proc,item) OF qsnode + self.item:=proc(self.item,item) + IF ctrlc AND CtrlC() THEN Raise("^C") + IF self.left THEN self.left.injectBackwards(proc,self.item) +ENDPROC + +EXPORT PROC do(proc) OF qsnode + proc(self.item) + IF ctrlc AND CtrlC() THEN Raise("^C") + IF self.right THEN self.right.do(proc) +ENDPROC + +EXPORT PROC doBackwards(proc) OF qsnode + proc(self.item) + IF ctrlc AND CtrlC() THEN Raise("^C") + IF self.left THEN self.left.doBackwards(proc) +ENDPROC + +EXPORT PROC collect(proc,add:PTR TO queuestack) OF qsnode + add.addLast(proc(self.item)) + IF ctrlc AND CtrlC() THEN Raise("^C") + IF self.right THEN self.right.collect(proc,add) +ENDPROC + +EXPORT PROC collectBackwards(proc,add:PTR TO queuestack) OF qsnode + add.addLast(proc(self.item)) + IF ctrlc AND CtrlC() THEN Raise("^C") + IF self.left THEN self.left.collectBackwards(proc,add) +ENDPROC + +EXPORT PROC conform(proc) OF qsnode + IF ctrlc AND CtrlC() THEN Raise("^C") + RETURN IF self.right THEN self.right.conform(proc) AND proc(self.item) ELSE proc(self.item) +ENDPROC + +EXPORT PROC detect(proc,baditem) OF qsnode + IF ctrlc AND CtrlC() THEN Raise("^C") + RETURN IF proc(self.item) THEN self.item ELSE IF self.right THEN self.right.detect(proc,baditem) ELSE baditem +ENDPROC + +EXPORT PROC detectBackwards(proc,baditem) OF qsnode + IF ctrlc AND CtrlC() THEN Raise("^C") + RETURN IF proc(self.item) THEN self.item ELSE IF self.left THEN self.left.detectBackwards(proc,baditem) ELSE baditem +ENDPROC + +EXPORT PROC reject(proc,add:PTR TO queuestack) OF qsnode + IF ctrlc AND CtrlC() THEN Raise("^C") + IF proc(self.item)<>TRUE + add.addLast(self.item) + ENDIF + IF self.right THEN self.right.reject(proc,add) +ENDPROC + +EXPORT PROC rejectBackwards(proc,add:PTR TO queuestack) OF qsnode + IF ctrlc AND CtrlC() THEN Raise("^C") + IF proc(self.item)<>TRUE + add.addLast(self.item) + ENDIF + IF self.left THEN self.left.rejectBackwards(proc,add) +ENDPROC + +EXPORT PROC choose(proc,add:PTR TO queuestack) OF qsnode + IF ctrlc AND CtrlC() THEN Raise("^C") + IF proc(self.item) + add.addLast(self.item) + ENDIF + IF self.right THEN self.right.choose(proc,add) +ENDPROC + +EXPORT PROC chooseBackwards(proc,add:PTR TO queuestack) OF qsnode + IF ctrlc AND CtrlC() THEN Raise("^C") + IF proc(self.item) + add.addLast(self.item) + ENDIF + IF self.left THEN self.left.choose(proc,add) +ENDPROC + +EXPORT PROC end() OF qsnode + tmp:=self.right + IF tmp THEN END tmp +ENDPROC + +EXPORT PROC size() OF queuestack IS 20 + +EXPORT PROC name() OF queuestack IS 'QueueStack' + +EXPORT PROC select(opts,i) OF queuestack + DEF item + item:=ListItem(opts,i) + SELECT item + CASE "bad" + INC i + self.baditem:=ListItem(opts,i) + CASE "set" + INC i + self.set(ListItem(opts,i)) + ENDSELECT +ENDPROC i + +EXPORT PROC set(item) OF queuestack + IF (item = self.baditem) AND (self.first = NIL) THEN RETURN + IF self.first = NIL + self.first := NEW tmp.new(["set",item]) + self.mysize := 1 + self.last:=self.first + ELSE + tmp:=self.first + END tmp + self.first:=0 + self.last:=0 + ENDIF +ENDPROC + +EXPORT PROC addFirst(item) OF queuestack + IF item = self.baditem THEN RETURN self.error({baditem}) + self.mysize:=self.mysize+1 + IF self.first = NIL + self.first:=NEW tmp.new(["set",item]) + self.last:=self.first + ELSE + self.first.left := NEW tmp.new(["set",item]) + self.first.left.right:=self.first + self.first := self.first.left + ENDIF +ENDPROC + +EXPORT PROC addLast(item) OF queuestack + IF item = self.baditem THEN RETURN self.error({baditem}) + self.mysize:=self.mysize+1 + IF self.first = NIL + self.first:=NEW tmp.new(["set",item]) + self.last:=self.first + ELSE + self.last.right := NEW tmp.new(["set",item]) + self.last.right.left:=self.last + self.last := self.last.right + ENDIF +ENDPROC + +EXPORT PROC getFirst() OF queuestack + DEF out=0 + IF self.mysize + self.mysize:=self.mysize-1 + out:=self.first.item + tmp:=self.first + self.first:=self.first.right + tmp.right:=0 + END tmp + IF self.mysize = NIL + self.first:=NIL + self.last:=NIL + ENDIF + ELSE + out:=FALSE + Raise("qstk") + ENDIF +ENDPROC out + +EXPORT PROC getLast() OF queuestack + DEF out=0 + IF self.mysize + self.mysize:=self.mysize-1 + out:=self.last.item + tmp:=self.last + self.last:=self.last.left + tmp.right := 0 + END tmp + IF self.mysize = NIL + self.first:=NIL + self.last:=NIL + ENDIF + ELSE + out:=FALSE + Raise("qstk") + ENDIF +ENDPROC out + +EXPORT PROC length() OF queuestack IS self.mysize + +EXPORT PROC addFirstQS(in:PTR TO queuestack) OF queuestack + IF in.first + self.first.left:=in.last + in.last.right:=self.first + self.mysize := self.mysize + in.mysize + self.first := in.first + in.mysize := 0 + in.first := NIL;in.last := NIL + ENDIF +ENDPROC + +EXPORT PROC addLastQS(in:PTR TO queuestack) OF queuestack + IF in.first + self.last.right:=in.first + in.first.left:=self.last + self.last := in.last + self.mysize := self.mysize + in.mysize + in.mysize := 0 + in.first := NIL; in.last := NIL + ENDIF +ENDPROC + +EXPORT PROC inject(proc,item=0) OF queuestack + IF self.first THEN RETURN self.first.inject(proc,item) +ENDPROC + +EXPORT PROC injectBackwards(proc,item=0) OF queuestack + IF self.last THEN RETURN self.last.injectBackwards(proc,item) +ENDPROC + +EXPORT PROC do(proc) OF queuestack + IF self.first THEN self.first.do(proc) +ENDPROC + +EXPORT PROC doBackwards(proc) OF queuestack + IF self.last THEN self.last.doBackwards(proc) +ENDPROC + +EXPORT PROC collect(proc) OF queuestack + DEF add:PTR TO queuestack + NEW add.new(["bad",[self.baditem]]) + IF self.first THEN self.first.collect(proc,add) + RETURN add +ENDPROC + +EXPORT PROC collectBackwards(proc) OF queuestack + DEF add:PTR TO queuestack + NEW add.new(["bad",[self.baditem]]) + IF self.last THEN self.last.collectBackwards(proc,add) + RETURN add +ENDPROC + +EXPORT PROC conform(proc) OF queuestack + RETURN IF self.first THEN self.first.conform(proc) ELSE FALSE +ENDPROC + +EXPORT PROC detect(proc) OF queuestack + RETURN IF self.first THEN self.first.detect(proc,self.baditem) ELSE self.baditem +ENDPROC + +EXPORT PROC detectBackwards(proc) OF queuestack + RETURN IF self.last THEN self.last.detectBackwards(proc,self.baditem) ELSE self.baditem +ENDPROC + +EXPORT PROC reject(proc) OF queuestack + DEF add:PTR TO queuestack + NEW add + IF self.first THEN self.first.reject(proc,add) + RETURN add +ENDPROC + +EXPORT PROC rejectBackwards(proc) OF queuestack + DEF add:PTR TO queuestack + NEW add + IF self.last THEN self.last.rejectBackwards(proc,add) + RETURN add +ENDPROC + +EXPORT PROC choose(proc) OF queuestack + DEF add:PTR TO queuestack + NEW add + IF self.first THEN self.first.choose(proc,add) + RETURN add +ENDPROC + +EXPORT PROC chooseBackwards(proc) OF queuestack + DEF add:PTR TO queuestack + NEW add + IF self.last THEN self.last.chooseBackwards(proc,add) + RETURN add +ENDPROC + +EXPORT PROC asList() OF queuestack + moo:=List(self.length()) + self.do({makeList}) +ENDPROC moo + +EXPORT PROC asListBackwards() OF queuestack + moo:=List(self.length()) + self.doBackwards({makeList}) +ENDPROC + +EXPORT PROC asQueueStack(in) OF queuestack + DEF i,mytmp + mytmp:=in + WHILE mytmp + FOR i:=0 TO ListLen(mytmp)-1 + IF ListItem(mytmp,i)<>self.baditem THEN self.addLast(ListItem(mytmp,i)) ELSE RETURN self.error({baditem}) + ENDFOR + mytmp:=Next(mytmp) + ENDWHILE +ENDPROC + +EXPORT PROC asQueueStackBackwards(in) OF queuestack + DEF i,mytmp + mytmp:=in + WHILE mytmp + FOR i:=0 TO ListLen(mytmp)-1 + IF ListItem(mytmp,i)<>self.baditem THEN self.addFirst(ListItem(mytmp,i)) ELSE RETURN self.error({baditem}) + ENDFOR + mytmp:=Next(mytmp) + ENDWHILE +ENDPROC + +EXPORT PROC error(text=0,opt=0) OF queuestack + SELECT text + CASE 0 + RETURN FALSE + CASE {baditem} + RETURN text + CASE {queuestackempty} + RETURN text + DEFAULT + RETURN SUPER self.error(text,opt) + ENDSELECT +ENDPROC + +EXPORT PROC kill() OF queuestack + self.do({murder}) + self.end() + self.first:=0 + self.last:=0 + self.mysize:=0 +ENDPROC + +EXPORT PROC end() OF queuestack + tmp:=self.first + END tmp +ENDPROC + +PROC murder(i) + END i +ENDPROC + +PROC makeList(i) + ListAdd(moo,[i,0],1) +ENDPROC + +baditem: + CHAR 'Bad item\n',0 +queuestackempty: + CHAR 'Empty\n',0 diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/object.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/object.e new file mode 100644 index 0000000..d3ed5f2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/object.e @@ -0,0 +1,491 @@ +/****** object/--background-- ****************************************** + + PURPOSE + The base object for everything in the oomodules/ hierarchy. + + CREATION + in early 1995 by Trey van Riper + + HISTORY + +****************************************************************************** + +History + + +*/ + +OPT MODULE +OPT EXPORT,PREPROCESS + +#define LOCALE_SUPPORT 1 + + +/* MODULE 'other/stderr' */ + +#ifdef LOCALE_SUPPORT + +MODULE 'oomodules/library/locale/catalogList', + 'oomodules/old' + +EXPORT DEF catalogList:PTR TO catalogList + +#endif + + +OBJECT object +/****** object/--object-- ****************************************** + + NAME + object + + NOTES + The Object object (hmm.. sounds redundant) has no attributes, and + tons of methods. + + We may decide to create one or two very important global variables + in the future. These variables will hold information on various + system settings which will allow a smoother halt() and some other + handy functions. At the moment, though, no global variables exist + in the Object module. + +****************************************************************************** + +History + + +*/ +ENDOBJECT + +PROC new(opts=0) OF object +/****** object/new ****************************************** + + NAME + new() -- Create a new instance of an object. + + SYNOPSIS + object.new(opts=0) + + FUNCTION + This allows new instances of objects to be created. It takes as + an argument an Amiga E list ['such','as','this'] which is then + parsed by the opts() method, which places a call to the select() + method. My might want to read up on those. + + In general, you will only want to create new select() statements + for your objects... new() most likely can be left alone. + + INPUTS + opts=0 -- The optionlist + + EXAMPLE + When folks go to use objects, they ought to do something like the + following: + + NEW object.new() + + or if there are options to parse... + + NEW object.new(["boo",'SCREAM']) + + SEE ALSO + select(), init() +****************************************************************************** + +History + + +*/ + /* + * NEW the global catalog list. Don't do it in init() for it could be needed + * in there... + */ + +#ifdef LOCALE_SUPPORT + + IF catalogList = NIL THEN NEW catalogList.new() + +#endif + + + self.init() + self.opts(opts) + +ENDPROC + +PROC init() OF object IS EMPTY +/****** object/init ****************************************** + + NAME + init() -- Initialize an object. + + SYNOPSIS + object.init() + + FUNCTION + Initializes an object to default startup values. You very likely + will want to create your own init() method in your derived objects, + in order to properly initialize your attributes. This init() + method does nothing. If you're not concerned about the internal + attributes during initialization, then this method can be left + alone. + + SEE ALSO + new(), select() +****************************************************************************** + +History + + +*/ + + +PROC size() OF object IS 4 +/****** object/size ****************************************** + + NAME + size() -- Get the size of the object in bytes + + SYNOPSIS + object.size() + + FUNCTION + This returns the SIZEOF the current object. Most likely, this is + a superfluous method, and might need to be reconsidered. In the + meantime, if you want this method to have any meaning at all, you + need to calculate the 'SIZEOF' your object either by adding up all + the attributes and adding four more bytes (for the pointer to its + methods), or by compiling the object and using ShowModule to see + the SIZEOF it comes up with. + + RESULT + The size in bytes + +****************************************************************************** + +History + + +*/ + +PROC opts(opts) OF object +/****** object/opts ****************************************** + + NAME + opts() -- Parse options. + + SYNOPSIS + object.opts(optionlist) + + FUNCTION + This runs a FOR/ENDFOR loop that calls select(). It's most + unlikely that you'll need to modify this method. This method + may disappear in the future (it might be absorbed by new()). + + INPUTS + optionlist -- The optionlist to parse. + + SEE ALSO + select(), new() +****************************************************************************** + +History + + +*/ + DEF i,next + IF opts=0 THEN RETURN + next:=opts +-> REPEAT + FOR i:=0 TO ListLen(next)-1 + i:=self.select(next,i) + ENDFOR +-> next:=Next(next) +-> UNTIL next=NIL +ENDPROC + +PROC select(opt,i) OF object IS i +/****** object/select ****************************************** + + NAME + select() -- Selection of action on initialization. + + SYNOPSIS + object.select(optionlist,index) + + FUNCTION + You'll definately want to create a 'select' statement if you want + new() to have options enabled. All select statements should have + this general format: + + PROC select(optionlist,index) OF myBlowOutObject + DEF item + item:=ListItem(optionlist,index) + SELECT item + -> various cases and perhaps a default.. could look like this: + CASE "boo" + INC index + self.boo(ListItem(optionlist,index)) + ENDSELECT + ENDPROC i + + NOTE THE LAST LINE! If you fail to return i, you could wind up + with an endless loop! This would be a bad thing. + + INPUTS + optionlist -- An elist with tags (or options) that define object + specific actions. + + index -- Position of item we process next in the list. + + SEE ALSO + new(), init() +****************************************************************************** + +History + + +*/ + +PROC error(string,number) OF object +/****** object/error ****************************************** + + NAME + error() -- Report error to stderr + + SYNOPSIS + object.error(string,number) + + FUNCTION + This calles err_WriteF(a,b) as it stands, and returns NIL. You may + want to overload this behavior to do something else, or perhaps + call this from within your own error() routine via SUPER. The + err_WriteF() procedure was written by Joseph E. Van Riper III as + an easy kind of standard error port for Amiga E... it should be + found in the emodules:other directory of your structure. If you + don't have it, you can get it from aminet:dev/e. + + If err_WriteF() is ever called, the programmer must end hir main() + program with 'err_Dispose()' before exiting. This is due to + certain housekeeping matters in Van Riper's StdErr port. + + INPUTS + string -- String to report. + +****************************************************************************** + +History + + +*/ + /* err_WriteF(string,[number]) */ + RETURN NIL +ENDPROC + +PROC name() OF object IS 'Object' +/****** object/name ****************************************** + + NAME + name() -- Get the name of the object. + + SYNOPSIS + object.name() + + FUNCTION + This method should be overloaded for each new class. It should + return a short string of the name of the object. In the object + Object, it's called 'Object'. This is useful for trying to track + down certain internal things in the system (particularly some of + the really funky stuff in the Numbers hierarchy). + + RESULT + A string with the name of the object. + +****************************************************************************** + +History + + +*/ + +PROC end() OF object IS EMPTY +/****** object/end ****************************************** + + NAME + end() -- Global destructor. + + SYNOPSIS + object.end() + + FUNCTION + This is the automatic deallocator. Whenever an object is ENDed, + this will be called. While the Object's end() statement does + nothing, other objects in the hierarchy may be doing some kind + of housekeeping before deallocating the object. If you do not + know whether or not your parent object needs to do some kind of + housekeeping, do a SUPER self.end() somewhere within your own + end() statement (if you even need an end() statement). + + SEE ALSO + new() +****************************************************************************** + +History + + +*/ + +PROC derivedClassResponse() OF object +/****** object/derivedClassResponse ****************************************** + + NAME + derivedClassResponse() -- Standard proc for derived responsibility. + + SYNOPSIS + object.derivedClassResponse() + + FUNCTION + Call this proc in a method that is non-functional by now, but is + functional in objects that derive from this. It writes a message + to stdout that tells that this method isn't implemented. + +****************************************************************************** + +History + + +*/ +DEF msg:PTR TO CHAR + +#ifdef LOCALE_SUPPORT + + IF catalogList + + catalogList.setCurrentCatalog(NIL,OLDC_OBJECT, OLDL_ENGLISH) + msg := catalogList.getString(OLDM_OBJECT_DERIVED_RESPONSE, 'Method not implemented for this derived class') + + ELSE +#endif + msg := 'Method not implemented for this derived class' +#ifdef LOCALE_SUPPORT + ENDIF +#endif + + + WriteF('\s:\s\n',self.name(), msg) + +ENDPROC + +PROC halt(i) OF object +/****** object/halt ****************************************** + + NAME + halt() -- Stop program execution immediately. + + SYNOPSIS + object.halt(i) + + FUNCTION + This is intended to stop the entire program dead in its tracks. + Use this with extreme prejudice, as it doesn't bother to + deallocate anything (yet), and will likely leave filehandles + open or memory allocated or any of a hundred other horrible + system-unfriendly things (it calls CleanUp()). + + In the future, this statement will likely be used to Raise() an + exception rather than die. + + INPUTS + i -- Anything you like. Passed to CleanUp(). + +****************************************************************************** + +History + + +*/ + CleanUp(i) +ENDPROC + +PROC sameAs(a:PTR TO object) OF object IS IF a.name() = self.name() THEN TRUE ELSE FALSE +/****** object/sameAs ****************************************** + + NAME + sameAs() -- Compare to another object. + + SYNOPSIS + object.sameAs(obj:PTR TO object) + + FUNCTION + This method determines whether or not the current object is the + same kind of object as the parameter object. obj is assumed to + be in the Object heirarchy at some point. Basically, this simply + compares self.name() to a.name() to see if it's the same value. + + INPUTS + obj:PTR TO object -- Pointer to any object in the oomodules/ + hierarchy. + + RESULT + TRUE if both objects are the same, FALSE if not. + +****************************************************************************** + +History + + +*/ + +PROC differentFrom(a) OF object IS self.derivedClassResponse() +/****** object/differentFrom ****************************************** + + NAME + differentFrom() -- Are the objects not of the same kind? + + SYNOPSIS + object.differentFrom(obj) + + FUNCTION + This method determines whether or not the current object is a + different kind of object from the parameter object. obj is + assumed to be in the Object heirarchy at some point. + + INPUTS + obj -- Pointer to any object in the oomodules/ hierarchy. + + RESULT + TRUE if objects are different, FALSE if the same. + + NOTES + Doesn't do anything by now, derived objects have to handle this. + +****************************************************************************** + +History + + +*/ + +PROC update(a=0) OF object IS self.derivedClassResponse() +/****** object/update ****************************************** + + NAME + update() -- Update the object. + + SYNOPSIS + object.update(a) + + FUNCTION + This method currently does nothing, but the idea behind this method + is to cause the object to update itself (freshen its current + information, perhaps). + + INPUTS + a -- Use it as you want. + +****************************************************************************** + +History + + +*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/gg.guide b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/gg.guide new file mode 100644 index 0000000..070ffc0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/gg.guide @@ -0,0 +1,71 @@ +@database gregorGoldbach + +@node main "Gregor Goldbach" + + @{" OO and me " link oo_and_me} + @{" The ooep " link ooep} + +@endnode + +@node oo_and_me "OO and me" + +OO came to me via E. I started with E in late 1993 when I found Ev2.1b on a +Fish disk (I think it was 848). E was - and still is - easy to learn, easy to +use and EC compiles fast. And there are a lot of exotic features. Still I +avoided to use unification successfully :) + +When Ev3 was released I tried to use objects and methods rather than +structures and procs. Unluckily I failed for back then I was coding on my +old A500. After the code generation bug was fixed I tried to figure out what +OO was. I don't think I know it by now but I use some features in my sources. + +Encapsulation and polymorphism are just to good to miss... + +@endnode + +@node ooep "The ooep" + +About one and a half years ago Trey mentioned the ooep. Almost instantly I +wanted to contribute to it. Well, I did contribute a lot. Right now (June +1996) I am the only one who works on it. Trey is busy with his job and the +people I mailed about the ooep are quiet. + +If you read this in June '96 you're probably linked either to Aminet/dev/e +or the E mailing list. I'm launching the project to the public for the above +reasons. I've put too much work in it to let it go down. + +The whole archive is provided as found on my hard disk. That leads to these +consequences: + + - Some objects may not work correctly. The reason for this is very simple: + I'm all alone. I coded the objects and tested them. That's not how it + should be. The programmer is not a good tester for his own program. + + - The documentation may be somewhat weird. I don't know if the docs are any + good or just crap. Also they differ in style since my doc-writing style + evolved over the months. + + - Test programs are missing. Often I designed an object to be able to design + another. The test program of the first object mutated to an inheriting + object. + +I didn't launch the archive earlier for this very reasons. + +I hope the whole archive is still useable. In fact I use these objects very +often: + + - elist + - execlist + - associative array + - string list + - GUI/requester/standard + - file/textfile/programsource/* + +The last things I worked on were exec/port/* and commodity before I returned +to my database objects. + +You may have wondered what this guy did who had the idea of the Amiga E +Encyclopedia. Well, now you know what I fiddled around with :) + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/jevr.guide b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/jevr.guide new file mode 100644 index 0000000..a57a75c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/authors/jevr.guide @@ -0,0 +1,202 @@ +@DATABASE "jevr.doc" + +@NODE MAIN "jevr.doc" + +I, Joseph Edwards Van Riper III, as of this writing, am busy +writing music and developing object technologies for the +public domain community, with the hopes of getting things +going in these areas. The technology is too good to allow +the industrial sector to abuse. + +I had intended to graduate this semester, but I blew it +(wasn't able to finish my project in time). I hope to +graduate by the end of the summer of '95. + +Most of the work in building objects for a system is in the +design, not in the programming; programming should be +relatively simple once the analysis and design is taken care +of. It is my sincere hope that this meager beginning might +help folks start developing a system that would work with +the Amiga and Amiga E, with elegance and efficiency. + +Ultimately, I would like to see object equivalences to the +entire Amiga OS handled by these objects, but I cannot +possibly do this on my own without desiring to charge for +the work . + +In this way, I see this rather daunting project of +developing a system of objects for Amiga E as an excellent +opportunity for the Amiga E Encyclopedia, for as folks code +examples of the OS, that same code can be re-written as +objects applicable to this project. + +If Object Technology works as I understand it to work, this +job will never be completed.. only perfected. As such, I am +concerned that this project be handled with as much +responsibility and care as possible. Please examine +documents carefully. Please try to grok Object Technology, +its advantages, methodology issues, and other related +matters as much as possible while you contribute. + +We may not be able to resurrect the Amiga from Commodore's +flames, but we can put up a good fight . + +Those of you familiar with Smalltalk may notice some +similarities in what I'm trying to do and the GNU Smalltalk +available for unix systems. I've taken many of the ideas +and reapplied them. Because this is not actually Smalltalk, +we have several significant differences in the way we handle +things. This is normal. + +@{" Table Of Contents " Link Table_Of_Contents} + +@{" My OT History " Link 1.} +@{" OT Satori " Link 2.} +@ENDNODE + +@NODE Table_Of_Contents " Table Of Contents " +MAIN@{" jevr.doc " Link MAIN} + 1.@{" My OT History " Link 1.} + 2.@{" OT Satori " Link 2.} +@ENDNODE + +@NODE 1. "My OT History" + +I've been trying to gather an understanding of Object +Technology since 1990, when I left the US military (I am +honorably discharged, something I think of as remarkable +considering my distaste for the military). I bought the +Lattice C++ compilor for $300, only to find Lattice had but +one object with the compilor... 'stream'. I felt as if I'd +been ripped off. + +Now SAS owns Lattice, and no longer freely provides the +technical support they used to provide, something I consider +horrid as the manuals are terribly misleading, and the +compilor will GURU if coaxed none-too-carefully. + +Thus I started working with Amiga E. Amiga E is faster, +handles objects with greater facility than C++, makes +smaller code, and has the greatest bunch of folks using it +that one could ever hope for. I'll admit that Amiga E has +its shortcomings, but that I have put Amiga E on my 40 meg +harddrive and not SAS's C++ compilor should speak volumes. +My $35 for Amiga E feels better spent than the $300 on SAS's +C++. + +I'm now taking Object Technology as a course at +UNC-Asheville. I'm probably not going to do well in the +course, though, because I can't stand the volumes of +busy-work this instructor loads the students with. A +three-credit hour course does not require papers written +each week on various readings we do... and my ability to +retain information is not so weak as to necessitate this +kind of work. Unfortunately, I cannot seem to convince the +instructor to ease up, so I'll probably not do well. + +None-the-less, I am learning what I want to learn from the +course. I figured out fairly early (during my SAS C++ +miseries) that the key to making Object Technology work was +not as much in the programming as the organization, but I +hadn't quite figured out the way to approach organizing what +I wanted to do. + +So I thought I'd try leaping into the whole mess with my +first fairly significant programming project for the Amiga, +'Quip'. Some of you may have seen it haunting Aminet... it +lurks as a rather large, hulking entity, and boasts itself +as The Fortune Cookie Program from Hell. The first version +I wrote was written in C++, although I took advantage of +none of the object features in the language, having been +accustomed to procedural ways of programming. Thus, C++ was +a failure for me, in terms of learning object technology. +Amiga E suffers from the same problem, frankly. They are +both hybrid languages, incorporating both Object and +Procedural methodologies. + +I realized I wasn't really working with objects, so I +attempted to reprogram the entire thing as a set of objects. +I made the classic OT programming mistake of turning the +main() part into a separate object and thinking "Object +Oriented". I had done a little more than this, though, but +ultimately I had failed to really grasp it, and I could tell +that my work was still somehow 'weak' in terms of +programming elegance; I couldn't reuse my code very well. + +It wasn't long after this that I abandoned programming for +a long time, concentrating on my music studies. Eventually, +I picked up the GNU C++ compilor, but I had to get rid of +it, since it was taking up too much space on my tiny +harddrive. Then I stumbled into Amiga E, which proved to be +faster than any compilor I'd run across on any platform. + +I was saddened that Amiga E wasn't object oriented (this was +the old 2.?? version). I still had demands set up for +myself for Quip, so I reprogrammed the entire thing from +scratch (this was at least the second or third time I had +done so), but I had to use procedural ways of doing things +to avoid global variables. I STILL hadn't really grasped OT +that well. Considering some of the comments I had made to +Wouter, and that Wouter had had a chance to examine some of +my code before I finished it (in the process of hunting down +errors I perceived in his compilors.. I think the errors +were mostly mine, as usual.. Wouter is the most patient +programmer I have ever stumbled across) I sometimes think I +must have looked like a total dolt as far as Object +Technology is concerned. + +I could tell I hadn't quite figured SOMETHING out, but I +didn't really quite grasp it until I picked up 'IBM +Smalltalk; The Language' for my Object Technology course. I +started reading some of it before the course started, and +suddenly figured out what my basic problem was, and how to +go about creating good objects. + +When the course started, everything fell right into place. +I had alread grasped the single most difficult concept this +way of programming threw to me, and I was hungry for more +information. + +One might say that this attempt to create a system of +objects for Amiga E and the Amiga is the culmination of +literally years of searching for The Way to program in this +kind of methodology. + +@ENDNODE + +@NODE 2. "OT Satori" + +The trick to working with OT is in the design (as I +mentioned before). Before writing the first character of +code, one must analyse and design what one is attempting to +do, and with what one must do it. + +This is the biggest difference: 'with what one must do it'. + +In the past, I had been trying to figure out 'how one must +do it' rather than 'with what one must do it.' The +difference is staggering. In fact, one begins to find a +greater ease in programming in an OT fashion than in the +older procedural way... the hard part becomes the analysis +and design. + +You find yourself building little objects, and ways for the +little objects to communicate to each other so they might, +in a tiny little community that makes up your program, get a +specific set of tasks done. Together, they form a kind of +community (or 'system' as the parlance goes). The focus is +on the data you're trying to play with, and not on the +actual "playing with the data". + +I've already uploaded a couple of examples of the Object +Technology approach, by way of showing its benefits (and, +hopefully, how to think about the matter elegantly). The +best example prior to this starting project that I uploaded +was my most recent set of Quip objects (which are still not +even close to being done , since I've been working on +this project and a zillion other things). I urge you to +examine that code (and this code) to get an idea of what I'm +up to. + +@ENDNODE + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/Examples new file mode 100644 index 0000000..671bfc7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/Examples @@ -0,0 +1,104 @@ +@database "OOEP Examples" + +@node main "OOEP demo sources" + +This database contains links to the example sources of the OOEP. Each +paragraph contains an introduction to the object and links to related +files (e.g. autodocs). + +Note that the entries with asterisks before them aren't included in this release. + + @{" General " link usingTheHierarchy/main} General hints + +* @{" Coordinate " link Coordinate} + + +Database related modules. Experimental. + +* @{" database " link database} +* @{" database/datafile " link database/datafile} +* @{" database/dbcreator " link database/dbcreator} +* @{" database/field " link database/field} +* @{" database/record " link database/record} + + +File related modules. Includes basic text and binary modules as well as +hypertext files. + +* @{" file " link file} +* @{" file/textfile " link file/textfile} +* @{" file/textfile/document " link file/textfile/document} +* @{" file/textfile/document/hypertextDocument " link file/textfile/document/hypertextDocument} +* @{" file/textfile/document/hypertextDocument/amigaguideDocument " link file/textfile/document/hypertextDocument/amigaguideDocument} +* @{" file/textfile/programsource " link file/textfile/programsource} +* @{" file/textfile/programsource/esource " link file/textfile/programsource/esource} + +* @{" font " link font} + + +Modules for use with graphical user interface. + +* @{" GUI " link //GUI/examples/main} +* @{" GUI/requester " link //GUI/requester/Examples/main} +* @{" GUI/requester/standard " link //GUI/requester/standard/Examples/main} + + +Library derived stuff. Involves basic library objects and modules that are +based on those libraries. catalogList for example makes it possible to use +many catalogs in your application. + + @{" library " link //library/examples/main} +* @{" library/asl " link library/asl} +* @{" library/device " link library/device} +* @{" library/device/audio " link library/device/audio} +* @{" library/device/printer " link library/device/printer} +* @{" library/device/trackdisk " link library/device/trackdisk} + @{" library/exec " link //library/exec/Examples/main} + @{" library/exec/port " link //library/exec/port/Examples/main} +* @{" library/exec/port/arexxPort " link library/exec/port/arexxPort} +* @{" library/exec/port/portList " link library/exec/port/portList} + @{" library/locale " link //library/locale/examples/main} + @{" library/locale/catalogList " link //library/locale/catalogList/Examples/main} +* @{" library/reqtools " link library/reqtools} + + +All kinds of lists. Simple lists, doubly linked lists, lists that are +queues, stacks or both. + + @{" list " link //list/Examples/main} + @{" list/associativeArray " link //list/associativeArray/Examples/main} +* @{" list/doublylinked " link //list/doublylinked/Examples/main} +* @{" list/doublylinked/stringlist " link //list/doublylinked/stringlist/Examples/main} + @{" list/elist " link //list/elist/examples/main} +* @{" list/execlist " link //list/execlist/examples/main} + + +Logic objects. + +* @{" logic " link logic} + + +Resources tracking modules for the ooep. Experimental. + +* @{" resource " link resource} +* @{" resource/master " link resource/master} + + +Objects that can be sorted - strings, numbers and so on. + +* @{" sort " link //sort/Examples/main} +* @{" sort/numbers " link //sort/numbers/Examples/main} +* @{" sort/numbers/fraction " link sort/numbers/fraction} +* @{" sort/numbers/fraction/coordinate " link sort/numbers/fraction/coordinate} + @{" sort/string " link //sort/string/Examples/main} + + +Stream objects. + +* @{" stream " link stream} + +Misc + +* @{" byteArray " link //byteArray/Examples/main} + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/OOEproject b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/OOEproject new file mode 100644 index 0000000..fd54894 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/guides/OOEproject @@ -0,0 +1,351 @@ +@DATABASE "OOEproject" +@MASTER "ram:OOEproject.doc" + +@NODE MAIN "OOEproject.doc" + + @{b}ooep@{ub} + +@{"0. Preface" LINK "0.Preface"} +@{"1. Why" LINK "1.Why"} +@{"2. Caveats" LINK "2.Caveats"} +@{"3. Submissions" LINK "3.Submissions"} +@{"4. Implementation" LINK "4.Implementation"} +@{"5. The Plan" LINK "5.The Plan"} +@{"6. Notes from the Authors" LINK "6.Notes from the Authors"} +@{"7. Addresses" LINK "7.Addresses"} +@{"8. Next Steps" LINK "8.Next Steps"} + +@ENDNODE +@NODE "0.Preface" "ooep/0. Preface" + + + This document explains the goals and current accomplishments + of the Object Oriented E Project, much of which was started + by Joseph E. Van Riper III, but loosely maintained by the + Amiga E Encyclopedia folks in general. + + Those of you who don't like to read any big docs can just + browse through the hierarchie via the @{" Examples " link EMODULES:oomodules/oodoc/guides/Examples/main} document. + +@ENDNODE +@NODE "1.Why" "ooep/1. Why" + + + OOEP was started because, as of this writing, the Amiga E + programming language, while very powerful, lacks a very + comfortable, easily extensible object library to take + advantage of its Object Technology features. So, while you + may program objects, you aren't getting the full benefits of + Object Technology. + + So, you have the option of creating your own extensible set + of objects and whatnot on your own, which will take you a + certain measure of time, or you can use ours. Since the + source code is included, you can fix any bugs you might + stumble upon, or optimize anything that doesn't work quickly + enough for you, or otherwise improve the system in some way. + Or, if you want, you may contribute new objects to extend + the system. All of these should be sent to the AEE (Amiga E + Encyclopedia) folks for approval and submission to the + greater Amiga E audience. + + With this set of objects, Amiga E can become a more friendly + environment to work with. + +@ENDNODE +@NODE "2.Caveats" "ooep/2. Caveats" + + + In building reusable code, and building it to be as + extensible as this hopes to be, one often finds him/herself + having to make various tradeoffs. This almost always takes + the form of speed vs. memory, although in the case of reuse, + sometimes it's speed/memory vs. reuse. + + A case in point might be some of the stuff that will be done + in the 'Numbers' objects. Both memory and speed will be + used due to the coersion schemes to convert sets of numbers + to other sets of numbers. + + Sometimes, you'll find the more classical Amiga E approaches + to be stronger than anything developed here. If you need + speed and efficiency or better use of memory, and these + modules don't exactly offer it for you, you may have to + build your objects a little more by scratch (say, perhaps, + using Amiga E's float numbers rather than our object + 'Float'). + + The goals of this project is reuse and extensibility. We + attempt to make our objects as efficient and + memory-conserving as possible, but our primary goal is + reuse. + + If there are any glaring problems (say, an object simply + doesn't work properly), we ask you either fix the problem + yourself and send the AEE team your fix (which will make you + part of the AEE team ) or make the AEE team aware of + the problem (many of them are also on the Amiga E mailing + list). + + You'll note the comments in the code are somewhat lacking. + We apologize for this.. in the interest of getting this + coded quickly, we dropped internal documentation. However, + this document is intended to explain the attributes and + methods of each object in the library, so you may find + your answers here. + +@ENDNODE +@NODE "3.Submissions" "ooep/3. Submissions" + + + You can submit extensions/corrections to this library + through the AEE mailing list or the Amiga E mailing list, or + perhaps by ftp to Aminet dev/e. Please include an e-mailing + address that we can contact you by, in case we have some + problems of some kind with your submission. + + You may as well send your contribution to one of us via snail + mail but eMail is strongly preferred. Getting in touch is so + much easier. + + If you want to contribute anything please make sure that it's + documented. It's very hard to find out how something's working + just by browsing through the source code. As you can see the + preferred way is to write autodocs in the modules and to turn + the autodocs extracted from them into Amigaguide databases. + + Read the @{"Addresses" LINK "7.Adresses"} chapter to know where + to send what. + +@ENDNODE +@NODE "4.Implementation" "ooep/4. Implementation" + + + You'll note that this library comes with its own + subdirectory 'oomodules'. This subdirectory is an idea of + Gregor, who started putting his devices objects in it. From + this directory, you can find the hierarchy of objects that + make up this project. You should put 'oomodules' in your + emodules: set of directories if you want to use them.. or + recompile all the codes with your own idea of how things + should be set up. + + If you make a correction in a higher-level object, all + objects derived from the corrected object will also need to + be recompiled. This is an unfortunate result of the way + Amiga E handles some of its internal stuff with the modules. + Therefore, if you make corrections to 'object', EVERYTHING + would need to be recompiled IN ORDER according to hierarchy. + + We hope to get things right the first time . + + In the following list, we'll outline each object and its + methods. As you click deeper into the guide (or pay + attention to the numbers preceding the titles in the doc), + you'll note that the methods from preceding objects are + automatically applied to the current objects. + + And so, we start with the one object from which all other + objects are derived.... + + @{"object/main" LINK "object/main"} + +@ENDNODE +@NODE "5.The Plan" "ooep/5. The Plan" + + There is, believe it or not, a general plan to all this. + We're attempting to apply as much of the GNU Smalltalk + structure (with perhaps some additional stuff out of IBM + Smalltalk) as we can in our designs. We acknowledge that we + cannot do things the same exact way (nor would we want to), + but we are attempting to loosely follow this plan. + + So, VERY roughly, here's a road-map to some of the basic + objects, and their heirarchy, that we hope to have + implemented and designed sometime in the future. Some of + these have already been at least partially implemented, + although not many of them. + + Object + Logic + Boolean + Bitwise + Categorical + List + QueueStack + Bag + TreeAVL + Set + Dictionary + Sort + Number + Integer + Real + Fraction + Complex + Coordinate + String + DateStamp + Time + Hour + Minutes + Seconds + Date + Weekday + Day + Month + Year + Hook + Library + Device + Stream + Printer + Serial + File + Console + StdErr + Clipboard + Rexx + Keyboard + Timer + Gameport + Audio + ReqTools + IffParse + Commodities + GadTools + Graphics + Icon + Keymap + Layers + Translator + Utility + Workbench + + You can help! Point out problems with this heirarchy, build + some of these objects, make out CRC cards or use-cases to + get a better idea what we're up against... help this come to + fruition. See `Submissions' to get an idea of how to + contribute. + + BTW: CRC cards might look something like the following: + + -------------+ + CLASS Object | + =============+================================================ + Attributes: | + -------------+ + + [none] + + -------------+------------------------------------------------ + Methods: | + -------------+ + new + init + size + opts + select + error + name + end + halt + sameAs + differentFrom + update + + -------------------------------------------------------------- + + They are intended to give an idea what the object is + supposed to do, and how it's supposed to do it. They're + only a tool towards developing the system. + +@ENDNODE +@NODE "6.Notes from the Authors" "ooep/6. Notes from the Authors" + + + As of this document, only two authors have contributed to this + project. Hopefully, more folks will catch on to this, and + contribute useful objects into this system, perhaps even improving + this system for everyone's benefit. + + This section of the document is included for special notes + (perhaps pleas, perhaps other things) from the various + authors who submit work to this daunting project. If you're + adding something to this document, please add your name to + the list. + + Authors of the ooep: + + @{" Joseph E. 'Trey' van Riper III " link /authors/jevr.guide/main} - This text is more than one year old. + @{" Gregor Goldbach " link /authors/gg.guide/main} + +@ENDNODE +@NODE "7.Addresses" "ooep/7. Addresses" + + + There are a number of ways to get in touch with us. First, there + is the E mailing list. You can subscribe it via writing a mail to + listserv.bkhouse.cts.com, the subject doesn't matter. Just write + SUBSCRIBE AmigaE in the body. That's it. To get the rules of this + mailing list write FAQ AmigaE or HELP AmigaE in the body. + + You may also touch us via the Web-site of the AEE since the OOEP is + a part of it. The address is + + http://grove.mv.com/amigae/AEE/index.html + + If there are any questions or remarks about objects you can of course + direct them to the author of that particular module or anybody else + of us. So here are our email and snail mail addresses. + + + Joseph E. van Riper III + email: + mu3@vnet.net + + (snail mail unknown) + + + Gregor Goldbach + email: + Glauschwuffel@amt.comlink.de + + snail mail: + Grüner Weg 10 + 21423 Pattensen + Germany +@ENDNODE + +@NODE "8.Next Steps" "ooep/8. Next Steps" + + For the reasons I, @{" Gregor Goldbach " link /authors/gg.guide/main}, stated elsewhere, the archive + is not in the state it should be. These are the things that have to + be done next (discussion wanted): + + - Check documentation (major) + + - Test objects and provide test programs (major) + + - Include introductory texts to OO and the oomodules/hierarchy (major) + + - Work out an exception and return code scheme for all objects (major) + + - Make build file (major) + + - include other objects and object collections (dd_modules, oo + framework) + + + + - Localize objects with library/locale/catalogList (minor) + + - Tidy up sources (minor) + + + + Discussion should take place in the e mailing list. Everyone is + encouraged to contribute thoughts, opinions and ideas. Modifications + to the hierarchy are coordinated through the e mailing list. + +@ENDNODE diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/misc/todo b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/misc/todo new file mode 100644 index 0000000..4ede67d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/misc/todo @@ -0,0 +1,111 @@ +This text is just a short list of things that have to be done in the +object oriented e project. As of this writing the ooep is only at the +beginning, so a lot of things have to be done. + + +1. General + + +creation of basic objects: stream. This object is needed for files, +devices and a lot more objects. + +The stream object represents any kind of data stream. Basically there are +two streams: input and output. Input from file or keyboard is an example +for input stream, output to the screen or to files for output stream. + +The opposite of stream is a record based handling of e.g. files. + + +documentation of the modules. *I* know how to use them since I wrote +most of them. Trey may recognize what I have done but someone else may +not. Up to now I don't know what you think of the objects, please tell +me. + +As you may see when you take a look at the sources I chose the autodoc way +of documenting things. Though the autodocs are nice when you want to know +what a single function does it has one great disadvantage: it doesn't show +which procs work with each other. There have to be guides to show this. + + +implement other objects as listed in The Plan. The Plan can be found in +emodules:oomodules/oodco/OOEProject. + +Increase communication :) The list has almost no traffic at all, let's +change this. If is keeps to be so quiet I'll prepare the package to post it +to aminet. + +Notify the e mailing list. When we're working and both lists are running +we should try to involve more people. + + +2. Objects + +2.1 General + +Modify the resource tracking system to work with the Explorer. Only the +Resource Master needs some simple modifications. + + +2.2 Application object + +This object basically does what MUI does. It builds a commodity with an arexx +port and opens the application catalog(s) and libraries. An optional GUI is +created and handled. + +The commodity creation uses the commodity object (if it exists). The GUI +is a list for MUI, BGUI, EasyGUI or a pointer to a proc provided by the +programmer. This is also the case for opening/closing/handling the gui. + + +2.3 Database objects + +- Support external record headers + + Build datafile of names of files that contain record headers. The record + headers look like those in standard data files and can be parsed by the + same methods. + + +2.4 Reference object + +When the reference object is used a global instance is needed. It should be +initialized by the application object. + + + +Exceptions +---------- + +Work out and implement an exeption scheme. + +Libraries: Raise "LIB",text on failure +Devices: Raise "dev", "" +GUI: + guis - screens + guiw - windows + guif - fonts + guir - requesters + + +Exception handling: + +The application should display a message that tells the user what went wrong. +This can be done using requesters and/or status lines. The proc that +handles the display could be implemented in the application.m or in an extra +exception.m. Exception.m could have a compiler switch to minimize the code, +e.g. simple text messages for a small shell-based program and requesters for +gui-based applications. + +After displaying the application should + +a) use a work-around to solve the problem, e.g. use a smaller font if the gui +couldn't be opened with the large font. + +b) continue its work at the position before the function was called that +caused the exception with the old status - no data should be lost. + +Gui-based apps should have an exception handler at their handle-idcmp() +proc to catch any Rethrow()'ed exceptions. It would exit nicely to the next +Wait(). That would be the case for the application object to create (see the +corresponding chapter for the application object). + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/ADoc2AG.sh b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/ADoc2AG.sh new file mode 100644 index 0000000..6949a53 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/ADoc2AG.sh @@ -0,0 +1,42 @@ +# Turn autodoc files to amigagiude databases. +# +# Second draft July 7 1996 Gregor Goldbach +# +# Usage: makedoc source_dir destination_dir [-buildref] +# +# -buildref builds autodoc.xref, otherwise the one in +# source_dir is used + + +if $# < 2; abort; endif + +set currentdir $_cwd + +set ad2agpath "Work:Entwicklung/Werkzeuge/AD2AG/" + +set tempdir $1 +set destdir $2 +md $destdir + + +strcmp $3 "-buildref" + +if @strcmp( $3 "-buildref" ) = 0; $ad2agpath""AD2AG >NIL: FILES $tempdir TO $tempdir XREF; endif + + +$ad2agpath""AD2AG >NIL: FILES $tempdir TO $tempdir XREFFILE $tempdir/autodocs.xref + +cd $tempdir +# del *.doc <>NIL: +cp -m ~(*.doc) $destdir <>NIL: + +# cd / +# del $tempdir <>NIL: + + +cd $currentdir + +unset currentdir +unset ad2agpath +unset destdir +unset tempdir diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/getADoc.sh b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/getADoc.sh new file mode 100644 index 0000000..32c5d25 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/getADoc.sh @@ -0,0 +1,34 @@ +# Get autodoc information from E sources. +# Takes all *.e (recursively) from the current location. +# +# Second draft July 7 1996 Gregor Goldbach +# +# +# Usage: makedoc destination_directory +# + + +if $# = 0; abort; endif + +set currentdir $_cwd +set adocpath "Work:Entwicklung/Werkzeuge/Autodoc/" +set tempdir $1 + + +# note that the autodoc options are case sensitive +alias getADoc "%source%dest $adocpath\"\"Autodoc -t8 -I -C $source >$tempdir/$dest " + +md $tempdir + +# take all E sources recursively and extract autodocs. +# +# take this line to get all file names printed: +# foreach i ( .../*.e ) "strhead x \".\" $i; basename n $x; echo -n \"Get docs from \"$x; getADoc $i $n.doc; if @filelen( $tempdir/$n.doc ) = 20; del $tempdir/$n.doc; echo \" (purged)\"; else; echo \" (exists)\"; endif" + +foreach i ( .../*.e ) "strhead x \".\" $i; basename n $x; getADoc $i $n.doc; if @filelen( $tempdir/$n.doc ) = 20; del $tempdir/$n.doc; else; echo \"Get docs from \"$x; endif" + +cd $currentdir + +unset currentdir +unset adocpath +unset tempdir diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/readme b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/readme new file mode 100644 index 0000000..3e8cc4a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/scripts/readme @@ -0,0 +1,23 @@ +This directory contains two scripts for use with Csh (tested with version +5.48): + + GetADoc + Extract autodocs from all E sources in the current directory to a + destiation directory. Works recursively. + + Modify this script to your needs, you have to provide a path where + C='s autodoc program (or similar) resides. + + A recommended place to put the docs you get would be oodoc/autodocs. + The docs of the original distribution have been removed for they were + turned into amigaguide databases and can be found in oodoc/guides/. + + ADoc2AG + Converts autodoc files source directory to amigaguide databases and + puts them into a destination directory. + + Modify this script to your needs, you have to provide a path where + C='s ad2ag program (or similar) resides. + + The recommended place to put the databases you get would be + oodoc/guides. diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/Examples new file mode 100644 index 0000000..f436ab9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/Examples @@ -0,0 +1,25 @@ +@database ..._example + +@node main "Introduction to ..." + + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/elist/main} file available or this object. + + +@endnode + + +@node initilisation "Allocation and initilisation of ..." + + +@endnode + +@node where "Where to use this object" + + +@endnode + +@node see_also "See also" + + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/new_object.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/new_object.e new file mode 100644 index 0000000..28fc3c5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/oodoc/templates/new_object.e @@ -0,0 +1,256 @@ +/* + +Object template. + +Replace 'new_object' with your object name and 'parent_object' with the +object name you inherit from. + +You definitely have to modify select(), init() and end(). The methods +open( and close() are just for your convenience, you may delete them if you +don't need them. + +First template version + +October 31 1996 Gregor Goldbach + +*/ + +OPT MODULE + +MODULE 'oomodules/' + +EXPORT OBJECT new_object OF parent_object +/****** library/new_object ****************************** + + NAME + new_object() of parent_object -- + + SYNOPSIS + parent_object.new_object() + + PURPOSE + Describe what the object's purpose is. + + ATTRIBUTES + List the attributes with their type and a description. If a default + value is set in init() you should write this down. + + attribute:type -- description + + SEE ALSO + parent_object + +********/ +ENDOBJECT + + + + + + +EXPORT PROC init() OF new_object +/****** new_object/init ****************************** + + NAME + init() of new_object -- Initialization of the new new_object object + instance. + + SYNOPSIS + new_object.init() + + FUNCTION + Sets attribute foobar to default value xxx. + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + Calls parental object's init() method. + + SEE ALSO + new_object + +********/ + + /* + * Call parental object's init() method if needed. + */ + + SUPER self.init() + +ENDPROC + + + + + + +PROC open() OF new_object +/****** new_object/open ****************************** + + NAME + open() of new_object -- + + SYNOPSIS + new_object.open() + + FUNCTION + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + new_object + +********/ + +ENDPROC + + + + + + +PROC close() OF new_object +/****** new_object/close ****************************** + + NAME + close() of new_object -- + + SYNOPSIS + new_object.close() + + FUNCTION + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + + SEE ALSO + new_object + +********/ + +ENDPROC + + + + + + +PROC select(optionlist, index) OF new_object +/****** new_object/close ****************************** + + NAME + select() of new_object -- Selection of action upon initialization. + + SYNOPSIS + new_object.select() + + FUNCTION + The following tags are recognized: + "tag" -- description + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + Calls parental object's select() method. + + SEE ALSO + new_object + +********/ + +DEF item + + item:=ListItem(optionlist,index) + + SELECT item + + CASE -> "open" + + INC index + self.your method(ListItem(optionlist,index)) + + DEFAULT + + /* + * Call parental object's select() method if we don't know the tag. + */ + + index := SUPER self.select(optionlist, index) + + ENDSELECT + +ENDPROC index + + + + + + +PROC end() OF new_object +/****** new_object/end ****************************** + + NAME + end() of new_object -- Global destructor for object instance. + + SYNOPSIS + new_object.end() + + FUNCTION + + RESULT + + EXAMPLE + + CREATION + + HISTORY + + NOTES + Calls parental object's end() method. + + SEE ALSO + new_object + +********/ + + /* + * Call parental object's end() method if needed. + */ + + SUPER self.end() + +ENDPROC + + + + + + +PROC name() OF new_object IS -> insert name constant here diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort.e new file mode 100644 index 0000000..04c61b8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort.e @@ -0,0 +1,358 @@ +-> sortobj.e: An abstract data manipulation class for Amiga E +-> It's written by Trey Van Riper of the Cheese Olfactory Workshop. +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/object' + +-> This is a totally abstract object to handle comparable objects. + +OBJECT sort OF object +/****** sort/--sort-- ****************************************** + + NAME + sort of object + + PURPOSE + The sort object basically handles sortable objects. Objects that + can be sorted in any way (alphanumerically, numerically, category, + etc) should be derived from Sort. All one should really have to do + to make their Sort object work is to create a method 'cmp()', per + below. + + ATTRIBUTES + None at all. + + NOTES + The following functions are comparitive functions for deciding what + is greater than, less than, or equal to what. You'll note that to + make all of these work, one only needs to define 'cmp()' in one's + own derived object... the rest of these will auto-magically work! + +****************************************************************************** + +History + + +*/ +ENDOBJECT + + +-> lt() means 'less than'. + +PROC lt(item:PTR TO sort) OF sort IS IF self.cmp(item)<0 THEN TRUE ELSE FALSE +/****** sort/lt ****************************************** + + NAME + lt() -- Test if an item is lower than itself. + + SYNOPSIS + self.lt(item:PTR TO sort) + + FUNCTION + It tests if the item provided is in some way lower than itself. + + INPUTS + item:PTR TO sort -- Item to compare to. + + RESULT + TRUE if item is lower than itself, FALSE otherwise. + + SEE ALSO + cmp() +****************************************************************************** + +History + + +*/ + +-> gt() means 'greater than'. + +PROC gt(item:PTR TO sort) OF sort IS IF self.cmp(item)>0 THEN TRUE ELSE FALSE +/****** sort/gt ****************************************** + + NAME + lt() -- Test if an item is greater than itself. + + SYNOPSIS + self.gt(item:PTR TO sort) + + FUNCTION + It tests if the item provided is in some way greater than itself. + + INPUTS + item:PTR TO sort -- Item to compare to. + + RESULT + TRUE if item is greater than itself, FALSE otherwise. + + SEE ALSO + cmp() +****************************************************************************** + +History + + +*/ + +-> et() means 'equal to'. + +PROC et(item:PTR TO sort) OF sort IS IF self.cmp(item)=0 THEN TRUE ELSE FALSE +/****** sort/et ****************************************** + + NAME + lt() -- Test if an item is equal to itself. + + SYNOPSIS + self.et(item:PTR TO sort) + + FUNCTION + It tests if the item provided is the same as itself. + + INPUTS + item:PTR TO sort -- Item to compare to. + + RESULT + TRUE if item is the same as itself, FALSE otherwise. + + SEE ALSO + cmp() +****************************************************************************** + +History + + +*/ + +-> le() means 'Less than/Equal to'. + +PROC le(item:PTR TO sort) OF sort IS IF self.lt(item) OR self.et(item) THEN TRUE ELSE FALSE +/****** sort/le ****************************************** + + NAME + le() -- Test if an item is lower than or equal to itself. + + SYNOPSIS + self.le(item:PTR TO sort) + + FUNCTION + It tests if the item provided is in some way lower than or equal + to itself. + + INPUTS + item:PTR TO sort -- Item to compare to. + + RESULT + TRUE if item is lower than or equal to itself, FALSE otherwise. + + SEE ALSO + cmp() +****************************************************************************** + +History + + +*/ + +-> ge() means 'Greater than/Equal to'. + +PROC ge(item:PTR TO sort) OF sort IS IF self.gt(item) OR self.et(item) THEN TRUE ELSE FALSE +/****** sort/ge ****************************************** + + NAME + ge() -- Test if an item is greater than or equal to itself. + + SYNOPSIS + self.ge(item:PTR TO sort) + + FUNCTION + It tests if the item provided is in some way greater than or equal + to itself. + + INPUTS + item:PTR TO sort -- Item to compare to. + + RESULT + TRUE if item is greater than or equal to itself, FALSE otherwise. + + SEE ALSO + cmp() +****************************************************************************** + +History + + +*/ + +-> ne() means 'Not Equal to'. + +PROC ne(item:PTR TO sort) OF sort IS IF self.et(item) THEN FALSE ELSE TRUE +/****** sort/ne ****************************************** + + NAME + ne() -- Test if an item is not equeal to itself. + + SYNOPSIS + self.ne(item:PTR TO sort) + + FUNCTION + It tests if the item provided is not equal to itself. + + INPUTS + item:PTR TO sort -- Item to compare to. + + RESULT + TRUE if item is not equal to itself, FALSE otherwise. + + SEE ALSO + cmp() +****************************************************************************** + +History + + +*/ + +-> cmp() means 'Compare', and will return 1, 0, or -1 depending upon whether +-> the internal item is Less than, Equal to, or Greater than the incoming item. +-> All the other comparative functions above depend upon this one, so don't +-> mess it up . + +PROC cmp(item:PTR TO sort) OF sort IS self.derivedClassResponse() +/****** sort/cmp ****************************************** + + NAME + cmp() -- Compare an item to itself. + + SYNOPSIS + self.cmp(item:PTR TO sort) + + FUNCTION + cmp() means 'Compare', and will return 1, 0, or -1 depending upon + whether the internal item is Less than, Equal to, or Greater than + the incoming item. All the other comparative functions above depend + upon this one, so don't mess it up . + + INPUTS + item:PTR TO sort -- Item to compare to. + + RESULT + -1 -- item is lower than itself + 0 -- item is equal to itself + +1 -- item is greater than itself + +****************************************************************************** + +History + + +*/ + +-> set() merely sets a value. + +PROC set(in) OF sort IS self.derivedClassResponse() +/****** sort/set ****************************************** + + NAME + set() -- Set value of instance. + + SYNOPSIS + sort.set(objectSpecific) + + FUNCTION + Set the value of the instance. + + INPUTS + objectSpecific -- use it as you want. + + NOTES + Does nothing. + +****************************************************************************** + +History + + +*/ + +-> write() creates a string of an item to print. + +PROC write() OF sort IS self.derivedClassResponse() +/****** sort/write ****************************************** + + NAME + write() -- Create printable string from object. + + SYNOPSIS + sort.write() + + FUNCTION + Creates a string of an item to print. + + NOTES + Does nothing. + +****************************************************************************** + +History + + +*/ + +-> get() returns the item itself (if appropriate). + +PROC get() OF sort IS self.derivedClassResponse() +/****** sort/get ****************************************** + + NAME + get() -- Get instance value. + + SYNOPSIS + sort.get() + + FUNCTION + Gets the instance's value. + + RESULT + Hopefully the value. + + NOTES + Does nothing for now. + + SEE ALSO + set() +****************************************************************************** + +History + + +*/ + +-> name() returns a unique name for the type of object. + +PROC name() OF sort IS 'Sort' +/****** sort/name ****************************************** + + NAME + name() -- Get name of object. + + SYNOPSIS + sort.name() + + FUNCTION + Gets the name of the object. + + RESULT + Pointer to string containing the name. + +****************************************************************************** + +History + + +*/ +/*EE folds +1 +10 29 +EE folds*/ diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/Examples new file mode 100644 index 0000000..d515222 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/Examples @@ -0,0 +1,12 @@ +@database sort_example + +@node main "Introduction to sort" + +The sort object basically handles sortable objects. Objects that can be +sorted in any way (alphanumerically, numerically, category etc) should be +derived from Sort. All one should really have to do to make their Sort object +work is to create a method 'cmp()' (see autodoc). + +There is an @{" autodoc " link EMODULES:oomodules/oodoc/guides/sort/main} file available or this object. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/address.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/address.e new file mode 100644 index 0000000..7fd1709 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/address.e @@ -0,0 +1,157 @@ +OPT MODULE +OPT EXPORT +-> address.e by Trey Van Riper of the Cheese Olfactory Workshop + +MODULE 'oomodules/sort/string','oomodules/sort' + +-> address.e is a derived object from 'sortobj', but we'll sort to lname. + +OBJECT address OF sort + lname:PTR TO string + fname:PTR TO string + street:PTR TO string + city:PTR TO string + phone:PTR TO string +ENDOBJECT + +PROC size() OF address IS 48 + +PROC name() OF address IS 'Address' + +-> We have much to initialize here. + +PROC init() OF address + DEF tmp:PTR TO string + NEW tmp.new() + self.fname:=tmp + NEW tmp.new() + self.lname:=tmp + NEW tmp.new() + self.street:=tmp + NEW tmp.new() + self.city:=tmp + NEW tmp.new() + self.phone:=tmp +ENDPROC + +-> select() does tons-o-stuff for new() + +PROC select(opt,i) OF address + DEF item + item:=ListItem(opt,i) + SELECT item + CASE "set" + INC i + self.set(ListItem(opt,i)) + CASE "sfnm" + INC i + self.setFname(ListItem(opt,i)) + CASE "slnm" + INC i + self.setLname(ListItem(opt,i)) + CASE "scty" + INC i + self.setCity(ListItem(opt,i)) + CASE "sstr" + INC i + self.setStreet(ListItem(opt,i)) + CASE "sphn" + INC i + self.setPhone(ListItem(opt,i)) + ENDSELECT +ENDPROC i + +-> Sets the first name. + +PROC setFname(in) OF address + self.fname.set(in) +ENDPROC + +-> These two functions set the last name. + +PROC set(in) OF address + self.setLname(in) +ENDPROC + +PROC setLname(in) OF address + self.lname.set(in) +ENDPROC + +-> Sets the Street address. + +PROC setStreet(in) OF address + self.street.set(in) +ENDPROC + +-> Sets the City/State + +PROC setCity(in) OF address + self.city.set(in) +ENDPROC + +-> Sets the phone #. + +PROC setPhone(in) OF address + self.phone.set(in) +ENDPROC + +-> Most addresses are sorted to the last name (at least +-> where I'm from), so the sorting is doing according to the +-> last name. + +PROC cmp(item:PTR TO address) OF address IS self.lname.cmp(item.lname) + +-> This helps determine how much 'write' will require. + +PROC length() OF address + DEF out + out := self.lname.length() + self.street.length() + self.city.length() + + self.phone.length() + self.fname.length() + 40 +ENDPROC out + +-> write() comes up with a text suitable to printing out an +-> address. Could be neater, but hey, it's only an example. +-> This, of course, gives a String output. + +PROC write() OF address + DEF out:PTR TO string + NEW out.new() + out.cat('Name: "') + out.catString(self.lname) + out.cat(', ') + out.catString(self.fname) + out.cat('"\nStreet: ') + out.catString(self.street) + out.cat('\nCity: ') + out.catString(self.city) + out.cat('\nPhone: ') + out.catString(self.phone) + out.cat('\n') + /* + StringF(out,'Name: "\s, \s"\nStreet: \s\nCity: \s\nPhone: \s\n',self.lname.write(), + self.fname.write(), + self.street.write(), + self.city.write(), + self.phone.write()) + */ +ENDPROC out + +-> This is a unique id # for address: "addr" + +PROC id() OF address IS "addr" + +-> Tons-o-stuff to deallocate. + +PROC end() OF address + DEF tmp:PTR TO string + tmp:=self.street + END tmp + tmp:=self.city + END tmp + tmp:=self.phone + END tmp + tmp:=self.lname + END tmp + tmp:=self.fname + END tmp +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers.e new file mode 100644 index 0000000..f30115e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers.e @@ -0,0 +1,31 @@ +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/sort' + +OBJECT number OF sort +ENDOBJECT + +PROC name() OF number IS 'Number' + +PROC add(in:PTR TO number) OF number IS self.derivedClassResponse() + +PROC subtract(in:PTR TO number) OF number IS self.derivedClassResponse() + +PROC multiply(in:PTR TO number) OF number IS self.derivedClassResponse() + +PROC power(in:PTR TO number) OF number IS self.derivedClassResponse() + +PROC max(in:PTR TO number) OF number IS self.derivedClassResponse() + +PROC abs() OF number IS self.derivedClassResponse() + +PROC neg() OF number IS self.derivedClassResponse() + +PROC min(in:PTR TO number) OF number IS self.derivedClassResponse() + +PROC sign() OF number IS self.derivedClassResponse() + +PROC bounds(min:PTR TO number,max:PTR TO number) OF number IS self.derivedClassResponse() + +PROC rnd(min=0:PTR TO number,max=0:PTR TO number) OF number IS self.derivedClassResponse() diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/Examples new file mode 100644 index 0000000..0836eb6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/Examples @@ -0,0 +1,7 @@ +@database numbers_example + +@node main "Introduction to numbers" + +This object does nothing and is just a skeleton for derived objects. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/float.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/float.e new file mode 100644 index 0000000..87d75b3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/float.e @@ -0,0 +1,103 @@ +/* + +First draft of a Float object. It's very rudimentary, just to get the +Coordinate going... + +Gregor Goldbach +*/ + +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/sort/numbers' + +OBJECT float OF number + value +ENDOBJECT + +PROC name() OF float IS 'Float' + +PROC set(value) OF float + self.value := value +ENDPROC + +PROC get() OF float IS self.value + +PROC cmp(what:PTR TO float) OF float + IF self.value < what.value THEN RETURN -1 + RETURN IF self.value > what.value THEN 1 ELSE 0 +ENDPROC + +PROC write() OF float +DEF out + + out := String(42) + IF out + RealF(out,self.value,8) + RETURN out + ELSE + RETURN NIL + ENDIF + +ENDPROC + +PROC add(in:PTR TO float) OF float +DEF value + + value := !self.get() + in.get() + self.set( value) +ENDPROC + +PROC substract(in:PTR TO float) OF float + self.set( !self.get() - in.get() ) +ENDPROC + +PROC multiply(in:PTR TO float) OF float + self.set( !self.get() * in.get() ) +ENDPROC + +PROC divide(in:PTR TO float) OF float + self.set( !self.get() / in.get() ) +ENDPROC + + + +->PROC power(in:PTR TO float) OF float IS EMPTY + +->PROC max(in:PTR TO float) OF float IS EMPTY + +PROC abs() OF float +DEF value + IF !self.value < 0 + value := self.get() + RETURN ! value * (-1) + ELSE + RETURN self.get() + ENDIF +ENDPROC + +PROC neg() OF float + self.set( !0-self.get()) +ENDPROC + +->PROC min(in:PTR TO float) OF float IS EMPTY + +->PROC sign() OF float IS EMPTY + +->PROC bounds(min:PTR TO float,max:PTR TO float) OF float IS EMPTY + +->PROC rnd(min=0:PTR TO float,max=0:PTR TO float) IS EMPTY + +PROC copy(to:PTR TO float) OF float + to.set( self.get() ) +ENDPROC + +PROC flt2int() OF float +DEF value:PTR TO float,dummy1,dummy2 + + NEW value.new() + + value.set( self.get() + 0.5) + value.set(Ffloor(value.get())) + RETURN !value.get()! +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/floattest.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/floattest.e new file mode 100644 index 0000000..331df1d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/floattest.e @@ -0,0 +1,30 @@ +MODULE 'oomodules/sort/numbers/float' + +PROC main() +DEF flt:PTR TO float, + fl2:PTR TO float + + NEW flt.new() + NEW fl2.new() + + flt.set(3.5) + fl2.set(2.0) + + WriteF('a=\s\n', flt.write()) + + flt.add(fl2) + + WriteF('+b=\s\n', flt.write()) + + flt.substract(fl2) + + WriteF('-b=\s\n', flt.write()) + + flt.neg() + + WriteF('-a=\s\n', flt.write()) + + flt.divide(fl2) + + WriteF('a/-b=\s\n', flt.write()) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fractest.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fractest.e new file mode 100644 index 0000000..ab61f6f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fractest.e @@ -0,0 +1,72 @@ +MODULE 'oomodules/sort/numbers/fraction' + +PROC main() +DEF bruch_1:PTR TO fraction, + bruch_2:PTR TO fraction, zkette[80]:STRING + + NEW bruch_1.new(["set",2,3]) + NEW bruch_2.new(["copy",bruch_1]) + + WriteF('\s\n', bruch_1.write()) + WriteF('+\n\s\n', bruch_2.write()) + + bruch_1.add( bruch_2 ) + + WriteF('=\n\s\n', bruch_1.write()) + + bruch_1.substract( bruch_2 ) + + WriteF('-\n\s\n', bruch_2.write()) + + WriteF('=\n\s\n', bruch_1.write()) + + + + WriteF('now multiply...\n\n') + + bruch_1.opts(["set",2,3]) + + WriteF('\s\n', bruch_1.write()) + + bruch_2.opts(["set",2,4]) + + WriteF('*\n\s\n', bruch_2.write()) + + bruch_1.multiply( bruch_2 ) + + WriteF('=\n\s\n', bruch_1.write()) + + + + WriteF('now divide...\n\n') + + bruch_1.opts(["set",2,3]) + + WriteF('\s\n', bruch_1.write()) + + bruch_2.opts(["set",2,5]) + + WriteF('/\n\s\n', bruch_2.write()) + + bruch_1.divide( bruch_2 ) + + WriteF('=\n\s\n', bruch_1.write()) + + -> now just copy + + bruch_1.opts(["set", 3,7]) + bruch_1.copy( bruch_2 ) + + WriteF('\s\n', bruch_1.write()) + WriteF('\s\n', bruch_2.write()) + + bruch_1.flt2fraction(2.25) + WriteF('\s\n', bruch_1.write()) + bruch_1.flt2fraction(7.9675) + WriteF('\s\n', bruch_1.write()) + bruch_1.flt2fraction(3.1415926) + WriteF('\s\n', bruch_1.write()) + + RealF(zkette,bruch_1.fraction2flt(),5) + WriteF('\s\n', zkette) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fraction.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fraction.e new file mode 100644 index 0000000..4c086b0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/fraction.e @@ -0,0 +1,242 @@ +/* + +Things which are marked with 'CHANGE' should be changed + + +NOTE: this object is basically based on integer, so why not inherit from it? + In other words, it inherits technically, but not logically. So don't + let it inherit from integer but from number? + + - make it possible for add(), multiply() etc. to take 'Integer' as + argument, too? +*/ + +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/sort/numbers', 'oomodules/sort/numbers/integer' + + +OBJECT fraction OF number + upper:PTR TO integer + lower:PTR TO integer +ENDOBJECT + +PROC name() OF fraction IS 'Fraction' + +PROC init() OF fraction +DEF up:PTR TO integer,lo:PTR TO integer + + NEW up.new() + self.upper:=up + NEW lo.new() + self.lower:=lo +ENDPROC + +PROC getUpper() OF fraction IS self.upper.get() +PROC getLower() OF fraction IS self.lower.get() + +PROC setUpper(value) OF fraction IS self.upper.set(value) +PROC setLower(value) OF fraction IS self.lower.set(value) + +/* + * negate the fraction just by nagating the Upper + */ +PROC negate() OF fraction + self.upper.negate() +ENDPROC + +PROC add(what:PTR TO fraction) OF fraction +DEF resultingUpper:PTR TO integer, + resultingLower:PTR TO integer, + result_a,result_b + + NEW resultingUpper.new() + NEW resultingLower.new() + + IF self.lower.cmp(what.lower)=0 -> nenner sind gleich + self.setUpper(self.getUpper() + what.getUpper()) -> CHANGE when integer.add() exists + ELSE -> nenner sind unterschiedlich + resultingUpper.set( (self.getUpper() * what.getLower()) + (self.getLower() * what.getUpper())) -> zähler1 * nenner2 + nenner1 * zähler2 + resultingLower.set( self.getLower() * what.getLower()) -> nenner1 * nenner2 + + /* kürzen fehlt noch */ + + self.upper.set( resultingUpper.get() ) + self.lower.set( resultingLower.get() ) + + ENDIF + + END resultingUpper + END resultingLower + +ENDPROC + +PROC substract(what:PTR TO fraction) OF fraction +/* + +pure lazyness: + +just negate the argument, then add it... +*/ + what.negate() + self.add(what) + what.negate() +ENDPROC + +PROC multiply(what:PTR TO fraction) OF fraction +DEF resultingUpper:PTR TO integer, + resultingLower:PTR TO integer + + NEW resultingUpper.new() + NEW resultingLower.new() + + resultingUpper.set( self.getUpper() * what.getUpper() ) /* CHANGE integer.mul */ + resultingLower.set( self.getLower() * what.getLower() ) /* dto. */ + + /* kürzen fehlt */ + + self.upper.set( resultingUpper.get() ) + self.lower.set( resultingLower.get() ) + + END resultingUpper + END resultingLower + +ENDPROC + +PROC divide(bywhat:PTR TO fraction) OF fraction +DEF swapper:PTR TO integer + + NEW swapper.new() -> we need something to store + + swapper.set( bywhat.getUpper() ) -> store upper + + bywhat.setUpper( bywhat.getLower() ) -> set upper + bywhat.setLower( swapper.get() ) -> set lower + + self.multiply( bywhat ) -> multiply + + -> now swap back + + bywhat.setLower( bywhat.getUpper() ) + bywhat.setUpper( swapper.get() ) + + END swapper +ENDPROC + +PROC write() OF fraction +DEF out + + out := String(30) -> think that's enough + + StringF(out, '\d/\d', self.getUpper(), self.getLower()) +ENDPROC out + +PROC end() OF fraction +DEF integer:PTR TO integer + + integer := self.upper + END integer + + integer := self.lower + END integer + +ENDPROC + +PROC select(optionlist,index) OF fraction +/* + + With select up to now two arguments are taken: + + "copy" - takes a fraction as argument and gets its values. Take it as a + simple copy. + "set" - takes two numbers and uses them as Upper, Lower +*/ +DEF item, fraction:PTR TO fraction + + item := ListItem(optionlist, index) + + SELECT item + CASE "copy" + INC index + fraction := ListItem(optionlist,index) -> typed list + + self.setUpper( fraction.getUpper() ) + self.setLower( fraction.getLower() ) + CASE "set" + INC index + item := ListItem(optionlist,index) + self.setUpper( item ) + INC index + item := ListItem(optionlist,index) + self.setLower( item ) + ENDSELECT + +ENDPROC index + +-> just copies its attributes +PROC copy(to:PTR TO fraction) OF fraction + to.setUpper( self.getUpper() ) + to.setLower( self.getLower() ) +ENDPROC + +PROC flt2fraction(flt) OF fraction +/* + +This method sets its objects attributes to the values found in +the float. + +*/ +DEF index,lower=-1, gefunden=0, fltindex, + result, out[80]:STRING, + fltupper,upper, fltlower + + FOR index := 1 TO 1000 + fltindex := index! -> richtig + result := !flt * fltindex ->richtig + + ->RealF(out,result,5); WriteF('::\s\n',out) + + result := !Fceil(result)-result + + result := result < 0.0001 + + IF result THEN gefunden := 1 + IF gefunden=1 + lower:= index + index:=1000 + ENDIF + ENDFOR + + IF lower=-1 THEN lower:=1000 +-> the lower is found + + fltlower := lower! + fltupper := !flt * fltlower + upper := !fltupper! + + self.setUpper(upper) + IF upper=0 + self.setLower(1) + ELSE + self.setLower(lower) + ENDIF +ENDPROC + +PROC fraction2flt() OF fraction -> move to Float +DEF flt,upper,lower,kleiner=0 + + IF (upper := self.getUpper())<0 + upper:=upper*(-1) + INC kleiner + ENDIF + IF (lower := self.getLower())<0 + lower:=lower*(-1) + INC kleiner + ENDIF + + flt := ! upper / lower + + IF kleiner=1 THEN flt := ! 0 - flt + +ENDPROC flt diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/integer.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/integer.e new file mode 100644 index 0000000..f5d686e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/integer.e @@ -0,0 +1,80 @@ +-> integer.e is a very SIMPLE object for handling integers. +-> It's writen by Trey Van Riper of the Cheese Olfactory Workshop +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/sort/numbers' + +-> NOTE: In the future, 'integer' will be derived from 'number'. +-> In the meantime, though, I'll just leave it like this. + +OBJECT integer OF number + number +ENDOBJECT + +-> size() returns how much memory you can expect to use. + +PROC size() OF integer IS 8 + +-> name() returns the name of this kind of object. + +PROC name() OF integer IS 'Integer' + +-> The all-important 'cmp()' method! + +PROC cmp(item:PTR TO integer) OF integer + IF self.number < item.number THEN RETURN -1 + RETURN IF self.number > item.number THEN 1 ELSE 0 +ENDPROC + +-> select() doesn't do much.. lets you set a value from new(). + +PROC select(opt,i) OF integer + DEF item + item:=ListItem(opt,i) + SELECT item + CASE "set" + INC i + self.set(ListItem(opt,i)) + ENDSELECT +ENDPROC i + +-> write(), to create a string out of the integer. + +PROC write() OF integer + DEF out + out:=String(14) + StringF(out,'\d',self.number) +ENDPROC out + +-> get()ing the integer itself. + +PROC get() OF integer IS self.number + +-> set()ing the integer in some way. + +PROC set(in) OF integer + self.number:=in +ENDPROC + +PROC add(in) OF integer + self.number := self.number + in +ENDPROC + +PROC subtract(in) OF integer + self.number := self.number - in +ENDPROC + +PROC divide(in) OF integer + self.number := self.number / in +ENDPROC + +PROC multiply(in) OF integer + self.number := self.number * in +ENDPROC + +-> addition by GG: negate it +PROC negate() OF integer + self.number := 0 - self.number +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/twoNumbers.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/twoNumbers.e new file mode 100644 index 0000000..95bc404 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/numbers/twoNumbers.e @@ -0,0 +1,26 @@ +/* + +twoNumbers + +Take two objects that consist of numbers, e.g. Complex and Fraction. +Those exist of two numbers, only the methods are a bit different, so why +don't make a class of it and derive those two from it? Well, here you are. + +Objects to derive from this: + +Fraction +Complex +Line? + +*/ + +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/sort/numbers' + +OBJECT twoNumbers OF number +PRIVATE + value1:PTR TO number + value2:PTR TO number +ENDOBJECT diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string.e new file mode 100644 index 0000000..b58ea4b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string.e @@ -0,0 +1,853 @@ +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/sort','oomodules/sort/numbers/integer' + +-> string.e: a derived object from 'sort' to handle +-> strings. Much more work needs to be done with this. + +OBJECT string OF sort +/****** string/--string-- ****************************************** + + NAME + string of sort + + ATTRIBUTES + item -- Pointer to the characters in this string. Is the first + element of a string chain that is modified by such functions + as cat(). Various functions work with the string chain, write() + for example reduces the size of it to one entry. + + len:PTR TO integer -- The length of this instance. + + NOTES + Through this document the following terms are used: + 'String' -- this is the object we're talking about. + string -- a chain of characters ('this is one'). It is terminated + with a 0-byte. When there is a string required you may + also provide an estring. + + SEE ALSO + sort/--sort-- +****************************************************************************** + +History + + +*/ + item + len:PTR TO integer -> I made this 'integer' in order to use the cmp in there. +ENDOBJECT + +-> size() gives an idea how much memory you can expect is used + +PROC size() OF string IS 12 +/****** string/size ****************************************** + + NAME + size() -- Get size of instance. + + SYNOPSIS + string.size() + + FUNCTION + Returns the size of the instance. + +****************************************************************************** + +History + + +*/ + +-> name() returns the name of this kind of object. + +PROC name() OF string IS 'String' +/****** string/name ****************************************** + + NAME + name() -- Get name of object. + + SYNOPSIS + string.name() + + FUNCTION + Returns the name of the object. In this case 'String'. + +****************************************************************************** + +History + + +*/ + +-> We need to have a way to initialize 'len'. + +PROC init() OF string +/****** string/init ****************************************** + + NAME + init() -- Initialize the object. + + SYNOPSIS + string.init() + + FUNCTION + Allocates the Integer object used for len. + + SEE ALSO + integer/--integer-- +****************************************************************************** + +History + + +*/ + DEF tmp:PTR TO integer + NEW tmp.new() + self.len := tmp +ENDPROC + + +PROC select(opt,i) OF string +/****** string/select ****************************************** + + NAME + select() -- Select action on initialization. + + SYNOPSIS + string.select(optionlist,index) + + FUNCTION + Recognizes the following items: + "set" -- calls self.cat() with the following item + + "sset" -- calls self.catString() with the following item + + INPUTS + optionlist -- The optionlist + + index -- The index of the optionlist + + SEE ALSO + object/select() +****************************************************************************** + +History + + +*/ + DEF item + item:=ListItem(opt,i) + SELECT item + CASE "set" + INC i + self.cat(ListItem(opt,i)) + CASE "sset" + INC i + self.catString(ListItem(opt,i)) + ENDSELECT +ENDPROC i + +-> We have to dispose of the string and the 'len' pointer. + +PROC end() OF string +/****** string/end ****************************************** + + NAME + end() -- Global destructor. + + SYNOPSIS + string.end() + + FUNCTION + Frees used resources of the instance. It frees the string and the + length Integer. + + SEE ALSO + object/end() +****************************************************************************** + +History + + +*/ + DEF tmp,str + str:=self.item + tmp:=self.len + DisposeLink(str) -> get rid of the string. + END tmp -> get rid of its length, too +ENDPROC + + +-> cmp() compares two strings quickly.. but it doesn't handle international characters. +-> Many improvements could be made to this, I'm sure, but it has the virtue of being +-> fairly quick. Perhaps locale.library support would be nice. + +PROC cmp(item:PTR TO string) OF string +/****** string/cmp ****************************************** + + NAME + cmp() -- Compare to another 'String'. + + SYNOPSIS + string.cmp(item:PTR TO string) + + FUNCTION + Compares itself to another 'String' via E's builtin OstrCmp(). + + INPUTS + item:PTR TO string -- The 'String' to compare to. + + RESULT + 'Ordered String Compare' returns 1 if string2>string1, 0 for equal + and 1 for less. + + NOTES + cmp() compares two strings quickly.. but it doesn't handle + international characters. Many improvements could be made to this, + I'm sure, but it has the virtue of being fairly quick. Perhaps + locale.library support would be nice. + + SEE ALSO + E reference/OstrCmp() +****************************************************************************** + +History + + +*/ + DEF i,inner,outer + inner:=self.write() + outer:=item.write() + RETURN OstrCmp(inner,outer) +ENDPROC + +-> set() lets you put a value into the string. + +PROC set(in) OF string +/****** string/set ****************************************** + + NAME + set() -- Set the 'String''s contents. + + SYNOPSIS + string.set(in) + + FUNCTION + Sets the contents of itself. An already present string will be freed + first. + + INPUTS + in -- Pointer to normal 0-terminated string. Could be an estring + as well. + + EXAMPLE + + PROC main() + DEF string:PTR TO string + + NEW string.new() -> allocate and initialize + string.set('build no schools, construct no roads') + string.cat(' mark them as fools, let ignorance rule') + + WriteF('\s\n', string.write()) ->get string and write it + + ENDPROC + + SEE ALSO + cat() +****************************************************************************** + +History + + +*/ + IF self.item + DisposeLink(self.item) + self.item := NIL + ENDIF + + self.len.set(0) + self.cat(in) + +ENDPROC + +-> length() returns the length of the string. + +PROC length() OF string +/****** string/length ****************************************** + + NAME + length() -- Get length of 'String'. + + SYNOPSIS + string.length() + + FUNCTION + Gets the length of itself. + + RESULT + Length of itself. + + SEE ALSO + integer/get() +****************************************************************************** + +History + + +*/ + RETURN self.len.get() +ENDPROC + + +PROC write() OF string +/****** string/write ****************************************** + + NAME + write() -- Turn 'String' into printable string. + + SYNOPSIS + string.write() + + FUNCTION + If you want to turn 'String' into a normal string (or estring) so + you can work with it as if it was a normal series of characters you + should call this function. It returns a pointer to an estring that + contains 'String''s contents. + + RESULT + Pointer to estring containing + + NOTES + Works on the internal string chain and builds one continuous string + from it. The string chain contains only one entry after the call + of this proc. + + EXAMPLE + PROC main() + DEF string:PTR TO string + + NEW string.new() -> allocate and initialize + string.set('build no schools, construct no roads') + string.cat('mark them as fools, let ignorance rule') + + WriteF('\s\n', string.write()) ->get string and write it + + ENDPROC + +****************************************************************************** + +History + + +*/ + DEF out,this,next=0 + this:=self.item + next:=Next(this) + IF next + out:=String(self.len.get()+1) + WHILE next + next:=Next(this) + StrAdd(out,this) + this:=next + ENDWHILE + DisposeLink(self.item) + self.item:=out + ELSE + out:=self.item + ENDIF +ENDPROC out + + +PROC get() OF string +/****** string/get ****************************************** + + NAME + get() -- Get 'String''s item. + + SYNOPSIS + string.get() + + FUNCTION + Gets its item. Only for internal use, if you want to print the 'String' + or work with it you have to call write(). + + RESULT + string.item + + SEE ALSO + write() +****************************************************************************** + +History + + +*/ + RETURN self.item +ENDPROC + + +PROC cat(in) OF string +/****** string/cat ****************************************** + + NAME + cat() -- Add normal string. + + SYNOPSIS + string.cat(in) + + FUNCTION + Adds a normal string to itself. This can be a 0-terminated array of + char or an estring. The string is copied and added at the end. + + INPUTS + in -- string to add. + + RESULT + Pointer to the estring copy of the string to add. + + EXAMPLE + PROC main() + DEF string:PTR TO string + + NEW string.new() -> allocate and initialize + string.set('build no schools, construct no roads ') + string.cat('mark them as fools, let ignorance rule') + + WriteF('\s\n', string.write()) ->get string and write it + + ENDPROC + + + SEE ALSO + concat(), catString(), concatString() +****************************************************************************** + +History + + +*/ + DEF tmp,count + count:=StrLen(in) + tmp := String(count+1) + StrCopy(tmp,in) + self.concat(tmp,count) +ENDPROC tmp + + +PROC concat(in,count=0) OF string +/****** string/concat ****************************************** + + NAME + concat() -- Add string to the internal string chain. + + SYNOPSIS + string.concat(in,count=0) + + FUNCTION + Adds a string to the internal string chain. The length is set to the + new length. + + INPUTS + in -- normal string to add. + + count -- the length of in. Can be left 0 normally, in that case the + length is found out by StrLen(). + + NOTES + Mainly for internal use. Mortal beings use catString(). + + SEE ALSO + cat(), concatString(), catString() +****************************************************************************** + +History + + +*/ + DEF tmp,next + IF self.item + next:=tmp:=self.item + WHILE next + IF next:=Next(tmp) THEN tmp:=next + ENDWHILE + Link(tmp,in) + ELSE + self.item:=in + ENDIF + IF count THEN self.len.add(count) ELSE self.len.add(StrLen(in)) +ENDPROC + + +PROC concatString(in:PTR TO string) OF string +/****** string/concatString ****************************************** + + NAME + concatString() -- Add 'String' to the internal string chain. + + SYNOPSIS + string.concatString(in:PTR TO string) + + FUNCTION + Adds a 'String' to the internal string chain. The length is set to the + new length. + + INPUTS + in -- 'String' to add. + + RESULT + Pointer to new string or 0 if in was NIL. + + NOTES + Mainly for internal use. Mortal beings use catString(). + + SEE ALSO + cat(), concat(), catString() +****************************************************************************** + +History + + +*/ + IF in THEN self.concat(in.item,in.length()) ELSE RETURN 0 +ENDPROC self.item + + +PROC catString(in:PTR TO string) OF string +/****** string/catString ****************************************** + + NAME + catString() -- Cat a 'String' to another. + + SYNOPSIS + catString(in:PTR TO string) + + FUNCTION + Puts a 'String' at the end of itself. + + INPUTS + in:PTR TO string -- 'String' to add. + + RESULT + item of itself. + + SEE ALSO + concatString() + +****************************************************************************** + +History + + +*/ + IF in THEN self.cat(in.write()) ELSE RETURN 0 +ENDPROC self.item + + +PROC upper() OF string +/****** string/upper ****************************************** + + NAME + upper() -- Change the case of each character to upper. + + SYNOPSIS + string.upper() + + FUNCTION + The case of each character in the 'String' is turned to upper. + + NOTES + Calls write(). + +****************************************************************************** + +History + + +*/ + self.write() + UpperStr(self.item) +ENDPROC + + +PROC lower() OF string +/****** string/lower ****************************************** + + NAME + lower() -- Change the case of each character to lower. + + SYNOPSIS + string.lower() + + FUNCTION + The case of each character in the 'String' is turned to lower. + + NOTES + Calls write(). + +****************************************************************************** + +History + + +*/ + self.write() + LowerStr(self.item) +ENDPROC + + +PROC trimmed() OF string +/****** string/trimmed ****************************************** + + NAME + trimmed() -- Trim whitespace from 'String'. + + SYNOPSIS + string.trimmed() + + FUNCTION + Trims itself, i.e. returns a string that starts with the first + non-whitespace character. + + RESULT + Pointer to 'String' which contains the trimmed contents of self. + It is a newly created 'String', you have to END() it yourself when + you don't need it anymore. + +****************************************************************************** + +History + + +*/ + DEF out,tmp,spank:PTR TO string + self.write() + out:=String(self.length()+1) + tmp:=TrimStr(self.item) + StrCopy(out,tmp) + NEW spank.new(["set",out]) + DisposeLink(out) +ENDPROC spank + + +PROC find(in:PTR TO string) OF string +/****** string/find ****************************************** + + NAME + find() -- Test if 'String' is in 'String'. + + SYNOPSIS + string.find(in:PTR TO string) + + FUNCTION + Searches a 'String' in itself. + + INPUTS + in:PTR TO string -- 'String' to search for + + RESULT + TRUE if in is in self, FALSE otherwise. + + NOTES + Calls write() on in. + +****************************************************************************** + +History + + +*/ + DEF me,he + me:=self.write() + he:=in.write() + RETURN IF InStr(me,he,0)<>-1 THEN TRUE ELSE FALSE +ENDPROC + + +PROC asInteger() OF string +/****** string/asInteger ****************************************** + + NAME + asInteger() -- Turn 'String' to Integer + + SYNOPSIS + string.asInteger() + + FUNCTION + Tries to turn itself to an Integer. + + RESULT + PTR TO integer -- The integer that was in 'String'. + + NOTES + Only call when you know that the string contains an integer. There + is actually no way to test if the proc ran successful over the + strings contents. + + Call write(). + +****************************************************************************** + +History + + +*/ + DEF valstring,value,read,out:PTR TO integer + valstring:=self.write() + value,read:=Val(valstring) + NEW out.new(["set",value]) +ENDPROC out + + +PROC right(n) OF string +/****** string/right ****************************************** + + NAME + right() -- Get right part of 'String'. + + SYNOPSIS + string.right(length) + + FUNCTION + Gets part from the right side of itself and builds a new 'String' + from it. + + INPUTS + length -- get how many characters. + + RESULT + PTR TO string -- a freshly created 'String' that contains the desired + string part. + + EXAMPLE + + PROC main() + DEF mainString:PTR TO string, + partOfString:PTR TO string + + NEW mainString.new(["set", 'down in Los Angeles']) + + partOfString := mainString.right(11) + + WriteF('\s\n', partOfString.write()) + + END partOfString + END mainString + ENDPROC + + SEE ALSO + left(), middle() +****************************************************************************** + +History + + +*/ + RETURN self.middle(self.length()-n-1,n) +ENDPROC + + +PROC middle(pos,len=ALL) OF string +/****** string/middle ****************************************** + + NAME + middle() -- Get a part of 'String'. + + SYNOPSIS + string.middle(position,length) + + FUNCTION + Gets a part from itself and builds a new 'String' from it. + + INPUTS + position -- Start at what position of itself. + + length -- get how many characters from position up to the end. + + RESULT + PTR TO string -- a freshly created 'String' that contains the desired + string part. + + EXAMPLE + + PROC main() + DEF mainString:PTR TO string, + partOfString:PTR TO string + + NEW mainString.new(["set", 'down in Los Angeles']) + + partOfString := mainString.middle(5,2) + + WriteF('\s\n', partOfString.write()) + + END partOfString + END mainString + ENDPROC + + SEE ALSO + left(), right() +****************************************************************************** + +History + + +*/ + DEF out:PTR TO string,buffer,other + IF pos>=self.length() THEN RETURN 0 + buffer:=String(IF len=ALL THEN self.length()-pos ELSE len) + other:=self.write() + MidStr(buffer,other,pos,len) + NEW out.new(["set",buffer]) + DisposeLink(buffer) +ENDPROC out + + +PROC left(n) OF string +/****** string/left ****************************************** + + NAME + left() -- Get left part of 'String'. + + SYNOPSIS + string.left(length) + + FUNCTION + Gets a part from the left side of itself and builds a new 'String' + from it. + + INPUTS + length -- get how many characters. + + RESULT + PTR TO string -- a freshly created 'String' that contains the desired + string part. + + EXAMPLE + + PROC main() + DEF mainString:PTR TO string, + partOfString:PTR TO string + + NEW mainString.new(["set", 'down in Los Angeles']) + + partOfString := mainString.left(4) + + WriteF('\s\n', partOfString.write()) + + END partOfString + END mainString + ENDPROC + + SEE ALSO + middle(), right() +****************************************************************************** + +History + + +*/ + RETURN self.middle(0,n) +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/Examples b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/Examples new file mode 100644 index 0000000..d2d2b7e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/Examples @@ -0,0 +1,15 @@ +@database string_example + +@node main "Introduction to string" + +Wrapper object for strings or, in other words, estring with associated +methods. Those methods are more powerful than those provided by E itself, +however, they are based on them. + +Whenever you want to use estrings you can use this object. + + @{" Autodoc " link EMODULES:oomodules/oodoc/guides/string/main} + + @{" Example " link EMODULES:oomodules/sort/string/test.e/main} -- simple example that fiddles around with basic functions. + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/rawstring.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/rawstring.e new file mode 100644 index 0000000..856ef99 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/rawstring.e @@ -0,0 +1,12 @@ +OPT MODULE +OPT EXPORT + +-> This module is for handling blocks of memory in general. +-> The quirky thing about this is that it can compare +-> 'string' objects as well as rawstring. + +MODULE 'oomodules/sort/string' + +OBJECT rawstring OF string +ENDOBJECT + diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/test.e new file mode 100644 index 0000000..439cc51 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/string/test.e @@ -0,0 +1,19 @@ +MODULE 'oomodules/sort/string' + +PROC main() +DEF string:PTR TO string + + NEW string.new() + + string.cat('blue') + string.cat(' in the ') + string.cat('face.') + + WriteF('\s\n', string.write()) + + string.set(' hi there.\n') + WriteF('\s\n', string.write()) + + END string + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/test.e b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/test.e new file mode 100644 index 0000000..1082fdf --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/OOmodules/sort/test.e @@ -0,0 +1,47 @@ +MODULE 'oomodules/sort/string','oomodules/sort/address' + +PROC main() HANDLE + DEF mystr:PTR TO string,hisstr:PTR TO string, + myaddr:PTR TO address + NEW mystr.new(["set",'aaaaaa']) + NEW hisstr.new(["set",'aaab']) + WriteF('mystr = «\s»\n',mystr.write()) + mystr.cat('bbbbbb') + WriteF('mystr after cat = «\s»\n',mystr.write()) + + WriteF('mystr = «\s»\nhisstr = «\s»\n',mystr.write(),hisstr.write()) + WriteF('mystr has a length of \d.\nhisstr has a length of \d.\n',mystr.length(),hisstr.length()) + + WriteF('Is mystr less than hisstr?\n') + IF mystr.lt(hisstr) THEN WriteF('Yes\n') ELSE WriteF('No\n') + + WriteF('Is mystr greater than hisstr?\n') + IF mystr.gt(hisstr) THEN WriteF('Yes\n') ELSE WriteF('No\n') + + WriteF('Is mystr less than or equal to hisstr?\n') + IF mystr.le(hisstr) THEN WriteF('Yes\n') ELSE WriteF('No\n') + WriteF('And mystr is a «\s».\n',mystr.name()) + mystr.catString(hisstr) + WriteF('Concatenating the two strings yields «\s» of length \d\n', + mystr.write(),mystr.length()) + WriteF('===================================================\nTesting address:\n---\n') + NEW myaddr.new(["sfnm",'Joseph', + "slnm",'Van Riper', + "scty",'Asheville, NC', + "sstr",'19-A Dredge Ave.', + "sphn",'(704) 555-6545']) + END mystr + END hisstr + mystr := myaddr.write() + WriteF('\s---\naddress string length: \d\n',mystr.write(),mystr.length()) + hisstr := mystr.left(5) + WriteF('left(5) :«\s»\n',hisstr.write()) + END hisstr + hisstr := mystr.right(5) + WriteF('right(5) :«\s»\n',hisstr.write()) + END hisstr + hisstr := mystr.middle(5,5) + WriteF('middle(5,5):«\s»\n',hisstr.write()) +EXCEPT + WriteF('error\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/ARexxPort.e b/amigae33a/E_v3.3a/Src/Src/Pd/ARexxPort.e new file mode 100644 index 0000000..09b9f5f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/ARexxPort.e @@ -0,0 +1,367 @@ +/* FOLD info + ~~~~ */ + +/* ARexxPort.e 1.0 - by Leon Woestenberg (leon@stack.urc.tue.nl) */ +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* + + Here I present some basic functions to make your E programs + capable of communicating with other multitasking programs via + ARexx. With these functions your program can: + + · Receive and react to ARexx commands that are sent to it. + · Invoke Rexx Master to run commands that your program does not + understand. This can be an ARexx script (in REXX:) too. + · Send ARexx commands to other programs or to Rexx Master. + + This source is public domain, so use it :) + + The source is fully commented and is almost self explaining. The + only hard thing is this: When an incoming ARexx message contains + a command that is not supported by your program, this message + is NOT YET REPLIED. First, a NEW message is created that is sent + to Rexx Master. This new message contains a pointer to the first + message. Now, when the new message is replied by Rexx Master, we + can remove the first message from memory (by using the pointer). + In this way, ARexx scripts can transparantly be used with ARexx + commands. Note that the default extension for these script can + be adapted for your program in the sendRexxMsg procedure. + + ARexx adds a really nice capability to your multitasking Amiga, + as tasks can interact in realtime with each other, so that they + can use each others features. Think about how your programs can + be extended with a nice ARexx interface. + + If you have any questions, suggestions or even bugreports, reach + me via Internet email. More common questions/discussions about + this source are also welcome on the Amiga E mailing list. + + Leon Woestenberg (leon@stack.urc.tue.nl) + +*/ +/* FEND */ +/* FOLD "modules" */ + +MODULE 'exec/ports','exec/nodes' +MODULE 'rexxsyslib','rexx/rexxio','rexx/rxslib','rexx/errors','rexx/storage' +MODULE 'dos/dos' + +/* FEND */ +/* FOLD "definitions" */ + +DEF hostport=NIL:PTR TO mp +DEF runflag=TRUE +DEF unconfirmed=0 + +/* FEND */ + +/* FOLD "main" */ +PROC main() HANDLE + + /* open rexx library */ + IF (rexxsysbase:=OpenLibrary('rexxsyslib.library',0)) + + /* create a host port for arexx */ + IF (hostport:=createPort('ExampleHost',0)) + + /* examples of your program sending arexx commands to others + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + /* + + /* tell GoldED to move cursor up one line */ + sendRexxMsg('GOLDED.1','UP',NIL,0) + + /* tell the command shell to execute the list command */ + sendRexxMsg('REXX','"ADDRESS COMMAND list"',NIL,0) + + /* run a script from REXX: (set the default extension in sendRexxMsg) */ + sendRexxMsg('REXX','scriptname',NIL,0) + + /* send a 'QUIT' command to ourselves :o) */ + sendRexxMsg('ExampleHost','QUIT',NIL,0) + + */ + + /* inform the user we are running */ + WriteF('Waiting for events to occur. Send me an ARexx QUIT command by typing:\nrx "ADDRESS \aExampleHost\a; QUIT" from a shell. Or press CTRL-C to break me.\n') + + /* wait for events */ + wait() + + deletePort(hostport) + ELSE + WriteF('Sorry dude, seems like I\am already running once.\n') + ENDIF + CloseLibrary(rexxsysbase) + ELSE + WriteF('Could not open the rexxsyslib.library. I really need it!\n') + ENDIF +EXCEPT + WriteF('Something like \d went wrong, ya see?\n') + deletePort(hostport) + hostport:=NIL + IF rexxsysbase + CloseLibrary(rexxsysbase) + rexxsysbase:=NIL + ENDIF +ENDPROC +/* FEND */ +/* FOLD "wait" */ +PROC wait() + + DEF signalmask=0 + DEF hostmask=0 + + /* signalmask for our host port */ + hostmask:=Shl(1,hostport.sigbit) + + /* still running or unconfirmed messages? */ + WHILE runflag OR unconfirmed + + /* wait for event signals */ + signalmask:=Wait(hostmask OR SIGBREAKF_CTRL_C) + + /* and handle all happened events */ + IF signalmask AND hostmask THEN handleRexxMsg() + IF signalmask AND SIGBREAKF_CTRL_C THEN runflag:=FALSE + + ENDWHILE +ENDPROC +/* FEND */ + +/* FOLD "handleRexxMsg" */ +PROC handleRexxMsg() + + /* pointer to handled message */ + DEF rexxmsg:PTR TO rexxmsg + /* pointer to messagenode */ + DEF msgnode:PTR TO mn + /* pointer to listnode of message */ + DEF listnode:PTR TO ln + + /* list of 16 pointers to command strings */ + DEF rexxargs:PTR TO LONG + + /* points to first char of trimmed command */ + DEF command:PTR TO CHAR + + /* (another) message in queue? */ + WHILE rexxmsg:=GetMsg(hostport) + + /* set pointer to messagenode */ + msgnode:=rexxmsg.mn + + /* set pointer to listnode */ + listnode:=msgnode.ln + + /* set pointer to commands */ + rexxargs:=rexxmsg.args + + /* confirmation reply of a message sent by us? */ + IF listnode.type=NT_REPLYMSG + + /* original message pointer present? */ + IF rexxargs[15] + /* reply original message */ + ReplyMsg(rexxargs[15]) + ENDIF + + /* delete this confirmation message */ + DeleteArgstring(rexxargs[0]) + DeleteRexxMsg(rexxmsg) + + /* decrease unconfirmed count */ + DEC unconfirmed + + /* a brand new message */ + ELSE + + /* point to command after skipping spaces etc. */ + command:=TrimStr(rexxargs[0]) + WriteF('We received an ARexx command: \s\n',command) + + /* initialize the resultcodes */ + rexxmsg.result1:=0 + rexxmsg.result2:=NIL + + /* example of handling a command that someone sent to us + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + /* command known? */ + IF StrCmp('QUIT',command,ALL) + WriteF('So let\as quit here.\n') + runflag:=FALSE + ReplyMsg(rexxmsg) + + /* command unknown */ + ELSE + WriteF('Hmmm. Unknown command. Let\as send it to Rexx Master...\n') + + /* forward this command to rexx master (maybe it's a script?) */ + /* the original unknown command message is not yet replied to */ + /* until we receive a confirmation from rexx master. */ + + /* therefore we remember this message by storing a messagepointer */ + /* in rexxargs[15] of the forwarded command to Rexx Master */ + + /* message can not be sent to rexx? */ + IF sendRexxMsg('REXX',rexxargs[0],rexxmsg,0)=NIL + + /* set fatal error returncodes */ + xReplyRexxCmd(rexxmsg,RC_FATAL,NIL) + + /* reply the message */ + ReplyMsg(rexxmsg) + + ENDIF + ENDIF + ENDIF + ENDWHILE +ENDPROC +/* FEND */ +/* FOLD "sendRexxMsg(hostname,command,unknownmsg,flags)" */ +PROC sendRexxMsg(hostname,command,unknownmsg,flags) + + DEF arexxport=NIL:PTR TO mp + DEF rexxmsg=NIL:PTR TO rexxmsg + DEF rexxargs:PTR TO LONG + DEF listnode=NIL:PTR TO ln + DEF temp=NIL + + /* return if hostport is not present */ + IF hostport=NIL THEN RETURN NIL + + listnode:=hostport.ln + + /* return if we can't make a rexxmessage */ + IF (rexxmsg:=CreateRexxMsg(hostport,'rexx',listnode.name))=NIL THEN RETURN NIL + + /* pointer to commands */ + rexxargs:=rexxmsg.args + + /* can we create an argstring? */ + IF temp:=CreateArgstring(command,StrLen(command)) + + /* set the first argstring */ + rexxargs[0]:=temp + + /* set the flags */ + rexxmsg.action:=RXCOMM OR flags + + /* store original message pointer into 16th argstring pointer */ + rexxargs[15]:=unknownmsg + + /* forbid multitasking */ + Forbid() + + /* send our message to an existing port for sure */ + IF (arexxport:=FindPort(hostname)) THEN PutMsg(arexxport,rexxmsg) + + /* permit multitasking */ + Permit() + + /* sended? */ + IF arexxport + + /* increase the unconfirmed counter */ + INC unconfirmed + + /* successfully sent this message */ + RETURN rexxmsg + ENDIF + ENDIF + + IF temp + DeleteArgstring(temp) + ENDIF + IF rexxmsg + DeleteRexxMsg(rexxmsg) + ENDIF + RETURN NIL +ENDPROC +/* FEND */ +/* FOLD "replyRexxMsg(rexxmsg,rc,returnstring)" */ +PROC xReplyRexxCmd(rexxmsg:PTR TO rexxmsg,rc,returnstring) + + /* set the returncode */ + rexxmsg.result1:=rc + + /* and a pointer to the result string */ + rexxmsg.result2:=IF (rexxmsg.action AND RXFF_RESULT) AND (returnstring<>NIL) THEN CreateArgstring(returnstring,StrLen(returnstring)) ELSE NIL + +ENDPROC +/* FEND */ +/* FOLD "createPort(portname,priority)" */ +PROC createPort(portname,priority) + + DEF port=NIL:PTR TO mp + DEF node=NIL:PTR TO ln + + /* make port public? */ + IF portname + + /* no-one make the same port please */ + Forbid() + + /* is our (soon to be) port unique? */ + IF FindPort(portname)=0 + + /* could we make a port? */ + IF port:=CreateMsgPort() + + node:=port.ln + + /* fill in the name */ + node.name:=portname + + /* public port priority */ + node.pri:=priority + + /* and make this port public */ + AddPort(port) + ENDIF + ENDIF + + /* multitask */ + Permit() + + /* just make private port */ + ELSE + + /* try to make a port */ + port:=CreateMsgPort() + + ENDIF +/* return pointer to port, or NIL if the port could not be made (unique) */ +ENDPROC port +/* FEND */ +/* FOLD "deletePort(port)" */ +PROC deletePort(port:PTR TO mp) + + DEF node=NIL:PTR TO ln + DEF msg=NIL:PTR TO mn + + /* pointer given? */ + IF port + + node:=port.ln + + /* if public then remove from public port list */ + IF node.name THEN RemPort(port) + + /* no more messages please */ + Forbid() + + /* remove all messages in queue */ + WHILE msg:=GetMsg(port) DO ReplyMsg(msg) + + /* delete the port */ + DeleteMsgPort(port) + + /* multitask */ + Permit() + ENDIF +ENDPROC +/* FEND */ + diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty-handler.e b/amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty-handler.e new file mode 100644 index 0000000..9043a04 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty-handler.e @@ -0,0 +1,172 @@ + +/*** + + empty-handler.e v1.00 + + By Vidar Hokstad + + This code is hereby declared public domain. + + Returns the number of ASCII NUL (0) specified as filename: + "Copy Empty:100 Ram:test" will create a file "test" in Ram: + containing 100 ASCII NUL + + The code uses the ReplyPkt() function of V36+ dos.library. + To use it with 1.2/1.3, uncomment the replypkt() function, and + change the case of the "ReplyPkt()" calls to "replypkt" + + Based on "empty-handler" in C by o.wagner@aworld-2.zer[.sub.org] + + Needs AmigaE3.1a or newer + +***/ + +OPT OSVERSION=37,PREPROCESS + +MODULE 'dos/dos','dos/dosextens','dos/filehandler','exec/ports', + 'exec/nodes' + + +#define Baddr(val) Shl(val,2) + +PROC getpacket (p:PTR TO process) + DEF port:PTR TO mp, + msg:PTR TO mn + + port:= p.msgport -> The port of our process + WaitPort (port) -> Wait for a message + msg:= GetMsg (port) +ENDPROC msg.ln::ln.name + +/* +PROC replypkt (packet:PTR TO dospacket,res1,res2) + + DEF msg:PTR TO mn, + replyport:PTR TO mp,p:PTR TO process + + p:= FindTask(0) + + ->--- Set return codes + + packet.res1:=res1 + packet.res2:=res2 + + ->--- Find reply port + + replyport:=packet.port + + ->--- Pointer to the execmessage of the packet + + msg:=packet.link + + ->--- Set packet-port + + packet.port:=p.msgport + + ->--- "Connect" message and packet + + msg.ln::ln.name:=packet; + msg.ln::ln.succ:=NIL + msg.ln::ln.pred:=NIL + + ->--- ... and send message + PutMsg(replyport,msg) +ENDPROC +*/ + +PROC main () + DEF hproc:PTR TO process, + packet:PTR TO dospacket, + devnode:PTR TO devicenode, + fh:PTR TO filehandle,o:PTR TO mn + + DEF running=TRUE, + opencount=0, + emptylen,readlen,c, + nump:PTR TO CHAR, + filename[64]:STRING,typ + + ->--- Initialize handler + + hproc:= FindTask(0) + o:= wbmessage + packet:=o.ln::ln.name -> getpacket(hproc) + wbmessage:=0 + + devnode:= Baddr (packet.arg3) + devnode.task:= hproc.msgport + + ->--- Return startup packet + + ReplyPkt (packet,DOSTRUE,0) + + ->--- Main loop + + WHILE running + packet:= getpacket (hproc) + typ:=packet.type + SELECT typ + + CASE ACTION_FINDINPUT + nump:= Baddr(packet.arg3) + c:=0 + WHILE c":")) DO INC nump + IF nump[]=":" THEN INC nump + emptylen:=Val (nump) + INC opencount + + ->--- Filehandle + + fh:= Baddr(packet.arg1) + fh.interactive:=0 -> Non-interactive file + fh.args:=fh + fh.arg2:=emptylen + + ->--- Return packet + ReplyPkt(packet,DOSTRUE,0) + + CASE ACTION_END + ->--- If no open files, end the handler + + DEC opencount + running:= opencount<>0 + ReplyPkt(packet,DOSTRUE,0) + + CASE ACTION_READ + + ->--- FileHandle from open + fh:=packet.arg1 + nump:=packet.arg2 + emptylen:=fh.arg2 + readlen:=packet.arg3 + + ->--- Check for "end of file" + readlen:=Min(readlen,emptylen) + + c:=0 + WHILE c--- Subtract lenght + fh.arg2:=fh.arg2-readlen + + ReplyPkt (packet,readlen,0) + + + CASE ACTION_WRITE + ReplyPkt (packet,DOSFALSE,ERROR_DISK_WRITE_PROTECTED) + DEFAULT + ReplyPkt (packet,DOSFALSE,ERROR_ACTION_NOT_KNOWN) + ENDSELECT + ENDWHILE + devnode.task:=FALSE +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty.mountlist b/amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty.mountlist new file mode 100644 index 0000000..9f44282 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/E-Empty/empty.mountlist @@ -0,0 +1,5 @@ +EMPTY: Handler = L:empty-handler + Stacksize = 4096 + Priority = 5 + GlobVec = -1 +# diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/FD2Module.e b/amigae33a/E_v3.3a/Src/Src/Pd/FD2Module.e new file mode 100644 index 0000000..d8d9503 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/FD2Module.e @@ -0,0 +1,204 @@ +/* + +fd2module V1.0 +Alex McCracken Mar 1994 + +This program is heavily based on Wouter van Oortmerssen's pragma2module. +In fact about 90% of the code belongs to Wouter, so I claim no credit for +this. However, since Wouter's praga2module works very well for files in +the correct format, I must state that if this fails it is most probably my +fault. You may use this program as you see fit, however should it fail and +eat your dog, cause your telly to explode, or cause any problems +what-so-ever, I will not be held responsible. In other word use this at +your own risk. I have made every effort to ensure it works, but I cannot +guarantee to have found all the niggly little ones that plauge almost all +programs. + +Usage + +The program in invoked by typing (CLI only): + + fd2module + +where libname is the name of the fd file minus the _lib.fd extension. +This will produce a file .m . At the moment the program echos the +fd file as it reads it, but this may change in a future release. You will +need to give the program the name of the library explicitly, again this may +change. + +Distribution + +This may be distributed by any means fit. However I retain the right to update + the package without informing anyone. This distribution should contain: + fd2module The executable + fd2module.doc This document + +Reaching me + +I can be reached in the following ways: + +Snail Mail: + Alex McCracken + 11 Charles Street + Kilmarnock + Ayrshire + KA1 2DX + Scotland + +Internet email: + mccracal@dcs.gla.ac.uk + +I only use my email account during term time so over the summer it is probally +best to write to me by snail mail. The email address should remain valid until +summer '95. + +*/ + +/* FD2Module + convert a library fd file to an E module. + Usage: fd2module + converts to */ + +ENUM INPUT_ERROR=10,OUTPUT_ERROR,FORMAT_ERROR + +DEF cfh,efh,eof,done, + gotbase=FALSE, + public=TRUE, + offset=30, + cfile[200]:STRING, + efile[200]:STRING, + cstring[200]:STRING + +PROC main() + StrCopy(cfile,arg,ALL) + StrAdd(cfile,'_lib.fd',ALL) + StrCopy(efile,arg,ALL) + StrAdd(efile,'.m',ALL) + WriteF('Amiga E FD2Module\nconverting: "\s" to "\s"\n',cfile,efile) + IF (cfh:=Open(cfile,OLDFILE))=0 THEN closeall(INPUT_ERROR) + IF (efh:=Open(efile,NEWFILE))=0 THEN closeall(OUTPUT_ERROR) + REPEAT + eof:=ReadStr(cfh,cstring) + done:=convert(cstring) + UNTIL eof OR done + WriteF('last offset: -\d\n',offset) + Out(efh,$FF) + WriteF('Done.\n') + closeall(0) +ENDPROC + +PROC closeall(er) + IF cfh<>0 THEN Close(cfh) + IF efh<>0 THEN Close(efh) + SELECT er + CASE INPUT_ERROR; WriteF('Could not open input file!\n') + CASE OUTPUT_ERROR; WriteF('Could not open output file!\n') + CASE FORMAT_ERROR; WriteF('Function definition file format error!\n') + ENDSELECT + CleanUp(er) +ENDPROC + +/* format of line to convert: + ##base _ + or + ##bias + or + ##public + or + ##private + or + ##end + or + * + or + ()()*/ + +PROC convert(str) +DEF pos,pos2,off2,len,narg,a,empty,dstr[50]:STRING,basestr[50]:STRING, + funcstr[50]:STRING,regstr[20]:STRING,libstr[50]:STRING, + tstr[80]:STRING,t2str[80]:STRING,t3str[80]:STRING,reg,check + MidStr(tstr,str,TrimStr(str)-str,ALL) + LowerStr(tstr) + WriteF('\s\n',str) + IF StrCmp(tstr,'##base ',STRLEN) OR StrCmp(tstr,'##base\t',STRLEN) + pos:=STRLEN + pos2:=InStr(tstr,'_',0) + IF pos2=-1 THEN closeall(FORMAT_ERROR) + IF gotbase=FALSE + gotbase:=TRUE + MidStr(basestr,str,(pos2+1),ALL) + LowerStr(basestr) + WriteF('Base will be: \s\n',basestr) + WriteF('Correct name of this library (with the ".library" or ".device"):\n>') + ReadStr(stdout,libstr) + Write(efh,["EM","OD",6]:INT,6) + Write(efh,libstr,EstrLen(libstr)+1) + Write(efh,basestr,EstrLen(basestr)+1) + ENDIF + ELSEIF StrCmp(tstr,'##bias ',STRLEN) OR StrCmp(tstr,'##bias\t',STRLEN) + pos:=STRLEN + MidStr(t2str,tstr,pos,ALL) + pos2:=TrimStr(t2str) + MidStr(t3str,t2str,pos2-t2str,ALL) + off2:=Val(t3str,NIL) + IF off2=0 THEN closeall(FORMAT_ERROR) + WHILE off2<>offset + Write(efh,'Dum',3) /* "empty function slots" */ + Out(efh,16) + IF offset>off2 THEN closeall(FORMAT_ERROR) + offset:=offset+6 + ENDWHILE + ELSEIF StrCmp(tstr,'##private',ALL) + public:=FALSE + ELSEIF StrCmp(tstr,'##public',ALL) + public:=TRUE + ELSEIF StrCmp(tstr,'##end',ALL) + RETURN TRUE + ELSEIF StrCmp(tstr,'*',STRLEN) + NOP + ELSE + IF public + pos:=0 + pos2:=InStr(str,'(',pos) + IF pos2=-1 THEN closeall(FORMAT_ERROR) + MidStr(funcstr,str,pos,pos2-pos) + IF funcstr[0]>="a" THEN funcstr[0]:=funcstr[0]-32 + IF funcstr[1]<"a" THEN funcstr[1]:=funcstr[1]+32 + Write(efh,funcstr,EstrLen(funcstr)) + pos:=pos2+1 + pos2:=InStr(str,'(',pos) + IF pos2=-1 THEN closeall(FORMAT_ERROR) + narg:=0 + MidStr(dstr,str,pos2+1,ALL) + UpperStr(dstr) + WHILE StrCmp(dstr,')',1)=FALSE + IF EstrLen(dstr)<2 THEN closeall(FORMAT_ERROR) + MidStr(regstr,dstr,0,2) + IF StrCmp(regstr,'D',1) OR StrCmp(regstr,'A',1) + IF StrCmp(regstr,'D',1) + reg:=0 + ELSEIF StrCmp(regstr,'A',1) + reg:=8 + ENDIF + MidStr(regstr,regstr,1,ALL) + reg:=reg+Val(regstr,{check}) + IF check<1 THEN closeall(FORMAT_ERROR) + ELSE + closeall(FORMAT_ERROR) + ENDIF + MidStr(dstr,dstr,2,ALL) + IF StrCmp(dstr,',',1) OR StrCmp(dstr,'/',1) + MidStr(dstr,dstr,1,ALL) + ENDIF + Out(efh,reg) + INC narg + ENDWHILE + IF narg=0 THEN Out(efh,16) + offset:=offset+6 + ELSE + Write(efh,'Dum',3) + Out(efh,16) + offset:=offset+6 + ENDIF + ENDIF +ENDPROC FALSE diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/IFF/README b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/README new file mode 100644 index 0000000..d6f7604 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/README @@ -0,0 +1,13 @@ +A few small, and almost identical in "layout", E sources for +Wouter van Oortsmersens excellent AmigaE3.1a compiler. + +Written to demonstrate simple use of the "iffparse.library". + +These sources are e-mailware - if you find them of any use, send me a +short e-mail message at and tell me you use them +(suggestions for improvements, and questions, are also welcomed). + +Please read the sources for additional copyright info. + +Have fun, +Vidar Hokstad diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/IFF/ReadIFF.e b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/ReadIFF.e new file mode 100644 index 0000000..36c8ed1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/ReadIFF.e @@ -0,0 +1,139 @@ + +/**** + + ReadIFF.e + © 1995 by Vidar Hokstad + + + COPYRIGHT NOTICE: + + This code can be distributed freely, and parts of the code, + or the whole code, can be used as is, or reused in any + product - free or commercial - provided the following terms + are met: + + - You accept that I give no guarantee, expressed or implied + of the usefulness or functionality of this code, and that + I accept no responsability for damage caused directly or + indirectly by the use of this program. + + - The product in which the code is used can not be used + for military applications. + + + INFO: + + Written as an exersize in using iffparse.library. It reads an + IFF file, and writes it's structure to stdout in a simple + format. + +***/ + + +OPT OSVERSION=37 + +MODULE 'iffparse','libraries/iffparse' + +RAISE "^C" IF CtrlC() = TRUE + +PROC readiff (name) HANDLE + + DEF iff:PTR TO iffhandle, -> Utility struct. for iffparse + node:PTR TO contextnode, -> additional info about chunk + fh, -> File handle of an IFF file + nest, -> How many levels deep in the + -> file are we? + ret,count + +-> --- INIT + + IF (iffparsebase:= OpenLibrary('iffparse.library',0))=NIL + Raise ("iffp") + ENDIF + + -> You *MUST* use AllocIFF() to allocate an iffhandle structure + IF (iff:=AllocIFF())=NIL THEN Raise ("iffh") + + -> Prepare the iffhandle to use a dos filehandle + InitIFFasDOS(iff) + + -> Open a file and fill inn the iffhandle + IF (fh:=Open (name,OLDFILE) )=0 THEN Raise ("open") + iff.stream:=fh + + -> Start a new IO session + IF OpenIFF (iff,IFFF_READ) THEN Raise ("oiff") + + +-> --- MAIN LOOP + + nest:=0;count:=0 + + WHILE (ret:=ParseIFF(iff,IFFPARSE_STEP))<>IFFERR_EOF + CtrlC() + + INC count + IF ret=IFFERR_EOC + DEC nest + Write (stdout,{spaces},nest*2) + Flush(stdout) + IF count>1 THEN PutStr ('\n') + PutStr ('}') + ELSE + count:=0 + PutStr ('\n') + node:= CurrentChunk(iff) + Write (stdout,{spaces},nest*2) + Flush(stdout) + Vprintf ('"%s" / "%s", size = %ld {', + [[node.id,0],[node.type,0],node.size]) + INC nest + ENDIF + ENDWHILE + + PutStr ('\n\n') +EXCEPT DO + +->--- CLEANUP: + + -> Was iffparse.library opened? + IF iffparsebase + + -> Was the iffhandle structure allocated? + IF iff + + -> Did OpenIFF() fail? + IF exception<>"oiff" THEN CloseIFF(iff) + + -> Was the file opened? + IF fh THEN Close(fh) + + -> Free the iffhandle. *MUST* be done with FreeIFF() + FreeIFF(iff) + ENDIF + CloseLibrary (iffparsebase) + ENDIF + + -> IF an exception occured, let the next exception handler deal + -> with it too... + + ReThrow() +ENDPROC + + +PROC main() HANDLE + DEF rdargs,args + + args:=[0] + IF rdargs:=ReadArgs ('FILENAME/A',args,NIL) + readiff (args[0]) + ENDIF +EXCEPT + IF exception = "^C" + PutStr ('***BREAK\n') + ELSE + Vprintf ('exception = %ld ("%s")\n',[exception,[exception,0]]) + ENDIF +ENDPROC + +spaces: CHAR ' ' diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/IFF/ScanIFF.e b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/ScanIFF.e new file mode 100644 index 0000000..7de10f4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/ScanIFF.e @@ -0,0 +1,149 @@ +/**** + + ScanIFF.e + © 1995 by Vidar Hokstad + + + COPYRIGHT NOTICE: + + This code can be distributed freely, and parts of the code, + or the whole code, can be used as is, or reused in any + product - free or commercial - provided the following terms + are met: + + - You accept that I give no guarantee, expressed or implied + of the usefulness or functionality of this code, and that + I accept no responsability for damage caused directly or + indirectly by the use of this program. + + - The product in which the code is used can not be used + for military applications. + + + INFO: + + Written as an exersize in using iffparse.library. It reads an + IFF file, and dumps the contents of any occurences of a given + type of chunk, given the type and id. + +***/ + + +OPT OSVERSION=37 + +MODULE 'iffparse','libraries/iffparse','dos/dos' + +RAISE "^C" IF CtrlC() = TRUE + +-> Convert type/id string to a longword + +PROC gettype (str) + DEF ret + MOVE.L str,A0 + MOVE.B (A0)+,D0 + ASL.W #8,D0 + MOVE.B (A0)+,D0 + SWAP D0 + MOVE.B (A0)+,D0 + ASL.W #8,D0 + MOVE.B (A0),D0 + MOVE.L D0,ret +ENDPROC ret + +PROC scaniff (name,type,id) HANDLE + + DEF iff:PTR TO iffhandle, -> Utility struct. for iffparse + node:PTR TO contextnode, -> additional info about chunk + fh, -> File handle of an IFF file + buf[16]:ARRAY OF CHAR, -> Buffer for ReadChunkBytes() + len,i + +-> --- INIT + + IF (iffparsebase:= OpenLibrary('iffparse.library',0))=NIL + Raise ("iffp") + ENDIF + + -> You *MUST* use AllocIFF() to allocate an iffhandle structure + IF (iff:=AllocIFF())=NIL THEN Raise ("iffh") + + -> Prepare the iffhandle to use a dos filehandle + InitIFFasDOS(iff) + + -> Open a file and fill inn the iffhandle + IF (fh:=Open (name,OLDFILE) )=0 THEN Raise ("open") + iff.stream:=fh + + -> Start a new IO session + IF OpenIFF (iff,IFFF_READ) THEN Raise ("oiff") + + IF StopChunk (iff,gettype(type),gettype(id)) THEN Raise ("schn") + + +-> --- MAIN LOOP + +-> While there's something left to read, parse the IFF stream. + + WHILE ParseIFF(iff,IFFPARSE_SCAN)<>IFFERR_EOF + CtrlC() + + node:= CurrentChunk(iff) + Vprintf ('"%s" / "%s", size = %ld {\n', + [[node.id,0],[node.type,0],node.size]) + + -> Dump the contents of the requested chunk + WHILE (len:=ReadChunkBytes(iff,buf,16))>0 + PutStr (' ') + FOR i:=0 TO len-1 DO Vprintf (' $%02.lx',[buf[i]]) + PutStr ('\n') + ENDWHILE + + PutStr ('}\n') + ENDWHILE + + PutStr ('\n\n') +EXCEPT DO + +->--- CLEANUP: + + -> Was iffparse.library opened? + IF iffparsebase + + -> Was the iffhandle structure allocated? + IF iff + + -> Did OpenIFF() fail? + IF exception<>"oiff" THEN CloseIFF(iff) + + -> Was the file opened? + IF fh THEN Close(fh) + + -> Free the iffhandle. *MUST* be done with FreeIFF() + FreeIFF(iff) + ENDIF + CloseLibrary (iffparsebase) + ENDIF + + -> IF an exception occured, let the next exception handler deal + -> with it too... + + ReThrow() +ENDPROC + +PROC main() HANDLE + DEF rdargs,args + + args:=[0,0,0] + IF rdargs:=ReadArgs ('FILENAME/A,TYPE/A,ID/A',args,NIL) + scaniff (args[0],args[1],args[2]) + ELSE + PrintFault (ERROR_BAD_TEMPLATE,'Dos error') + ENDIF +EXCEPT + IF exception = "^C" + PutStr ('***BREAK\n') + ELSE + Vprintf ('exception = %ld ("%s")\n',[exception,[exception,0]]) + ENDIF +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/IFF/readclip.e b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/readclip.e new file mode 100644 index 0000000..6ff6f65 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/IFF/readclip.e @@ -0,0 +1,166 @@ + +/**** + + ReadClipboard.e + © 1995 by Vidar Hokstad + + + COPYRIGHT NOTICE: + + This code can be distributed freely, and parts of the code, + or the whole code, can be used as is, or reused in any + product - free or commercial - provided the following terms + are met: + + - You accept that I give no guarantee, expressed or implied + of the usefulness or functionality of this code, and that + I accept no responsability for damage caused directly or + indirectly by the use of this program. + + - The product in which the code is used can not be used + for military applications. + + + INFO: + + Written as an exersize in using iffparse.library. Reads the + PRIMARY_CLIP clipboard unit, and prints it to stdout. + + Notice: Expects a FTXT clipboard, and will only utilize + FTXT CHRS chunks (which is what a standard clipboard contains). + + The only 2.04+ specific stuff is the use of Vprintf for writing + debug info. I don't really know if there's a version of + iffparse.library for older os-versions though. There ought to + be, but I dont really care :) + +***/ + + +OPT OSVERSION=37,PREPROCESS + +-> #define DEBUG + +MODULE 'iffparse','libraries/iffparse','devices/clipboard' + +RAISE "^C" IF CtrlC() = TRUE + + + +PROC readclip (unit) HANDLE + + DEF iff:PTR TO iffhandle, -> Utility struct. for iffparse + cliph=NIL, -> The clipboard handler + buf[200]:ARRAY OF CHAR, -> Buffer for ReadChunkBytes() + size -> Number of read bytes. + +#ifdef DEBUG + DEF node:PTR TO contextnode -> additional info about chunk +#endif + + +-> --- INIT + + IF (iffparsebase:= OpenLibrary('iffparse.library',0))=NIL + Raise ("iffp") + ENDIF + + -> You *MUST* use AllocIFF() to allocate an iffhandle structure + IF (iff:=AllocIFF())=NIL THEN Raise ("iffh") + + -> Prepare the iffhandle to use the clipboard + InitIFFasClip(iff) + + -> Open a clipboard stream and fill inn the iffhandle + IF (cliph:=OpenClipboard (unit) )=0 THEN Raise ("open") + iff.stream:=cliph + + -> Start a new IO session + IF OpenIFF (iff,IFFF_READ) THEN Raise ("oiff") + + -> Tell iffparse.library you want to examine chunks of type FTXT + -> and id CHRS which is pure ASCII text. + +#ifndef DEBUG + IF StopChunk (iff,"FTXT","CHRS") THEN Raise ("schn") +#endif + + +-> --- MAIN LOOP + +-> While theres something left to read, parse the IFF stream. +-> For a clipboard, there's usually only one chunk of interest, +-> but this way the code will work if theres more chunks too. + +-> IF "DEBUG" is defined, the IFF file is stepped through one +-> context change at a time, and additional info is dumped to +-> Output() + + +#ifndef DEBUG + WHILE ParseIFF(iff,IFFPARSE_SCAN)<>IFFERR_EOF +#endif + +#ifdef DEBUG + WHILE ParseIFF(iff,IFFPARSE_RAWSTEP)<>IFFERR_EOF +#endif + CtrlC() + +#ifdef DEBUG + node:= CurrentChunk(iff) + Vprintf ('id = "%s", type = "%s", size = %ld\n', + [[node.id,0],[node.type,0],node.size]) + Flush(stdout) + + -> Ensure that we only dump "CHRS" chunks + IF node.id="CHRS" +#endif + + -> Copy the chunk to the output file + WHILE (size:=ReadChunkBytes(iff,buf,200))>0 + Write(stdout,buf,size) + ENDWHILE + +#ifdef DEBUG + ENDIF +#endif + + ENDWHILE + +EXCEPT DO + +->--- CLEANUP: + + -> Was iffparse.library opened? + IF iffparsebase + + -> Was the iffhandle structure allocated? + IF iff + + -> Did OpenIFF() fail? + IF exception<>"oiff" THEN CloseIFF(iff) + + -> Was the Clipboard structure allocated? + IF cliph THEN CloseClipboard(cliph) + + -> Free the iffhandle. *MUST* be done with FreeIFF() + FreeIFF(iff) + ENDIF + CloseLibrary (iffparsebase) + ENDIF + + -> IF an exception occured, let the next exception handler deal + -> with it too... + + ReThrow() +ENDPROC + + +-> Read the PRIMARY_CLIP clipboard, and print it's contents to stdout +-> Display any exception that occurs. + +PROC main() HANDLE + readclip (PRIMARY_CLIP) +EXCEPT + Vprintf ('exception = %ld ("%s")\n',[exception,[exception,0]]) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/MakeKickFile.e b/amigae33a/E_v3.3a/Src/Src/Pd/MakeKickFile.e new file mode 100644 index 0000000..4869d65 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/MakeKickFile.e @@ -0,0 +1,109 @@ +;/* MakeKickFile.e - Execute me to compile with Amiga E v2.1 +ec MakeKickFile +quit +*/ +/* +** $Filename: MakeKickFile.e $ +** $Release: 1.1 $ +** +** (C) Copyright 1991-1993 Jaba Development. +** Written by Jan van den Baard +** +** Create a rom-kick file of the machine it is run on. +** It can create 256K and 512K ROM files. +** +** This is a direct translation from my original C code +** and the first thing I wrote in Amiga E. Therefore it +** might not make full use of E it's special features. +** Please forgive me for that. +** +** The usage is simple. You pass this program a filename +** and, if the rom size is known, it will write the ROM +** of the machine to the file. It writes the ROM, *NOT* +** a soft-kicked rom. +** +** The output can be used by setcpu or skick to boot up +** a machine with the ROM file. +** +** I have successfully tested it with an A1200 ROM on +** a A2500. +** +** No testing has been made with a 1.2/1.3 ROM file. +** I don't have access to a 1.2/1.3 machine. +** +** This really is a hack...but a hack that works! +**/ + +MODULE 'dos/dos' + +/* ROM size constants and magic cookies */ +CONST SMALLROM = $00040000, SMALLMAGIC = $11114EF9, + BIGROM = $00080000, BIGMAGIC = $11144EF9 + +/* C= RomFileHeader structure */ +OBJECT romfileheader + alwaysnil : LONG /* like it says -: always NIL */ + romsize : LONG /* the size of the ROM */ +ENDOBJECT + +/* only three excpetion errors... */ +ENUM ER_USAGE=1, ER_UNKNOWN, ER_IO + +/* here we go... */ +PROC main() HANDLE + DEF outfile = NIL, + base = NIL : PTR TO LONG, + size = NIL, + len = NIL, + rk, rfh : romfileheader + + WriteF( '\e[1mMakeKickFile version 1.1 - (C) 1991-1993 Jaba Development\e[0m\n' ); + + /* no args or "?" as arg then print the usage */ + IF StrCmp( arg, '', 1 ) OR StrCmp( arg, '?', 2 ) THEN Raise( ER_USAGE ) + + /* first try for a 512 KB ROM */ + base := $00F80000 + + /* if the magic cookie isn't BIGMAGIC then it must be a 256 KB ROM */ + IF ( base[ 0 ] <> BIGMAGIC ) THEN base := $00FC0000 + + /* let's see what ROM we are dealing with */ + rk := base[ 0 ] + + SELECT rk + CASE SMALLMAGIC; size := SMALLROM /* 256 KB */ + CASE BIGMAGIC; size := BIGROM /* 512 KB */ + DEFAULT; Raise( ER_UNKNOWN ) /* unknown... */ + ENDSELECT + + /* show the ROM size */ + WriteF( 'ROM Size = \dKByte.\n', size / 1024 ) + + /* open the kick-file */ + IF ( outfile := Open( arg, MODE_NEWFILE )) + WriteF( 'Writing KickFile image...\n' ) + + rfh.alwaysnil := NIL /* set this field to NIL */ + rfh.romsize := size /* put the ROM size here */ + + len := Write( outfile, rfh, 8 ) /* write the romfileheader */ + len := len + Write( outfile, base, size ) /* write the rom */ + + Close( outfile ) /* close the kick-file */ + + /* was the writing successfull? */ + IF ( ( len <> ( size + 8 )) OR IoErr() ) THEN Raise( ER_IO ) + ELSE + /* could not open the file! */ + WriteF( 'Unable to open the output file!\n' ) + ENDIF +EXCEPT + /* exception handler for when no output name was given + or the ROM is not recognized or an IO error. */ + SELECT exception + CASE ER_USAGE; WriteF( 'Usage: MakeKickFile \n' ) + CASE ER_UNKNOWN; WriteF( 'Unknown ROM! Exiting...\n' ) + DEFAULT; PrintFault( IoErr(), 'Error -' ) + ENDSELECT +ENDPROC IoErr() diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/PubScreenNames.e b/amigae33a/E_v3.3a/Src/Src/Pd/PubScreenNames.e new file mode 100644 index 0000000..f780bd6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/PubScreenNames.e @@ -0,0 +1,164 @@ +/* PubScreenNames.e + * Prints the names (and some other attributes) of the Public Screens actually + * opened. Also, tests for the presence of a particular screen. + * + * Public Domain by Diego Caravana. + * + * + * Thanks to Wouter van Oortmerssen for his VERY GOOD work, hoping that he + * will continue to improve E language ! + * + * Hey, consider to learn E !!! + * + */ + +/* TAB=4 */ + +OPT OSVERSION=37 + +/* Here is OBJECT we use for copying data inherent to Public Screen. Copying + * data is necessary because the locking of PubScreen List must be as short as + * possible (see Commodore Autodocs). This is due to the fact that the list + * cannot be modified (i.e. no public screen can be opened/closed) while it is + * locked by a task. + */ + +OBJECT mypubscreen + name, flags:INT, visitorcnt:INT, screen, task, next +ENDOBJECT + +MODULE 'intuition/screens', 'exec/lists', 'exec/nodes' + +CONST ARGS_NUM=2 +ENUM ARG_FULL, ARG_EXISTS + +ENUM ERR_NONE=0, ERR_PUBLOCK, ERR_MEM, ERR_WRONGARGS, OK_FOUND, OK_NOTFOUND + +DEF localpslist:mypubscreen, strflags[25]:STRING, args[ARGS_NUM]:ARRAY OF LONG + +RAISE ERR_MEM IF String()=NIL, + ERR_PUBLOCK IF LockPubScreenList()=NIL, + ERR_WRONGARGS IF ReadArgs()=NIL, + ERR_MEM IF New()=NIL + +PROC main() HANDLE +DEF pslist:PTR TO lh, psnode:PTR TO ln, i=0, localpsnode:PTR TO mypubscreen, + pubscreen:PTR TO pubscreennode, publock=NIL, rdargs=NIL + + VOID '$VER: PubScreenNames 1.1 (13.02.93) by Diego Caravana' + + rdargs := ReadArgs('FULL/S,EXISTS/K', args, 0) + + /* get the Public Screen List; it will not change while we are reading + */ + publock := LockPubScreenList() + + /* the first loop: copy all data we need as fast as possible + */ + pslist := publock + psnode := pslist.head + localpsnode := localpslist + + WHILE psnode.succ <> NIL + + /* test if EXISTS a screen with a specified name + */ + IF StrCmp(psnode.name, args[ARG_EXISTS], ALL) THEN Raise(OK_FOUND) + + /* allocate a estring dinamically to reduce memory usegand because + * STRINGs are not permitted (actually, I hope :) in OBJECTs + */ + localpsnode.name:=String(StrLen(psnode.name)+2) + StrCopy(localpsnode.name, psnode.name, ALL) + IF args[ARG_FULL]=-1 /* copy only if needed */ + pubscreen:=psnode + localpsnode.flags:=pubscreen.flags + localpsnode.visitorcnt:=pubscreen.visitorcount + localpsnode.task:=pubscreen.sigtask + localpsnode.screen:=pubscreen.screen + ENDIF + + /* allocate a OBJECT to contain the informations about the next + * screen + */ + localpsnode.next:=New(SIZEOF mypubscreen) + + /* change the pointers to examine the chain + */ + localpsnode:=localpsnode.next + psnode:=psnode.succ + ENDWHILE + + UnlockPubScreenList() + publock:=NIL /* to know that we have released the lock */ + + /* at this point, if a screen name was specified with EXISTS, it has not + * been found as a Public Screen in the previous loop, so we can surely + * exit with a null return code + */ + IF StrLen(args[ARG_EXISTS]) <> 0 THEN Raise(OK_NOTFOUND) + + /* print header with description of fields + */ + IF args[ARG_FULL]=-1 /* print the right one! */ + WriteF('\n N. Name Visitors Screen Task Flags\n') + WriteF( ' ---------------------------------------------------------------------------\n') + ELSE + WriteF('\n N. Name\n') + WriteF( ' ----------------------\n') + ENDIF + + /* the second loop: print all the data + */ + localpsnode:=localpslist + WHILE localpsnode.next <> NIL + i++ + + IF args[ARG_FULL]=-1 /* choose the infos to print */ + + /* not-so-simple code: the two flags are independent by one another + * and also we want a "|" (OR in C) put between them; then, there + * is a default string which is used when no flag is set + */ + StrCopy(strflags,'',ALL) + IF localpsnode.flags AND SHANGHAI + StrCopy(strflags,'SHANGHAI',ALL) + IF localpsnode.flags AND POPPUBSCREEN + StrAdd(strflags,'|POPPUBSCREEN',ALL) + ENDIF + ELSE + IF localpsnode.flags AND POPPUBSCREEN + StrCopy(strflags,'POPPUBSCREEN',ALL) + ENDIF + ENDIF + + WriteF(' \l\d[2] \l\s[18] \l\d[3] $\z\h[8] $\z\h[8] \l\s\n', + i, localpsnode.name, localpsnode.visitorcnt, + localpsnode.screen, localpsnode.task, strflags ) + ELSE + WriteF(' \l\d[2] \l\s[18]\n', i, localpsnode.name) + ENDIF + + localpsnode:=localpsnode.next + ENDWHILE + WriteF('\n Found \d Public Screen(s)\n\n', i) + + Raise(ERR_NONE) + +EXCEPT + IF publock THEN UnlockPubScreenList() + IF rdargs THEN FreeArgs(rdargs) + + SELECT exception + CASE ERR_NONE; + CASE OK_FOUND; CleanUp(5) /* if WARN will be true */ + CASE OK_NOTFOUND; CleanUp(0) + CASE ERR_PUBLOCK; WriteF('*** cannot obtain PubScreen infos!\n') + CASE ERR_MEM; WriteF('*** no memory!\n') + DEFAULT; PrintFault(IoErr(), '*** Error') + ENDSELECT + + IF exception THEN CleanUp(10) + CleanUp(0) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/Pyth2.e b/amigae33a/E_v3.3a/Src/Src/Pd/Pyth2.e new file mode 100644 index 0000000..f410a11 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/Pyth2.e @@ -0,0 +1,213 @@ +/* +** This is the E version of the 'Tree of Pythagoras'. +** Written by Raymond Hoving, Waardgracht 30, 2312 RP Leiden, +** The Netherlands. +** E-mail address: hoving@stpc.wi.leidenuniv.nl +** Requires Kickstart V3.0+ and reqtools.library V38+ +** Creation date: Sun Jul 17 17:30:07 1994, Version: 2.0 +*/ + +OPT REG=5,OSVERSION=39 /* Kickstart 3.0+ only. */ + +MODULE 'intuition/intuition', 'intuition/screens', 'utility/tagitem', + 'reqtools', 'exec/ports', 'exec/libraries', + 'libraries/reqtools', 'graphics/modeid', 'graphics/text' + +DEF pythscreen=NIL : PTR TO screen, + pythwindow=NIL : PTR TO window, + pythidcmp=NIL : PTR TO mp, + screenmodereq=NIL : PTR TO rtscreenmoderequester, + scrwidth, scrheight, fontheight, + winxsize, winysize, xbase, ybase, mbase, + depth=1, mdepth=10, + time0, time1 + +CONST BORDERSIZE = 4 + +ENUM MSG_READY, MSG_ABORT, ERROR_REQTLIB, ERROR_SCREEN, + ERROR_WINDOW, ERROR_OOM + +PROC pythcleanup(errornumber) + + /* This procedure will deallocate all objects that were succesfully + ** allocated. When an error occured, this will be told to the user. + */ + + IF pythwindow<>NIL THEN CloseWindow(pythwindow) + IF pythscreen<>NIL THEN CloseScreen(pythscreen) + IF screenmodereq<>NIL THEN RtFreeRequest(screenmodereq) + IF reqtoolsbase<>NIL THEN CloseLibrary(reqtoolsbase) + SELECT errornumber + CASE ERROR_OOM + WriteF('ERROR: Out of memory.\n') + CASE ERROR_REQTLIB + WriteF('ERROR: Couldn\at open reqtools.library.\n') + CASE ERROR_SCREEN + WriteF('ERROR: Couldn\at open new screen.\n') + CASE ERROR_WINDOW + WriteF('ERROR: Couldn\at open new window.\n') + CASE MSG_ABORT + WriteF('Drawing cancelled.\n') + CASE MSG_READY + WriteF('I just drew \d little house\s!\n', + Shl(1,mdepth)-1, + IF mdepth=1 THEN '' ELSE 's') + ENDSELECT + CleanUp(errornumber) /* Call the standard E finalizer. */ +ENDPROC + +PROC pythtree(a1,a2,b1,b2) + + /* This (recursively called) procedure will do the actual + ** drawing of the tree. + */ + + DEF c1,c2,d1,d2,e1,e2,ci1,ci2,di1,di2 + IF GetMsg(pythidcmp)<>NIL THEN pythcleanup(MSG_ABORT) + IF depth<=mdepth /* Check if we aren't too deep. */ + INC depth /* This depth is still allowed. */ + SetAPen(stdrast,depth) /* Drawing color depends on recursion depth. */ + c1 := !a1-a2+b2 ; ci1 := !c1! + c2 := !a1+a2-b1 ; ci2 := !c2! + d1 := !b1+b2-a2 ; di1 := !d1! + d2 := !a1-b1+b2 ; di2 := !d2! /* Calculate all */ + e1 := !0.5 * (!c1-c2+d1+d2) /* needed coordinates. */ + e2 := !0.5 * (!c1+c2-d1+d2) + /* + ** e Note the use of ! between () in the calculations of e1 and + ** /\ e2. We use some extra LONG's to minimize convertion + ** / \ overhead. + ** c+----+d The coordinates of c,d and e are calculated from the + ** | | coordinates of a and b. Lineair Algebra is great fun! + ** | | + ** a+----+b + */ + Move(stdrast,ci1,ci2) + Draw(stdrast,!a1!,!a2!) + Draw(stdrast,!b1!,!b2!) + Draw(stdrast,di1,di2) + Draw(stdrast,ci1,ci2) + Draw(stdrast,!e1!,!e2!) + Draw(stdrast,di1,di2) /* Draw the little house. */ + IF Rnd(2) = 0 /* Makes the growing a bit */ + pythtree(c1,c2,e1,e2) /* more interesting. */ + pythtree(e1,e2,d1,d2) + ELSE + pythtree(e1,e2,d1,d2) + pythtree(c1,c2,e1,e2) + ENDIF + DEC depth /* Ready with this branch. */ + ENDIF +ENDPROC + +PROC main() + + DEF a1,a2,b1,b2 + + /* Open reqtools.library and allocate memory for requester structure. + */ + + IF (reqtoolsbase := OpenLibrary('reqtools.library',38)) = NIL THEN + pythcleanup(ERROR_REQTLIB) + + IF (screenmodereq := RtAllocRequestA(RT_SCREENMODEREQ,NIL)) = NIL THEN + pythcleanup(ERROR_OOM) + + /* Let the user decide which screenmode he/she wishes. Note that + ** the tree looks best on a screen with approximately the same + ** number of pixels in both directions, like 640x512. + */ + + IF RtScreenModeRequestA(screenmodereq,'Tree of Pythagoras', [ + RTSC_FLAGS,SCREQF_OVERSCANGAD OR SCREQF_AUTOSCROLLGAD OR SCREQF_SIZEGADS, + RTSC_MINWIDTH,100, + RTSC_MINHEIGHT,100, + TAG_DONE]) = FALSE THEN pythcleanup(MSG_ABORT) + + /* Then ask the maximum depth of recursion. + */ + + IF (RtGetLongA({mdepth},'Tree of Pythagoras',NIL, [ + RTGL_MIN,1, + RTGL_MAX,14, + RTGL_TEXTFMT,'Enter maximum depth of the tree:', + RT_WINDOW,pythwindow, + TAG_DONE])) = FALSE THEN pythcleanup(MSG_ABORT) + + /* Get relevant data from the screenmode structure. + */ + + scrwidth := screenmodereq.displaywidth + scrheight := screenmodereq.displayheight + + /* Open the screen the user decided to want. + */ + + IF (pythscreen := OpenScreenTagList(NIL, [ + SA_DEPTH,4, + SA_TYPE,CUSTOMSCREEN, + SA_DISPLAYID,screenmodereq.displayid, + SA_WIDTH,scrwidth, + SA_HEIGHT,scrheight, + SA_TITLE,'Screen of Pythagoras', + TAG_DONE])) = NIL THEN pythcleanup(ERROR_SCREEN) + + /* Now open a screen filling window on the sceen that was just opened. + */ + + IF (pythwindow:=OpenWindowTagList(NIL, [ + WA_WIDTH,scrwidth, + WA_HEIGHT,scrheight, + WA_IDCMP,IDCMP_CLOSEWINDOW, + WA_FLAGS,WFLG_CLOSEGADGET OR WFLG_ACTIVATE, + WA_TITLE,'Tree of Pythagoras by Raymond Hoving', + WA_CUSTOMSCREEN,pythscreen, + TAG_DONE])) = NIL THEN pythcleanup(ERROR_WINDOW) + + /* Get some useful data from the window structure. + */ + + stdrast := pythwindow.rport + pythidcmp := pythwindow.userport + fontheight := pythwindow.ifont::textfont.ysize + + /* Set the palette for this screen (brown to green). + */ + + LoadRGB4(ViewPortAddress(pythwindow), [ + $000,$89a,$640,$752,$762,$771,$781,$680,$580,$080, + $090,$0a0,$0b0,$0c0,$0d0,$0e0] : INT, 16) + + + /* Build a 'real random' seed from the current time + */ + + CurrentTime({time0},{time1}) + Rnd(-Abs(Eor(time0,time1))) + + /* Now calculate how big the tree can be on the selected screen. + */ + + winxsize := scrwidth - (2 * BORDERSIZE) + winysize := scrheight - (6 * BORDERSIZE + fontheight) + xbase := winxsize! / 12.2 /* Divider found by trial and error. */ + ybase := winysize! / 8.0 /* This one as well. */ + IF !xbase < ybase THEN mbase := xbase ELSE mbase := ybase + a1 := scrwidth! / 2.0 - mbase + b1 := scrwidth! / 2.0 + mbase + a2 := scrheight - (4 * BORDERSIZE)! + b2 := a2 + + /* Set the busy pointer and start drawing. + */ + + SetWindowPointerA(pythwindow,[WA_BUSYPOINTER,TRUE,TAG_DONE]) + pythtree(a1,a2,b1,b2) + SetWindowPointerA(pythwindow,TAG_DONE) + + /* Ready! Wait for the user to close the window. + */ + + WaitPort(pythidcmp) + pythcleanup(MSG_READY) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/Talk.e b/amigae33a/E_v3.3a/Src/Src/Pd/Talk.e new file mode 100644 index 0000000..167052c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/Talk.e @@ -0,0 +1,150 @@ +/* Talk V1.0 - by Rob Verver in 1992 */ +/* */ +/* With this shellcommand you can make the narrator say any text using the */ +/* new OS2 features. See the helptemplate for more info. When specifying */ +/* a value which is out of range, the correct range will be displayed. */ +/* */ +/* Possible enhancements: */ +/* Ability to speak phonetic strings */ +/* Input from standard input, for piping */ +/* Preferences file in ascii format, controling all settings */ +/* Escape codes changes values halfway a text */ + +OPT OSVERSION=37 + +MODULE 'Translator', 'devices/narrator', 'dos/dos', 'exec/memory', 'exec/io' + +CONST AUDIOCHANSIZE=4 +ENUM NONE, ERR_DOS, ERR_MEM, ERR_FILE, ERR_DEVICE, ERR_TRANS, ERR_INVALID + +OBJECT arglist + file, rate, pitch, robotic, female, volume, enthusiasm, perturb, f1adj, + f2adj, f3adj, a1adj, a2adj, a3adj, articulate, centralize, centphon, avbias, + afbias, priority +ENDOBJECT + +DEF template, args: arglist, phonebuf=NIL, rdargs=NIL, file=NIL, msgport=NIL, + filebuf=NIL, ioreq: PTR TO ndi, audiochan: PTR TO CHAR, valid=TRUE, + length, phonebufsize + +PROC main () HANDLE + audiochan := [3, 5, 10, 12]:CHAR + + /* parse commandline options */ + args := [NIL, [DEFRATE], [DEFPITCH], 0, 0, [DEFVOL], [DEFF0ENTHUS], + [DEFF0PERT], [0], [0], [0], [0], [0], [0], [DEFARTIC], + [DEFCENTRAL], NIL, [0], [0], [25]]: arglist + template := 'FILE,RATE/K/N,PITCH/K/N,ROBOTIC/S,FEMALE/S,VOLUME/K/N,' + + 'ENTHUSIASM/K/N,PERTURB/K/N,F1ADJ/K/N,F2ADJ/K/N,F3ADJ/K/N,' + + 'A1ADJ/K/N,A2ADJ/K/N,A3ADJ/K/N,ARTICULATE/K/N,CENTRALIZE/K/N,' + + 'CENTPHON/K,AVBIAS/K/N,AFBIAS/K/N,PRIORITY/K/N' + rdargs := ReadArgs (template, args, NIL) + IF rdargs=NIL THEN Raise (ERR_DOS) + + /* open translator library */ + translatorbase := OpenLibrary ('translator.library', 37) + IF translatorbase=NIL THEN Raise (ERR_TRANS) + + /* open input file */ + file := Open (args.file, MODE_OLDFILE) + IF file=NIL THEN Raise (ERR_FILE) + length := FileLength (args.file) /* !!! ascii, no fh */ + IF length<1 THEN Raise (ERR_FILE) + + /* allocate input buffer */ + filebuf := AllocVec (length, MEMF_PUBLIC) + IF filebuf=NIL THEN Raise (ERR_MEM) + + /* allocate buffer for phonetic strings */ + phonebufsize := Shl (length, 1) + phonebuf := AllocVec (phonebufsize, MEMF_PUBLIC) + IF phonebuf=NIL THEN Raise (ERR_MEM) + + /* open narrator device */ + msgport := CreateMsgPort () + IF msgport=NIL THEN Raise (ERR_DEVICE) + ioreq := CreateIORequest (msgport, SIZEOF ndi) + IF ioreq=NIL THEN Raise (ERR_DEVICE) + ioreq.flags := NDF_NEWIORB + IF OpenDevice ('narrator.device', 0, ioreq, NIL)<>NIL THEN Raise (ERR_DEVICE) + + /* check values validity */ + checkVal (Long (args.rate), MINRATE, MAXRATE, 'Invalid rate') + checkVal (Long (args.pitch), MINPITCH, MAXPITCH, 'Invalid pitch') + checkVal (Long (args.volume), MINVOL, MAXVOL, 'Invalid volume') + checkVal (Long (args.centralize), MINCENT, MAXCENT, 'Invalid centralization') + IF valid=FALSE THEN Raise (ERR_INVALID) + + ioreq.chmasks := audiochan + ioreq.nummasks := AUDIOCHANSIZE + + /* init values */ + ioreq.rate := Long (args.rate) + ioreq.pitch := Long (args.pitch) + ioreq.volume := Long (args.volume) + ioreq.f0enthusiasm := Long (args.enthusiasm) + ioreq.f0perturb := Long (args.perturb) + ioreq.f1adj := Long (args.f1adj) + ioreq.f2adj := Long (args.f2adj) + ioreq.f3adj := Long (args.f3adj) + ioreq.a1adj := Long (args.a1adj) + ioreq.a2adj := Long (args.a2adj) + ioreq.a3adj := Long (args.a3adj) + ioreq.articulate := Long (args.articulate) + ioreq.centralize := Long (args.centralize) + ioreq.centphon := Long (args.centphon) + ioreq.avbias := Long (args.avbias) + ioreq.afbias := Long (args.afbias) + ioreq.priority := Long (args.priority) + IF args.robotic<>NIL THEN ioreq.mode := ROBOTICF0 ELSE ioreq.mode := MANUALF0 + IF args.female<>NIL THEN ioreq.sex := FEMALE + + process () + + Raise (0) +EXCEPT + SELECT exception + CASE ERR_DOS; PrintFault (IoErr(), 'Error') + CASE ERR_MEM; PutStr ('Error: not enough memory\n') + CASE ERR_FILE; PutStr ('Error: couldn\at open file\n') + CASE ERR_DEVICE; PutStr ('Error: couldn\at open narrator device\n') + CASE ERR_TRANS; PutStr ('Error: could\at open translator library V37\n') + CASE ERR_INVALID; PutStr ('Error: wrong parameters\n') + ENDSELECT + + IF ioreq<>NIL THEN CloseDevice (ioreq) BUT DeleteIORequest (ioreq) + IF translatorbase<>NIL THEN CloseLibrary (translatorbase) + IF rdargs<>NIL THEN FreeArgs (rdargs) + IF phonebuf<>NIL THEN FreeVec (phonebuf) + IF filebuf<>NIL THEN FreeVec (filebuf) + IF file<>NIL THEN Close (file) + IF msgport<>NIL THEN DeleteMsgPort (msgport) + IF exception THEN CleanUp (10) +ENDPROC + +PROC checkVal (val, min, max, str) + IF valmax) + Vprintf ('%s: valid values are between %ld and %ld\n', [str, min, max]) + valid := FALSE + ENDIF +ENDPROC + +PROC process () + DEF readlen /* !!!! was equal to globvar */ + + readlen := Read (file, filebuf, length) + IF readlen<>length THEN Raise (ERR_FILE) + + Translate (filebuf, length, phonebuf, phonebufsize) + /* WriteF ('phonetic string:\s\n', phonebuf) */ + speakBuffer (phonebuf, StrLen (phonebuf)) +ENDPROC + +PROC speakBuffer (buffer, length) + DEF ior:PTR TO iostd + ior := ioreq + ior.command := CMD_WRITE + ior.data := buffer + ior.length := length + DoIO (ioreq) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/agacc.e b/amigae33a/E_v3.3a/Src/Src/Pd/agacc.e new file mode 100644 index 0000000..2c5b5fd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/agacc.e @@ -0,0 +1,71 @@ +OPT OSVERSION=39 + +MODULE 'intuition/intuition' + +DEF s,w:PTR TO window,rast,x,m,mx,my,r,g,b + +PROC main() + IF s:=OpenS(320,256,8,$800,'AGA Colour Cube') + rast:=stdrast + IF w:=OpenW(0,11,320,245,0,WFLG_BORDERLESS,0,s,15,0) + SetTopaz(8) + fullcolour(0,0,0,0) + fullcolour(1,$40,$80,$c0) + fullcolour(11,0,0,0) + fullcolour(12,0,0,0) + fullcolour(13,0,0,0) + fullcolour(6,0,0,0) + r:=0 + g:=0 + b:=0 + Line(0,16,0,79,11) + Line(70,16,70,79,12) + Line(140,16,140,79,13) + FOR x:=0 TO 63 + Plot(1,16+x,192+x) + Plot(71,16+x,64+x) + Plot(141,16+x,128+x) + Line(2+x,16,2+x,79,64+x) + Line(72+x,16,72+x,79,128+x) + Line(142+x,16,142+x,79,192+x) + ENDFOR + Colour(6,0) + RectFill(w.rport,0,82,205,120) + Colour(5,0) + fullcolour(5,255,255,255) + TextF(44,10,'R:\z\h[2] G:\z\h[2] B:\z\h[2]',r,g,b) + TextF(0,130,'Left mouse on square changes') + TextF(0,138,'Red, Green or Blue colour') + TextF(0,146,'component. Right mouse exits.') + WHILE Mouse()<>2 + Delay(1) + mx:=MouseX(w) + my:=MouseY(w) + m:=Mouse() + IF (m=1) AND (my>=16) AND (my<=79) + IF (mx>=2) AND (mx<=65) + b:=mx-2*4 + g:=my-16*4 + ENDIF + IF (mx>=72) AND (mx<=135) + r:=mx-72*4 + b:=my-16*4 + ENDIF + IF (mx>=142) AND (mx<=205) + g:=mx-142*4 + r:=my-16*4 + ENDIF + fullcolour(11,r,0,0) + fullcolour(12,0,g,0) + fullcolour(13,0,0,b) + fullcolour(6,r,g,b) + TextF(44,10,'R:\z\h[2] G:\z\h[2] B:\z\h[2]',r,g,b) + ENDIF + ENDWHILE + CloseWindow(w) + ENDIF + CloseScreen(s) + ENDIF +ENDPROC + +PROC fullcolour(nr,r,g,b) IS SetColour(s,nr,r,g,b) diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/brush2image.e b/amigae33a/E_v3.3a/Src/Src/Pd/brush2image.e new file mode 100644 index 0000000..26d1e69 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/brush2image.e @@ -0,0 +1,131 @@ +/* + ILBM brush to Image. +*/ +MODULE 'dos/dos','intuition/intuition','asl','libraries/asl', +'libraries/iffparse','iffparse','utility/tagitem' +ENUM NOERROR,ER_LIBRARY,ER_NOMEM,ER_NOASLREQUEST,ER_FILENOTFOUND,ER_IFFERROR, + ER_NOBMHD +CONST ID_ILBM=$494C424D +CONST ID_BMHD=$424D4844 +CONST ID_BODY=$424F4459 +CONST ID_CMAP=$434D4150 + +DEF iff:PTR TO iffhandle + +PROC main() + DEF req:PTR TO filerequester,source[256]:STRING,err,xsize,ysize,depth,bmhd, + body,cmap,camg,cflag,p:PTR TO INT,bp:PTR TO CHAR,sp:PTR TO storedproperty + + IF KickVersion(37)=FALSE + WriteF('Sorry, Kickstart V37+ Required.\n') + getout(0) + ENDIF + IF (aslbase:=OpenLibrary('asl.library',37))=0 + error(ER_LIBRARY,'asl') + ENDIF + IF (iffparsebase:=OpenLibrary('iffparse.library',37))=0 + error(ER_LIBRARY,'iffparse') + ENDIF + IF (req:=AllocAslRequest(ASL_FILEREQUEST,[ASL_HAIL,'Choose ILBM toconvert',0]:tagitem))>0 + IF AslRequest(req,0)=0 + FreeAslRequest(req) + getout(0) + ELSE + StrCopy(source,req.drawer,ALL) ; AddPart(source,req.file,256) ; SetStr(source,StrLen(source)) + ENDIF + ELSE + error(ER_NOASLREQUEST,0) + ENDIF + IF FileLength(source)>0 + IF (iff:=AllocIFF())>0 + iff.stream:=Open(source,MODE_OLDFILE) + InitIFFasDOS(iff) + IF (err:=OpenIFF(iff,IFFF_READ))=0 + IF (err:=PropChunk(iff,"ILBM","BMHD"))=0 + IF (err:=ParseIFF(iff,IFFPARSE_SCAN)=IFFERR_EOF) + IF (sp:=FindProp(iff,"ILBM","BMHD"))>0 + bmhd:=sp.data + bp:=p:=bmhd ;xsize:=p[2] ; ysize:=p[3] + depth:=bp[13] ; cflag:=bp[14] + ELSE + error(ER_NOBMHD,0) + ENDIF + WriteF('Start:\z\h[8]Xsize:\d Ysize:\d Compression:\d Depth:\d\n',bmhd,xsize,ysize,cflag,depth) + getout(0) + ELSE + error(ER_IFFERROR,err) + ENDIF + ELSE + error(ER_IFFERROR,err) + ENDIF + ELSE + error(ER_IFFERROR,err) + ENDIF + ELSE + error(ER_IFFERROR,IFFERR_NOMEM) + ENDIF + ELSE + error(ER_FILENOTFOUND,source) + ENDIF +ENDPROC +CHAR '$VER: ILBM2Image v.01 (C) 1994 Jason Maskell',0 + +PROC getout(retcode) + IF iff + CloseIFF(iff) + Close(iff.stream) + FreeIFF(iff) + ENDIF + IF aslbase + CloseLibrary(aslbase) + ENDIF + IF iffparsebase + CloseLibrary(iffparsebase) + ENDIF + CleanUp(retcode) +ENDPROC + +PROC error(errnum,str) + DEF work[80]:STRING + SELECT errnum + CASE ER_LIBRARY + StringF(work,'Could not open \s.library V37+',str) + CASE ER_NOMEM + StringF(work,'Unable to allocate memory.') + CASE ER_NOASLREQUEST + StringF(work,'Unable to allocate ASL requester.') + CASE ER_FILENOTFOUND + StringF(work,'File "\s" not found.',str) + CASE ER_IFFERROR + SELECT str + CASE IFFERR_EOC + StringF(work,'Iffparse Error: Endof Context') + CASE IFFERR_NOSCOPE + StringF(work,'Iffparse Error: Novalid scope') + CASE IFFERR_NOMEM + StringF(work,'Iffparse Error:Internal Memory allocation failed.') + CASE IFFERR_READ + StringF(work,'Iffparse Error:Stream Read Error.') + CASE IFFERR_WRITE + StringF(work,'Iffparse Error:Stream Write Error.') + CASE IFFERR_SEEK + StringF(work,'Iffparse Error:Stream Seek Error.') + CASE IFFERR_MANGLED + StringF(work,'Iffparse Error: IFFfile is corrupt.') + CASE IFFERR_SYNTAX + StringF(work,'Iffparse Error: IFFSyntax Error.') + CASE IFFERR_NOTIFF + StringF(work,'Iffparse Error: Notan IFF file.') + DEFAULT + StringF(work,'Iffparse Error:Unknown Error code: \d',str) + ENDSELECT + CASE ER_NOBMHD + StringF(work,'No Bitmapheader found. Not a usable FORM') + DEFAULT + StringF(work,'Unknown Error code: \d',errnum) + ENDSELECT + request('ILBN2Image Error',work,'Ok',0) + getout(11) +ENDPROC +PROC request(title,body,gadgets,args) +ENDPROC EasyRequestArgs(0,[20,0,title,body,gadgets],0,args) diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/findf.e b/amigae33a/E_v3.3a/Src/Src/Pd/findf.e new file mode 100644 index 0000000..0127520 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/findf.e @@ -0,0 +1,244 @@ +/* + + findf + + A very fast case-sensitive grep-style search program using + async i/o and the Boyer-Moore search algorithm. + + Usage - same as 'c:search' for the commands implemented. + + Michael Zucchi 1994 + + */ + + +MODULE 'dos/dos', 'dos/dosasl', + 'locale', + 'tools/async' + +DEF skip[256]:ARRAY OF CHAR, -> skip array + line[1024]:ARRAY OF CHAR, -> input buffer + buffer[1024]:ARRAY OF CHAR, -> for case-sensitive searches + m, -> length of string + string:PTR TO CHAR, -> string to match + uppertable[256]:ARRAY OF CHAR,-> lower->upper conversion table + quiet, nonum, quick, ncase -> settings + + +PROC main() +DEF args:PTR TO LONG, rdargs, p:PTR TO LONG, an:PTR TO anchorpath,go, + fib:PTR TO fileinfoblock, loc, i + +args:=[0,0,0,0,0,0,0]; + +IF rdargs:=ReadArgs('FROM/M,SEARCH/A,ALL/S,NONUM/S,QUIET/S,QUICK/S,CASE/S', args, 0) + string:=args[1]; + nonum:=args[3]; + quiet:=args[4]; + quick:=args[5]; + ncase:=args[6]=0; + + IF ncase + IF localebase:=OpenLibrary('locale.library', 0) + IF loc:=OpenLocale(0); + FOR i:=0 TO 255 DO uppertable[i]:=ConvToUpper(loc, i); + CloseLocale(loc); + ELSE + FOR i:=0 TO 255 DO uppertable[i]:=IF i>="a" AND i<="z" THEN i-32 ELSE i + ENDIF + ELSE + FOR i:=0 TO 255 DO uppertable[i]:=IF i>="a" AND i<="z" THEN i-32 ELSE i + ENDIF + CloseLibrary(localebase); + MOVE.L uppertable,A0 + MOVE.L string,A1 + MOVEQ #0,D0 +mn_up: MOVE.B (A1),D0 + MOVE.B 0(A0,D0.W),(A1)+ + BNE.S mn_up + ENDIF + + initskip(); + + IF an:=New(SIZEOF anchorpath + 256) + an.strlen:=255 + an.breakbits:=SIGBREAKF_CTRL_C; + fib:=an.info + p:=args[0]; + go:=0 + WHILE p[] AND (go=0) + go:=MatchFirst(p[], an); + WHILE go=0 + IF (fib.direntrytype) <0 + go:=scanfile(an+SIZEOF anchorpath); + ELSE + IF args[2] + IF (an.flags AND APF_DIRCHANGED)=0 THEN an.flags:=an.flags OR APF_DODIR + ENDIF + ENDIF + IF go=0 THEN go:=MatchNext(an); + ENDWHILE + p++ + ENDWHILE + IF quick THEN WriteF('\e[M'); + Dispose(an); + ENDIF + FreeArgs(rdargs); +ELSE + WriteF('FindF, Michael Zucchi 1994.\nERROR: bad args\n'+ + ' FROM/M files/patterns to search\n'+ + ' SEARCH/A text to search for\n'+ + ' ALL/S recursively scan subdirectories\n'+ + ' NONUM/S do not output line numbers\n'+ + ' QUIET/S do not output matched lines\n'+ + ' QUICK/S faster file-scan display\n'+ + ' CASE/S do a case-sensitive search\n'); +ENDIF +ENDPROC + + +/* + search a single file, by filename, line at a time + */ + +PROC scanfile(name) +DEF number, file, found=0,go=0 + +IF quick + WriteF('\s\e[K\b', name); +ELSE + IF quiet=0 THEN WriteF('\s\n', name); +ENDIF + +number:=1; +IF (file:=as_Open(name, MODE_OLDFILE, 3, 10240)) + WHILE as_FGetS(file, line, 1023) AND (go=0) + IF testmatch() + IF quiet + IF found=0 THEN WriteF('\s\n', name); + JUMP close + ELSEIF nonum +-> IF quick AND found=0 THEN WriteF('\n'); + WriteF('\s', line); + ELSE +-> IF quick AND found=0 THEN WriteF('\n'); + WriteF('\d[6] \s', number, line); + ENDIF + found:=1 + ENDIF + number++ + go:=CheckSignal(SIGBREAKF_CTRL_C) + ENDWHILE +close: + as_Close(file); +ENDIF + +ENDPROC go + + + +/* + Initialise the skip table for a given search string + */ + +PROC initskip() +DEF i + +m:=StrLen(string); + +-> initialise skip table for all characters +FOR i:=0 TO 255 + skip[i]:=m+1; +ENDFOR + +-> set skip table for characters in the string +FOR i:=0 TO m-1 + skip[string[i]]:=m-i; +ENDFOR + +ENDPROC + +/* + Looks for a match in a given line + */ + +PROC testmatch() + +IF m<1 THEN RETURN + + MOVEM.L A4-A5,-(A7) + + MOVE.L m,D7 + SUBQ.L #1,D7 + + TST.L ncase + BEQ.S tm_case + + -> non case-sensitive + + MOVE.L line,A3 + MOVE.L buffer,A0 + LEA 1(A0,D7.L),A2 + MOVE.L uppertable,A1 + MOVEQ #0,D0 +tp_up: MOVE.B (A3)+,D0 + MOVE.B 0(A1,D0.W),(A0)+ + BNE.S tp_up + BRA.S tp_match + + -> case sensitive +tm_case: + MOVE.L line,A0 + LEA 1(A0,D7.L),A2 -> a[i] +tm_scan: + TST.B (A0)+ -> find end of string + BNE.S tm_scan + +tp_match: + MOVE.L string,A1 + MOVE.L A1,A5 + LEA 1(A1,D7.L),A1 -> p[j] + + MOVE.L skip,A4 + + MOVE.L D7,D3 + ADDQ.L #2,D3 + MOVEQ #0,D1 +tm_loop0: + MOVE.L D7,D2 + MOVE.L A1,A3 +tm_loop: + MOVE.B -(A2),D1 + CMP.B -(A3),D1 + BEQ.S tm_matchchar + + MOVE.L A5,D0 + SUB.L A3,D0 -> -j + ADD.L D3,D0 -> M-j+1 + + MOVE.B 0(A4,D1.W),D1 -> skip[character] + CMP.L D0,D1 + BLT.S tm_add0 + + ADD.L D1,A2 + +tm_ok: CMPA.L A0,A2 + BLT.S tm_loop0 + + MOVEQ #0,D0 + BRA.S tm_exit + +tm_add0: + ADD.L D0,A2 + BRA.S tm_ok + +tm_matchchar: + DBF D2,tm_loop + + MOVEQ #-1,D0 +tm_exit: + MOVEM.L (A7)+,A4-A5 + +ENDPROC D0 + + diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/floodwindow.e b/amigae33a/E_v3.3a/Src/Src/Pd/floodwindow.e new file mode 100644 index 0000000..e509134 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/floodwindow.e @@ -0,0 +1,80 @@ +/* + floodwindow.e + + A PROC which will flood inside the borders of any window in any colour + plus wrapper code showing how it works + + IMPORTANT NOTE: If you want to know title bar height _before_ you + open your window, eg, for font awareness, you should + use + DEF screen:PTR TO screen, + font:PTR TO textattr + screenfont:= screen.font + titlebarheight:= screen.wbortop+font.ysize+1 + + When Who What + ------- ------- --------------------------------------------------------- + 4/3/94 UWP! All of it! + +*/ + +MODULE 'intuition/screens','exec/lists','exec/nodes', + 'intuition/intuition', + 'intuition/screens','intuition/gadgetclass','graphics/text' + +PROC main() +DEF screen:PTR TO screen, window:PTR TO window,class, + imess:PTR TO intuimessage, quit + + screen:=(LockPubScreen(NIL)) /* no testing, I assume you have WB :) */ + window:=OpenWindowTagList(NIL,[ WA_TOP, screen.height/2, + WA_LEFT, screen.width/2, + WA_INNERWIDTH, screen.width/4, + WA_INNERHEIGHT, screen.height/2, + WA_CLOSEGADGET, TRUE, + WA_DRAGBAR, TRUE, + WA_DEPTHGADGET, TRUE, + WA_SIZEBBOTTOM, TRUE, /* toggle this */ + WA_SIZEGADGET, TRUE, + WA_MINHEIGHT, 100, + WA_MINWIDTH, 50, + WA_MAXHEIGHT, -1, + WA_MAXWIDTH, -1, + WA_IDCMP, IDCMP_CLOSEWINDOW OR + IDCMP_CHANGEWINDOW, + WA_TITLE, 'Use me! Abuse me!', + 0,0]) /* NB: no checking here either :<*/ + + floodwindow(window,3) + + quit:=FALSE + WHILE quit=FALSE + class:=NIL + IF imess:=GetMsg(window.userport) + class:=imess.class + IF class=IDCMP_CHANGEWINDOW + floodwindow(window,3) + ENDIF + IF class=IDCMP_CLOSEWINDOW + quit:=TRUE + ENDIF + ReplyMsg(imess) + ELSE + WaitPort(window.userport) + ENDIF + ENDWHILE + + CloseWindow(window) + UnlockPubScreen(NIL,screen) + +ENDPROC + +PROC floodwindow(window:PTR TO window,colour) + + SetAPen(window.rport,colour) + RectFill(window.rport, window.borderleft, + window.bordertop, + window.width-window.borderright-1, + window.height-window.borderbottom-1) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/gtlv.e b/amigae33a/E_v3.3a/Src/Src/Pd/gtlv.e new file mode 100644 index 0000000..7a47aa1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/gtlv.e @@ -0,0 +1,233 @@ +/*--------------------------------------------------------------------* + E Source generated by SRCGEN v0.1 + + Demo showing how to create, manage, and cleanup a gadtools listview. + Includes button gadgets and a string gadget for functionality. + AUTHOR: B. Wills + SRCGEN :-) + *--------------------------------------------------------------------*/ +OPT OSVERSION=37 + +MODULE 'gadtools', 'libraries/gadtools', 'intuition/intuition', + 'intuition/screens', 'graphics/text', + 'exec/lists', 'exec/nodes', 'utility/tagitem' + +/*-- Function return values. --*/ +ENUM NONE, NOCONTEXT, NOGADGET, NOWB, NOVISUAL, OPENGT, NOWINDOW, NOMENUS, MEM + +/*-- Gadget IDs. --*/ +ENUM ADDBUTTON_ID, DELETEBUTTON_ID, STRING_ID, LISTVIEW_ID + +RAISE "MEM" IF New()=NIL, + "MEM" IF String()=NIL + +/*-- Standard SrcGen stuff. --*/ +DEF win=NIL:PTR TO window, + scr=NIL:PTR TO screen, + glist=NIL, + visual=NIL, + infos:PTR TO gadget, + messageClass, + offx, offy, tattr + +/*-- Listview and supporting gadgets. --*/ +DEF list=NIL:PTR TO mlh, /* Exec list holds listview items */ + listView=NIL:PTR TO gadget, /* Listview gadget */ + addButton=NIL:PTR TO gadget, /* Button gadget to add an item */ + deleteButton=NIL:PTR TO gadget, /* Button gadget to delete an item */ + stringGadget=NIL:PTR TO gadget, /* String gadget, value added to listview */ + stringGadgetValue:PTR TO CHAR /* Pointer to string gadget buffer */ + +PROC initList(l:PTR TO mlh) +/*-- Initialize an exec list. --*/ + l.head:=l+4 + l.tail:=NIL + l.tailpred:=l +ENDPROC + +PROC setupScreen() +/*-- Open libraries and get screen info. --*/ + IF (gadtoolsbase:=OpenLibrary('gadtools.library',37))=NIL THEN RETURN OPENGT + IF (scr:=LockPubScreen('Workbench'))=NIL THEN RETURN NOWB + IF (visual:=GetVisualInfoA(scr,NIL))=NIL THEN RETURN NOVISUAL + offy:=scr.wbortop+Int(scr.rastport+58)-10 + tattr:=['topaz.font',8,0,0]:textattr +ENDPROC NONE + +PROC closeScreen() +/*-- Free resources, close screen and libraries. --*/ + IF glist THEN FreeGadgets(glist) + IF visual THEN FreeVisualInfo(visual) + IF scr THEN UnlockPubScreen(NIL,scr) + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) +ENDPROC + +PROC createGadgets() +/*-- Initialize gadget structures and create 'em. --*/ + DEF g, stringInfo:PTR TO stringinfo + /*-- Init exec list to hold listview items. Starts out empty. --*/ + list:=New(SIZEOF mlh) + initList(list) + IF (g:=CreateContext({glist}))=NIL THEN RETURN NOCONTEXT + IF (g:=listView:=CreateGadgetA(LISTVIEW_KIND, g, + [offx+7, offy+13, 243, 100, + 'My Mondo List', tattr, LISTVIEW_ID, 0, visual, 0]:newgadget, + [GTLV_LABELS, list, + GTLV_SHOWSELECTED, NIL, TAG_DONE]))=NIL THEN RETURN NOGADGET + IF (g:=stringGadget:=CreateGadgetA(STRING_KIND,g, + [offx+7, offy+111, 243, 12, + '', tattr, STRING_ID, 0, visual, 0]:newgadget, + [GTST_MAXCHARS,25, TAG_DONE]))=NIL THEN RETURN NOGADGET +/*-- This is where the string gadget buffer is hidden. --*/ + stringInfo:=stringGadget.specialinfo + stringGadgetValue:=stringInfo.buffer +/*-------------------------------------------------------*/ + IF (g:=addButton:=CreateGadgetA(BUTTON_KIND, g, + [offx+58, offy+111+15, 65, 17, + 'Add', tattr, ADDBUTTON_ID, 16, visual, 0]:newgadget, + [TAG_DONE]))=NIL THEN RETURN NOGADGET + IF (g:=deleteButton:=CreateGadgetA(BUTTON_KIND, g, + [offx+129, offy+111+15, 65, 17, + 'Delete', tattr, DELETEBUTTON_ID, 16, visual, 0]:newgadget, + [TAG_DONE]))=NIL THEN RETURN NOGADGET +ENDPROC NONE + +PROC openWindow() + IF createGadgets()<>NONE THEN RETURN NOGADGET + /*-- Note WA_IDCMP to get messages from the listview gadget: --*/ + IF (win:=OpenWindowTagList(NIL, + [WA_LEFT, 38, + WA_TOP, 14, + WA_WIDTH, offx+257, + WA_HEIGHT, offy+150, + WA_IDCMP, (IDCMP_REFRESHWINDOW OR IDCMP_CLOSEWINDOW OR IDCMP_GADGETUP OR + IDCMP_MOUSEMOVE OR LISTVIEWIDCMP OR SCROLLERIDCMP), + WA_FLAGS, (WFLG_DRAGBAR OR WFLG_DEPTHGADGET OR WFLG_CLOSEGADGET OR + WFLG_SMART_REFRESH OR WFLG_ACTIVATE), + WA_TITLE,NIL, + WA_CUSTOMSCREEN, scr, + WA_MINWIDTH, 67, + WA_MINHEIGHT, 21, + WA_MAXWIDTH, $2C0, + WA_MAXHEIGHT, 277, + WA_AUTOADJUST, 1, + WA_GADGETS, glist, + TAG_DONE]))=NIL THEN RETURN NOWINDOW + Gt_RefreshWindow(win, NIL) +ENDPROC NONE + +PROC closeWindow() + IF win THEN CloseWindow(win) +ENDPROC + +PROC wait4message(win:PTR TO window) + DEF mes:PTR TO intuimessage, type + REPEAT + type:=0 + IF mes:=Gt_GetIMsg(win.userport) + type:=mes.class + SELECT type + CASE IDCMP_GADGETUP + /*-- Any old gadget will do. The address is used --*/ + /*-- to identify which one sent the message. --*/ + infos:=mes.iaddress + infos.gadgetid:=mes.code + CASE IDCMP_REFRESHWINDOW + Gt_BeginRefresh(win) + Gt_EndRefresh(win,TRUE) + type:=0 + ENDSELECT + Gt_ReplyIMsg(mes) + ELSE + WaitPort(win.userport) + ENDIF + UNTIL type +ENDPROC type + +PROC addToList() + DEF newNode=NIL:PTR TO ln, node:PTR TO ln, + len, done=FALSE, itemPosition=0 + /*-- Don't add if there's nothing in the string gadget. --*/ + IF (len:=StrLen(stringGadgetValue))=0 THEN RETURN + /*-- Create a node and a string to add to the listview. --*/ + newNode:=New(SIZEOF ln) + newNode.name:=String(len) + StrCopy(newNode.name, stringGadgetValue, ALL) + /*-- Detach the exec list from the listview gadget. --*/ + Gt_SetGadgetAttrsA (listView, win, NIL, [GTLV_LABELS, -1, TAG_DONE]) + /*-- Decide where to insert the new item. Sorted on first character. --*/ + node:=list.head + IF list.tailpred=list + AddHead(list, newNode) + ELSEIF Char(node.name)>stringGadgetValue[] + AddHead(list, newNode) + ELSEIF node=list.tailpred + AddTail(list, newNode) + ELSE + WHILE done=FALSE + node:=node.succ + INC itemPosition + IF Char(node.name)>stringGadgetValue[] + done:=TRUE + ELSEIF node.succ=NIL + done:=TRUE + ENDIF + ENDWHILE + Insert(list, newNode, node.pred) + ENDIF + /*-- Reattach the exec list to the listview gadget. --*/ + Gt_SetGadgetAttrsA (listView, win, NIL, + [GTLV_LABELS, list, + GTLV_TOP, itemPosition, + TAG_DONE]) +ENDPROC + +PROC deleteFromList(itemPosition) + DEF node:PTR TO ln, i + /*-- Don't delete if no item is selected. --*/ + IF (itemPosition=-1) OR (list.tailpred=list) THEN RETURN + /*-- Detach the exec list from the listview gadget. --*/ + Gt_SetGadgetAttrsA (listView, win, NIL, [GTLV_LABELS, -1, TAG_DONE]) + /*-- Find the node that corresponds to itemPosition in the exec list. --*/ + node:=list.head + FOR i:=1 TO itemPosition DO node:=node.succ + /*-- Remove and deallocate the node's data. --*/ + Remove(node) + Dispose(node.name) + Dispose(node) + /*-- Reattach the exec list to the listview gadget. --*/ + Gt_SetGadgetAttrsA (listView, win, NIL, + [GTLV_LABELS, list, TAG_DONE]) +ENDPROC + +PROC main() HANDLE + DEF listItemPosition=-1 /* sentinel value, indicates no selection */ + IF setupScreen()=NONE + IF openWindow()=NONE + REPEAT + messageClass:=wait4message(win) + SELECT messageClass + CASE IDCMP_GADGETUP + SELECT infos /* pointer to gadget */ + CASE addButton + addToList() /* requires a value in the string gadget */ + CASE deleteButton + deleteFromList(listItemPosition) /* requires a selection */ + listItemPosition:=-1 /* sentinel value=no selection */ + CASE listView + listItemPosition:=infos.gadgetid /* note the use of this field! */ + ENDSELECT + CASE IDCMP_INTUITICKS + NOP /* these are being sent for some shitty reason }:-( */ + ENDSELECT + UNTIL messageClass=IDCMP_CLOSEWINDOW + closeWindow() + ENDIF + ENDIF + closeScreen() + CleanUp(0) +EXCEPT + WriteF('Exception: "\s"\n', [exception, 0]) + closeWindow() + closeScreen() + CleanUp(0) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/ham8demo.e b/amigae33a/E_v3.3a/Src/Src/Pd/ham8demo.e new file mode 100644 index 0000000..7c6b43c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/ham8demo.e @@ -0,0 +1,76 @@ +OPT OSVERSION=37 + +MODULE 'gadtools','libraries/gadtools','intuition/intuition','exec/nodes', + 'intuition/screens','intuition/gadgetclass','graphics/text' + +ENUM ER_NONE,ER_NOSCRN,ER_NOWINDOW + +DEF wnd=NIL:PTR TO window, + scr=NIL:PTR TO screen + +PROC shutdown() + IF wnd THEN CloseWindow(wnd) + IF scr THEN CloseScreen(scr) +ENDPROC + +PROC setup() + IF (scr:=OpenScreenTagList(NIL, + [SA_WIDTH,528,SA_HEIGHT,512,SA_DEPTH,8,SA_DISPLAYID,$8804, + NIL,NIL]))=NIL THEN Raise(ER_NOSCRN) + IF (wnd:=OpenWindowTagList(NIL, + [WA_LEFT,0, + WA_TOP,0, + WA_WIDTH,528, + WA_HEIGHT,512, + WA_IDCMP,IDCMP_MOUSEBUTTONS, + WA_FLAGS,WFLG_SIMPLE_REFRESH OR WFLG_NOCAREREFRESH OR + WFLG_ACTIVATE OR WFLG_BORDERLESS, + WA_CUSTOMSCREEN,scr, + NIL]))=NIL THEN Raise(ER_NOWINDOW) +ENDPROC + +PROC draw() + DEF r,loop1,loop2,loop3 + r:=wnd.rport + FOR loop1:=0 TO 7 + FOR loop2:=0 TO 7 + SetAPen(r,loop1*8+loop2+64) + Move(r,loop2*66,loop1*64) + Draw(r,loop2*66,loop1*64+63) + FOR loop3:=0 TO 63 + SetAPen(r,loop3+128) + Move(r,loop2*66+1,loop1*64+loop3) + Draw(r,loop2*66+1,loop1*64+loop3) + SetAPen(r,loop3+192) + Move(r,loop2*66+2+loop3,loop1*64) + Draw(r,loop2*66+2+loop3,loop1*64+63) + ENDFOR + ENDFOR + ENDFOR +ENDPROC + +PROC waitmouse() + DEF mes:PTR TO intuimessage,quit=FALSE + REPEAT + IF mes:=GetMsg(wnd.userport) + IF mes.class=IDCMP_MOUSEBUTTONS THEN quit:=TRUE + ReplyMsg(mes) + ELSE + WaitPort(wnd.userport) + ENDIF + UNTIL quit +ENDPROC + +PROC main() HANDLE + DEF erlist:PTR TO LONG + setup() + draw() + waitmouse() + Raise(ER_NONE) +EXCEPT + shutdown() + IF exception>0 + erlist:=['open screen','open window'] + EasyRequestArgs(0,[20,0,0,'Could not \s.','OK'],0,[erlist[exception-1]]) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/mweg.e b/amigae33a/E_v3.3a/Src/Src/Pd/mweg.e new file mode 100644 index 0000000..d65bb6e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/mweg.e @@ -0,0 +1,256 @@ +MODULE 'exec/nodes', 'exec/ports', + 'intuition/intuition', + 'gadtools', 'libraries/gadtools' + +ENUM ER_NONE, ER_NOGT, ER_NOSCRN, ER_NOVISUAL, ER_NOMENUS, ER_NOINITWIN + +ENUM CM_NONE, + CM_NEW, CM_QUIT, + CM_NEXT, CM_PREV, CM_ZOOM, CM_BACK, CM_FRONT, CM_CLOSE + +OBJECT wininfolist + head: LONG + tail: LONG + tailpred: LONG +ENDOBJECT + +OBJECT wininfo + succ: LONG + pred: LONG + winptr: LONG +ENDOBJECT + +DEF winlist: PTR TO wininfolist, /* linked list of windows */ + menuptr = NIL: PTR TO menu, /* menus built by GadTools */ + scr = NIL, /* pointer to default screen */ + visual = NIL /* pointer to VisualInfo */ + +/* Display an error using an EasyRequest */ +PROC errmsg(msgptr) + EasyRequestArgs(0, [20, 0, 'Error', msgptr, 'OK'], 0, 0) +ENDPROC + +/* Open a new window */ +PROC openwin() + DEF wi: PTR TO wininfo, w: PTR TO window, + success = FALSE + + /* Get some memory for the node */ + wi := New(SIZEOF wininfo) + + IF wi + IF (w := OpenWindowTagList(NIL, + [WA_LEFT, Rnd(300), WA_TOP, Rnd(100), + WA_WIDTH, 340, WA_HEIGHT, 156, + WA_MINWIDTH, 160, WA_MINHEIGHT, 70, + WA_MAXWIDTH, -1, WA_MAXHEIGHT, -1, + WA_TITLE, 'A window', + WA_FLAGS, WFLG_SIMPLE_REFRESH OR WFLG_ACTIVATE OR WFLG_DRAGBAR OR + WFLG_CLOSEGADGET OR WFLG_DEPTHGADGET OR WFLG_SIZEGADGET, + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_MENUPICK, + WA_SCREENTITLE, 'Multi-Windows Example by David Higginson', + NIL, NIL])) = NIL + errmsg('Could not open window.') + Dispose(wi) + ELSE + IF SetMenuStrip(w, menuptr) + wi.winptr := w + success := TRUE + ELSE + CloseWindow(w) + Dispose(wi) + errmsg('Could not attach menus to new window.') + ENDIF + ENDIF + ELSE + errmsg('Out of memory.') + ENDIF + + /* Link it in */ + IF success THEN AddHead(winlist, wi) + /* N.B. New nodes MUST be added at head of list */ +ENDPROC success + +PROC cm_new() + IF openwin() = FALSE THEN errmsg('Could not open window.') +ENDPROC + +PROC cm_next(wi: PTR TO wininfo) + wi := wi.succ + IF wi.succ = FALSE THEN wi := winlist.head + IF wi.succ THEN ActivateWindow(wi.winptr) +ENDPROC + +PROC cm_prev(wi: PTR TO wininfo) + wi := wi.pred + IF wi.pred = FALSE THEN wi := winlist.tailpred + IF wi.pred THEN ActivateWindow(wi.winptr) +ENDPROC + +/* Set up libraries, screens, menus */ +PROC setup() + /* Open gadtools library */ + IF (gadtoolsbase := OpenLibrary('gadtools.library', 37)) = NIL THEN + Raise(ER_NOGT) + + /* Set up exec list to hold window information */ + winlist := [0, 0, 0] + winlist.head := Mul(winlist + 4,1) + winlist.tailpred := winlist + + /* Get default screen and visualinfo info */ + IF (scr := LockPubScreen(NIL)) = NIL THEN Raise(ER_NOSCRN) + IF (visual := GetVisualInfoA(scr, NIL)) = NIL THEN Raise(ER_NOVISUAL) + + /* Create menus */ + IF (menuptr := CreateMenusA([NM_TITLE, 0, 'Project', 0, 0, 0, 0, + NM_ITEM, 0, 'New...', 'N', 0, 0, CM_NEW, + NM_ITEM, 0, NM_BARLABEL, 0 , 0, 0, 0, + NM_ITEM, 0, 'Quit', 'Q', 0, 0, CM_QUIT, + NM_TITLE, 0, 'Window', 0 , 0, 0, 0, + NM_ITEM, 0, 'Next', ',', 0, 0, CM_NEXT, + NM_ITEM, 0, 'Previous', '.', 0, 0, CM_PREV, + NM_ITEM, 0, NM_BARLABEL, 0 , 0, 0, 0, + NM_ITEM, 0, 'Zoom', 'Z', 0, 0, CM_ZOOM, + NM_ITEM, 0, NM_BARLABEL, 0 , 0, 0, 0, + NM_ITEM, 0, 'Bring to front', '>', 0, 0, CM_FRONT, + NM_ITEM, 0, 'Send to back', '<', 0, 0, CM_BACK, + NM_ITEM, 0, NM_BARLABEL, 0 , 0, 0, 0, + NM_ITEM, 0, 'Close', 'K', 0, 0, CM_CLOSE, + NM_END, 0, 0, 0, 0, 0, 0]:newmenu, NIL)) = NIL THEN Raise(ER_NOMENUS) + + IF LayoutMenusA(menuptr, visual, NIL) = FALSE THEN Raise(ER_NOMENUS) + + /* Open initial window */ + IF openwin() = FALSE THEN Raise(ER_NOINITWIN) +ENDPROC + +/* Wait for messages */ +PROC eventloop() + DEF quit = FALSE, + msg: PTR TO intuimessage, class, + sig, bitmask, recalc_bitmask = TRUE, + close_this_win, + wi: PTR TO wininfo, tempwi: PTR TO wininfo, + w: PTR TO window, u: PTR TO mp, + item: PTR TO menuitem, code, id + + REPEAT + /* Recalculate mask formed by ORing all sigbits */ + IF recalc_bitmask + bitmask := 0 + wi := winlist.head + WHILE wi.succ + w := wi.winptr + u := w.userport + bitmask := bitmask OR Shl(1,u.sigbit) + wi := wi.succ + ENDWHILE + ENDIF + + /* Wait for something to happen */ + sig := Wait(bitmask) + + /* Now test all windows' sigbits */ + wi := winlist.head + WHILE wi.succ + tempwi := wi.succ + w := wi.winptr + u := w.userport + IF sig AND Shl(1,u.sigbit) + /* Message(s) received from this window */ + + close_this_win := FALSE + + WHILE u + IF msg:=GetMsg(u) + class := msg.class + code := MENUNULL + + SELECT class + + CASE IDCMP_CLOSEWINDOW + /* User selected close gadget */ + /* Can't close yet because msgport would disappear */ + close_this_win := TRUE + + CASE IDCMP_MENUPICK + code := msg.code + + ENDSELECT + + ReplyMsg(msg) + + /* Process menu events after messaged replied */ + WHILE code <> MENUNULL + item := ItemAddress(menuptr, code) + IF item + id := Long(item + 34) + SELECT id + CASE CM_NEW; cm_new() + CASE CM_QUIT; quit := TRUE + CASE CM_NEXT; cm_next(wi) + CASE CM_PREV; cm_prev(wi) + CASE CM_ZOOM; IF w THEN ZipWindow(w) + CASE CM_FRONT; IF w THEN WindowToFront(w) + CASE CM_BACK; IF w THEN WindowToBack(w) + CASE CM_CLOSE; close_this_win := TRUE + ENDSELECT + code := item.nextselect + ELSE + code := MENUNULL + ENDIF + ENDWHILE + + IF close_this_win + recalc_bitmask := TRUE + + ClearMenuStrip(w) + CloseWindow(w) + Remove(wi) + Dispose(wi) + + IF winlist.tailpred = winlist THEN quit := TRUE + u := NIL + + ENDIF + ELSE + u := NIL /* No more messages */ + ENDIF + ENDWHILE + ENDIF + + wi := tempwi + + ENDWHILE + + UNTIL quit +ENDPROC + +PROC shutdown() + DEF wi: PTR TO wininfo + WHILE wi := RemTail(winlist) + ClearMenuStrip(wi.winptr) + CloseWindow(wi.winptr) + Dispose(wi) + ENDWHILE + FreeMenus(menuptr) + FreeVisualInfo(visual) + UnlockPubScreen(scr, NIL) + CloseLibrary(gadtoolsbase) +ENDPROC + +PROC main() HANDLE + DEF erlist:PTR TO LONG + setup() + eventloop() + Raise(ER_NONE) +EXCEPT + shutdown() + erlist := ['This program requires gadtools library.', + 'Could not find default public screen.', + 'Could not get visual info for screen.', + 'Could not create menus.', + 'Could not create initial window.'] + IF exception>0 THEN errmsg(erlist[exception - 1]) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/device.e b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/device.e new file mode 100644 index 0000000..6b9ff68 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/device.e @@ -0,0 +1,136 @@ +/* + +OBJECT device + +V1.2 by Gregor Goldbach with suggs by Trey van Riper + +methods: + +open() +close() +end() +doio() +sendio() +abortio() +reset() + +*/ + + + +OPT MODULE +OPT OSVERSION=37 +OPT EXPORT +OPT PREPROCESS + +MODULE 'exec/devices', 'exec/io', 'exec/nodes', 'exec/ports','exec/devices', + 'oomodules/library' + +CONST SIZE_OF_BIGGEST_DEVICE_BLOCK=100, -> the size of the biggest device block + LONGEST_NAME=40 + +OBJECT device OF library + name + unit + io:PTR TO io + flags + lasterror +ENDOBJECT + +PROC open(name, unit=NIL,flags=NIL) OF device +/* + +METHOD + + open(name,unit,flags) + +INPUTS + + name - the name of the device to be opened + unit - the unit number + flags - flags for this device + +DESCRIPTION + + Opens the given unit of the device. + +RESULTS + + TRUE if the device could be opened + +EXCEPTIONS + + May raise "dev" with exceptioninfo + + -2 - CreateMsgPort() failed + -3 - CreateIORequest() failed + -4 - OpenDevice() failed + +*/ + +DEF ioreq:PTR TO io, + meinport:mp,fehler + + self.name := name + self.unit := unit + self.flags := flags + +->try to open a no-name message port +->raise "dev,-2 if failed + + meinport := CreateMsgPort() + IF (meinport = NIL) + Throw("dev",-2) + ENDIF + +->try to create an iorequest +->close msgport and raise "dev",-3 if failed + + ioreq := CreateIORequest(meinport, SIZE_OF_BIGGEST_DEVICE_BLOCK) + IF (ioreq = NIL) + DeleteMsgPort(meinport) + Throw("dev",-3) + ENDIF + +->try to open the device +->close iorequest, msgport and raise "dev",-4 if failed + + fehler := OpenDevice(self.name,self.unit,ioreq,flags) + IF(fehler) + DeleteIORequest(ioreq) + DeleteMsgPort(meinport) + Throw("dev",-4) + ELSE + self.io := ioreq + RETURN(TRUE) + ENDIF +ENDPROC + +PROC close() OF device + CloseDevice(self.io) + DeleteIORequest(self.io) + DeleteMsgPort(self.io.mn::mn.replyport) +ENDPROC + +PROC end() OF device + self.close() +ENDPROC + +PROC doio() OF device + IF self.io THEN DoIO(self.io) +ENDPROC + +PROC sendio() OF device + IF self.io THEN SendIO(self.io) +ENDPROC + +PROC abortio() OF device + IF self.io THEN AbortIO(self.io) +ENDPROC + +PROC reset() OF device + IF self.io + self.io::iostd.command := CMD_RESET + DoIO(self.io) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/library.e b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/library.e new file mode 100644 index 0000000..c0b9582 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/library.e @@ -0,0 +1,21 @@ +OPT MODULE +OPT EXPORT + +OBJECT library + base +ENDOBJECT + +PROC open(name,version=NIL,dummy=NIL) OF library +/* + * Just opens a library and fills the entries. the dummy argument is needed for + * opne OF device uses three vars + */ + +DEF base + IF(base := OpenLibrary(name,version))=NIL THEN Raise("LIB") + self.base := base +ENDPROC base + +PROC close() OF library + IF self.base THEN CloseLibrary(self.base) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/objects.build b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/objects.build new file mode 100644 index 0000000..acf1bc3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/objects.build @@ -0,0 +1,23 @@ +# just type 'build FROM objects TARGET ' + +# printer +# +# uses: device, library + +printer.m: printer.e device.m library.m + echo "*Ncompiling printer.e" + ec printer.e + +# device +# +# uses: library + +device.m: device.e library.m + echo "*Ncompiling device.e" + ec device.e + +# library + +library.m: library.e + echo "*Ncompiling library.e" + ec library.e diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer.e b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer.e new file mode 100644 index 0000000..020279b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer.e @@ -0,0 +1,159 @@ +OPT MODULE +OPT OSVERSION=37 +OPT EXPORT + +MODULE 'devices/printer', 'exec/devices', 'exec/io', 'exec/nodes', + 'exec/ports','exec/devices', + 'oomodules/device' + +OBJECT printer OF device +ENDOBJECT + +PROC rawwrite(zkette,laenge) OF printer +/* + +METHOD + + rawwrite(string,len) + +INPUTS + + string - the characters to be printed, 0-terminated + len - number of characters + +DESCRIPTION + + Sends the characters to the printer. Esc-sequences will not be substituted. + Opens the printer.device if necessary. +*/ + + IF self.io=NIL + self.open('printer.device',0,0) + ENDIF + + IF self.io + + self.io::iostd.data := zkette + self.io::iostd.length := laenge + self.io::iostd.command := PRD_RAWWRITE + + self.doio() + + self.lasterror := self.io.error + ENDIF +ENDPROC + +PROC write(zkette,laenge) OF printer +/* + +METHOD + + rawwrite(string,len) + +INPUTS + + string - the characters to be printed, 0-terminated + len - number of characters + +DESCRIPTION + + Sends the characters to the printer. Esc-sequences will be substituted. + Opens the printer.device if necessary. +*/ + + IF self.io=NIL + self.open('printer.device',0,0) + ENDIF + + IF self.io + + self.io::iostd.data := zkette + self.io::iostd.length := laenge + + self.io::iostd.command := CMD_WRITE + + self.doio() + + self.lasterror := self.io.error + ENDIF +ENDPROC + +PROC xcommand(kommando,p0=NIL,p1=NIL,p2=NIL,p3=NIL) OF printer +/* + +METHOD + + xcommand(command,param0,param1,param2,param3) + +INPUTS + + command - the printer command to be executed (s. devices/printer) + param0-3 - command parameters + +DESCRIPTION + + Executes a printer command with the given parameters such as setting + left and right border, justification etc. + Opens the printer.device if necessary. + +*/ + + IF self.io=NIL + self.open('printer.device',0,0) + ENDIF + + self.io::ioprtcmdreq.prtcommand := kommando + self.io::ioprtcmdreq.parm0 := p0 + self.io::ioprtcmdreq.parm1 := p1 + self.io::ioprtcmdreq.parm2 := p2 + self.io::ioprtcmdreq.parm3 := p3 + self.io.command := PRD_PRTCOMMAND + self.doio() + +ENDPROC + +PROC graphicdump(rport,cmap,vmodes,srcx,srcy,srcwidth,srcheight,destcols,destrows,special) OF printer +/* + +METHOD + + graphicdump(params) + +INPUTS + + rport - the RastPort containing the image + cmap - screen's ColorMap + vmodes - ViewModes of the screen + srcx,srcy, + srcwidth, + srcheight - dimensionen: start point & width & height + destcols, + destrows - dimensions on the printer in points + Special - special flags + +DESCRIPTION + + Prints a part of the rastport. + Opens the printer.device if necessary. + +*/ + + IF self.io=NIL + self.open('printer.device',0,0) + ENDIF + + self.io::iodrpreq.rastport := rport + self.io::iodrpreq.colormap := cmap + self.io::iodrpreq.modes := vmodes + self.io::iodrpreq.srcx := srcx + self.io::iodrpreq.srcy := srcy + self.io::iodrpreq.srcwidth := srcwidth + self.io::iodrpreq.srcheight := srcheight + self.io::iodrpreq.destcols := destcols + self.io::iodrpreq.destrows := destrows + self.io::iodrpreq.special := special + + self.io.command := PRD_DUMPRPORT + self.doio() + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer_test.e b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer_test.e new file mode 100644 index 0000000..57b7022 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/printer_test.e @@ -0,0 +1,40 @@ +/* + * this tests the printer object. NOTE: those vars are only needed + * for the graphic dump :) + */ + +OPT OSVERSION=37 + +MODULE 'oomodules/device','exec/io','devices/printer', + 'oomodules/printer','devices/printer', + 'intuition/intuition', 'intuition/intuitionbase','graphics/gfxbase','graphics/view', + 'graphics/rastport' + +PROC main() +DEF drucker:PTR TO printer, + ibase:PTR TO intuitionbase, + gbase:PTR TO gfxbase, + vp:PTR TO viewport, + rp:PTR TO rastport + + ibase:=intuitionbase + gbase:=gfxbase + rp := ibase.activewindow::window.rport + vp := gbase.actiview::view.viewport + + NEW drucker + + drucker.graphicdump( rp, + vp.colormap, + vp.modes, + 0,0,100,100,100,100,0) + + drucker.rawwrite('Hallo', 5) + drucker.xcommand(27) -> superscript on + drucker.write('Hallo', 5) + + WriteF('Fehler:\d\n',drucker.io.error) + + + END drucker +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools.e b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools.e new file mode 100644 index 0000000..a0195a1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools.e @@ -0,0 +1,69 @@ +OPT MODULE +OPT EXPORT + +MODULE 'oomodules/library', 'reqtools', 'libraries/reqtools' + +CONST FILEREQ=0 + +OBJECT reqtools OF library + stringbuf + filebuf + dirbuf + number +ENDOBJECT + +PROC new() OF reqtools + self.open('reqtools.library', 0) + IF self.base = NIL + Raise("LIB") + ELSE + reqtoolsbase := self.base + ENDIF +ENDPROC + +PROC ez(body,gadgets,dunno,arglist,taglist) OF reqtools + IF reqtoolsbase + RETURN RtEZRequestA(body,gadgets,dunno,arglist,taglist) + ENDIF +ENDPROC + +PROC string(title=NIL,maxlen=200,dunno=NIL,dunno2=NIL) OF reqtools + IF self.stringbuf THEN Dispose(self.stringbuf) + self.stringbuf := New(maxlen) + + RtGetStringA(self.stringbuf,maxlen,title,dunno,dunno2) +ENDPROC + +PROC end() OF reqtools + IF self.stringbuf THEN Dispose(self.stringbuf) + CloseLibrary(reqtoolsbase) +ENDPROC + +PROC palette(title,dunno=NIL,dunno2=NIL) OF reqtools + self.number := RtPaletteRequestA(title,dunno,dunno2) +ENDPROC self.number + +PROC long(title,dunno=NIL,dunno2=NIL) OF reqtools +DEF number + RtGetLongA({number}, title, dunno, dunno2) + self.number := number +ENDPROC self.number + +PROC file(title,maxlen=200) OF reqtools HANDLE +DEF req:PTR TO rtfilerequester + + IF req:=RtAllocRequestA(FILEREQ,0) + + IF self.filebuf THEN Dispose(self.filebuf) + IF self.dirbuf THEN Dispose(self.dirbuf) + self.filebuf := NewR(maxlen) + self.dirbuf := NewR(maxlen) + + RtFileRequestA(req,self.filebuf,title,0) + AstrCopy(self.dirbuf,req.dir,maxlen) + RtFreeRequest(req) + ENDIF + +EXCEPT + NOP +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools_test.e b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools_test.e new file mode 100644 index 0000000..68b952a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/oomodules/reqtools_test.e @@ -0,0 +1,26 @@ +MODULE 'oomodules/reqtools','libraries/reqtools' + + +PROC main() +DEF req:PTR TO reqtools + + NEW req.new() + +/* req.ez('Nice to see ya!','Ah.|So what?',0,0,[RTEZ_REQTITLE,'Just a test',RT_REQPOS,REQPOS_POINTER]) + req.string('Just enter a string:') + WriteF('\s\n',req.stringbuf) + req.string('Just enter a string:') + WriteF('\s\n',req.stringbuf) + + req.long('just enter a number:') + WriteF('\d\n', req.number) + + req.palette('just choose a colour:') + WriteF('\d\n', req.number) +*/ + + req.file('FILE?') + WriteF('\s\n', req.filebuf) + WriteF('\s\n', req.dirbuf) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/queens.e b/amigae33a/E_v3.3a/Src/Src/Pd/queens.e new file mode 100644 index 0000000..69a297a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/queens.e @@ -0,0 +1,80 @@ + +-> Copyright © 1996 Guichard Damien. + +OPT OSVERSION=37 + +OBJECT queen + myrow:LONG + mycolumn:LONG + neighbor:PTR TO queen + boardsize:LONG +ENDOBJECT + +PROC build(aQueen,col,size) OF queen + self.neighbor:=aQueen + self.mycolumn:=col + self.myrow:=1 + self.boardsize:=size + IF self.neighbor THEN self.neighbor.first() +ENDPROC + +PROC checkCol(colNumber,rowNumber) OF queen + DEF cd + IF rowNumber=self.myrow THEN RETURN FALSE + cd:=colNumber-self.mycolumn + IF self.myrow+cd=rowNumber THEN RETURN FALSE + IF self.myrow-cd=rowNumber THEN RETURN FALSE + IF self.neighbor THEN RETURN self.neighbor.checkCol(colNumber,rowNumber) +ENDPROC TRUE + +PROC first() OF queen + self.myrow:=1 +ENDPROC self.checkrow() + +PROC next() OF queen + self.myrow:=self.myrow+1 +ENDPROC self.checkrow() + +PROC checkrow() OF queen + IF self.neighbor=NIL + IF self.myrow>self.boardsize THEN RETURN 0 + RETURN self.myrow + ENDIF + WHILE self.myrow<=self.boardsize + IF self.neighbor.checkCol(self.mycolumn,self.myrow) THEN + RETURN self.myrow + self.myrow:=self.myrow+1 + ENDWHILE + IF self.neighbor.next()=0 THEN RETURN 0 +ENDPROC self.first() + +PROC printboard() OF queen + DEF x + IF self.neighbor THEN self.neighbor.printboard() + FOR x:=1 TO self.boardsize + FputC(stdout,IF x=self.myrow THEN "Q" ELSE ".") + ENDFOR + FputC(stdout,"\n") +ENDPROC + +PROC main() HANDLE + DEF myargs:PTR TO LONG,rdargs + DEF lastq=NIL:PTR TO queen,newq:PTR TO queen + DEF size,x + myargs:=New(8) + IF (rdargs:=ReadArgs('BOARDSIZE/N/A,ALL/S',myargs,NIL))=NIL THEN Raise(1) + IF (size:=Long(myargs[0]))<=0 THEN Raise(1) + FOR x:=1 TO size DO lastq:=NEW newq.build(lastq,x,size) + IF lastq.first() THEN lastq.printboard() + IF myargs[1]=FALSE THEN Raise(0) + WHILE TRUE + EXIT CtrlC() + EXIT lastq.next()=0 + FputC(stdout,"\n") + lastq.printboard() + ENDWHILE +EXCEPT DO + IF rdargs THEN FreeArgs(rdargs) + IF exception THEN WriteF('Bad Args!\n') +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/readclip.e b/amigae33a/E_v3.3a/Src/Src/Pd/readclip.e new file mode 100644 index 0000000..e5e6a71 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/readclip.e @@ -0,0 +1,166 @@ + +/**** + + ReadClipboard.e + © 1995 by Vidar Hokstad + + + COPYRIGHT NOTICE: + + This code can be distributed freely, and parts of the code, + or the whole code, can be used as is, or reused in any + product - free or commercial - provided the following terms + are met: + + - You accept that I give no guarantee, expressed or implied + of the usefulness or functionality of this code, and that + I accept no responsability for damage caused directly or + indirectly by the use of this program. + + - The product in which the code is used can not be used + for military applications. + + + INFO: + + Written as an exersize in using iffparse.library. Reads the + PRIMARY_CLIP clipboard unit, and prints it to stdout. + + Notice: Expects a FTXT clipboard, and will only utilize + FTXT CHRS chunks (which is what a standard clipboard contains). + + The only 2.04+ specific stuff is the use of Vprintf for writing + debug info. I don't really know if there's a version of + iffparse.library for older os-versions though. There ought to + be, but I dont really care :) + +***/ + + +OPT OSVERSION=37,PREPROCESS + +-> #define DEBUG + +MODULE 'iffparse','libraries/iffparse','devices/clipboard' + +RAISE "^C" IF CtrlC() = TRUE + + + +PROC readclip (unit,out) HANDLE + + DEF iff:PTR TO iffhandle, -> Utility struct. for iffparse + cliph=NIL, -> The clipboard handler + buf[200]:ARRAY OF CHAR, -> Buffer for ReadChunkBytes() + size -> Number of read bytes. + +#ifdef DEBUG + DEF node:PTR TO contextnode -> additional info about chunk +#endif + + +-> --- INIT + + IF (iffparsebase:= OpenLibrary('iffparse.library',0))=NIL + Raise ("iffp") + ENDIF + + -> You *MUST* use AllocIFF() to allocate an iffhandle structure + IF (iff:=AllocIFF())=NIL THEN Raise ("iffh") + + -> Prepare the iffhandle to use the clipboard + InitIFFasClip(iff) + + -> Open a clipboard stream and fill inn the iffhandle + IF (cliph:=OpenClipboard (unit) )=0 THEN Raise ("open") + iff.stream:=cliph + + -> Start a new IO session + IF OpenIFF (iff,IFFF_READ) THEN Raise ("oiff") + + -> Tell iffparse.library you want to examine chunks of type FTXT + -> and id CHRS which is pure ASCII text. + +#ifndef DEBUG + IF StopChunk (iff,"FTXT","CHRS") THEN Raise ("schn") +#endif + + +-> --- MAIN LOOP + +-> While theres something left to read, parse the IFF stream. +-> For a clipboard, there's usually only one chunk of interest, +-> but this way the code will work if theres more chunks too. + +-> IF "DEBUG" is defined, the IFF file is stepped through one +-> context change at a time, and additional info is dumped to +-> Output() + + +#ifndef DEBUG + WHILE ParseIFF(iff,IFFPARSE_SCAN)<>IFFERR_EOF +#endif + +#ifdef DEBUG + WHILE ParseIFF(iff,IFFPARSE_RAWSTEP)<>IFFERR_EOF +#endif + CtrlC() + +#ifdef DEBUG + node:= CurrentChunk(iff) + Vprintf ('id = "%s", type = "%s", size = %ld\n', + [[node.id,0],[node.type,0],node.size]) + Flush(stdout) + + -> Ensure that we only dump "CHRS" chunks + IF node.id="CHRS" +#endif + + -> Copy the chunk to the output file + WHILE (size:=ReadChunkBytes(iff,buf,200))>0 + Write(out,buf,size) + ENDWHILE + +#ifdef DEBUG + ENDIF +#endif + + ENDWHILE + +EXCEPT DO + +->--- CLEANUP: + + -> Was iffparse.library opened? + IF iffparsebase + + -> Was the iffhandle structure allocated? + IF iff + + -> Did OpenIFF() fail? + IF exception<>"oiff" THEN CloseIFF(iff) + + -> Was the Clipboard structure allocated? + IF cliph THEN CloseClipboard(cliph) + + -> Free the iffhandle. *MUST* be done with FreeIFF() + FreeIFF(iff) + ENDIF + CloseLibrary (iffparsebase) + ENDIF + + -> IF an exception occured, let the next exception handler deal + -> with it too... + + ReThrow() +ENDPROC + + +-> Read the PRIMARY_CLIP clipboard, and print it's contents to stdout +-> Display any exception that occurs. + +PROC main() HANDLE + readclip (PRIMARY_CLIP,stdout) +EXCEPT + Vprintf ('exception = %ld ("%s")\n',[exception,[exception,0]]) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/ReadMe b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/ReadMe new file mode 100644 index 0000000..867055d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/ReadMe @@ -0,0 +1,247 @@ + +If you are an Amigoid to whom one or more of the following statements applies: + + + 1. You always wanted to learn ARexx but the fact that it can't even flash + the screen by itself bothered you (well I know that there is \007), + + 2. You badly need quick and easily created wrapper-programs for your new + great E routines using ARexx's monitoring capabilities, + + 3. You want to write something really useful as PD, Shareware or + something, but don't know what people out there would need and truly + appreciate, + + 4. You want to start programming in E in an unconventional way, + + 5. You need some speial and quick functions for your ARexx scripts, + + 6. You often listen to those PC/Macintosh los... sorry -- 'users' and + begin to envy them their 'servers' and stuff, + + 7. You have your nose more or less in the middle of your face... + + + THIS IS FOR YOU ! IT WILL MAKE YOU HAPPY ! + + +What it is you're asking? Well this is a E module, called rexxHostC.m, two +sources as example of using it, and this ReadMe. + +The module provides you with an extremely user-friendly 'engin' for writing +Rexx function-hosta (i.e. servers). Take a look on the 'mini_host.e' file to +see how concise can an E program be! And it really provides ARexx with a +Intuition function! The executable is 5112 bytes big. + +The engin is object-oriented, it has been pretty thoroughly tested, and it +returns all memory used. What else can I say...? Here comes the HOW-TO. + +--------------------------------------------------------------- + +After creating an instance of a rexxHostC object, by calling NEW rexxHostC() +with required parameter/s, the program by itself will open rexsyslib.library, +create a public port with the provided or default name, add it to ARexx's +host list and [possibly after executing some user-provided function] enter a +loop waiting for ARexx function-calls, intercepting them and executing. This +loop will be broken if either: + + 1. COMMAND 'bye' arrives at its port + + 2. the program got ^C + + 3. the method break() is executed [directly or not] by any callback + +and then our instance of the rexxHostC object will do the cleanup, that is: +reply the outstanding messages, delete the port, close the rexsyslib.library +etc. and commit suicide. In most cases the host will terminate [unless, for +some strange reason, you decide otherwise and put lots of other code after +it]. + +The rexxHostC class has quite a few methods, but you don't need most of them +if you don't want them; they are only there to help you. Notice that the +'mini_host' demo uses no other method but the constructor! + +Here comes short description of the available methods: + +--------------------------------------------------------------- + +CONSTRUCTOR: + + rexxHostC( callback_list, + name = 'rexx_host', + host_priority = -50, + func_ptr = NIL ) + +where: + + callback_list + ------------- + + is a list of pairs: [ S, C, S, C, ... , S, C ] + + 'S' being an UPPERCASE string like 'BEEP' or 'BYE_BYE' [quotes + included!], representing the name of the function you are adding to ARexx + 'C' is a callback i.e. a pointer to a PROC'ess; it can also be a quoted + expression, a string like 'I love this\n', or just NIL; in the last + case ARexx will not find any function with this callback's name -- + just as if the name-string was not there. This callback-list is + [roughly] checked for validity and if it doesn't conform exception 4 + i.e. ERR_BADLIST will be raised. + + Callbacks take no arguments [not directly anyway] and return either + nothing or [nicer thing to do] a string [not necessarily an EString] + like 'this is your callback speaking', 'TRUE', or '666'. ARexx will by + himself [!] translate those strings that represent numbers [like the last + one here] to numbers. It is as easy as that for direct values, for + variables you will probably use the supplied routines longToStr() and + charToStr(), which turn an integer like 69 or a char like "A" into a + string for ARexx. See the 'big_host' demo-source for that. As to + callbacks' arguments there are three support routines supplied for that + purpose: getNumArgs(), getStr( index ) and getNum( index ), read later on + about them. + + name + ---- + + [optional] is a string representing name for your message-port which must + be different from all currently present public ports present in the + system or you will get exception 2 i.e. 'ERR_NOTUNIQUE'. + + + host_priority + -------------- + + [optional] is the priority AMONG all Arexx libraries and hosts. It is NOT + any task priority, so don't be too surprised at the low default value. In + fact you SHOULD NEVER USE HIGHER priority than any of the libraries/hosts + you will be calling, DEADLOCK will result otherwise! I would personally + never attempt anything over 0. 'host_priority' value will be clipped to + a number between -100 and 100. + + + func_ptr + -------- + + is the [optional] pointer to function you want executed AFTER setup is + completed, probably nothing more important than announcing that it is + waiting for Rexx messages. + + +Note that 'callback_list' is the only argument you must give the constructor. +Another unusual thing is that we have no public destructor. + +--------------------------------------------------------------- + + num := getNumArgs() + ------------ + + returns the number of arguments the function in question got from ARexx, + it will be something between 0 and 15. + +--------------------------------------------------------------- + + string, fGood := getStr( index ) + --------------- + + gives you the argument number 'index' as a string, the second BOOLEAN + return-value tells you whether this argument is valid, that is -- if it + really came from ARexx [this you might already know if you have + previously called getNumArgs()]. + + N.B. It starts from 1, as the argument #0 is the command itself! + +--------------------------------------------------------------- + + num, fGood := getNum( index ) + --------------- + + gives you the argument number 'index' as an integer, the second BOOLEAN + return-value tells you whether this argument is valid, that is -- if the + argument-string with this index string really came from ARexx and if it + is a number. + + N.B. It starts from 1, as the argument #0 is the command itself! + +--------------------------------------------------------------- + + break() + ------- + + breaks the waiting/receiving/executing loop and kills the rexxHandlerC + object. + +--------------------------------------------------------------- + + str := longToStr( long ) + ----------------- + + str := charToStr( char ) + ----------------- + + as already said, these functions will turn an integer or a char + respectively into a string just as ARexx wants it for a return-value from + its function, it is only needed for variables, the direct values can be + returned with strings like '123' or 'oui monsieur'. + +--------------------------------------------------------------- + + major, minor := version() + --------- + + returns major and minor version number of the rexxHostC.m + the current values are bye the way: 0 and 4 + +======================================================================= + +EXCEPTIONS that might be raised by rexxHostC-object: + + +"MEM" meaning: 'not enough memory' + +"REXX" meaning: 'rexxsyslib.library not found' + +ERR_NONAME = 1 meaning: 'I got NIL as port-name' + +ERR_NOTUNIQUE = 2 meaning: 'port-name not unique' + +ERR_LISTNIL = 3 meaning: 'callback-list ptr NIL' + +ERR_BADLIST = 4 meaning: 'bad callback-list' + +ERR_NOTADDED = 5 meaning: 'host not added to ARexx list...' + +--------------------------------------------------------------- + +LIMITATIONS: + +There are two major I can think of: + + 1. As all other similar Rexx hosts I met [for example RexxFuncHost by + Donald T. Meyer] one such active host screens all other from receiving + function-calls; so that ONLY ONE CAN BE EFFECTIVE AT ANY TIME. This is + due to the fact that, differently than with libraries, ARexx will not + send your function-call to any other host whatever error was reported by + the one that received it. It would be possible to find a solution to that + -- if I still feel any urge to play with this piece of software I might + do that -- but in practice it shouldn't be so much of a problem + considering E's lightning speed of compilation. If you already have the + callbacks, you can create a new host in couple of minutes and launch it + in place of the previously running one. It might even be possible to have + dynamically created callback-lists: if/when we start to get flooded with + great PD/ShareWare/commercial modules containing just callback-lists and + callbacks themselves [there would be some problems with getting the + arguments for the callbacks though], you would be able to manage them + dynamically from ARexx to be included in just one rexxHostC-based server. + + 2. UPPER/lower case does not matter for all function-calls. It wouldn't + be any problem to implement this as optional, but I doubt whether it + would be so useful. Both ARexx and AmigaDOS tend to be case-insensitive + in most cases, and preventing ARexx from turning the name in your + function-call to uppercase requires additional work. + + +This was written in E v3.0b and v3.1a [registered version], by Piotr Obminski +in December 1994. It is, an off-spin of a much larger project, but I +found it so cute that I decided to polish it and present it to the so called +'Amiga community' [as community service]. The example-proggies are PD, but +the rexxHostC.m is Copyrighted FreeWare by me that is Piotr Obminski. diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.e b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.e new file mode 100644 index 0000000..4c8a344 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.e @@ -0,0 +1,144 @@ +-> +-> big_host.e +-> +-> ARexx host (i.e. server) with bunch of totally useless functions... +-> written in E v3.0 as a demo showing limitless possiblities of the... +-> rexxHostC class +-> +-> Public Domain · by Piotr Obminski · 27-Dec-94 20:34:44 +-> +-> +-> ! A M I G A F O R E V E R ! +-> +-> + +MODULE '*rexxHostC' + + +DEF rx_obj : PTR TO rexxHostC + + +PROC main() HANDLE + DEF cb_list : PTR TO LONG + + cb_list := [ 'LOVE', { love }, + 'HATE', { hate }, + 'SAY_PIPI', { beep }, + 'DISPLAYBEEP', { beep }, + 'GLOW', { glow }, + 'NOTHING', NIL, + 'WBENCHTOBACK', `WbenchToBack() BUT 'OK', + 'WBENCHTOFRONT', `WbenchToFront() BUT 'OK', + 'GO_AWAY', { go_away }, + 'RATS', `'BIG RODENTS!', -> <-- see this?! + 'ODD', { odd } ] + + + NEW rx_obj.rexxHostC( cb_list, 'big_host', -51, + `PrintF( 'Setup completed, now try me!\n' ) ) + + +EXCEPT DO + + SELECT exception + CASE 0 + PrintF( 'You\ave aborted...\n' ) + CASE ERR_NOTUNIQUE + PrintF( 'It seems that I\am ALREADY RUNNING...\n' ) + CASE ERR_LISTNIL + PrintF( 'I\ave got NIL for CALLBACK LIST!\n' ) + CASE ERR_NOTADDED + PrintF( 'HOST could NOT be ADDED!\n' ) + CASE ERR_BADLIST + PrintF( 'Check your CALLBACK LIST!\n' ) + CASE "MEM" + PrintF( 'Memory!\n' ) + CASE "REXX" + PrintF( 'I need rexxsyslib.library!\n' ) + DEFAULT + PrintF( '? ? ?\n' ) -> this should never happen + ENDSELECT +ENDPROC + +-> ------------------------ callbacks ----------------------------- + +-> +-> just says how many arguments it got and displays them, to do that +-> it calls another callback +-> +PROC love() + PrintF( 'love() here calling hate()...\n' ) + hate() -> just call another callback +ENDPROC 'it''s "kärlek" in Swedish' + + +-> +-> just says how many arguments it got and displays them +-> +PROC hate() + DEF num, i + + num := rx_obj.getNumArgs() + + PrintF( 'hate() here, I got \d args!\n', num ) + + FOR i := 1 TO num + PrintF( 'arg #\d = \s\n', i, rx_obj.getStr( i ) ) + ENDFOR +ENDPROC 'it''s "hat" in Swedish' + + +-> +-> Intuition support -- wow! +-> +PROC beep() + DEF i, how_many = 3, fGotArg = FALSE + + IF rx_obj.getNumArgs() > 0 THEN how_many, fGotArg := rx_obj.getNum( 1 ) + + FOR i := 1 TO 3 + DisplayBeep( NIL ) + Delay( 10 ) + ENDFOR + + IF ( fGotArg = TRUE ) AND ( how_many = 3 ) + RETURN 'here you are: as many beeps as you requested!' + ELSE + RETURN 'you\ave got default number of beeps which is 3!' + ENDIF +ENDPROC + + +-> +-> some hardware-generated colors in inline assembly +-> +PROC glow() + DEF i + + FOR i := 0 TO 100000 + MOVE.W $DFF006, $DFF180 + BCHG #1, $BFE001 + ENDFOR +ENDPROC rx_obj.longToStr( i ) -> because Rexx wants strings! + + +-> +-> E's own Odd() for ARexx, it returns '1' for TRUE and '0' for FALSE +-> (which ARexx will see as numbers anyway!), it returns ARexx error +-> RX_WARN (i.e. 5) for bad number of arguments +-> +-> NOTE THAT THEY MUST BE RETURNED AS STRINGS FOR AREXX! (which will then +-> treat them as numbers) +-> +PROC odd() + IF rx_obj.getNumArgs() <> 1 THEN RETURN 5, 0 +ENDPROC IF Odd( rx_obj.getNum( 1 ) ) THEN '1' ELSE '0' + + +-> +-> this aborts rexxHostC object (we have the internal COMMAND 'BYE', +-> but let's define a FUNCTION doing exactly the same) +-> +PROC go_away() + rx_obj.break() -> that' how our method break() is used +ENDPROC 'if you must...' diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.info b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.info new file mode 100644 index 0000000000000000000000000000000000000000..4d822c406b34377313b974c319c5dd3be9d52efa GIT binary patch literal 626 zcmZwEu}i~H5C-r|(i-Ssx z(Xrs-=-?n$J-_dzk`_G3k9&8Im%PhMQ#@hxB$BQy$pY4%bdE>TIXQHlS-fD;EmxoO z90{K)w%ac6N-Vzk*R`N(m7UZTQVEwuQVG7OKcw|13me51?3puoba@LO&-dZvehB+3 z2FgZ}!_z&g3O!>6P}QP>n3^eKOw?M|Wlpc@Di_p?sbA2#*@2w`4QsY`;TjuO>a0tH zb%_mSSTQqsS)n;8V>*wUgTSr-`6A9kEaw50hH7D?Z!pmhm?_#;^@l!SlkK;tB$~s_ ziFx2QxbUAii+dQk)6sUOb8;S-B3^|*vq?i8z(_|hnY_a6?j5d&pHNDpZ{{s0&O`40 O2~y^j8LvIYy7mkCiIrUd literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.rexx b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.rexx new file mode 100644 index 0000000..590d287 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/big/big_host.rexx @@ -0,0 +1,20 @@ +/* big_host.rexx */ + +say "love( 69, amor ) returns" "'" || love( 69, amor ) || "'" + +say "hate( you, 666, odio ) returns" "'" || hate( you, 666, odio ) || "'" + +say "displaybeep( 20 ) returns" "'" || displaybeep( 20 ) || "'" + +say "glow() returns" glow() + +say "rats() returns" "'" || rats() || "'" + +say WBenchToBack() WBenchToFront() WBenchToBack() WBenchToFront() + + +address 'big_host' 'bye' + +/* or like this (which is slightly crazy): */ + +/* call go_away() */ diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.e b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.e new file mode 100644 index 0000000..595e24b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.e @@ -0,0 +1,14 @@ +-> +-> mini_host.e « Intuition for ARexx ;-) » +-> +-> Public Domain · by Piotr Obminski · 26-Dec-94 04:38:59 +-> + +MODULE '*rexxHostC' + + +PROC main() + DEF rx_obj : PTR TO rexxHostC + + NEW rx_obj.rexxHostC( [ 'BEEP', `DisplayBeep( NIL ) BUT '0' ] ) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.info b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.info new file mode 100644 index 0000000000000000000000000000000000000000..4d822c406b34377313b974c319c5dd3be9d52efa GIT binary patch literal 626 zcmZwEu}i~H5C-r|(i-Ssx z(Xrs-=-?n$J-_dzk`_G3k9&8Im%PhMQ#@hxB$BQy$pY4%bdE>TIXQHlS-fD;EmxoO z90{K)w%ac6N-Vzk*R`N(m7UZTQVEwuQVG7OKcw|13me51?3puoba@LO&-dZvehB+3 z2FgZ}!_z&g3O!>6P}QP>n3^eKOw?M|Wlpc@Di_p?sbA2#*@2w`4QsY`;TjuO>a0tH zb%_mSSTQqsS)n;8V>*wUgTSr-`6A9kEaw50hH7D?Z!pmhm?_#;^@l!SlkK;tB$~s_ ziFx2QxbUAii+dQk)6sUOb8;S-B3^|*vq?i8z(_|hnY_a6?j5d&pHNDpZ{{s0&O`40 O2~y^j8LvIYy7mkCiIrUd literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.rexx b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.rexx new file mode 100644 index 0000000..cbacf22 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/mini/mini_host.rexx @@ -0,0 +1,5 @@ +/* mini_host.rexx */ + +say beep() + +address 'rexx_host' 'bye' diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/rexxhostc.m b/amigae33a/E_v3.3a/Src/Src/Pd/rexxHostC/rexxhostc.m new file mode 100644 index 0000000000000000000000000000000000000000..887e68bff06e382fda8cae32c7fddb3db7807072 GIT binary patch literal 4126 zcmb_fU1(d`5gu8xe4|`!HJHT&v$+x4tZI9uP(pEwSR~7`m7v_Xj+44!cjZ6XR#rb3 z$xfZc4>#MbDWQ~gAIeff=~K5aYy4W+2h*39J}mnfN+F@JO&?O$P`7ne*|*=!x%#m; zp)bAW+_{=FXXebzH*=2D*KdqdHxY#~D9A5<&dA$Ko*|ke&$naX7?Yu?P=PL++c&-> zpF7_r^XGYmF?lgTS$qZ6T(W-lcf%P9Vr|e}8&qpY$ncAH;??vg!!K)nnGNz7lg29f zEDA=bFGjMbYp|z@gvPpr7vVj)^TYft^D|f-p&7BS55?(v`a1M)DsGH;b!NkHM8oS? zr85UZclW2u{s{hBhjE%xku`**Bc z#h3SLQT7QvHQzSZRc5?2q8Ss|`Bax!5&HwenTe4xA#vAK?1YQxV}~Ez_|j>p-?0Qq zMzc@4$lN*pNM+aAe368QC4L+wWyMl?GeVPU&GFV8Ie&QBx}!N)^F0guLcV>?U5aku9%H`jHEN?)e4;N3 zeL=(jq=Co{z`w6*YPg!ZTAE(}pPKZOnp%0AiV;_-SPn_H5!Jm1QhigB?NeEm-1tt$ zp1Toysp<%w09iohrcsHSXil{_PMM-Ke_=X?qG|-)ODywPjT$0bQs9snJ1Iqm~mTV;uEt zAjeF@pgmy1WETjO>G@U$S$K8m|hf`c|vX zxiu6vw^7}{>a0rVAoJ`34QWfk`C;m}A!zv}R^-g8&13iq`4m&A@|!bpvv?#&%% zR(9*hsS!0&sKSV$AsQ)Y9PF|kfD~bg1B$f!0W!aalZdRo-K}?t;)Z|P4ihSNl55sT zOAY(KczDt7{Ka!k8>CHhzuLnIl19`rSQ$jD(~^w=l@0c5IO!Y?k2#GwBHM_2n%3_q zc|jC1%qL2+-rXJ3TBpQo;Of$4hGJfzkI~=MZ-{=~wKnSZ{5N4^u<0)!$GYv{fv<=O zosW5AZ#V}Sh_dX`)iOuNk0dXLZFET0@#$2eAiOh}syGq?D7#v1b*?_w!foX0kh#c| zuT@d%yiD*Zan#5@@c`w{`>x)wt2ZoBeZ>ki?OEQYLEh~cCu+HaaCF!|7u)?R+Z`SLkdZx{aT*p~ zBBO-P8KErKha0J_n7`d^hA7+(O?6x(?LCgQVOhJW`H=dhx( zdxfQe_8!+l*qAgwjG*HHlfahcs2;#LnBAKG0g(H1s~ddWbSzxo-2Tvk0J*bqg`jV7 zP9;OVDicS`&~wK=uBwBUHJ=F z+dadNI6ggzM8tsaOB{zssDdSlU4iQZ@rm~k>O!5=K2;a(Omt?8>n9fH%jwIco#&i4 z?$sQ*OBkFFdGB|0DP$G==avs1P4JzOy%R~?+kmM9aM8uM3K0JUa8g26BNS+3%*$0^ z0UKU7Ur*Z|%dH~DE>}_Ktut}5iePgeC;7gs;}L(Ouh^U~BZayh#20Ru`0`n}FS{|` zOx5XUZrtBPfAgUhdX4cA`Y7MbkAK?A1q zZWnlWw=ie4dh}ha`HBScCCKCd1!(MhX?m@=h_OV~{KiIZwNhJ?uiE`uv9J)usLogK zlkq81Ih(5g{n5p%G?S|TBMLf|s{b3>rz*|9u-YoT}IV0&1k{|M>uP5cB|aAXRU$y?)T&g9cOeqYS7H z`aY-z`fE_1xlRn!ew)rt*c6zx=}Z=5(3a!0XVj*ikWIeNF?KL!Fv2!@|A_I>rmkh1 zJU_xXXXC#X49L-^7&wjb#tB9`2MZxun6Kr*&~bY^JA=`WOU@p~F2)u{FB--wQI`dw zCBq&gaFIj;{9AHU#rcpV1-142I<^#HJ@*?bMr+s zbl3I(=GM!LYuIEizmZ>DU#q~r^0A*@SuT{9axH;EIalo1cM#sd-?eER_NONE THEN WriteF('There was an error.\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.e b/amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.e new file mode 100644 index 0000000..3dc99bc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.e @@ -0,0 +1,107 @@ +/* setf.e -- a SnoopDos-like program to monitor calls to OpenLibrary() */ + +OPT OSVERSION=37 + +MODULE 'dos/dos', 'exec/ports', 'exec/tasks', 'exec/nodes', 'exec/memory' + +CONST OFFSET=$fdd8 /* execbase offset of OpenLibrary() */ + +/* "mymsg" must begin with the standard message object "mn", followed by + any kind of data (in this case, two pointers [to strings]). +*/ +OBJECT mymsg + msg:mn + s, t +ENDOBJECT + +/* "port" will be used from the patched routine, too, so it's global */ +DEF port:PTR TO mp + +/* You can change the library function to be patched by changing OFFSET + and the "execbase" in the *two* calls to SetFunction(). If you want to + patch a library other than dos, exec, graphics and intuition you need + to OpenLibrary() it first. + (Note: some [old?] libraries cannot be patched in this way. Also, some + functions in some libraries can't be patched like this either! Even the + RKRM's aren't too clear about this...) +*/ +PROC main() + DEF ps, us, loop, sig, oldf + IF port:=CreateMsgPort() + Forbid() /* Don't let anyone mess things up... */ + IF oldf:=SetFunction(execbase, OFFSET, {newf}) + PutLong({patch}, oldf) + Permit() /* Now we can let everyone else back in */ + LEA store(PC), A0 + MOVE.L A4, (A0) /* Store the A4 register... */ + ps:=Shl(1,port.sigbit) /* Set up port and user signal bits */ + us:=SIGBREAKF_CTRL_C + loop:=TRUE + WHILE loop + sig:=Wait(ps OR us) + IF sig AND ps + printmsgs() + ENDIF + IF sig AND us + loop:=FALSE + ENDIF + ENDWHILE + Forbid() /* Paranoid... */ + SetFunction(execbase, OFFSET, oldf) + ENDIF + Permit() + printmsgs() /* Make sure the port is empty */ + DeleteMsgPort(port) + ENDIF +ENDPROC + +/* Nicely (?) print the messages out... */ +PROC printmsgs() + DEF msg:PTR TO mymsg + WHILE msg:=GetMsg(port) + WriteF('Task \l\s[25] wants \r\s[20]\n', + IF msg.t THEN msg.t ELSE '*unnamed*', + IF msg.s THEN msg.s ELSE '*unnamed library*') + ReplyMsg(msg) + DisposeLink(msg.s) + DisposeLink(msg.t) + Dispose(msg) + ENDWHILE +ENDPROC + +/* Send a message to the patching process */ +PROC sendmsg() + DEF m:PTR TO mymsg, s, tsk:tc, l:ln + MOVE.L A1, s + /* Allocate a new message */ + m:=New(SIZEOF mymsg) + IF s + m.s:=String(StrLen(s)) + StrCopy(m.s,s,ALL) + ENDIF + tsk:=FindTask(NIL) /* Find out who we are */ + m.t:=NIL + IF tsk + l:=tsk.ln + IF l AND l.name + m.t:=String(StrLen(l.name)) + StrCopy(m.t, l.name, ALL) + ENDIF + ENDIF + PutMsg(port, m) +ENDPROC + +/* Place to store A4 register */ +store: LONG 0 +/* Place to store real call */ +patch: LONG 0 + +/* The new routine which will replace the original library function */ +newf: + MOVEM.L D0-D7/A0-A6, -(A7) + LEA store(PC), A0 + MOVE.L (A0), A4 /* Reinstate the A4 register so we can use E code */ + sendmsg() + MOVEM.L (A7)+, D0-D7/A0-A6 + MOVE.L patch(PC), -(A7) + RTS diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.readme b/amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.readme new file mode 100644 index 0000000..e59d11e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/setf/setf.readme @@ -0,0 +1,18 @@ +Short: Running E code from other processes +Type: dev/e +Uploader: m88jrh@uk.ac.ox.ecs (Jason R. Hulance) +Author: m88jrh@uk.ac.ox.ecs (Jason R. Hulance) + +This archive contains a few E sources which use SetFunction() to patch some +library calls. They serve to show how to run E code from other processes. +The important point is that E uses the A4 register for its global variables +so this must be preserved. The examples show a running E program setting up +a storage place for a copy of A4, and then code from this program can be run +from another process (after first restoring A4). The "other process" is the +examples is the process which calls the patched system function. + +Code which does not use global variables is easier to deal with, since this +does not require restoration of A4. However, a lot of code implicitly uses +global variables, since things like library calls use the global library +base variables. Also, E built-in functions use a number of globals, e.g., +WriteF uses "stdout" and "conout". diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/showiff.e b/amigae33a/E_v3.3a/Src/Src/Pd/showiff.e new file mode 100644 index 0000000..d902bf4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/showiff.e @@ -0,0 +1,71 @@ +MODULE 'iff','libraries/iff','intuition/intuition','intuition/screens', + 'exec/memory' + +ENUM ER_NONE,ER_IFFLIB,ER_OPENIFF,ER_NOBMHD,ER_SCREEN,ER_WINDOW,ER_DECODE + +DEF iff=NIL,s=NIL,ct[256]:ARRAY OF INT,bmhd,w=NIL:PTR TO window, + quit=FALSE,msg:PTR TO intuimessage,sprite=NIL + +PROC main() HANDLE + /* Open library first */ + IF (iffbase:=OpenLibrary('iff.library',22))=NIL THEN Raise(ER_IFFLIB) + + /* arg = filename of IFF file */ + IF (iff:=IfFL_OpenIFF(arg,IFFL_MODE_READ))=NIL THEN Raise(ER_OPENIFF) + + /* BMHD = BitMap HeaDer (contains dimensions of picture) */ + IF (bmhd:=IfFL_GetBMHD(iff))=NIL THEN Raise(ER_NOBMHD) + + /* Open screen with correct dimensions */ + IF (s:=OpenScreenTagList(NIL, + [SA_WIDTH,Int(bmhd),SA_HEIGHT,Int(bmhd+2),SA_DEPTH,Char(bmhd+8), + SA_DISPLAYID,IfFL_GetViewModes(iff), + 0,0]))=NIL THEN Raise(ER_SCREEN) + + /* Open a full size dummy window */ + IF (w:=OpenWindowTagList(NIL, + [WA_LEFT,0,WA_TOP,0,WA_WIDTH,Int(bmhd),WA_HEIGHT,Int(bmhd+2), + WA_FLAGS,WFLG_SIMPLE_REFRESH OR WFLG_NOCAREREFRESH OR + WFLG_BORDERLESS OR WFLG_ACTIVATE, + WA_IDCMP,IDCMP_MOUSEBUTTONS OR IDCMP_RAWKEY, + WA_CUSTOMSCREEN,s, + NIL,NIL]))=NIL THEN Raise(ER_WINDOW) + + /* Blank the mouse pointer */ + IF sprite:=AllocMem(20,MEMF_CHIP OR MEMF_CLEAR) + SetPointer(w,sprite,1,16,0,0) + ENDIF + + /* Set the palette of the screen */ + LoadRGB4(s+44,ct,IfFL_GetColorTab(iff,ct)) + + /* Try to load the picture */ + IF (IfFL_DecodePic(iff,s+184))=FALSE THEN Raise(ER_DECODE) + + /* Wait for the user to press a mouse button */ + REPEAT + IF msg:=GetMsg(w.userport) + quit:=(msg.class AND (IDCMP_MOUSEBUTTONS OR IDCMP_RAWKEY)) + ELSE + quit:=(Wait(-1) AND Shl(1,12)) + ENDIF + UNTIL quit + + Raise(ER_NONE) +EXCEPT + /* Clean up */ + IF w THEN CloseWindow(w) + IF sprite THEN FreeMem(sprite,20) + IF s THEN CloseScreen(s) + IF iff THEN IfFL_CloseIFF(iff) + IF iffbase THEN CloseLibrary(iffbase) + + /* Display possible error message */ + IF exception>0 + WriteF('Error: \s.\n', + ListItem(['No IFF library','Could not open IFF file', + 'IFF File had no bitmap header','Could not open screen', + 'Could not open window','Could not decode picture'], + exception-1)) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread.e b/amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread.e new file mode 100644 index 0000000..be9d469 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread.e @@ -0,0 +1,44 @@ +-> thread.e - the very basic way to setup a thread under v37+ + +MODULE 'dos/dos' +MODULE 'dos/dostags' +MODULE 'dos/dosextens' +MODULE 'utility/tagitem' + +MODULE '*modules/geta4' + +PROC main() + -> pointer to the thread process + DEF mythread:PTR TO process + + -> store the global data pointer (a4) so the thread can later get this. + -> IMPORTANT: this must be done before any thread does a geta4(). + -> to be safe, just do it at the begin of main(), as done here. + storea4() + + -> create a thread process + IF mythread:=CreateNewProc( + [ + NP_ENTRY,{thread}, -> where the thread process begins + NP_NAME,'MyThread', -> the thread process name + TAG_DONE + ]) + + ENDIF + Delay(50) + + -> IMPORTANT: the main process may never end when threads are running. + -> In this small example, we simply wait a while, which is NOT RIGHT!! + Delay(50) + +ENDPROC + +PROC thread() + -> get the global data pointer, previously stored by the main process. + -> IMPORTANT: do this before using global variables or functioncalls. + geta4() + + PrintF('Hello, it\as me, your newly created thread.\n') + PrintF('I stopped now\n') + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread2.e b/amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread2.e new file mode 100644 index 0000000..a5ca182 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/threads/Thread2.e @@ -0,0 +1,93 @@ +-> thread2.e - a safer way to implement threads than thread.e + +MODULE 'dos/dos' +MODULE 'dos/dostags' +MODULE 'dos/dosextens' +MODULE 'utility/tagitem' + +MODULE 'exec/nodes' +MODULE 'exec/ports' +MODULE 'exec/memory' + +MODULE '*modules/geta4' + +PROC main() + -> message for interprocess communication + DEF message:PTR TO mn + -> port of main process + DEF port:PTR TO mp + -> pointer to the thread process + DEF mythread:PTR TO process + + storea4() + + -> port to talk with thread + IF port:=CreateMsgPort() + + -> allocate message + IF message:=AllocMem(SIZEOF mn,MEMF_CLEAR OR MEMF_PUBLIC) + + -> fill in message node + message::ln.type:=NT_MESSAGE + message.length:=SIZEOF mn + message.replyport:=port + + -> create a thread process + IF mythread:=CreateNewProc( + [ + NP_ENTRY,{thread}, -> where the thread process begins + NP_NAME,'MyThread', -> the thread process name + TAG_DONE + ]) + + -> send the thread a startup message + PutMsg(mythread.msgport,message) + + /* main program here */ + + -> wait for the threads' death + WaitPort(port) + + ENDIF + + FreeMem(message,SIZEOF mn) + ENDIF + DeleteMsgPort(port) + ENDIF +ENDPROC + +PROC thread() + -> pointer to this process + DEF thisthread:PTR TO process + -> pointer to the received message + DEF message:PTR TO mn + + -> get the global data pointer, previously stored by the main process. + -> IMPORTANT: do this before using global variables or functioncalls. + geta4() + + -> find out about ourselves + thisthread:=FindTask(0) + + -> wait for the startup message (sent by the main process) + WaitPort(thisthread.msgport) + + -> get the startup message + message:=GetMsg(thisthread.msgport) + + /* thread program begins here */ + + -> useless program, just waits a second + PrintF('Hello, I\am a newbie thread. It\as nice to be here.\n') + Delay(50) + + /* thread program ends here */ + + -> make sure there is no taskswitching after we replied the message + Forbid() + + -> reply to main process + ReplyMsg(message) + +-> thread dies here +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/threads/modules/geta4.e b/amigae33a/E_v3.3a/Src/Src/Pd/threads/modules/geta4.e new file mode 100644 index 0000000..cf7a3fa --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Pd/threads/modules/geta4.e @@ -0,0 +1,17 @@ +-> geta4.e - store and get the global data pointer kept in register A4 + +OPT MODULE + +EXPORT PROC storea4() + LEA a4storage(PC),A0 + MOVE.L A4,(A0) +ENDPROC + +EXPORT PROC geta4() + LEA a4storage(PC),A0 + MOVE.L (A0),A4 +ENDPROC + +a4storage: + LONG NIL + diff --git a/amigae33a/E_v3.3a/Src/Src/Pd/threads/modules/geta4.m b/amigae33a/E_v3.3a/Src/Src/Pd/threads/modules/geta4.m new file mode 100644 index 0000000000000000000000000000000000000000..38a69b29fb270e4548e9f8cb50c93273e71e5661 GIT binary patch literal 122 zcmZ?u^><-lWq^VS3Qz_om}Ul&oPMDU4357Tq!fAz82n=WN}+r%jQ|KAtdfO+Ej_g) d(FDX1U|0 THEN WriteF('Could not \s !\n', + ListItem(['','open "gadtools.library" v37','lock workbench', + 'get visual infos','create context','create gadget', + 'open window','allocate menus'],exception)) +ENDPROC + +PROC openinterface() + IF (gadtoolsbase:=OpenLibrary('gadtools.library',37))=NIL THEN + Raise(ER_OPENLIB) + IF (scr:=LockPubScreen('Workbench'))=NIL THEN Raise(ER_WB) + IF (visual:=GetVisualInfoA(scr,NIL))=NIL THEN Raise(ER_VISUAL) + offy:=scr.wbortop+Int(scr.rastport+58)+1 + IF (g:=CreateContext({glist}))=NIL THEN Raise(ER_CONTEXT) + IF (menu:=CreateMenusA([1,0,'Project',0,0,0,0, + 2,0,'Load','l',0,0,0, + 2,0,'Save','s',0,0,0, + 2,0,'Bla ->',0,0,0,0, + 3,0,'aaargh','a',0,0,0, + 3,0,'hmmm','h',0,0,0, + 2,0,'Quit','q',0,0,0, + 0,0,0,0,0,0,0]:newmenu,NIL))=NIL THEN Raise(ER_MENUS) + IF LayoutMenusA(menu,visual,NIL)=FALSE THEN Raise(ER_MENUS) + IF (g:=CreateGadgetA(SCROLLER_KIND,g, + [scr.wborleft+20,offy+9,155,22,NIL,NIL,1,0,visual,0]:newgadget, + [GTSC_TOP,2, + GTSC_VISIBLE,3, + GTSC_TOTAL,10, + GTSC_ARROWS,22, + PGA_FREEDOM,LORIENT_HORIZ, + GA_RELVERIFY,TRUE, + GA_IMMEDIATE,TRUE,0]))=NIL THEN Raise(ER_GADGET) + listv:=[0,0,0,0]; listv[0]:=listv+4; listv[2]:=listv + AddTail(listv,[0,0,0,0,'aaaargh']:ln) + AddTail(listv,[0,0,0,0,'hmmmm']:ln) + IF (g:=CreateGadgetA(LISTVIEW_KIND,g, + [scr.wborleft+20,offy+40,155,100,NIL,NIL,2,0,visual,0]:newgadget, + [GTLV_SCROLLWIDTH,20, + GTLV_LABELS,listv,0]))=NIL THEN Raise(ER_GADGET) + IF (wnd:=OpenW(10,15,200,offy+165,$304 OR SCROLLERIDCMP,$E, + 'E gadtools dEmO',NIL,1,glist))=NIL THEN Raise(ER_WINDOW) + IF SetMenuStrip(wnd,menu)=FALSE THEN Raise(ER_MENUS) + Gt_RefreshWindow(wnd,NIL) +ENDPROC + +PROC closeinterface() + IF wnd THEN ClearMenuStrip(wnd) + IF menu THEN FreeMenus(menu) + IF visual THEN FreeVisualInfo(visual) + IF wnd THEN CloseWindow(wnd) + IF glist THEN FreeGadgets(glist) + IF scr THEN UnlockPubScreen(NIL,scr) + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) +ENDPROC + +PROC wait4message() + DEF mes:PTR TO intuimessage,g:PTR TO gadget + REPEAT + type:=0 + IF mes:=Gt_GetIMsg(wnd.userport) + type:=mes.class + IF type=IDCMP_MENUPICK + infos:=mes.code + ELSEIF (type=IDCMP_GADGETDOWN) OR (type=IDCMP_GADGETUP) + g:=mes.iaddress + infos:=g.gadgetid + ELSEIF type=IDCMP_REFRESHWINDOW + Gt_BeginRefresh(wnd) + Gt_EndRefresh(wnd,TRUE) + type:=0 + ELSEIF type<>IDCMP_CLOSEWINDOW + type:=0 + ENDIF + Gt_ReplyIMsg(mes) + ELSE + Wait(-1) + ENDIF + UNTIL type +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Reqs/ReqDemo.e b/amigae33a/E_v3.3a/Src/Src/Reqs/ReqDemo.e new file mode 100644 index 0000000..e3996b7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Reqs/ReqDemo.e @@ -0,0 +1,20 @@ +/* Another demo how to use other librarys from E. + a requester from the req.library. */ + +MODULE 'Req' + +PROC main() + IF reqbase:=OpenLibrary('req.library',2) + IF request('This is some standard requester ...','Positive','Negative') + request('I guessed that ...','Sure!','Get Real!') + ELSE + request('Try to be more positive!','I will','Why should I?') + ENDIF + CloseLibrary(reqbase) + ELSE + WriteF('Could not open req.library!\n') + ENDIF +ENDPROC + +PROC request(messy,yes,no) +ENDPROC TextRequest([messy,0,0,0,yes,no,'Huh?',0,0,$2FFFF,0,0]) diff --git a/amigae33a/E_v3.3a/Src/Src/Reqs/ReqToolsDemo.e b/amigae33a/E_v3.3a/Src/Src/Reqs/ReqToolsDemo.e new file mode 100644 index 0000000..ece764f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Reqs/ReqToolsDemo.e @@ -0,0 +1,35 @@ +/* Yet another demo to use other librarys from E. + Now we do some requesters from the reqtools.library. */ + +MODULE 'ReqTools' + +CONST FILEREQ=0,REQINFO=1 + +DEF colour,num=10,buf[120]:STRING,req + +PROC main() + IF reqtoolsbase:=OpenLibrary('reqtools.library',37) + RtEZRequestA('Lets test that handy ReqTools library, shall we ?', + 'Why?|Not again!|Yes! lets see that!',0,0,0) + IF (colour:=RtPaletteRequestA('Pick your colour:',0,0))=-1 + RtEZRequestA('Hard to choose eh?','Damn right.',0,0,0) /* colreq */ + ELSE + RtEZRequestA('Did you really like colour \d ?','Nope|Zure!',0,[colour],0) + ENDIF + RtEZRequestA('Now for some input ...','What?',0,0,0) + RtGetLongA({num},'Enter a number:',0,0) /* longreq */ + StrCopy(buf,'bla',ALL) + RtGetStringA(buf,100,'Enter something:',0,0) /* stringreq */ + RtEZRequestA('Lets have that nice filerequester ...', + 'More!more!|Boring!',0,0,0) + IF req:=RtAllocRequestA(FILEREQ,0) + buf[0]:=0 + RtFileRequestA(req,buf,'Pick your file:',0) + RtFreeRequest(req) + ENDIF + RtEZRequestA('That\as it.','Phew.',0,0,0) + CloseLibrary(reqtoolsbase) + ELSE + WriteF('Could not open reqtools.library!\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filehook.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filehook.e new file mode 100644 index 0000000..100e6a8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filehook.e @@ -0,0 +1,98 @@ +-> filehook.e + +OPT PREPROCESS + +-> E-Note: eCodeASLHook() sets up an E PROC for use as an ASL hook function +-> (i.e., you can use globals and not worry about trashing registers). +MODULE 'asl', + 'other/ecode', + 'dos/dos', + 'dos/dosasl', + 'intuition/intuition', + 'libraries/asl', + 'utility/hooks' + +ENUM ERR_NONE, ERR_AFILE, ERR_ECODE, ERR_KICK, ERR_LIB, ERR_WIN + +RAISE ERR_AFILE IF AllocFileRequest()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST DESTPATLENGTH=20 + +DEF window=NIL, sourcepattern, pat[DESTPATLENGTH]:ARRAY + +PROC main() HANDLE + DEF fr=NIL:PTR TO filerequester, myFunc + + -> This is the pattern matching string that the hook function uses + sourcepattern:='(#?.info)' + + KickVersion(37) -> E-Note: requires V37 + + aslbase:=OpenLibrary('asl.library', 37) + + -> This is a V37 dos.library function that turns a pattern matching string + -> into something the DOS pattern matching functions can understand. + ParsePattern(sourcepattern, pat, DESTPATLENGTH) + + -> Open a window that gets ACTIVEWINDOW events + window:=OpenWindowTagList(NIL, [WA_TITLE, 'ASL Hook Function Example', + WA_IDCMP, IDCMP_ACTIVEWINDOW, + WA_FLAGS, WFLG_DEPTHGADGET, + NIL]) + + fr:=AllocFileRequest() + -> E-Note: eCodeASLHook() sets up an E PROC for use as an ASL hook function + IF NIL=(myFunc:=eCodeASLHook({hookFunc})) THEN Raise(ERR_ECODE) + IF AslRequest(fr, [ASL_DIR, 'SYS:Utilities', + ASL_WINDOW, window, + ASL_TOPEDGE, 0, + ASL_HEIGHT, 200, + ASL_HAIL, 'Pick an icon, select save', + -> E-Note: use the value returned from aslhook() + ASL_HOOKFUNC, myFunc, + ASL_FUNCFLAGS, FILF_DOWILDFUNC OR FILF_DOMSGFUNC OR + FILF_SAVE, + ASL_OKTEXT, 'Save', + NIL]) + WriteF('PATH=\s FILE=\s\n', fr.drawer, fr.file) + WriteF('To combine the path and filename, copy the path\n') + WriteF('to a buffer, add the filename with Dos AddPart().\n') + ENDIF +EXCEPT DO + IF fr THEN FreeFileRequest(fr) + IF window THEN CloseWindow(window) + IF aslbase THEN CloseLibrary(aslbase) + SELECT exception + CASE ERR_AFILE; WriteF('Error: Could not allocate file request\n') + CASE ERR_ECODE; WriteF('Error: Ran out of memory in eCodeASLHook()\n') + CASE ERR_KICK; WriteF('Error: Requires V37\n') + CASE ERR_LIB; WriteF('Error: Could not open ASL library\n') + CASE ERR_WIN; WriteF('Error: Could not open window\n') + ENDSELECT +ENDPROC + +PROC hookFunc(type, obj:PTR TO anchorpath, fr) + DEF returnvalue + SELECT type + CASE FILF_DOMSGFUNC + -> We got a message meant for the window + WriteF('You activated the window\n') + RETURN obj + CASE FILF_DOWILDFUNC + -> We got an AnchorPath structure, should the requester display this file? + + -> MatchPattern() is a dos.library function that compares a matching + -> pattern (parsed by the ParsePattern() DOS function) to a string and + -> returns TRUE if they match. + returnvalue:=MatchPattern(pat, obj.info.filename) + + -> We have to negate MatchPattern()'s return value because the file + -> requester expects a zero for a match not a TRUE value + RETURN returnvalue=FALSE + ENDSELECT +ENDPROC + +vers: CHAR 0, '$VER: filehook 37.0', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filepat.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filepat.e new file mode 100644 index 0000000..5f63319 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filepat.e @@ -0,0 +1,82 @@ +-> filepat.e + +MODULE 'asl', + 'intuition/intuition', + 'intuition/screens', + 'graphics/modeid', + 'libraries/asl', + 'workbench/startup' + +ENUM ERR_NONE, ERR_ASL, ERR_KICK, ERR_LIB, ERR_SCRN, ERR_WIN + +RAISE ERR_ASL IF AllocAslRequest()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +DEF screen=NIL, window=NIL + +PROC main() HANDLE + DEF fr=NIL:PTR TO filerequester, frargs:PTR TO wbarg, x + KickVersion(37) -> E-Note: requires V37 + aslbase:=OpenLibrary('asl.library',37) + screen:=OpenScreenTagList(NIL, [SA_DISPLAYID, HIRESLACE_KEY, + SA_TITLE, 'ASL Test Screen', + NIL]) + window:=OpenWindowTagList(NIL, + [WA_CUSTOMSCREEN, screen, + WA_TITLE, 'Demo Customscreen, File Pattern, Multi-select', + -> E-Note: C version uses obsolete tags + WA_FLAGS, WFLG_DEPTHGADGET OR WFLG_DRAGBAR, + NIL]) + fr:=AllocAslRequest(ASL_FILEREQUEST, + [ASL_HAIL, 'FilePat/MultiSelect Demo', + ASL_DIR, 'libs:', + ASL_FILE, 'asl.library', + + -> Initial pattern string for pattern matching + ASL_PATTERN, '~(rexx#?|math#?)', + + -> Enable multiselection and pattern match gadget + ASL_FUNCFLAGS, FILF_MULTISELECT OR FILF_PATGAD, + + -> This requester comes up on the screen of this window + -> (and uses window's message port, if any). + ASL_WINDOW, window, + NIL]) + + -> Put up file requester + IF AslRequest(fr, 0) + -> If the file requester's numargs field is not zero, the user + -> multiselected. The number of files is stored in numargs. + IF fr.numargs + -> arglist is an array of wbarg objects (see 'workbench/startup.m'). + -> Each entry in this array corresponds to one of the files the user + -> selected (in alphabetical order). + frargs:=fr.arglist + + -> The user multiselected, step through the list of selected files. + FOR x:=0 TO fr.numargs-1 + WriteF('Argument \d: PATH=\s FILE=\s\n', x, fr.drawer, frargs[x].name) + ENDFOR + ELSE + -> The user didn't multiselect, use the normal way to get the file name. + WriteF('PATH=\s FILE=\s\n', fr.drawer, fr.file) + ENDIF + ENDIF +EXCEPT DO + IF fr THEN FreeAslRequest(fr) + IF window THEN CloseWindow(window) + IF screen THEN CloseScreen(screen) + IF aslbase THEN CloseLibrary(aslbase) + SELECT exception + CASE ERR_ASL; WriteF('Error: Could not allocate ASL request\n') + CASE ERR_KICK; WriteF('Error: Requires V37\n') + CASE ERR_LIB; WriteF('Error: Could not open ASL library\n') + CASE ERR_SCRN; WriteF('Error: Could not open screen\n') + CASE ERR_WIN; WriteF('Error: Could not open window\n') + ENDSELECT +ENDPROC + +vers: CHAR 0, '$VER: filepat 37.0', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filereq.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filereq.e new file mode 100644 index 0000000..edb71f5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/filereq.e @@ -0,0 +1,47 @@ +-> filereq.e + +MODULE 'asl', + 'libraries/asl' + +ENUM ERR_NONE, ERR_ASL, ERR_KICK, ERR_LIB + +RAISE ERR_ASL IF AllocAslRequest()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL + +CONST MYLEFTEDGE=0, MYTOPEDGE=0, MYWIDTH=320, MYHEIGHT=400 + +PROC main() HANDLE + DEF fr:PTR TO filerequester + KickVersion(37) -> E-Note: requires V37 + aslbase:=OpenLibrary('asl.library',37) + fr:=AllocAslRequest(ASL_FILEREQUEST, + [ASL_HAIL, 'The RKM file requester', + ASL_HEIGHT, MYHEIGHT, + ASL_WIDTH, MYWIDTH, + ASL_LEFTEDGE, MYLEFTEDGE, + ASL_TOPEDGE, MYTOPEDGE, + ASL_OKTEXT, 'O KAY', + ASL_CANCELTEXT, 'not OK', + ASL_FILE, 'asl.library', + ASL_DIR, 'libs:', + NIL]) + IF AslRequest(fr, NIL) + WriteF('PATH=\s FILE=\s\n', fr.drawer, fr.file) + WriteF('To combine the path and filename, copy the path\n') + WriteF('to a buffer, add the filename with Dos AddPart().\n') + ELSE + -> E-Note: C version gets this wrong! + WriteF('User Cancelled\n') + ENDIF +EXCEPT DO + IF fr THEN FreeAslRequest(fr) + IF aslbase THEN CloseLibrary(aslbase) + SELECT exception + CASE ERR_ASL; WriteF('Error: Could not allocate ASL request\n') + CASE ERR_KICK; WriteF('Error: Requires V37\n') + CASE ERR_LIB; WriteF('Error: Could not open ASL library\n') + ENDSELECT +ENDPROC + +vers: CHAR 0, '$VER: filereq 37.0', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/fontreq.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/fontreq.e new file mode 100644 index 0000000..460c5bb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/ASL/fontreq.e @@ -0,0 +1,61 @@ +-> fontreq.e + +MODULE 'asl', + 'graphics/text', + 'libraries/asl' + +ENUM ERR_NONE, ERR_ASL, ERR_KICK, ERR_LIB + +RAISE ERR_ASL IF AllocAslRequest()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL + +PROC main() HANDLE + DEF fr=NIL:PTR TO fontrequester + KickVersion(37) -> E-Note: requires V37 + aslbase:=OpenLibrary('asl.library', 37) + fr:=AllocAslRequest(ASL_FONTREQUEST, + -> Tell the requester to use my custom mode names: + -> Our replacement strings for the "mode" cycle gadget. The first + -> string is the cycle gadget's label. The other strings are the + -> actual strings that will appear on the cycle gadget. + [ASL_MODELIST, ['RKM Modes', 'Mode 0', 'Mode 1', 'Mode 2', + 'Mode 3', 'Mode 4',NIL], + -> Supply initial values for requester + ASL_FONTNAME, 'topaz.font', + ASL_FONTHEIGHT, 11, + ASL_FONTSTYLES, FSF_BOLD OR FSF_ITALIC, + ASL_FRONTPEN, 0, + ASL_BACKPEN, 1, + + -> Only display font sizes between 8 and 14, inclusive. + ASL_MINHEIGHT, 8, + ASL_MAXHEIGHT, 14, + + -> Give all the gadgetry, but only display fixed width fonts + ASL_FUNCFLAGS, FONF_FRONTCOLOR OR FONF_BACKCOLOR OR + FONF_DRAWMODE OR FONF_STYLES OR FONF_FIXEDWIDTH, + NIL]) + -> Pop up the requester + IF AslRequest(fr, NIL) + -> The user selected something, report their choice + WriteF('\s\n YSize = \d Style = $\h Flags = $\h\n'+ + ' FPen = $\h BPen = $\h DrawMode = $\h\n', + fr.attr.name, fr.attr.ysize, fr.attr.style, fr.attr.flags, + fr.frontpen, fr.backpen, fr.drawmode) + ELSE + -> The user cancelled the requester, or some kind of error occurred + -> preventing the requester from opening. + WriteF('Request Cancelled\n') + ENDIF +EXCEPT DO + IF fr THEN FreeAslRequest(fr) + IF aslbase THEN CloseLibrary(aslbase) + SELECT exception + CASE ERR_ASL; WriteF('Error: Could not allocate ASL request\n') + CASE ERR_KICK; WriteF('Error: Requires V37\n') + CASE ERR_LIB; WriteF('Error: Could not open ASL library\n') + ENDSELECT +ENDPROC + +vers: CHAR 0, '$VER: fontreq 37.0', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.e new file mode 100644 index 0000000..ec2b238 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.e @@ -0,0 +1,309 @@ +-> Cbio.e +-> +-> Provide standard clipboard device interface routines +-> such as Open, Close, Post, Read, Write, etc. +-> +-> NOTES: These functions are useful for writing and reading simple FTXT. +-> Writing and reading complex FTXT, ILBM, etc., requires more work. You +-> should use the iffparse.library to write and read FTXT, ILBM and other IFF +-> file types. When this code is used with older versions of the Amiga OS +-> (i.e., before V36) a memory loss of 536 bytes will occur due to bugs in the +-> clipboard device. + +->>> Header (globals) +OPT MODULE + +MODULE 'devices/clipboard', + 'exec/io', + 'exec/memory', + 'exec/ports', + 'amigalib/ports', + 'amigalib/io' + +ENUM ERR_NONE, ERR_DERR, ERR_DEV, ERR_DLEN, ERR_DOIO, ERR_IO, ERR_PORT + +RAISE ERR_DEV IF OpenDevice()<>0, + ERR_DOIO IF DoIO()<>0 + +-> E-Note: don't need size field since using NewM()/Dispose() +EXPORT OBJECT cbbuf + count -> Number of characters after stripping + mem +ENDOBJECT + +EXPORT CONST ID_FORM="FORM", ID_FTXT="FTXT", ID_CHRS="CHRS" +->>> + +->>> EXPORT PROC cbOpen(unit) +-> +-> FUNCTION +-> Opens the clipboard.device. A clipboard unit number must be passed in +-> as an argument. By default, the unit number should be 0 (currently +-> valid unit numbers are 0-255). +-> +-> RESULTS +-> A pointer to an initialised IOClipReq structure. An exception is +-> raised if the function fails ("CBOP") +EXPORT PROC cbOpen(unit) HANDLE + DEF mp=NIL, ior=NIL + IF NIL=(mp:=createPort(0,0)) THEN Raise(ERR_PORT) + IF NIL=(ior:=createExtIO(mp, SIZEOF ioclipreq)) THEN Raise(ERR_IO) + OpenDevice('clipboard.device', unit, ior, 0) +EXCEPT + IF ior THEN deleteExtIO(ior) + IF mp THEN deletePort(mp) + Raise("CBOP") +ENDPROC ior +->>> + +->>> EXPORT PROC cbClose(ior:PTR TO ioclipreq) +-> +-> FUNCTION +-> Close the clipboard.device unit which was opened via cbOpen(). +-> +EXPORT PROC cbClose(ior:PTR TO ioclipreq) + DEF mp + mp:=ior.message.replyport + CloseDevice(ior) + deleteExtIO(ior) + deletePort(mp) +ENDPROC +->>> + +->>> EXPORT PROC cbWriteFTXT(ior:PTR TO ioclipreq, string) +-> +-> FUNCTION +-> Write a NIL terminated string of text to the clipboard. The string +-> will be written in simple FTXT format. +-> +-> Note that this function pads odd length strings automatically to +-> conform to the IFF standard. +-> +-> RESULTS +-> If the write did not succeed an exception is raised ("CBWR") +-> +EXPORT PROC cbWriteFTXT(ior:PTR TO ioclipreq, string) HANDLE + DEF length, slen, odd + slen:=StrLen(string) + odd:=Odd(slen) -> Pad byte flag + length:=IF odd THEN slen+1 ELSE slen + + -> Initial set-up for offset, error, and clipid + ior.offset:=0 + ior.error:=0 + ior.clipid:=0 + + -> Create the IFF header information + writeLong(ior, 'FORM') -> 'FORM' + length:=length+12 -> + length '[size]FTXTCHRS' + writeLong(ior, {length}) -> Total length + writeLong(ior, 'FTXT') -> 'FTXT' + writeLong(ior, 'CHRS') -> 'CHRS' + writeLong(ior, {slen}) -> String length + + -> Write string + ior.data:=string + ior.length:=slen + ior.command:=CMD_WRITE + DoIO(ior) + + -> Pad if needed + IF odd + ior.data:='' + ior.length:=1 + DoIO(ior) + ENDIF + + -> Tell the clipboard we are done writing + ior.command:=CMD_UPDATE + DoIO(ior) + -> Check if error was set by any of the preceding IO requests + IF ior.error THEN Raise(ERR_DERR) +EXCEPT + Raise("CBWR") +ENDPROC +->>> + +->>> PROC writeLong(ior:PTR TO ioclipreq, ldata) +PROC writeLong(ior:PTR TO ioclipreq, ldata) + ior.data:=ldata + ior.length:=4 + ior.command:=CMD_WRITE + DoIO(ior) + IF ior.actual<>4 THEN Raise(ERR_DLEN) +ENDPROC +->>> + +->>> EXPORT PROC cbQueryFTXT(ior:PTR TO ioclipreq) +-> +-> FUNCTION +-> Check to see if the clipboard contains FTXT. If so, call cbReadCHRS() +-> one or more times until all CHRS chunks have been read. +-> +-> RESULTS +-> TRUE if the clipboard contains an FTXT chunk, else FALSE. +-> +-> NOTES +-> If this function returns TRUE, you must either call cbReadCHRS() until +-> cbReadCHRS() returns FALSE, or call cbReadDone() to tell the +-> clipboard.device that you are done reading. +-> +EXPORT PROC cbQueryFTXT(ior:PTR TO ioclipreq) HANDLE + DEF cbuff[4]:ARRAY OF LONG + + -> Initial set-up for offset, error, and clipid + ior.offset:=0 + ior.error:=0 + ior.clipid:=0 + + -> Look for 'FORM[size]FTXT' + ior.command:=CMD_READ + ior.data:=cbuff + ior.length:=12 + + DoIO(ior) + + -> Check to see if we have at least 12 bytes + IF ior.actual<>12 THEN Raise(ERR_DERR) + -> Check to see if it starts with 'FORM' + IF cbuff[]<>ID_FORM THEN Raise(ERR_DERR) + -> Check to see if it is 'FTXT' + IF cbuff[2]<>ID_FTXT THEN Raise(ERR_DERR) + -> E-Note: all checks passed... + RETURN TRUE +EXCEPT + -> It's not 'FORM[size]FTXT', so tell clipboard we are done + cbReadDone(ior) +ENDPROC FALSE +->>> + +->>> EXPORT PROC cbReadCHRS(ior:PTR TO ioclipreq) +-> +-> FUNCTION +-> Reads and returns the text in the next CHRS chunk (if any) from the +-> clipboard. +-> +-> Allocates memory to hold data in next CHRS chunk. +-> +-> RESULTS +-> Pointer to a cbbuf object, or NIL if no more CHRS chunks. An +-> exception ("CBRD") is raised if failure (e.g., not enough memory). +-> +-> ***Important*** +-> +-> The caller must free the returned buffer when done with the +-> data by calling cbFreeBuf(). +-> +-> NOTES +-> This function strips NIL bytes, however, a full reader may wish to +-> perform more complete checking to verify that the text conforms to the +-> IFF standard (stripping data as required). +-> +EXPORT PROC cbReadCHRS(ior:PTR TO ioclipreq) HANDLE + DEF chunk, size, gotchunk + -> Find next CHRS chunk + -> E-Note: loop until exception from reading or found non-empty CHRS chunk + LOOP + gotchunk:=FALSE + readLong(ior, {chunk}) + gotchunk:=TRUE + -> Is CHRS chunk? + IF chunk=ID_CHRS + -> Get size of chunk, and copy data + readLong(ior, {size}) + -> E-Note: C version is wrong, should keep looping if empty CHRS chunk + IF size THEN RETURN fillCBData(ior, size) + ELSE + -> If not, skip to next chunk + readLong(ior, {size}) + IF Odd(size) THEN INC size -> If odd size, add pad byte + ior.offset:=ior.offset+size + ENDIF + ENDLOOP +EXCEPT + cbReadDone(ior) -> Tell clipboard we are done + -> E-Note: pass on exception if there are chunks left + IF gotchunk THEN Raise("CBRD") +ENDPROC NIL +->>> + +->>> PROC readLong(ior:PTR TO ioclipreq, ldata) +PROC readLong(ior:PTR TO ioclipreq, ldata) + ior.command:=CMD_READ + ior.data:=ldata + ior.length:=4 + DoIO(ior) + IF ior.actual<>4 THEN Raise(ERR_DLEN) + IF ior.error THEN Raise(ERR_DERR) +ENDPROC +->>> + +->>> PROC fillCBData(ior:PTR TO ioclipreq, size) +PROC fillCBData(ior:PTR TO ioclipreq, size) HANDLE + DEF to, from, x, count, length, buf=NIL:PTR TO cbbuf + -> E-Note: clear mem to make sure buf.mem is NIL if NewM() succeeds + buf:=NewM(SIZEOF cbbuf, MEMF_PUBLIC OR MEMF_CLEAR) + length:=size + IF Odd(size) THEN INC length -> If odd size, read 1 more + buf.mem:=NewM(length+1, MEMF_PUBLIC) + + ior.command:=CMD_READ + ior.data:=buf.mem + ior.length:=length + + to:=buf.mem + count:=0 + + DoIO(ior) + IF ior.actual<>length THEN Raise(ERR_DLEN) + + -> Strip NIL bytes + from:=buf.mem + FOR x:=0 TO size-1 + IF from[] + to[]:=from[] + to++ + INC count + ENDIF + from++ + ENDFOR + to[]:=NIL -> NIL terminate buffer + buf.count:=count -> Cache count of chars in buf +EXCEPT + IF buf + IF buf.mem THEN Dispose(buf.mem) + Dispose(buf) + ENDIF + ReThrow() +ENDPROC buf +->>> + +->>> EXPORT PROC cbReadDone(ior:PTR TO ioclipreq) +-> +-> FUNCTION +-> Reads past end of clipboard file until actual is equal to 0. +-> This is tells the clipboard that we are done reading. +-> +EXPORT PROC cbReadDone(ior:PTR TO ioclipreq) HANDLE + DEF buffer[256]:ARRAY + ior.command:=CMD_READ + ior.data:=buffer + ior.length:=254 + -> Falls through immediately if actual=0 + WHILE ior.actual DO DoIO(ior) +EXCEPT + -> E-Note: ignore exceptions from DoIO() +ENDPROC +->>> + +->>> EXPORT PROC cbFreeBuf(buf:PTR TO cbbuf) +-> +-> FUNCTION +-> Frees a buffer allocated by cbReadCHRS(). +-> +EXPORT PROC cbFreeBuf(buf:PTR TO cbbuf) + Dispose(buf.mem) + Dispose(buf) +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.m b/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/cbio.m new file mode 100644 index 0000000000000000000000000000000000000000..e893439202a3cf90ea75d1674f1585d9e90e7ba3 GIT binary patch literal 2948 zcma)8O=ufe5T0GFrOla>tmXbpcIfUj?8XuBa2T_C(e*Na{pDfwIG9$g6+4=uw zo-Z$C(=w9nmc@(k;eFB-r8mV!3*`W6iXmk!}41^jp zd-^4Fob-4_bZV3=izk_1_R}9at43-P4psNf(IrH;gs7Ip)-utQIW9V@@D5*{z>fxQ z+vB!FZfbIFHoF*lWZi4esGa#V)5zRJcFz?uE2PgnHWPGmg5o%PaZIHUS(l~3@N5%o zIIa!R;;QynQu*1hq-Q5W39b?<*zqEdP}<|Pz32^&FXtf3D4+0d%jWou)6+s4dZbT_5vNtx#kL9Z2cP(6dSrTnF6nR<%w##w&D(|IIyPIYm9k{mVQyc8W* zk6yW!Vcm@-!O?l=Gj@be?@iM?sGi|f?_$tJ&8tW0kS0in{KoAY{c>CMRNd@(KFPC@r^p@P3;W|)2NjEj^Lf;4(H~)Dcq6fu znE>VVl+kJnmhdzf&fI+NI`-A9_nwdHZ5P#Yo5WehbBQT2ncowsv)r#==l2fIvP51q z_dreuS2p?BJEIfHWfF@$cF(#MP;bMQzr!RpbLnoxgf$_O{g(4~I7(kPNsQ^B--lq6 z0dp0 zsqTa;e0zqQ*0rb|%*sQC%*sU_@emX58RBI`#d66mRP(i!i52UMQqe+`M1!Ey4(Sg; zo1n5oga3k_g8l@Z2Ms$E{T1{h$N^1)-UX=+4Qzw%I;25Qy9Sy74LKC~26PVuU9}DR z8w4BbR}LxPgJ6gDL61P+g6@z;MzN5y@+&fIBGMl69EcVlOVt|g=VIZbhE@Agri6de zzLWA!xBOPERJT02@-gJ9)Hk4?T(8$kYXAwIC>E~NENixb4M+M9Yy}5+DKN*2B3)gR z6&n1n$BSMpWNm9rYT(~TMA*hT+E^>q@eAo(xw_7(%1~&T;}?Qdu#*(UiHZg3EsDIU zSZ%DaGS2v`SQS3Q7KkHDlFl``nqG2CqjQ3Ia`V)=x%|XE#^(*tCJkGa>Pn+*tzXJl zN~`&DsgNpFC)lux3~N@tZe8A}U(NC}`>>h6VwJ6ckJ`cgMaZ6j-tM<&S8MfkHW^r4 V1V?&ci&LRRkMCMcL-q=U&;NorVx|B9 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/changehook_test.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/changehook_test.e new file mode 100644 index 0000000..0767cdc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/changehook_test.e @@ -0,0 +1,101 @@ +-> Changehook_Test.e +-> +-> Demonstrate the use of CBD_CHANGEHOOK command. The program will set a hook +-> and wait for the clipboard data to change. You must put something in the +-> clipboard in order for it to return. +-> +-> Requires Kickstart 36 or greater. + +->>> Header (globals) +MODULE '*cbio', + 'tools/inithook', + 'devices/clipboard', + 'dos/dos', + 'utility/hooks' + +DEF version=1 + +-> Data to pass around with the clipHook +OBJECT chData + task + clipID +ENDOBJECT + +-> E-Note: clip_port is not actually used... +DEF hook:hook, ch:chData +->>> + +->>> PROC clipHook(h:PTR TO hook, o, msg:PTR TO cliphookmsg) +PROC clipHook(h:PTR TO hook, o, msg:PTR TO cliphookmsg) + DEF ch:PTR TO chData + ch:=h.data + IF ch + -> Remember the ID of clip + ch.clipID:=msg.clipid + + -> Signal the task that started the hook + Signal(ch.task, SIGBREAKF_CTRL_E) + ENDIF +ENDPROC +->>> + +->>> PROC openCB(unit) +PROC openCB(unit) + DEF clipIO:PTR TO ioclipreq + -> Open clipboard + -> E-Note: the C version opens 0 instead of using the parameter! + clipIO:=cbOpen(unit) + -> Fill out the IORequest + clipIO.data:=hook + clipIO.length:=1 + clipIO.command:=CBD_CHANGEHOOK + + -> Set up the hook data + ch.task:=FindTask(NIL) + + -> Prepare the hook + inithook(hook, {clipHook}, ch) + + -> Start the hook + WriteF(IF DoIO(clipIO) THEN 'Unable to set hook\n' ELSE 'Hook set\n') +ENDPROC clipIO +->>> + +->>> PROC closeCB(clipIO:PTR TO ioclipreq) +PROC closeCB(clipIO:PTR TO ioclipreq) + -> Fill out the IO request + clipIO.data:=hook + clipIO.length:=0 + clipIO.command:=CBD_CHANGEHOOK + + -> Stop the hook + WriteF(IF DoIO(clipIO) THEN 'Unable to stop hook\n' ELSE 'Hook is stopped\n') + + cbClose(clipIO) +ENDPROC +->>> + +->>> PROC main() +PROC main() HANDLE + DEF clipIO=NIL, sig_rcvd + WriteF('Test v\d\n', version) + + clipIO:=openCB(0) + + sig_rcvd:=Wait(SIGBREAKF_CTRL_C OR SIGBREAKF_CTRL_E) + + IF sig_rcvd AND SIGBREAKF_CTRL_C + WriteF('^C received\n') + ENDIF + + IF sig_rcvd AND SIGBREAKF_CTRL_E + WriteF('Clipboard change, current ID is \d\n', ch.clipID) + ENDIF +EXCEPT DO + IF clipIO THEN closeCB(clipIO) + SELECT exception + CASE "CBOP"; WriteF('Error: could not open clipboard device\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/clipdemo.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/clipdemo.e new file mode 100644 index 0000000..b60a338 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Clipboard/clipdemo.e @@ -0,0 +1,218 @@ +-> Clipdemo.e +-> +-> Demonstrate use of clipboard I/O. Uses general functions provided in the +-> module cbio. Important note: when this code is run with older versions of +-> the Amiga OS (i.e., before V36) a memory loss of 536 bytes will occur due +-> to bugs in the clipboard device. + +->>> Header (globals) +MODULE '*cbio', + 'devices/clipboard', + 'dos/dos', + 'exec/ports', + 'amigalib/ports', + 'other/split' + +ENUM ERR_NONE, ERR_ARGS, ERR_PORT + +ENUM FORGETIT, READIT, WRITEIT, POSTIT +->>> + +->>> PROC main() +PROC main() HANDLE + DEF todo, string, arglist:PTR TO LONG + todo:=FORGETIT + -> Very simple code to parse for arguments - will suffice for the sake of + -> this example + -> E-Note: use argSplit() to get arguments + IF NIL=(arglist:=argSplit()) THEN Raise(ERR_ARGS) + IF ListLen(arglist)>0 + IF StrCmp(arglist[], '-r') + todo:=READIT + ELSEIF StrCmp(arglist[], '-w') + todo:=WRITEIT + ELSEIF StrCmp(arglist[], '-p') + todo:=POSTIT + ENDIF + + string:=NIL + + IF ListLen(arglist)>1 THEN string:=arglist[1] + ENDIF + + SELECT todo + CASE READIT + readClip() + CASE POSTIT + postClip(string) + CASE WRITEIT + writeClip(string) + DEFAULT + WriteF('\nPossible switches are:\n\n'+ +'-r Read, and output contents of clipboard.\n\n'+ +'-w [string] Write string to clipboard.\n\n'+ +'-p [string] Write string to clipboard using the clipboard POST mechanism.\n\n'+ +' The Post can be satisfied by reading data from\n'+ +' the clipboard. Note that the message may never\n'+ +' be received if some other application posts, or\n') + WriteF( +' performs an immediate write to the clipboard.\n\n'+ +' To run this test you must run two copies of this example.\n'+ +' Use the -p switch with one to post data, and the -r switch\n'+ +' with another to read the data.\n\n'+ +' The process can be stopped by using the BREAK command,\n'+ +' in which case this example checks the CLIP write ID\n'+ +' to determine if it should write to the clipboard before\n'+ +' exiting.\n\n') + ENDSELECT +EXCEPT DO + SELECT exception + CASE ERR_ARGS; WriteF('Error: could not split arguments\n') + ENDSELECT +ENDPROC +->>> + +->>> PROC readClip() +-> Read, and output FTXT in the clipboard. +PROC readClip() HANDLE + DEF ior=NIL, buf:PTR TO cbbuf + -> Open clipboard.device unit 0 + ior:=cbOpen(0) + -> Look for FTXT in clipboard + IF cbQueryFTXT(ior) + -> Obtain a copy of the contents of each CHRS chunk + WHILE buf:=cbReadCHRS(ior) + -> Process data + WriteF('\s\n', buf.mem) + -> Free buffer allocated by cbReadCHRS() + cbFreeBuf(buf) + ENDWHILE + + -> The next call is not really needed if you are sure you read to the end of + -> the clip. + cbReadDone(ior) + ELSE + WriteF('No FTXT in clipboard\n') + ENDIF +EXCEPT DO + IF ior THEN cbClose(ior) + SELECT exception + CASE "CBOP"; WriteF('Error opening clipboard unit 0\n') + CASE "CBRD"; WriteF('Error reading from clipboard\n') + ENDSELECT + ReThrow() +ENDPROC +->>> + +->>> PROC writeClip(string) +-> Write a string to the clipboard +PROC writeClip(string) HANDLE + DEF ior=NIL:PTR TO ioclipreq + IF string=NIL + WriteF('No string argument given\n') + RETURN + ENDIF + + -> Open clipboard.device unit 0 + ior:=cbOpen(0) + cbWriteFTXT(ior, string) +EXCEPT DO + IF ior THEN cbClose(ior) + SELECT exception + CASE "CBWR"; WriteF('Error writing to clipboard: error = \d\n', ior.error) + CASE "CBOP"; WriteF('Error opening clipboard.device\n') + ENDSELECT + ReThrow() +ENDPROC +->>> + +->>> PROC postClip(string) +-> Write a string to the clipboard using the POST mechanism +-> +-> The POST mechanism can be used by applications which want to defer writing +-> text to the clipboard until another application needs it (by attempting to +-> read it via CMD_READ). However note that you still need to keep a copy of +-> the data until you receive a SatisfyMsg from the clipboard.device, or your +-> program exits. +-> +-> In most cases it is easier to write the data immediately. +-> +-> If your program receives the SatisfyMsg from the clipboard.device, you MUST +-> write some data. This is also how you reply to the message. +-> +-> If your program wants to exit before it has received the satisfymsg, you +-> must check the clipid field at the time of the post against the current +-> post ID which is obtained by sending the CBD_CURRENTWRITEID command. +-> +-> If the value in clipid (returned by CBD_CURRENTWRITEID) is greater than +-> your post ID, it means that some other application has performed a post, or +-> immediate write after your post, and that you're application will never +-> receive the satisfymsg. +-> +-> If the value in clipid (returned by CBD_CURRENTWRITEID) is equal to your +-> post ID, then you must write your data, and send CMD_UPDATE before exiting. +PROC postClip(string) HANDLE + DEF satisfy=NIL:PTR TO mp, sm:PTR TO satisfymsg, ior=NIL:PTR TO ioclipreq, + mustwrite, postID + IF string=NIL + WriteF('No string argument given\n') + RETURN + ENDIF + + IF NIL=(satisfy:=createPort(0, 0)) THEN Raise(ERR_PORT) + -> Open clipboard.device unit 0 + ior:=cbOpen(0) + mustwrite:=FALSE + + -> Notify clipboard we have data + ior.data:=satisfy + ior.clipid:=0 + ior.command:=CBD_POST + DoIO(ior) + + postID:=ior.clipid + + WriteF('\nClipID = \d\n', postID) + + -> Wait for CTRL-C break, or message from clipboard + Wait(SIGBREAKF_CTRL_C OR Shl(1, satisfy.sigbit)) + + -> See if we got a message, or a break + WriteF('Woke up\n') + + IF sm:=GetMsg(satisfy) + WriteF('Got a message from the clipboard\n\n') + + -> We got a message - we MUST write some data + mustwrite:=TRUE + -> E-Note: I think we should reply to the msg... + ReplyMsg(sm) + ELSE + -> Determine if we must write before exiting by checking to see if our + -> POST is still valid + ior.command:=CBD_CURRENTWRITEID + DoIO(ior) + + WriteF('CURRENTWRITEID = \d\n', ior.clipid) + + IF postID>=ior.clipid THEN mustwrite:=TRUE + ENDIF + + -> Write the string of text + IF mustwrite + cbWriteFTXT(ior, string) + ELSE + WriteF('No need to write to clipboard\n') + ENDIF +EXCEPT DO + IF ior THEN cbClose(ior) + IF satisfy THEN deletePort(satisfy) + SELECT exception + CASE ERR_PORT; WriteF('Error creating message port\n') + CASE "CBOP"; WriteF('Error opening clipboard.device\n') + CASE "CBWR"; WriteF('Error writing to clipboard\n') + ENDSELECT + ReThrow() +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/HotKey.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/HotKey.e new file mode 100644 index 0000000..d101df3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/HotKey.e @@ -0,0 +1,163 @@ +-> HotKey.e - Simple hot key commodity + +OPT PREPROCESS -> E-Note: we are using the CxXXX creation macros + +MODULE 'commodities', + 'icon', + 'amigalib/argarray', + 'dos/dos', + 'exec/ports', + 'libraries/commodities' + +ENUM ERR_NONE, ERR_ARG, ERR_BRKR, ERR_CRCX, ERR_CXERR, ERR_LIB, ERR_PORT + +RAISE ERR_BRKR IF CxBroker()=NIL, + ERR_CRCX IF CreateCxObj()=NIL, -> E-Note: the CxXXX macros use this + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL + +CONST EVT_HOTKEY=1 + +DEF broker_mp=NIL:PTR TO mp, broker=NIL, filter=NIL, sender, translate, + cxsigflag + +PROC main() HANDLE + DEF hotkey, ttypes=NIL, msg + cxbase:=OpenLibrary('commodities.library', 37) + -> Open the icon.library for the support functions, argArrayXXX() + iconbase:=OpenLibrary('icon.library', 36) + broker_mp:=CreateMsgPort() + cxsigflag:=Shl(1, broker_mp.sigbit) + + -> argArrayInit() is a support function (from the 2.0 version of amiga.lib) + -> that makes it easy to read arguments from either a CLI or from Workbench's + -> ToolTypes. Because it uses icon.library, the library has to be open before + -> calling this function. argArrayDone() cleans up after this function. + -> E-Note: argArrayInit() needs no arguments: it uses global arg and wbmessage + IF (ttypes:=argArrayInit())=NIL THEN Raise(ERR_ARG) + + broker:=CxBroker([NB_VERSION, 0, + 'RKM HotKey', -> String to identify this broker + 'A Simple Hotkey', + 'A simple hot key commodity', + -> Don't want any new commodities starting with this name. + -> If someone tries it, let me know + NBU_UNIQUE OR NBU_NOTIFY, + -> argInt() (also in amiga.lib) searches through the array set up by + -> argArrayInit() for a specific ToolType. If it finds one, it returns the + -> numeric value of the number that followed the ToolType (e.g., + -> CX_PRIORITY=7). If it doesn't find the ToolType, it returns the default + -> value (the third argument). + 0, argInt(ttypes, 'CX_PRIORITY', 0), 0, + broker_mp, 0]:newbroker, NIL) + + -> argString() works just like argInt(), except it returns a pointer to a + -> string rather than an integer. In the example below, if there is no + -> ToolType 'HOTKEY', the function returns a pointer to 'rawkey control esc'. + hotkey:=argString(ttypes, 'HOTKEY', 'rawkey control esc') + + -> CxFilter() is a macro that creates a filter CxObject. This filter passes + -> input events that match the string pointed to by hotkey. + filter:=CxFilter(hotkey) + -> Add a CxObject to another's personal list + AttachCxObj(broker, filter) + + -> CxSender() creates a sender CxObject. Every time a sender gets a + -> CxMessage, it sends a new CxMessage to the port pointed to in the first + -> argument. CxSender()'s second argument will be the ID of any CxMessages + -> the sender sends to the port. The data pointer associated with the + -> CxMessage will point to a *COPY* of the InputEvent structure associated + -> with the orginal CxMessage. + sender:=CxSender(broker_mp, EVT_HOTKEY) + AttachCxObj(filter, sender) + + -> CxTranslate() creates a translate CxObject. When a translate CxObject + -> gets a CxMessage, it deletes the original CxMessage and adds a new input + -> event to the input.device's input stream after the Commodities input + -> handler. CxTranslate's argument points to an InputEvent structure from + -> which to create the new input event. In this example, the pointer is NIL, + -> meaning no new event should be introduced, which causes any event that + -> reaches this object to disappear from the input stream. + translate:=CxTranslate(NIL) + AttachCxObj(filter, translate) + + -> CxObjError() is a commodities.library function that returns the internal + -> accumulated error code of a CxObject. + IF CxObjError(filter)<>FALSE THEN Raise(ERR_CXERR) + + ActivateCxObj(broker, TRUE) + processMsg() + +EXCEPT DO + -> DeleteCxObjAll() is a commodities.library function that not only deletes + -> the CxObject pointed to in its argument, but it deletes all of the + -> CxObjects that are attached to it. + IF broker THEN DeleteCxObjAll(broker) + IF broker_mp + WHILE msg:=GetMsg(broker_mp) DO ReplyMsg(msg) + DeleteMsgPort(broker_mp) -> E-Note: C version incorrectly uses DeletePort() + ENDIF + IF ttypes THEN argArrayDone() + IF iconbase THEN CloseLibrary(iconbase) + IF cxbase THEN CloseLibrary(cxbase) + SELECT exception + CASE ERR_ARG; WriteF('Error: Could not init arg array\n') + CASE ERR_BRKR; WriteF('Error: Could not create broker\n') + CASE ERR_CRCX; WriteF('Error: Could not create CX object\n') + CASE ERR_CXERR; WriteF('Error: Could not activate broker\n') + CASE ERR_LIB; WriteF('Error: Could not open required library\n') + CASE ERR_PORT; WriteF('Error: Could not create message port\n') + ENDSELECT +ENDPROC + +PROC processMsg() + DEF msg, sigrcvd, msgid, msgtype, done=FALSE + REPEAT + sigrcvd:=Wait(SIGBREAKF_CTRL_C OR cxsigflag) + WHILE msg:=GetMsg(broker_mp) + msgid:=CxMsgID(msg) + msgtype:=CxMsgType(msg) + ReplyMsg(msg) + SELECT msgtype + CASE CXM_IEVENT + WriteF('A CXM_IEVENT, ') + SELECT msgid + CASE EVT_HOTKEY -> We got the message from the sender CxObject + WriteF('You hit the HotKey.\n') + DEFAULT + WriteF('unknown.\n') + ENDSELECT + CASE CXM_COMMAND + WriteF('A command: ') + SELECT msgid + CASE CXCMD_DISABLE + WriteF('CXCMD_DISABLE\n') + ActivateCxObj(broker, FALSE) + CASE CXCMD_ENABLE + WriteF('CXCMD_ENABLE\n') + ActivateCxObj(broker, TRUE) + CASE CXCMD_KILL + WriteF('CXCMD_KILL\n') + done:=TRUE + CASE CXCMD_UNIQUE + -> Commodities Exchange can be told not only to refuse to launch a + -> commodity with a name already in use but also can notify the + -> already running commodity that it happened. It does this by + -> sending a CXM_COMMAND with the ID set to CXMCMD_UNIQUE. If the + -> user tries to run a windowless commodity that is already running, + -> the user wants the commodity to shut down. + WriteF('CXCMD_UNIQUE\n') + done:=TRUE + DEFAULT + WriteF('Unknown msgid\n') + ENDSELECT + DEFAULT + WriteF('Unknown msgtype\n') + ENDSELECT + ENDWHILE + IF sigrcvd AND SIGBREAKF_CTRL_C + WriteF('CTRL C signal break\n') + done:=TRUE + ENDIF + UNTIL done +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/PopShell.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/PopShell.e new file mode 100644 index 0000000..c286ee9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/PopShell.e @@ -0,0 +1,153 @@ +-> PopShell.e - Simple hot key commodity + +OPT PREPROCESS -> E-Note: we are using the CxXXX creation macros + +MODULE 'commodities', + 'icon', + 'amigalib/argarray', + 'amigalib/cx', + 'devices/timer', + 'devices/inputevent', + 'dos/dos', + 'exec/ports', + 'libraries/commodities' + +ENUM ERR_NONE, ERR_ARGS, ERR_BRKR, ERR_CRCX, ERR_CXERR, ERR_HOT, ERR_IE, + ERR_LIB, ERR_PORT + +RAISE ERR_BRKR IF CxBroker()=NIL, + ERR_CRCX IF CreateCxObj()=NIL, -> E-Note: the CxXXX macros use this + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL + +CONST EVT_HOTKEY=1 + +DEF broker_mp=NIL:PTR TO mp, broker=NIL, filter=NIL, + cxsigflag, ie=NIL:PTR TO inputevent + +PROC main() HANDLE + DEF hotkey, ttypes=NIL, msg, newshell + -> E-Note: we can use invertStringRev(), so we don't need to spell backwards! + newshell:='newshell\b' + cxbase:=OpenLibrary('commodities.library', 37) + iconbase:=OpenLibrary('icon.library', 36) + broker_mp:=CreateMsgPort() + cxsigflag:=Shl(1, broker_mp.sigbit) + -> E-Note: argArrayInit() uses global "wbmessage" and "arg" by default + -> E-Note: C version fails to check return value + IF NIL=(ttypes:=argArrayInit()) THEN Raise(ERR_ARGS) + hotkey:=argString(ttypes, 'HOTKEY', 'rawkey control esc') + + broker:=CxBroker([NB_VERSION, 0, -> E-Note: pad byte! + 'RKM PopShell', -> String to identify this broker + 'A Simple PopShell', + 'A simple PopShell commodity', + -> Don't want any new commodities starting with this name. + -> If someone tries it, let me know + NBU_UNIQUE OR NBU_NOTIFY, + 0, argInt(ttypes, 'CX_PRIORITY', 0), + 0, broker_mp, 0]:newbroker, NIL) + + -> hotKey() is an amigalib function that creates a filter, sender and + -> translate CxObject and connects them to report a hot key press and + -> delete its input event. + IF NIL=(filter:=hotKey(hotkey, broker_mp, EVT_HOTKEY)) THEN Raise(ERR_HOT) + + -> Add a CxObject to another's personal list + AttachCxObj(broker, filter) + IF CxObjError(filter)<>FALSE THEN Raise(ERR_CXERR) + + -> invertString() is an amigalib function that creates a linked list of input + -> events which would translate into the string passed to it. Note that it + -> puts the input events in the opposite order in which the corresponding + -> letters appear in the string. A translate CxObject expects them backwards. + -> E-Note: ...so use invertStringRev() and stay sane... + IF NIL=(ie:=invertStringRev(newshell, NIL)) THEN Raise(ERR_IE) + + ActivateCxObj(broker, TRUE) + processMsg() + +EXCEPT DO + -> We have to release the memory allocated by invertStringRev. + -> E-Note: ...well, this isn't really necessary since it uses NEW + IF ie THEN freeIEvents(ie) + -> DeleteCxObjAll() is a commodities.library function that not only deletes + -> the CxObject pointed to in its argument, but deletes all of the CxObjects + -> attached to it. + IF broker THEN DeleteCxObjAll(broker) + -> This amigalib function cleans up after argArrayInit() + IF ttypes THEN argArrayDone() + IF broker_mp -> Empty the port of all CxMsgs + WHILE msg:=GetMsg(broker_mp) DO ReplyMsg(msg) + DeleteMsgPort(broker_mp) + ENDIF + IF iconbase THEN CloseLibrary(iconbase) + IF cxbase THEN CloseLibrary(cxbase) + SELECT exception + CASE ERR_ARGS; WriteF('Error: Could not parse tooltypes/arguments\n') + CASE ERR_BRKR; WriteF('Error: Could not create broker\n') + CASE ERR_CRCX; WriteF('Error: Could not create CX object\n') + CASE ERR_CXERR; WriteF('Error: Could not activate broker\n') + CASE ERR_HOT; WriteF('Error: Could not create hot key\n') + CASE ERR_LIB; WriteF('Error: Could not open required library\n') + CASE ERR_PORT; WriteF('Error: Could not create message port\n') + ENDSELECT +ENDPROC + +PROC processMsg() + DEF msg, sigrcvd, msgid, msgtype, done=FALSE + REPEAT + sigrcvd:=Wait(SIGBREAKF_CTRL_C OR cxsigflag) + + WHILE msg:=GetMsg(broker_mp) + msgid:=CxMsgID(msg) + msgtype:=CxMsgType(msg) + ReplyMsg(msg) + + SELECT msgtype + CASE CXM_IEVENT + WriteF('A CXM_EVENT, ') + SELECT msgid + CASE EVT_HOTKEY + -> We got the message from the sender CxObject + WriteF('You hit the HotKey.\n') + -> Add the string "newshell" to input * stream. If a shell gets it, + -> it'll open a new shell. + AddIEvents(ie) + DEFAULT + WriteF('unknown.\n') + ENDSELECT + CASE CXM_COMMAND + WriteF('A command: ') + SELECT msgid + CASE CXCMD_DISABLE + WriteF('CXCMD_DISABLE\n') + ActivateCxObj(broker, FALSE) + CASE CXCMD_ENABLE + WriteF('CXCMD_ENABLE\n') + ActivateCxObj(broker, TRUE) + CASE CXCMD_KILL + WriteF('CXCMD_KILL\n') + done:=TRUE + CASE CXCMD_UNIQUE + -> Commodities Exchange can be told not only to refuse to launch a + -> commodity with a name already in use but also can notify the + -> already running commodity that it happened. It does this by + -> sending a CXM_COMMAND with the ID set to CXMCMD_UNIQUE. If the + -> user tries to run a windowless commodity that is already running, + -> the user wants the commodity to shut down. + WriteF('CXCMD_UNIQUE\n') + done:=TRUE + DEFAULT + WriteF('Unknown msgid\n') + ENDSELECT + DEFAULT + WriteF('Unknown msgtype\n') + ENDSELECT + ENDWHILE + IF sigrcvd AND SIGBREAKF_CTRL_C + done:=TRUE + WriteF('CTRL C signal break\n') + ENDIF + UNTIL done +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/broker.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/broker.e new file mode 100644 index 0000000..b860754 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/broker.e @@ -0,0 +1,113 @@ +-> broker.e - Simple skeletal example of opening a broker. + +MODULE 'commodities', + 'dos/dos', + 'exec/libraries', + 'exec/ports', + 'libraries/commodities' + +ENUM ERR_NONE, ERR_ARG, ERR_BRKR, ERR_CXERR, ERR_LIB, ERR_PORT + +RAISE ERR_BRKR IF CxBroker()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL + +DEF broker=NIL, broker_mp=NIL:PTR TO mp, cxsigflag + +PROC main() HANDLE + DEF msg + -> Before bothering with anything else, open the library + cxbase:=OpenLibrary('commodities.library', 37) + -> Commodities talks to a Commodities application through an Exec Message + -> port, which the application provides + broker_mp:=CreateMsgPort() + + -> The commodities.library function CxBroker() adds a broker to the master + -> list. It takes two arguments, a pointer to a NewBroker structure and a + -> pointer to a LONG. The NewBroker structure contains information to set + -> up the broker. If the second argument is not NIL, CxBroker will fill it + -> in with an error code. + broker:=CxBroker( + [NB_VERSION, -> Version of the NewBroker object + 0, -> E-Note: pad byte + 'RKM broker', -> Name: commodities uses for this commodity + 'Broker', -> Title of commodity that appears in CXExchange + 'A simple example of a broker', -> Description + 0, -> Unique: tells CX not to launch a commodity with the same name + 0, -> Flags: tells CX if this commodity has a window + 0, -> Pri: this commodity's priority + 0, -> E-Note: pad byte + broker_mp, -> Port: mp CX talks to + 0 -> ReservedChannel: reserved for later use + ]:newbroker, NIL) + cxsigflag:=Shl(1, broker_mp.sigbit) + + -> After it's set up correctly, the broker has to be activated + ActivateCxObj(broker, TRUE) + + -> The main processing loop + processMsg() + +EXCEPT DO + -> It's time to clean up. Start by removing the broker from the Commodities + -> master list. The DeleteCxObjAll() function will take care of removing a + -> CxObject and all those connected to it from the Commodities network + IF broker THEN DeleteCxObj(broker) + IF broker_mp + -> Empty the port of CxMsgs + WHILE msg:=GetMsg(broker_mp) DO ReplyMsg(msg) + DeleteMsgPort(broker_mp) -> E-Note: C version incorrectly uses DeletePort() + ENDIF + IF cxbase THEN CloseLibrary(cxbase) + SELECT exception + CASE ERR_BRKR; WriteF('Error: Could not create broker\n') + CASE ERR_CXERR; WriteF('Error: Could not activate broker\n') + CASE ERR_LIB; WriteF('Error: Could not open commodities.library\n') + CASE ERR_PORT; WriteF('Error: Could not create message port\n') + ENDSELECT +ENDPROC + +PROC processMsg() + DEF msg, sigrcvd, msgid, msgtype, done=FALSE + REPEAT + -> Wait for something to happen + sigrcvd:=Wait(SIGBREAKF_CTRL_C OR cxsigflag) + + -> Process any messages + WHILE msg:=GetMsg(broker_mp) + -> Extract any necessary information from the CxMessage and return it + msgid:=CxMsgID(msg) + msgtype:=CxMsgType(msg) + ReplyMsg(msg) + + SELECT msgtype + CASE CXM_IEVENT + -> Shouldn't get any of these in this example + CASE CXM_COMMAND + -> Commodities has sent a command + WriteF('A command: ') + SELECT msgid + CASE CXCMD_DISABLE + WriteF('CXCMD_DISABLE\n') + -> The user clicked CX Exchange disable gadget, better disable + ActivateCxObj(broker, FALSE) + CASE CXCMD_ENABLE + -> User clicked enable gadget + WriteF('CXCMD_ENABLE\n') + ActivateCxObj(broker, TRUE) + CASE CXCMD_KILL + -> User clicked kill gadget, better quit + WriteF('CXCMD_KILL\n') + done:=TRUE + ENDSELECT + DEFAULT + WriteF('Unknown msgtype\n') + ENDSELECT + ENDWHILE + -> Test to see if user tried to break + IF sigrcvd AND SIGBREAKF_CTRL_C + done:=TRUE + WriteF('CTRL C signal break\n') + ENDIF + UNTIL done +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/divert.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/divert.e new file mode 100644 index 0000000..f4868a3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Commodities/divert.e @@ -0,0 +1,163 @@ +-> divert.e - commodity to monitor user inactivity + +OPT PREPROCESS -> E-Note: we are using the CxXXX creation macros + +MODULE 'icon', + 'commodities', + 'amigalib/argarray', + 'other/ecode', + 'devices/inputevent', + 'dos/dos', + 'exec/libraries', + 'exec/ports', + 'libraries/commodities' + +ENUM ERR_NONE, ERR_ARGS, ERR_BRKR, ERR_CRCX, ERR_CXERR, ERR_ECODE, ERR_LIB, + ERR_PORT, ERR_SIG + +RAISE ERR_BRKR IF CxBroker()=NIL, + ERR_CRCX IF CreateCxObj()=NIL, -> E-Note: the CxXXX macros use this + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL, + ERR_SIG IF AllocSignal()=-1 + +CONST TIMER_CLICKS=100 + +DEF broker_mp=NIL:PTR TO mp, broker=NIL, cocustom=NIL, cosignal=NIL, + task, cxsigflag, signal=-1, cxobjsignal + +-> E-Note: the C static used in the custom function is just a global variable +DEF time=0 + +PROC main() HANDLE + DEF ttypes=NIL, msg, cxfunc + cxbase:=OpenLibrary('commodities.library', 37) + -> Open the icon.library for support functions, argXXX() + iconbase:=OpenLibrary('icon.library', 36) + broker_mp:=CreateMsgPort() + cxsigflag:=Shl(1, broker_mp.sigbit) + + -> argArrayInit() is a support function (in the 2.0 version of amigalib) + -> that makes it easy to read arguments from either a CLI or from + -> Workbench's ToolTypes. Because it uses icon.library, the library has + -> to be open before before calling this function. argArrayDone() cleans + -> up after this function. + -> E-Note: uses global "wbmessage" and "arg" so it needs no arguments + ttypes:=argArrayInit() + + broker:=CxBroker([NB_VERSION, 0, 'Divert', -> String to identify this broker + 'Divert', 'Show divert', + -> Don't want any new commodities starting with this name. + -> If someone tries it, let me know + NBU_UNIQUE OR NBU_NOTIFY, 0, + -> argInt() (in amigalib) searches through the array set up by argArrayInit() + -> for a specific ToolType. If it finds one, it returns the numeric value of + -> the number that followed the ToolType (e.g., CX_PRIORITY=7). If it doesn't + -> find the ToolType, it returns the default value (the third argument). + argInt(ttypes, 'CX_PRIORITY', 0), + 0, broker_mp, 0]:newbroker, NIL) + + -> CxCustom() takes two arguments, a pointer to the custom function and an + -> ID. Commodities Exchange will assign that ID to any CxMsg passed to the + -> custom function. + -> E-Note: eCodeCxCustom() protects an E function so you can use it as a + -> CX custom function + IF NIL=(cxfunc:=eCodeCxCustom({cxFunction})) THEN Raise(ERR_ECODE) + cocustom:=CxCustom(cxfunc, 0) + AttachCxObj(broker, cocustom) + + -> Allocate a signal bit for the signal CxObj + signal:=AllocSignal(-1) + -> Set up the signal mask + cxobjsignal:=Shl(1, signal) + cxsigflag:=cxsigflag OR cxobjsignal + + -> CxSignal takes two arguments, a pointer to the task to signal (normally + -> the commodity) and the number of the signal bit the commodity acquired + -> to signal with. + task:=FindTask(NIL) + cosignal:=CxSignal(task, signal) + AttachCxObj(cocustom, cosignal) + ActivateCxObj(broker, TRUE) + processMsg() + +EXCEPT DO + IF signal<>-1 THEN FreeSignal(signal) + -> DeleteCxObjAll() is a commodities.library function that not only deletes + -> the CxObject pointed to in its argument, but it deletes all of the + -> CxObjects that are attached to it. + IF broker THEN DeleteCxObjAll(broker) + -> This amigalib function cleans up after argArrayInit() + IF ttypes THEN argArrayDone() + IF broker_mp + -> Empty the port of all CxMsgs + WHILE msg:=GetMsg(broker_mp) DO ReplyMsg(msg) + DeleteMsgPort(broker_mp) -> E-Note: C version incorrectly uses DeletePort() + ENDIF + IF iconbase THEN CloseLibrary(iconbase) + IF cxbase THEN CloseLibrary(cxbase) + SELECT exception + CASE ERR_ARGS; WriteF('Error: Could not parse tooltypes/arguments\n') + CASE ERR_BRKR; WriteF('Error: Could not create broker\n') + CASE ERR_CRCX; WriteF('Error: Could not create CX object\n') + CASE ERR_CXERR; WriteF('Error: Could not activate broker\n') + CASE ERR_ECODE; WriteF('Error: Ran out of memory in eCodeCxCustom()\n') + CASE ERR_LIB; WriteF('Error: Could not open commodities.library\n') + CASE ERR_PORT; WriteF('Error: Could not create message port\n') + CASE ERR_SIG; WriteF('Error: Could not allocate signal\n') + ENDSELECT +ENDPROC + +PROC processMsg() + DEF msg, sigrcvd, msgid, done=FALSE + REPEAT + sigrcvd:=Wait(SIGBREAKF_CTRL_C OR cxsigflag) + + WHILE msg:=GetMsg(broker_mp) + msgid:=CxMsgID(msg) + ReplyMsg(msg) + + SELECT msgid + CASE CXCMD_DISABLE + ActivateCxObj(broker, FALSE) + CASE CXCMD_ENABLE + ActivateCxObj(broker, TRUE) + CASE CXCMD_KILL + done:=TRUE + CASE CXCMD_UNIQUE + done:=TRUE + ENDSELECT + ENDWHILE + + IF sigrcvd AND SIGBREAKF_CTRL_C THEN done:=TRUE + + -> Check to see if the signal CxObj signalled us. + IF sigrcvd AND cxobjsignal THEN WriteF('Got Signal\n') + UNTIL done +ENDPROC + +-> The custom function for the custom CxObject. Any code for a custom CxObj +-> must be short and sweet because it runs as part of the input.device task. +PROC cxFunction(cxm, co) + DEF ie:PTR TO inputevent + + -> Get the struct InputEvent associated with this CxMsg. Unlike the + -> InputEvent extracted from a CxSender's CxMsg, this is a *REAL* input + -> event, be careful with it. + ie:=CxMsgData(cxm) + + -> This custom function counts the number of timer events that go by while + -> no other input events occur. If it counts more than a certain amount of + -> timer events, it clears the count and diverts the timer event CxMsg to the + -> custom object's personal list. If an event besides a timer event passes + -> by, the timer event count is reset. + IF ie.class=IECLASS_TIMER + time++ + IF time>=TIMER_CLICKS + time:=0 + DivertCxMsg(cxm, co, co) + ENDIF + ELSE + time:=0 + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/AskKeymap.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/AskKeymap.e new file mode 100644 index 0000000..8303d4a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/AskKeymap.e @@ -0,0 +1,65 @@ +-> AskKeymap.e + +->>> Header (globals) +MODULE 'devices/console', + 'devices/conunit', + 'devices/keymap', + 'exec/io', + 'exec/memory', + 'exec/ports' + +ENUM ERR_NONE, ERR_DEV, ERR_IO, ERR_PORT + +RAISE ERR_DEV IF OpenDevice()<>0, + ERR_IO IF CreateIORequest()=NIL, + ERR_PORT IF CreateMsgPort()=NIL +->>> + +->>> PROC main() +PROC main() HANDLE + DEF consoleMP:PTR TO mp, consoleIO:PTR TO iostd, keymap:PTR TO keymap, + i, j, prt, dev_open=FALSE + -> Release 2 (V36) or a later version of the OS is required + KickVersion(36) + -> Create the message port + consoleMP:=CreateMsgPort() + -> Create the IORequest + consoleIO:=CreateIORequest(consoleMP, SIZEOF iostd) + -> Open Console device + OpenDevice('console.device', CONU_LIBRARY, consoleIO, 0) + dev_open:=TRUE + -> Allocate memory for the keymap + keymap:=NewM(SIZEOF keymap, MEMF_PUBLIC OR MEMF_CLEAR) + -> Device opened, send query command to it + consoleIO.length:=SIZEOF keymap + -> Where to put it + consoleIO.data:=keymap + consoleIO.command:=CD_ASKKEYMAP + IF DoIO(consoleIO) + -> Inform user that CD_ASKKEYMAP failed + WriteF('CD_ASKKEYMAP failed. Error - \d\n', consoleIO.error) + ELSE + -> Print values for top row of keyboard + prt:=keymap.lokeymap + WriteF('Result of CD_ASKKEYMAP for top row of keyboard\n\n' + + '\tShift\n' + + '\tAlt\tAlt\tShift\tNo Qualifier\n') + FOR j:=0 TO 13 + FOR i:=0 TO 3 DO WriteF('\t\c', prt[]++) + WriteF('\n') + ENDFOR + ENDIF +EXCEPT DO + IF keymap THEN Dispose(keymap) + IF dev_open THEN CloseDevice(consoleIO) + IF consoleIO THEN DeleteIORequest(consoleIO) + IF consoleMP THEN DeleteMsgPort(consoleMP) + SELECT exception + CASE ERR_DEV; WriteF('Error: could not open console device\n') + CASE ERR_IO; WriteF('Error: could not create I/O\n') + CASE ERR_PORT; WriteF('Error: could not create port\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/Console.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/Console.e new file mode 100644 index 0000000..ee8a474 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/Console.e @@ -0,0 +1,230 @@ +-> Console.e +-> +-> Example of opening a window and using the console device to send text and +-> control sequences to it. The example can be easily modified to do +-> additional control sequences. + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'devices/console', + 'exec/io', + 'exec/ports', + 'intuition/intuition', + 'intuition/screens', + 'amigalib/io', + 'amigalib/ports' + +ENUM ERR_NONE, ERR_DEV, ERR_IO, ERR_PORT + +RAISE ERR_DEV IF OpenDevice()<>0 + +-> Note - using two character ESC[. Hex 9B could be used instead +#define RESETCON '\ec' +#define CURSOFF '\e[0 p' +#define CURSON '\e[ p' +#define DELCHAR '\e[P' + +-> SGR (set graphic rendition) +#define COLOR02 '\e[32m' +#define COLOR03 '\e[33m' +#define ITALICS '\e[3m' +#define BOLD '\e[1m' +#define UNDERLINE '\e[4m' +#define NORMAL '\e[0m' + +DEF win=NIL:PTR TO window, writeReq=NIL:PTR TO iostd, writePort=NIL:PTR TO mp, + readReq=NIL:PTR TO iostd, readPort=NIL:PTR TO mp, openedConsole=FALSE +->>> + +->>> PROC main() +PROC main() HANDLE + DEF winmsg:PTR TO intuimessage, signals, conreadsig, windowsig, lch, + inControl=0, going=TRUE, ch, ibuf, obuf[200]:STRING, error, class + + -> Create reply port and io block for writing to console + IF NIL=(writePort:=createPort('RKM.console.write', 0)) THEN Raise(ERR_PORT) + IF NIL=(writeReq:=createExtIO(writePort, SIZEOF iostd)) THEN Raise(ERR_IO) + + -> Create reply port and io block for reading from console + IF NIL=(readPort:=createPort('RKM.console.read', 0)) THEN Raise(ERR_PORT) + IF NIL=(readReq:=createExtIO(readPort, SIZEOF iostd)) THEN Raise(ERR_IO) + + -> Open a window + win:=OpenWindow([10, 10, 620, 180, -1, -1, IDCMP_CLOSEWINDOW, + WFLG_DEPTHGADGET OR WFLG_SIZEGADGET OR WFLG_DRAGBAR OR + WFLG_CLOSEGADGET OR WFLG_SMART_REFRESH OR WFLG_ACTIVATE, + NIL, NIL, 'Console Test', NIL, NIL, + 100, 45, 640, 200, WBENCHSCREEN]:nw) + + -> Now, attach a console to the window + openConsole(writeReq, readReq, win) + openedConsole:=TRUE + + -> Demonstrate some console escape sequences + conPuts(writeReq, 'Here''s some normal text\n') + StringF(obuf, '\s\sHere''s some text in color 3 and italics\n', + COLOR03, ITALICS) + conPuts(writeReq, obuf) + conPuts(writeReq, NORMAL) + Delay(50) -> Delay for dramatic effect + + conPuts(writeReq, 'We will now delete this asterisk =*=') + Delay(50) + conPuts(writeReq, {bspace}) -> Backspace twice + Delay(50) + conPuts(writeReq, DELCHAR) -> Delete the character + Delay(50) + + queueRead(readReq, {ibuf}) -> Send the first console read request + + conPuts(writeReq, '\n\nNow reading console\n') + conPuts(writeReq, 'Type some keys. Close window when done.\n\n') + + conreadsig:=Shl(1, readPort.sigbit) + windowsig:=Shl(1, win.userport.sigbit) + WHILE going + -> A character, or an IDCMP msg, or both could wake us up + signals:=Wait(conreadsig OR windowsig) + + -> If a console signal was received, get the character + IF signals AND conreadsig + IF -1<>(lch:=conMayGetChar(readPort, {ibuf})) + ch:=lch + -> Show hex and ascii (if printable) for char we got. If you want to + -> parse received control sequences, such as function or Help keys, + -> you would buffer control sequences as you receive them, starting to + -> buffer whenever you receive $9B (or $1B[ for user-typed sequences) + -> and ending when you receive a valid terminating character for the + -> type of control sequence you are receiving. For CSI sequences, + -> valid terminating characters are generally $40 through $7E. In our + -> example, InControl has the following values: 0 = no, 1 = have $1B, + -> 2 = have $9B OR $1B and [, 3 = now inside control sequence, + -> -1 = normal end esc, -2 = non-CSI(no [) $1B end esc + -> NOTE - a more complex parser is required to recognize other types + -> of control sequences. + + -> $1B ESC not followed by "[", is not CSI seq + IF inControl=1 THEN (inControl:=IF ch="[" THEN 2 ELSE -2) + IF (ch=$9B) OR (ch=$1B) -> Control seq starting + inControl:=IF ch=$1B THEN 1 ELSE 2 + conPuts(writeReq, '=== Control Seq ===\n') + ENDIF + -> We'll show the value of this char we received + IF ((ch>=$1F) AND (ch<=$7E)) OR (ch>=$A0) + StringF(obuf, 'Received: hex $\z\h[2] = \c\n', ch, ch) + ELSE + StringF(obuf, 'Received: hex $\z\h[2]\n', ch) + ENDIF + conPuts(writeReq, obuf) + ENDIF + ENDIF + + -> If IDCMP messages received, handle them + IF signals AND windowsig + -> We have to ReplyMsg these when done with them + WHILE winmsg:=GetMsg(win.userport) + class:=winmsg.class + SELECT class + CASE IDCMP_CLOSEWINDOW + going:=FALSE + ENDSELECT + ReplyMsg(winmsg) + ENDWHILE + ENDIF + ENDWHILE + + -> We always have an outstanding queued read request so we must abort it if + -> it hasn't completed, and we must remove it. + IF CheckIO(readReq)=FALSE THEN AbortIO(readReq) + WaitIO(readReq) -> Clear it from our replyport + +EXCEPT DO + IF openedConsole THEN closeConsole(writeReq) + IF win THEN CloseWindow(win) + IF readReq THEN deleteExtIO(readReq) + IF readPort THEN deletePort(readPort) + IF writeReq THEN deleteExtIO(writeReq) + IF writePort THEN deletePort(writePort) + SELECT exception + CASE ERR_DEV; WriteF('Error: could not open console device\n') + CASE ERR_IO; WriteF('Error: could not create I/O\n') + CASE ERR_PORT; WriteF('Error: could not create port\n') + ENDSELECT +ENDPROC + +-> E-Note: simple way to get a string with two backspaces +bspace: CHAR 8, 8, 0 +->>> + +->>> PROC openConsole(writereq:PTR TO iostd, readReq:PTR TO iostd, window) +-> Attach console device to an open Intuition window. +-> E-Note: This function will raise an exception if the console device is not +-> opened correctly. +PROC openConsole(writereq:PTR TO iostd, readreq:PTR TO iostd, window) + DEF error + writereq.data:=window + writereq.length:=SIZEOF window + error:=OpenDevice('console.device', 0, writereq, 0) + readreq.device:=writereq.device -> Clone required parts + readreq.unit:=writereq.unit +ENDPROC error +->>> + +->>> PROC closeConsole(writereq) +PROC closeConsole(writereq) IS CloseDevice(writereq) +->>> + +->>> PROC conPutChar(writereq:PTR TO iostd, char) +-> Output a single character to a specified console. +PROC conPutChar(writereq:PTR TO iostd, char) + writereq.command:=CMD_WRITE + -> E-Note: use typed list to get address of the CHAR in the LONG 'char' + writereq.data:=[char]:CHAR + writereq.length:=1 + DoIO(writereq) + -> Command works because DoIO blocks until command is done (otherwise + -> pointer to string could become invalid in the meantime). +ENDPROC +->>> + +->>> PROC conWrite(writereq:PTR TO iostd, string, length) +-> Output a stream of known length to a console. +PROC conWrite(writereq:PTR TO iostd, string, length) + writereq.command:=CMD_WRITE + writereq.data:=string + writereq.length:=length + DoIO(writereq) +ENDPROC +->>> + +->>> PROC conPuts(writereq:PTR TO iostd, string) +-> Output a NIL-terminated string of characters to a console. +PROC conPuts(writereq:PTR TO iostd, string) + writereq.command:=CMD_WRITE + writereq.data:=string + writereq.length:=-1 -> This means print until terminating NIL + DoIO(writereq) +ENDPROC +->>> + +->>> PROC queueRead(readreq:PTR TO iostd, whereto) +-> Queue up a read request to console, passing it pointer to a buffer into +-> which it can read the character +PROC queueRead(readreq:PTR TO iostd, whereto) + readreq.command:=CMD_READ + readreq.data:=whereto + readreq.length:=1 + SendIO(readreq) +ENDPROC +->>> + +->>> PROC conMayGetChar(msgport, whereto) +-> Check if a character has been received. If none, return -1 +PROC conMayGetChar(msgport, whereto) + DEF temp, readreq:PTR TO iostd + IF NIL=(readreq:=GetMsg(msgport)) THEN RETURN -1 + temp:=whereto[] -> Get the character... + queueRead(readreq, whereto) -> ...then re-use the request block +ENDPROC temp +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/console b/amigae33a/E_v3.3a/Src/Src/Rkrm/Console/console new file mode 100644 index 0000000000000000000000000000000000000000..de9d43115c384246788956a2b099ec2ca2e5742b GIT binary patch literal 4052 zcma)9eP~w5==3)BsW5FZAX?IHygpkL9&}p^=dg^Yr>jgEB3P@`YgTb zBTgU;WrH$C$W}5&VIeDHu&^n?j8M9NhTDyijr<{4C|(Im=nT=AwwhH8VdUKX&V5g^ zoH;NX-H&t5{oV6*&%KYx^(9$<4!cL^dWhfOxer_*cV9F};tbd;%O`WmbgD^7Wa8$z#r$1=KrYA5Sl+ZfKl!_fYl{lU8Oz7MK@@%L zATdXp=%LOa1-|CP82ryodgCD#V&Af)Lj9ygFVH}oXxGFSkZ7TUb{#agMU(aDi=toFp?$5PC9hR`4Vsc|WlT|Mj2Xci zW7NsoupZk=Y?Dd0RW)UmRC=*(wM}gMv|*bm5!EF`;6s*&-+Y_cSF>%XMM~J$W7~%r ztlet5VVyPBOvFdlK;6c6+2ielmx%0LK4Tg%yo{*q-01_w=H8eh>QZQB>J(bY%EPm4 z9q?+czJui0Q}cr?gD81J=-2(insgK-{=idu*}E;61Qhsfga4J!kzpRC-8LWQw*31| z&wK57u$G01FW6Fo?cN^R9tvBw0@DGnE^HnnBKG0wg39IsdyO=B1y*wAs4?(3o+kB% z*D9)AQEgSVb=B5XTaMG#Ze+HG^S;byK$e<${mA4zs6fX9`zGXrkyD87U80d+{BKUU zuQqdnLKIom7DIfFC{Ald&U5Hd^^w@UaCsJf1jmJa?^&4_qEKM1YMr|JO@f6xE2F`^mjcNX9ohaJDt8xI{^;SR9(vHJ>ss1a+GIEn}M=`bZYW#&Xy+b2U> zoVFZh&5(Pj@9iR_L6aIrUZDjG=v~NXL>N{;R_lOlr^1Ci);iT%h1PbT(cCLc$qXX* zP(S66wNu+Q#k;>5&-H7?`)D&>+bPB4+P4w29{Hy%@kzsucbIGM<5lv;I%UhB73G^u zfej8}tReeU#$#>!51EckTef)>agN?>;hQ#p38%4=AV*o9ntr)lxFwgKIy0XDX9aRA zi?`%5pF+oRQ>qNBwP<_DMl4%-0I9&fIa$V8?3a%^3W%%&dHRxd`Z0S8GtG2P@ri$e z9Ue6~KRLA+EkqYXIFno{Ap4?4VdTPPRR@CWJcZ*>I8Mf~Jm$W^{&5YlR!!O6XP!p> z_N1aP^5W%|9Y3%nTX(cF$=zdR5@QAn+^%QQmOo&(PH5t@WL?WjmOTJjM8b{C`Wa-r z>zU?!-`0@5yQFM8tzu!URZ#WbT#p6k|C1}Qu%@I2xi0g~3rdx5XeTY)l2zpmzGW&t z@a;*mGqURVvdO=~eA9X@-f!GDnueES<6UD_elKo;9`-JM z5BC7i{J^d@Sc-$88EvvzYbzoB_^)n+;luIm_m?83_rCve?@D?#G(r|vh+l!*3A z;PSoh4N$0^Z}K?Fs~kzu27fNH@21nKY}(L+Gy3`Dv`$AdnRI4IOsDh4j7X((VmhP8 zbGk6onVjdD+}A@Bn=sR+o&u7>7Z$#Uj_cEU^1MDXB+ls&USSw8b{s z4cfigz1gUq(O=G53gq+)Igw;*jdVu5BI2nTk<7&ne3W>oRWOy#%*74C@*aXk?0a!i z&*td(*T;j6V6dVa2=kd_PN$s2>nJ}~RIkL>MmdflRF!#6JF-fH{1ww}$VLBi`0Dx( zzH@3~WUOnJWc|HQx<|XU6W>L~@?BgKuI}ez`4<*rd7P3ypXSF&bp6ZbevVgImA}AH z@2;Dj{3a8IEXPWt6S1Lz(Ek0QuO1i(9UKTv?KU|yo}Bjf)cYAla>My?8)tvtf`D$$lQdelkRU0mEJaqINp Pw}8UefnS>~_wWA#rNoP| literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/DeviceIO/deviceuse.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/DeviceIO/deviceuse.e new file mode 100644 index 0000000..ca08fc0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/DeviceIO/deviceuse.e @@ -0,0 +1,85 @@ +-> DeviceUse.e - an example of using an Amiga device (here, serial device) +-> - attempt to create a message port with createPort() (from amigalib) +-> - attempt to create the I/O request with ereateExtIO() (from amigalib) +-> - attempt to open the serial device with Exec OpenDevice() +-> +-> If successful, use the serial command SDCMD_QUERY, then reverse our steps. +-> If we encounter an error at any time, we will gracefully exit. Note that +-> applications which require at least V37 OS should use the Exec functions +-> CreateMsgPort()/DeleteMsgPort() and CreateIORequest()/DeleteIORequest() +-> instead of the similar amigalib functions which are used in this example. + +OPT PREPROCESS + +MODULE 'amigalib/io', + 'amigalib/ports', + 'devices/serial', + 'exec/io', + 'exec/ports' + +ENUM ERR_NONE, ERR_DEV, ERR_IO, ERR_PORT + +RAISE ERR_DEV IF OpenDevice()<>0 + +PROC main() HANDLE + DEF serialMP=NIL:PTR TO mp, serialIO=NIL:PTR TO ioextser, + reply:PTR TO ioextser + -> Create the message port. + IF NIL=(serialMP:=createPort(NIL,NIL)) THEN Raise(ERR_PORT) + + -> Create the I/O request. Note that 'devices/serial' defines the type of + -> io required by the serial device--an ioextser. Many devices require + -> specialised extended IO requests which start with an embedded io object. + -> E-Note: ignore the rubbish about casting + IF NIL=(serialIO:=createExtIO(serialMP, SIZEOF ioextser)) THEN Raise(ERR_IO) + + -> Open the serial device (non-zero return value means failure here). + OpenDevice(SERIALNAME, 0, serialIO, 0) + + -> Device is open + serialIO.iostd.command:=SDCMD_QUERY + -> DoIO - demonstrates synchronous device use, returns error or 0. + IF DoIO(serialIO) + WriteF('Query failed. Error - \d\n', serialIO.iostd.error) + ELSE + -> Print serial device status - see include file for meaning. + -> Note that with DoIO, the Wait and GetMsg are done by Exec. + WriteF('Serial device status: $\h\n\n', serialIO.status) + ENDIF + + serialIO.iostd.command:=SDCMD_QUERY + -> SendIO - demonstrates asynchronous device use (returns immediately). + SendIO(serialIO) + -> We could do other things here while the query is being done. And to + -> manage our asynchronous device IO: + -> - we can CheckIO(serialIO) to check for completion + -> - we can AbortIO(serialIO) to abort the command + -> - we can WaitPort(serialMP) to wait for any serial port reply + -> OR we can WaitIO(serialIO) to wait for this specific IO request + -> OR we can Wait(Shl(1, serialMP.sigbit)) for reply port signal + Wait(Shl(1, serialMP.sigbit)) + + WHILE reply:=GetMsg(serialMP) + -> Since we sent out only one serialIO request the while loop is not + -> really needed--we only expect one reply to our one query command, and + -> the reply message pointer returned by GetMsg() will just be another + -> pointer to our one serialIO request. With Wait() or WaitPort(), you + -> must GetMsg() the message. + IF reply.iostd.error + WriteF('Query failed. Error - \d\n', reply.iostd.error) + ELSE + WriteF('Serial device status: $\h\n\n', reply.status) + ENDIF + ENDWHILE + CloseDevice(serialIO) -> Close the serial device. +EXCEPT DO + IF serialIO THEN deleteExtIO(serialIO) -> Delete the I/O request. + IF serialMP THEN deletePort(serialMP) -> Delete the message port. + SELECT exception + CASE ERR_DEV; WriteF('Error: \s did not open\n', SERIALNAME) + -> Inform user that the I/O request could be created. + CASE ERR_IO; WriteF('Error: Could not create I/O request\n') + -> Inform user that the message port could not be created. + CASE ERR_PORT; WriteF('Error: Could not create message port\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/rbf.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/rbf.e new file mode 100644 index 0000000..53be0b0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/rbf.e @@ -0,0 +1,140 @@ +-> rbf.e - Serial receive buffer full interrupt handler example. +-> +-> To receive characters, this example requires ASCII serial input at your +-> Amiga's current serial hardware baud rate (i.e., 9600 after reboot, else +-> last baud rate used). + +-> E-Note: E does not (as of v3.1a) support Resources in the conventional way +MODULE 'other/ecode', + 'other/misc', + 'dos/dos', + 'exec/execbase', + 'exec/interrupts', + 'exec/nodes', + 'exec/memory', + 'hardware/custom', + 'hardware/intbits', + 'resources/misc' + +ENUM ERR_NONE, ERR_BITS, ERR_ECODE, ERR_PORT, ERR_SIG + +RAISE ERR_SIG IF AllocSignal()=-1 + +CONST BUFFERSIZE=256, NAMESIZE=32 +CONST ALLOCEDBUFFER=BUFFERSIZE+2 + +OBJECT rbfData + task + signal + bufferCount -> E-Note: C version disagrees with Assembly handler! + charBuffer[ALLOCEDBUFFER]:ARRAY + flagBuffer[ALLOCEDBUFFER]:ARRAY + name[NAMESIZE]:ARRAY +ENDOBJECT + +-> E-Note: set-up "custom" +DEF custom=CUSTOMADDR:PTR TO custom + +PROC main() HANDLE + -> E-Note: to help with cleaning up, currentuser has been replaced by + -> portuser and bitsuser, both initialised to non-zero + DEF allocname, rbfdata=NIL:PTR TO rbfData, portuser=-1, bitsuser=-1, + signr=-1, serdevice, rbfint=NIL:PTR TO is, priorint:PTR TO is, + priorenable, signal, exec:PTR TO execbase + -> E-Note: get the right type for execbase + exec:=execbase + + allocname:='rbf-example' + + miscbase:=OpenResource('misc.resource') + + -> Allocate the serial port registers. + IF portuser:=allocMiscResource(MR_SERIALPORT, allocname) + -> Hey! Someone's got it! + WriteF('serial hardware allocated by \s. Trying to remove it\n', portuser) + + Forbid() + IF serdevice:=FindName(exec.devicelist, portuser) THEN RemDevice(serdevice) + Permit() + + IF portuser:=allocMiscResource(MR_SERIALPORT, allocname) -> And try again + -> E-Note: error if still allocated + Raise(ERR_PORT) + ENDIF + ENDIF + + -> Get the serial control bits. (Give up if allocated.) + IF bitsuser:=allocMiscResource(MR_SERIALBITS, allocname) THEN Raise(ERR_BITS) + -> Got them both + WriteF('serial hardware allocated\n') + + -> Allocate a signal bit for the interrupt handler to signal us. + signr:=AllocSignal(-1) + + rbfint:=NewM(SIZEOF is, MEMF_PUBLIC OR MEMF_CLEAR) + rbfdata:=NewM(SIZEOF rbfData, MEMF_PUBLIC OR MEMF_CLEAR) + rbfdata.task:=FindTask(NIL) -> Init rbfdata object + rbfdata.signal:=Shl(1, signr) + + rbfint.ln.type:=NT_INTERRUPT -> Init interrupt node. + -> E-Note: copy *safely* to rbfdata.name + AstrCopy(rbfdata.name, allocname, NAMESIZE) + rbfint.ln.name:=rbfdata.name + rbfint.data:=rbfdata + rbfint.code:=eCodeIntHandler({rbfHandler}) + IF rbfint.code=NIL THEN Raise(ERR_ECODE) + + -> Save state of RBF and interrupt disable it. + priorenable:=custom.intenar AND INTF_RBF + custom.intena:=INTF_RBF + IF priorint:=SetIntVector(INTB_RBF, rbfint) + WriteF('replaced the \s RBF interrupt handler\n', priorint.ln.name) + ENDIF + + WriteF('enabling RBF interrupt\n') + custom.intena:=INTF_SETCLR OR INTF_RBF + + WriteF('waiting for buffer to fill up. Use CTRL-C to break\n') + signal:=Wait(Shl(1, signr) OR SIGBREAKF_CTRL_C) + + IF signal AND SIGBREAKF_CTRL_C THEN WriteF('>break<\n') + WriteF('Character buffer contains:\n\s\n', rbfdata.charBuffer) + + custom.intena:=INTF_RBF -> Restore previous handler. + SetIntVector(INTB_RBF, priorint) -> Enable it if it was enabled before. + IF priorenable THEN custom.intena:=INTF_SETCLR OR INTF_RBF + +EXCEPT DO + -> E-Note: these next two aren't really necessary + IF rbfdata THEN Dispose(rbfdata) + IF rbfint THEN Dispose(rbfint) + IF signr<>-1 THEN FreeSignal(signr) + -> Release serial hardware + IF bitsuser=NIL THEN freeMiscResource(MR_SERIALBITS) + IF portuser=NIL THEN freeMiscResource(MR_SERIALPORT) + -> There is no 'CloseResource()' function + SELECT exception + CASE ERR_BITS; WriteF('Serial control already allocated by \s\n', bitsuser) + CASE ERR_ECODE; WriteF('Ran out of memory in eCodeIntHandler()\n') + CASE ERR_PORT; WriteF('Serial hardware already allocated by \s\n', portuser) + CASE ERR_SIG; WriteF('Can''t allocate signal\n') + CASE "MEM"; WriteF('Ran out of memory\n') + ENDSELECT +ENDPROC + +-> Note - This simple handler just receives one buffer full of serial +-> input data, signals main, then ignores all subsequent serial data. + +-> E-Note: we could use Assembly, but we'll show how to use an E PROC +-> E-Note: you get rbfint.data as first arg, interrupt flags as second +PROC rbfHandler(data:PTR TO rbfData, intflags) + DEF input + IF data.bufferCount timersoftint.e - Timer device software interrupt message port example. + +-> E-Note: we need eCodeSoftInt() in order to execute E code as an interrupt +MODULE 'amigalib/io', + 'amigalib/lists', + 'other/ecode', + 'devices/timer', + 'dos/dos', + 'exec/interrupts', + 'exec/io', + 'exec/memory', + 'exec/nodes', + 'exec/ports' + +ENUM ERR_NONE, ERR_DEVICE, ERR_ECODE, ERR_TIMER + +RAISE ERR_DEVICE IF OpenDevice()<>0 + +CONST MICRO_DELAY=1000 + +ENUM OFF, ON, STOPPED + +OBJECT tsiData + counter + flag + port:PTR TO mp +ENDOBJECT + +DEF tsidata=NIL:PTR TO tsiData + +PROC main() HANDLE + DEF port=NIL:PTR TO mp, softint=NIL:PTR TO is, tr:PTR TO timerequest, + endcount, code + + -> Allocate message port, data and interrupt objects. Don't use createPort() + -> or CreateMsgPort() since they allocate a signal (don't need that) for a + -> PA_SIGNAL type port. We need PA_SOFTINT. + tsidata:=NewM(SIZEOF tsiData, MEMF_PUBLIC OR MEMF_CLEAR) + port:=NewM(SIZEOF mp, MEMF_PUBLIC OR MEMF_CLEAR) + newList(port.msglist) -> Initialise message list + softint:=NewM(SIZEOF is, MEMF_PUBLIC OR MEMF_CLEAR) + + -> Set up the (software) interrupt structure. Note that this task runs at + -> priority 0. Software interrupts may only be priority -32, -16, 0, +16, + -> +32. Also not that the correct node type for a software interrupt is + -> NT_INTERRUPT. (NT_SOFTINT is an internal Exec flag). This is the same + -> setup as that for a software interrupt which you Cause(). + -> E-Note: We can initialise data here to contain a pointer to shared data + -> structures. The interrupt routine will receive the data in A1. + -> E-Note: eCodeSoftInt() protects an E function and preserves non-scratch + -> registers so you can call it from, for instance, interrupts. + IF NIL=(code:=eCodeSoftInt({tsoftcode})) THEN Raise(ERR_ECODE) + softint.code:=code -> The software interrupt routine + softint.data:=tsidata + softint.ln.pri:=0 + + port.ln.type:=NT_MSGPORT -> Set up the PA_SOFTINT message port (no need to + port.flags:=PA_SOFTINT -> make this port public). + port.sigtask:=softint -> Pointer to interrupt object + + -> Allocate timerequest + IF NIL=(tr:=createExtIO(port, SIZEOF timerequest)) THEN Raise(ERR_TIMER) + + -> Open timer.device. 0 is success + OpenDevice('timer.device', UNIT_MICROHZ, tr, 0) + tsidata.flag:=ON -> Init data structure to share globally. + tsidata.port:=port + + -> Send of the first timerequest to start. IMPORTANT: Do NOT beginIO() to + -> any device other than audio or timer from within a software or hardware + -> interrupt. The beginIO() code may allocate memory, wait or perform other + -> functions which are illegal or dangerous during interrupts. + WriteF('starting softint. CTRL-C to break...\n') + + tr.io.command:=TR_ADDREQUEST -> Initial iorequest to start + tr.time.micro:=MICRO_DELAY -> software interrupt + beginIO(tr) + + Wait(SIGBREAKF_CTRL_C) + endcount:=tsidata.counter + WriteF('timer softint counted \d milliseconds.\n', endcount) + + WriteF('Stopping timer...\n') + tsidata.flag:=OFF + + WHILE tsidata.flag<>STOPPED DO Delay(10) + CloseDevice(tr) + +EXCEPT DO + IF tr THEN deleteExtIO(tr) + IF softint THEN Dispose(softint) + IF port THEN Dispose(port) + IF tsidata THEN Dispose(tsidata) + SELECT exception + CASE ERR_DEVICE; WriteF('Couldn''t open timer.device\n') + CASE ERR_ECODE; WriteF('Ran out of memory in eCodeSoftInt()\n') + CASE ERR_TIMER; WriteF('Couldn''t create timerequest\n') + CASE "MEM"; WriteF('Ran out of memory\n') + ENDSELECT +ENDPROC + +PROC tsoftcode(data) + DEF tr:PTR TO timerequest + -> E-Note: thanks to eCodeSoftInt() we get the softint.data as an argument, + -> so we could use that instead of the global tsidata. This means + -> that tsidata could be made local to main()... + + -> Remove the message from the port. + tr:=GetMsg(tsidata.port) + + -> Keep on going if main() hasn't set flag to OFF. + IF tr AND (tsidata.flag=ON) + -> Increment counter and re-send timerequest -- IMPORTANT: This + -> self-perpetuating technique of calling beginIO() during a software + -> interrupt may only be used with the audio and timer device. + tsidata.counter:=tsidata.counter+1 + tr.io.command:=TR_ADDREQUEST + tr.time.micro:=MICRO_DELAY + beginIO(tr) + ELSE + -> Tell main() we're out of here. + tsidata.flag:=STOPPED + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/vertb.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/vertb.e new file mode 100644 index 0000000..023771c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Interrupts/vertb.e @@ -0,0 +1,64 @@ +-> vertb.e - Vertical blank interrupt server example. + +-> E-Note: we need eCodeSoftInt() in order to execute E code as an interrupt +-> (this wouldn't be needed if we just used Assembly, see below) +MODULE 'other/ecode', + 'dos/dos', + 'exec/interrupts', + 'exec/memory', + 'exec/nodes', + 'hardware/intbits' + +ENUM ERR_NONE, ERR_ECODE + +PROC main() HANDLE + DEF vbint:PTR TO is, counter=0, endcount + + -> Allocate memory for interrupt node. + vbint:=NewM(SIZEOF is, MEMF_PUBLIC OR MEMF_CLEAR) + vbint.ln.type:=NT_INTERRUPT -> Initialise the node. + vbint.ln.pri:=-60 + vbint.ln.name:='VertB-Example' + vbint.data:={counter} + vbint.code:=eCodeIntServer({vertBServer}) + IF vbint.code=NIL THEN Raise(ERR_ECODE) + + AddIntServer(INTB_VERTB, vbint) -> Kick this interrupt server into life. + + WriteF('VBlank server will increment a counter every frame.\n') + WriteF('counter started at zero, CTRL-C to remove server\n') + + Wait(SIGBREAKF_CTRL_C) + endcount:=counter + WriteF('\d vertical blanks occurred\nRemoving server\n', endcount) + + RemIntServer(INTB_VERTB, vbint) + +EXCEPT DO + -> E-Note: not really necessary... + IF vbint THEN Dispose(vbint) + SELECT exception + CASE ERR_ECODE; WriteF('Error: Ran out of memory in eCodeIntServer()\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC + +-> Entered with: A0 == scratch (execpt for highest pri vertb server) +-> D0 == scratch A1 == is_Data +-> D1 == scratch A5 == vector to interrupt code (scratch) +-> A6 == scratch +-> +-> E-Note: we could use this Assembly, but we'll show how to use a PROC instead +-> (so we needed eCodeIntServer() above) +-> +-> vertBServer: +-> ADDI.L #1, (A1) -> Increments counter is_Data points to +-> MOVEQ.L #0, D0 -> Set Z flag to continue to process other vb-servers +-> RTS -> Return to exec + +-> E-Note: we get vbint.data as an argument, and the PROC result should be +-> zero to continue with other servers in this chain (the default), +-> or non-zero (e.g., RETURN TRUE) to skip them +PROC vertBServer(data:PTR TO LONG) + data[]:=data[]+1 +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Lists/buildlist.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Lists/buildlist.e new file mode 100644 index 0000000..7459f5c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Lists/buildlist.e @@ -0,0 +1,95 @@ +-> buildlist.e - Example which uses an application-specific Exec list + +MODULE 'amigalib/lists', + 'exec/lists', + 'exec/nodes' + +CONST DATASIZE=62 + +OBJECT nameNode + ln:ln -> System Node structure + data[DATASIZE]:ARRAY -> Node-specific data +ENDOBJECT + +CONST NAMENODE_ID=100 -> The type of 'nameNode' + +PROC main() HANDLE + DEF nameList=NIL:PTR TO lh -> Note that a mlh would also work + NEW nameList + newList(nameList) -> Important: prepare header for use + + addName(nameList, 'Name7'); addName(nameList, 'Name6') + addName(nameList, 'Name5'); addName(nameList, 'Name4') + addName(nameList, 'Name2'); addName(nameList, 'Name0') + + addName(nameList, 'Name7'); addName(nameList, 'Name5') + addName(nameList, 'Name3'); addName(nameList, 'Name1') + + displayName(nameList, 'Name5') + displayNameList(nameList) + +EXCEPT DO + IF nameList + -> E-Note: none of this is necessary, since the program is terminating + -> and the memory will be freed automatically + freeNameNodes(nameList) + END nameList -> Free list header + ENDIF + SELECT exception + CASE "MEM"; WriteF('Error: Out of memory\n') + ENDSELECT +ENDPROC + +-> Allocate a NameNode structure, copy the given name into the structure, then +-> add it the specified list. This example does not provide an error return +-> for the out of memory condition. +-> E-Note: ...instead it raises an exception which is handled by the caller +PROC addName(list, name) + DEF namenode:PTR TO nameNode + NEW namenode + -> E-Note: copy *safely* to namenode.data + AstrCopy(namenode.data, name, DATASIZE) + namenode.ln.name:=namenode.data + namenode.ln.type:=NAMENODE_ID + namenode.ln.pri:=0 + AddHead(list, namenode) +ENDPROC + +-> Free the entire list, including the header. The header is not updated as +-> the list is freed. This function demonstrates how to avoid referencing +-> freed memory when deallocating nodes. +PROC freeNameNodes(list:PTR TO lh) + DEF worknode:PTR TO nameNode, nextnode + worknode:=list.head -> First node + WHILE nextnode:=worknode.ln.succ + END worknode + worknode:=nextnode + ENDWHILE +ENDPROC + +-> Print the names of each node in a list. +PROC displayNameList(list:PTR TO lh) + DEF node:PTR TO ln + IF list.tailpred=list + WriteF('List is empty.\n') + ELSE + node:=list.head + WHILE node.succ + WriteF('$\h -> \s\n', node, node.name) + node:=node.succ + ENDWHILE + ENDIF +ENDPROC + +-> Print the location of all nodes with a specified name. +PROC displayName(list, name) + DEF node:PTR TO ln + IF node:=FindName(list,name) + WHILE node + WriteF('Found a \s at location $\h\n', node.name, node) + node:=FindName(node, name) + ENDWHILE + ELSE + WriteF('No node with name \s found.\n', name) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocate.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocate.e new file mode 100644 index 0000000..16b22e0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocate.e @@ -0,0 +1,40 @@ +-> allocate.e - Example of allocating and using a private memory pool. + +MODULE 'exec/memory', + 'exec/nodes' + +CONST BLOCKSIZE=4000 -> Or whatever you need + +PROC main() HANDLE + DEF mh=NIL:PTR TO mh, mc=NIL:PTR TO mc, block1, block2 + + -> Get the MemHeader needed to keep track of our new block. + NEW mh + + -> Get the actual block the above MemHeader will manage. + mc:=NewR(BLOCKSIZE) + + mh.ln.type:=NT_MEMORY + mh.first:=mc + mh.lower:=mc + mh.upper:=mc+BLOCKSIZE + mh.free:=BLOCKSIZE + + mc.next:=NIL -> Set up first chunk in the freelist + mc.bytes:=BLOCKSIZE + + block1:=Allocate(mh, 20) + block2:=Allocate(mh, 314) + + WriteF('Our mh object at $\h. Our block of memory at $\h\n', mh, mc) + WriteF('Allocated from our pool: block1 at $\h, block2 at $\h\n', + block1, block2) + +EXCEPT DO + -> E-Note: the freeing is not necessary, since the program is terminating + IF mc THEN Dispose(mc) + IF mh THEN END mh + SELECT exception + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocentry.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocentry.e new file mode 100644 index 0000000..7dda765 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Memory/allocentry.e @@ -0,0 +1,43 @@ +-> allocentry.e - Example of allocating several memory areas. + +MODULE 'exec/memory' + +CONST ALLOCERROR=$80000000 + +-> E-Note: like the Assembly version, a ml does not contain a me, so body[4] +OBJECT memBlocks + head:ml -> One entry in the header, additional entries follow + body[4]:ARRAY OF me -> directly as part of the same data structure +ENDOBJECT + +DEF memlist:PTR TO ml, -> Pointer to a ml object + memblocks:memBlocks + +PROC main() + memblocks.head.numentries:=4 -> E-Note: The ml does not contain another me! + + -> Describe the first piece of memory we want. + -> E-Note: every me is in the body, unlike the C version + memblocks.body[0].reqs:=MEMF_CLEAR + memblocks.body[0].length:=4000 + + -> Describe the other pieces of memory we want. Additional me's are + -> initialised this way. If we wanted even more entries, we would need to + -> declare a larger me array in our memBlocks object. + memblocks.body[1].reqs:=MEMF_CHIP OR MEMF_CLEAR + memblocks.body[1].length:=100000 + memblocks.body[2].reqs:=MEMF_PUBLIC OR MEMF_CLEAR + memblocks.body[2].length:=200000 + memblocks.body[3].reqs:=MEMF_PUBLIC + memblocks.body[3].length:=25000 + + memlist:=AllocEntry(memblocks) + + IF memlist AND ALLOCERROR -> 'error' bit 31 is set (see below). + WriteF('AllocEntry FAILED\n') + ENDIF + + -> We got all memory we wanted. Use it and call FreeEntry() to free it + WriteF('AllocEntry succeeded - now freeing all allocated blocks\n') + FreeEntry(memlist) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port1.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port1.e new file mode 100644 index 0000000..c8ef9dc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port1.e @@ -0,0 +1,51 @@ +-> port1.e - Port and message example, run at the same time as port2.e + +MODULE 'amigalib/ports', + 'dos/dos', + 'exec/ports' + +ENUM ERR_NONE, ERR_PORT + +OBJECT xyMessage + msg:mn + x:INT + y:INT +ENDOBJECT + +PROC main() HANDLE + DEF xyport=NIL:PTR TO mp, xymsg:PTR TO xyMessage, + portsig, usersig, signal, abort=FALSE + IF NIL=(xyport:=createPort('xyport', 0)) THEN Raise(ERR_PORT) + portsig:=Shl(1, xyport.sigbit) + usersig:=SIGBREAKF_CTRL_C -> Give user a 'break' signal. + + WriteF('Start port2 in another shell. CTRL-C here when done.\n') + -> port1 will wait forever and reply to messages, until the user breaks + REPEAT + signal:=Wait(portsig OR usersig) + -> Since we only have one port that might get messages we have to reply + -> to, it is not really necessary to test for the portsignal. If there + -> is not a message at the port, xymsg simply will be NIL. + IF signal AND portsig + WHILE xymsg:=GetMsg(xyport) + WriteF('port1 received: x = \d y = \d\n', xymsg.x, xymsg.y) + xymsg.x:=xymsg.x+50 -> Since we have not replied yet to the owner of + xymsg.y:=xymsg.y+50 -> xymsg, we can change the data contents of xymsg. + WriteF('port1 replying with: x = \d y = \d\n', xymsg.x, xymsg.y) + ReplyMsg(xymsg) + ENDWHILE + ENDIF + IF signal AND usersig -> The user wants to abort. + abort:=TRUE + ENDIF + UNTIL abort +EXCEPT DO + IF xyport + -> Make sure the port is empty. + WHILE xymsg:=GetMsg(xyport) DO ReplyMsg(xymsg) + deletePort(xyport) + ENDIF + SELECT exception + CASE ERR_PORT; WriteF('Couldn''t create "xyport"\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port2.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port2.e new file mode 100644 index 0000000..016a594 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Ports/port2.e @@ -0,0 +1,69 @@ +-> port2.e - Port and message example, run at the same time as port1.e + +MODULE 'amigalib/ports', + 'dos/dos', + 'exec/memory', + 'exec/nodes', + 'exec/ports' + +ENUM ERR_NONE, ERR_FINDPORT, ERR_CREATEPORT + +OBJECT xyMessage + msg:mn + x:INT + y:INT +ENDOBJECT + +PROC main() HANDLE + DEF xyreplyport=NIL:PTR TO mp, xymsg=NIL:PTR TO xyMessage, + reply:PTR TO xyMessage + -> Using createPort() with no name because this port need not be public. + IF NIL=(xyreplyport:=createPort(NIL, 0)) THEN Raise(ERR_CREATEPORT) + xymsg:=NewM(SIZEOF xyMessage, MEMF_PUBLIC OR MEMF_CLEAR) + xymsg.msg.ln.type:=NT_MESSAGE -> Make up a message, including the + xymsg.msg.length:=SIZEOF xyMessage -> reply port. + xymsg.msg.replyport:=xyreplyport + xymsg.x:=10 -> Our special message information + xymsg.y:=20 + + WriteF('Sending to port1: x = \d y = \d\n', xymsg.x, xymsg.y) + + -> port2 will simply try to put one message to port1, wait for the reply, + -> and then exit + IF FALSE=safePutToPort(xymsg, 'xyport') THEN Raise(ERR_FINDPORT) + + WaitPort(xyreplyport) + IF reply:=GetMsg(xyreplyport) + -> We don't ReplyMsg since WE initiated the message. + WriteF('Reply contains: x = \d y = \d\n', xymsg.x, xymsg.y) + ENDIF + + -> Since we only use this private port for receiving replies, and we sent + -> only one and got one reply there is no need to cleanup. For a public port, + -> or if you pass a pointer to the port to another process, it is a very + -> good habit to always handle all messages at the port before you delete it. +EXCEPT DO + IF xymsg THEN Dispose(xymsg) -> E-Note: not really necessary + IF xyreplyport THEN deletePort(xyreplyport) + SELECT exception + CASE ERR_CREATEPORT + WriteF('Couldn''t create "xyreplyport"\n') + CASE ERR_FINDPORT + WriteF('Can''t find "xyport"; start port1 in a separate shell\n') + CASE "MEM" + WriteF('Couldn''t get memory\n') + ENDSELECT +ENDPROC + +PROC safePutToPort(message, portname) + DEF port:PTR TO mp + Forbid() + port:=FindPort(portname) + IF port THEN PutMsg(port, message) + Permit() + -> Once we've done a Permit(), the port might go away and leave us with an + -> invalid port address. So we return just a boolean to indicate whether + -> the message has been sent or not. + -> E-Note: Be careful - if FindPort() automatically raised an exception + -> you might forget to Permit()! +ENDPROC port<>NIL -> FALSE if the port was not found diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Semaphores/semaphore.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Semaphores/semaphore.e new file mode 100644 index 0000000..3f42c4b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Semaphores/semaphore.e @@ -0,0 +1,13 @@ +-> semaphore.e - Exec semaphore example + +MODULE 'exec/semaphores' + +PROC main() + DEF lockSemaphore:ss + InitSemaphore(lockSemaphore) + ObtainSemaphore(lockSemaphore) -> Task now owns the semaphore. + + -> ... + + ReleaseSemaphore(lockSemaphore) -> Task has released the semaphore. +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Signals/signals.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Signals/signals.e new file mode 100644 index 0000000..6952da7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Signals/signals.e @@ -0,0 +1,71 @@ +-> signals.e + +-> E-Note: eCodeTask() protects an E function so you can call it from other +-> tasks and have access to the global variables of this program +MODULE 'amigalib/tasks', + 'other/ecode', + 'dos/dos' + +ENUM ERR_NONE, ERR_ECODE, ERR_SIG, ERR_TASK + +RAISE ERR_SIG IF AllocSignal()=-1 + +DEF mainsignum=-1, mainsig, wakeupsigs, maintask=NIL, subtask=NIL + +PROC main() HANDLE + DEF done=FALSE, waitingForSubtask=TRUE, ecode, subtaskname + subtaskname:='RKM_signal_subtask' + + -> We must allocate any special signals we want to receive. + mainsignum:=AllocSignal(-1) + + mainsig:=Shl(1, mainsignum) -> subtask can access this global + maintask:=FindTask(NIL) -> subtask can access this global + + WriteF('We alloc a signal, create a task, wait for signals\n') + IF NIL=(ecode:=eCodeTask({subtaskcode})) THEN Raise(ERR_ECODE) + IF NIL=(subtask:=createTask(subtaskname, 0, ecode, 2000)) THEN Raise(ERR_TASK) + + WriteF('After subtask signals, press CTRL-C or CTRL-D to exit\n') + + REPEAT + -> Wait on the combined mask for all of the signals we are interested in. + -> All processes have the CTRL_C thru CTRL_F signals. We're also Waiting + -> on the mainsig we allocated for our subtask to signal us with. We could + -> also Wait on the signals of any ports/windows our main task created... + wakeupsigs:=Wait(mainsig OR SIGBREAKF_CTRL_C OR SIGBREAKF_CTRL_D) + + -> Deal with all signals that woke us up - may be more than one + IF wakeupsigs AND mainsig + WriteF('Signalled by subtask\n') + waitingForSubtask:=FALSE -> OK to kill subtask now + ENDIF + IF wakeupsigs AND SIGBREAKF_CTRL_C + WriteF('Got CTRL-C signal\n') + done:=TRUE + ENDIF + IF wakeupsigs AND SIGBREAKF_CTRL_D + WriteF('Got CTRL-D signal\n') + done:=TRUE + ENDIF + UNTIL done AND (waitingForSubtask=FALSE) +EXCEPT DO + IF subtask + Forbid() + deleteTask(subtask) + Permit() + ENDIF + IF mainsignum<>-1 THEN FreeSignal(mainsignum) + SELECT exception + CASE ERR_SIG; WriteF('No signals available\n') + CASE ERR_TASK; WriteF('Can''t create subtask\n') + CASE ERR_ECODE; WriteF('Ran out of memory in eCodeTask()\n') + ENDSELECT +ENDPROC + +PROC subtaskcode() + Signal(maintask, mainsig) + Wait(NIL) -> Safe state in which this subtask can be deleted +ENDPROC + +verstag: CHAR 0, '$VER: signals 37.1 (28.3.91)', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/simpletask.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/simpletask.e new file mode 100644 index 0000000..3519049 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/simpletask.e @@ -0,0 +1,56 @@ +-> simpletask.e - Uses the amigalib function createTask() to create a simple +-> subtask. See the Includes and Autodocs manual for createTask() source code. + +MODULE 'amigalib/tasks', + 'other/ecode', + 'dos/dos' + +ENUM ERR_NONE, ERR_ECODE, ERR_TASK + +CONST STACK_SIZE=1000 + +-> Task name, pointers for allocated task struct and stack +DEF task=NIL, simpletaskname, sharedvar + +PROC main() HANDLE + DEF taskcode + simpletaskname:='SimpleTask' + + sharedvar:=0 + + -> E-Note: eCodeTask() protects an E function so you can call it from other + -> tasks and have access to the global variables of this program + IF NIL=(taskcode:=eCodeTask({simpletask})) THEN Raise(ERR_ECODE) + IF NIL=(task:=createTask(simpletaskname, 0, taskcode, STACK_SIZE)) + Raise(ERR_TASK) + ENDIF + + WriteF('This program initialised a variable to zero, then started a\n') + WriteF('separate task which is incrementing that variable right now,\n') + WriteF('while this program waits for you to press RETURN.\n') + WriteF('Press RETURN now: ') + -> E-Note: WriteF() opens a window if necessary, so use stdout if no stdin + Inp(IF stdin THEN stdin ELSE stdout) + + WriteF('The shared variable now equals \d\n', sharedvar) + +EXCEPT DO + IF task + -> We can simply remove the task we added because our simpletask does + -> not make any system calls which could cause it to be awakened or + -> signalled later. + Forbid() + deleteTask(task) + Permit() + ENDIF + SELECT exception + CASE ERR_ECODE; WriteF('Ran out of memory in eCodeTask()\n') + CASE ERR_TASK; WriteF('Can''t create task\n') + ENDSELECT +ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK + +PROC simpletask() + WHILE sharedvar<$8000000 DO sharedvar++ + -> Wait forever because main() is going to RemTask() us + Wait(NIL) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/tasklist.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/tasklist.e new file mode 100644 index 0000000..501b135 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/tasklist.e @@ -0,0 +1,102 @@ +-> tasklist.e - Snapshots and prints the ExecBase task list + +MODULE 'amigalib/lists', + 'exec/execbase', + 'exec/lists', + 'exec/nodes', + 'exec/tasks' + +CONST NAMELEN=32 + +-> Use extended structure to hold task information +OBJECT taskNode + ln:ln + taskaddress + sigalloc + sigwait + name[NAMELEN]:ARRAY +ENDOBJECT + +PROC main() HANDLE + DEF ourtasklist:PTR TO lh, task:PTR TO tc, node:PTR TO taskNode, + tnode:PTR TO taskNode, rnode, exec:PTR TO execbase + -> E-Note: get the right type for execbase + exec:=execbase + + -> Allocate memory for out list + NEW ourtasklist + -> Initialise list structure (ala newList()) + -> E-Note: so why not use newList()!?! + newList(ourtasklist) + + -> Make sure tasks won't switch lists or go away + Disable() + + -> Snapshot task WAIT list + snapshot(exec.taskwait, ourtasklist) + + -> Snapshot task READY list + -> E-Note: rnode will be first READY task + rnode:=snapshot(exec.taskready, ourtasklist) + + -> Re-enable interrupts and taskswitching + Enable() + + -> Print now (printing above would have defeated a Forbid or Disable) + WriteF('Pri Address SigAlloc SigWait Taskname\n') + + node:=ourtasklist.head + WriteF('\nWAITING:\n') + WHILE tnode:=node.ln.succ + IF tnode=rnode THEN WriteF('\nREADY:\n') -> We set rnode above + WriteF('\z\d[2] \z$\h[8] \z$\h[8] \z$\h[8] \s\n', + node.ln.pri, node.taskaddress, node.sigalloc, + node.sigwait, node.name) + -> E-Note: ignore the messy clean up - see exception handler + node:=tnode + ENDWHILE + + -> Say who we are + WriteF('\nTHIS TASK:\n') + task:=FindTask(NIL) + WriteF('\z\d[2] \z$\h[8] \z$\h[8] \z$\h[8] \s\n', + task.ln.pri, task, task.sigalloc, task.sigwait, task.ln.name) + +EXCEPT DO + IF ourtasklist + -> E-Note: none of this is necessary, since the program is terminating + node:=ourtasklist.head + WHILE tnode:=node.ln.succ + END node + node:=tnode + ENDWHILE + END ourtasklist + ENDIF + SELECT exception + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC + +-> E-Note: having a separate procedure avoids repeating all this code as well +-> as localising any exception from NEW +PROC snapshot(from:PTR TO lh, to:PTR TO lh) HANDLE + -> E-Note: we are really dealing with "tc" (task) nodes not "ln" nodes + DEF exectask:PTR TO tc, tnode:PTR TO taskNode, first=NIL + exectask:=from.head + WHILE exectask.ln.succ + NEW tnode + -> Save task information we want to print + -> E-Note: copy *safely* to tnode.name + AstrCopy(tnode.name, exectask.ln.name, NAMELEN) + tnode.ln.pri:=exectask.ln.pri + tnode.taskaddress:=exectask + tnode.sigalloc:=exectask.sigalloc + tnode.sigwait:=exectask.sigwait + AddTail(to, tnode) + IF first=NIL THEN first:=tnode -> E-Note: first task copied + exectask:=exectask.ln.succ + ENDWHILE +EXCEPT DO +ENDPROC first + +versTag: CHAR 0, '$VER: tasklist 37.2 (31.3.92)', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/trap.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/trap.e new file mode 100644 index 0000000..1bd15ab --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Exec_Library/Tasks/trap.e @@ -0,0 +1,43 @@ +-> trap.e - E example of sample integer divide-by-zero trap + +MODULE 'exec/tasks' + +DEF oldTrapCode, countdiv0 + +PROC main() + DEF thistask:PTR TO tc, k, j, z + + thistask:=FindTask(NIL) + + -> Save our task's current trap code pointer + oldTrapCode:=thistask.trapcode + + -> Point task to our assembler trap handler code. Ours will just count + -> divide-by-zero traps, and pass other traps on to the normal TrapCode. + thistask.trapcode:={trapa} + + countdiv0:=0 + + z:=0 -> E-Note: the E compiler will not allow an explicit "k/0"! + FOR k:=0 TO 3 -> Let's divide by zero a few times + WriteF('dividing \d by zero... ', k) + j:=k/z + WriteF('did it\n') + ENDFOR + WriteF('\nDivide by zero happened \d times\n', countdiv0) + + thistask.trapcode:=oldTrapCode -> Restore old trap code +ENDPROC + +trapa: -> Our trap handler entry + CMPI.L #5, (A7) -> Is this a divide by zero ? + BNE.S notdiv0 -> No + ADD.L #1, countdiv0 -> Yes, increment our div0 count +endtrap: + ADDQ #4, A7 -> Remove exception number from SSP + RTE -> Return from exception +notdiv0: + TST.L oldTrapCode -> Is there another trap handler ? + BEQ.S endtrap -> No, so we'll exit + MOVE.L oldTrapCode, -(A7) -> Yes, go on to old TrapCode + RTS -> Jumps to old TrapCode diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Expansion/findboards.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Expansion/findboards.e new file mode 100644 index 0000000..cc63207 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Expansion/findboards.e @@ -0,0 +1,80 @@ +-> findboards.e + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'expansion', + 'libraries/configregs', + 'libraries/configvars' + +ENUM ERR_NONE, ERR_LIB + +RAISE ERR_LIB IF OpenLibrary()=NIL + +-> E-Note: used to convert an INT to unsigned +#define UNSIGNED(x) ((x) AND $FFFF) +-> E-Note: used to convert a LONG to unsigned CHAR +#define UNSIGNEDCHAR(x) ((x) AND $FF) +->>> + +->>> PROC main() +PROC main() HANDLE + DEF myCD:PTR TO configdev, m, i, p, f, t + expansionbase:=OpenLibrary('expansion.library', 0) + + -> FindConfigDev(oldConfigDev,manufacturer,product) + -> oldConfigDev = NIL for the top of the list + -> manufacturer = -1 for any manufacturer + -> product = -1 for any product + myCD:=NIL + WHILE myCD:=FindConfigDev(myCD, -1, -1) -> Search for all ConfigDevs + WriteF('\n---ConfigDev structure found at location $\h---\n', myCD) + + -> These values were read directly from the board at expansion time + WriteF('Board ID (ExpansionRom) information:\n') + + t:=myCD.rom.type + m:=UNSIGNED(myCD.rom.manufacturer) + p:=myCD.rom.product + f:=myCD.rom.flags + i:=UNSIGNED(myCD.rom.initdiagvec) + + WriteF('er_Manufacturer =\d=$\z\h[4]=(~$\h[4])\n', + m, m, UNSIGNED(Not(m))) + WriteF('er_Product =\d=$\z\h[2]=(~$\h[2])\n', + p, p, UNSIGNEDCHAR(Not(p))) + + WriteF('er_Type =$\z\h[2]', myCD.rom.type) + IF myCD.rom.type AND ERTF_MEMLIST + WriteF(' (Adds memory to free list)\n') + ELSE + WriteF('\n') + ENDIF + + WriteF('er_Flags =$\z\h[2]=(~$\h[2])\n', + f, UNSIGNEDCHAR(Not(f))) + WriteF('er_InitDiagVec =$\z\h[4]=(~$\h[4])\n', + i, UNSIGNED(Not(i))) + + -> These values are generated when the AUTOCONFIG(tm) software relocates + -> the board + WriteF('Configuration (ConfigDev) information:\n') + WriteF('cd_BoardAddr =$\h\n', myCD.boardaddr) + WriteF('cd_BoardSize =$\h (\dK)\n', + myCD.boardsize, myCD.boardsize/1024) + + WriteF('cd_Flags =$\h', myCD.flags) + IF myCD.flags AND CDF_CONFIGME + WriteF('\n') + ELSE + WriteF(' (driver clears CONFIGME bit)\n') + ENDIF + ENDWHILE +EXCEPT DO + IF expansionbase THEN CloseLibrary(expansionbase) + SELECT exception + CASE ERR_LIB; WriteF('Error: could not open expansion library\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsgadgets.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsgadgets.e new file mode 100644 index 0000000..dc48738 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsgadgets.e @@ -0,0 +1,273 @@ +-> gadtoolsgadgets.e +-> Simple example of using a number of gadtools gadgets. + +MODULE 'gadtools', + 'exec/ports', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens', + 'libraries/gadtools' + +ENUM ERR_NONE, ERR_FONT, ERR_GAD, ERR_KICK, ERR_LIB, ERR_PUB, ERR_VIS, ERR_WIN + +RAISE ERR_FONT IF OpenFont()=NIL, + ERR_GAD IF CreateGadgetA()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PUB IF LockPubScreen()=NIL, + ERR_VIS IF GetVisualInfoA()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +-> Gadget ENUM to be used as GadgetIDs and also as the indexes into the +-> gadget array my_gads[]. +ENUM MYGAD_SLIDER, MYGAD_STRING1, MYGAD_STRING2, MYGAD_STRING3, MYGAD_BUTTON + +-> Range for the slider: +CONST SLIDER_MIN=1, SLIDER_MAX=20 + +DEF topaz80 + +-> Function to handle a GADGETUP or GADGETDOWN event. For GadTools gadgets, +-> it is possible to use this function to handle MOUSEMOVEs as well, with +-> little or no work. +-> E-Note: slider_level is not a 'PTR TO INT', but 'PTR TO LONG' +PROC handleGadgetEvent(win, gad:PTR TO gadget, code, + slider_level:PTR TO LONG, my_gads:PTR TO LONG) + DEF id + id:=gad.gadgetid + SELECT id + CASE MYGAD_SLIDER + -> Sliders report their level in the IntuiMessage Code field: + WriteF('Slider at level \d\n', code) + slider_level[]:=code + CASE MYGAD_STRING1 + -> String gadgets report GADGETUP's + WriteF('String gadget 1: "\s".\n', gad.specialinfo::stringinfo.buffer) + CASE MYGAD_STRING2 + -> String gadgets report GADGETUP's + WriteF('String gadget 2: "\s".\n', gad.specialinfo::stringinfo.buffer) + CASE MYGAD_STRING3 + -> String gadgets report GADGETUP's + WriteF('String gadget 3: "\s".\n', gad.specialinfo::stringinfo.buffer) + CASE MYGAD_BUTTON + -> Buttons report GADGETUP's (button resets slider to 10) + WriteF('Button was pressed, slider reset to 10.\n') + slider_level[]:=10 + Gt_SetGadgetAttrsA(my_gads[MYGAD_SLIDER], win, NIL, + [GTSL_LEVEL, slider_level[], NIL]) + ENDSELECT +ENDPROC + +-> Function to handle vanilla keys. +-> E-Note: slider_level is not a 'PTR TO INT', but 'PTR TO LONG' +PROC handleVanillaKey(win, code, slider_level:PTR TO LONG, my_gads:PTR TO LONG) + SELECT "w" OF code + CASE "v" + -> Increase slider level, but not past maximum + slider_level[]:=Min(slider_level[]+1, SLIDER_MAX) + Gt_SetGadgetAttrsA(my_gads[MYGAD_SLIDER], win, NIL, + [GTSL_LEVEL, slider_level[], NIL]) + CASE "V" + -> Decrease slider level, but not past maximum + slider_level[]:=Max(slider_level[]-1, SLIDER_MIN) + Gt_SetGadgetAttrsA(my_gads[MYGAD_SLIDER], win, NIL, + [GTSL_LEVEL, slider_level[], NIL]) + CASE "c", "C" + -> Button resets slider to 10 + slider_level[]:=10 + Gt_SetGadgetAttrsA(my_gads[MYGAD_SLIDER], win, NIL, + [GTSL_LEVEL, slider_level[], NIL]) + CASE "f", "F" + ActivateGadget(my_gads[MYGAD_STRING1], win, NIL) + CASE "s", "S" + ActivateGadget(my_gads[MYGAD_STRING2], win, NIL) + CASE "t", "T" + ActivateGadget(my_gads[MYGAD_STRING3], win, NIL) + ENDSELECT +ENDPROC + +-> Here is where all the initialisation and creation of GadTools gadgets take +-> place. This function requires a pointer to a NIL-initialised gadget list +-> pointer. It returns a pointer to the last created gadget. +-> E-Note: exceptions raised by CreateGadgetA() will be handled by caller +PROC createAllGadgets(glistptr:PTR TO LONG, vi, topborder, + slider_level, my_gads:PTR TO LONG) + DEF gad, ng:PTR TO newgadget + -> All the gadget creation calls accept a pointer to the previous gadget, and + -> link the new gadget to that gadget's NextGadget field. Also, they exit + -> gracefully, returning NIL, if any previous gadget was NIL. This limits + -> the amount of checking for failure that is needed. You only need to check + -> before you tweak any gadget structure or use any of its fields, and + -> finally once at the end, before you add the gadgets. + + -> The following operation is required of any program that uses GadTools. + -> It gives the toolkit a place to stuff context data. + gad:=CreateContext(glistptr) + + -> Since the NewGadget structure is unmodified by any of the CreateGadgetA() + -> calls, we need only change those fields which are different. + ng:=[140, (20+topborder), 200, 12, '_Volume: ', topaz80, + MYGAD_SLIDER, NG_HIGHLABEL, vi, 0]:newgadget + + my_gads[MYGAD_SLIDER]:=(gad:=CreateGadgetA(SLIDER_KIND, gad, ng, + [GTSL_MIN, SLIDER_MIN, + GTSL_MAX, SLIDER_MAX, + GTSL_LEVEL, slider_level, + GTSL_LEVELFORMAT, '\d[2]', + GTSL_MAXLEVELLEN, 2, + GT_UNDERSCORE, "_", + NIL])) + + ng.topedge := ng.topedge+20 + ng.height := 14 + ng.gadgettext := '_First:' + ng.gadgetid := MYGAD_STRING1 + my_gads[MYGAD_STRING1]:=(gad:=CreateGadgetA(STRING_KIND, gad, ng, + [GTST_STRING, 'Try pressing', + GTST_MAXCHARS, 50, + GT_UNDERSCORE, "_", + NIL])) + + ng.topedge := ng.topedge+20 + ng.gadgettext := '_Second:' + ng.gadgetid := MYGAD_STRING2 + my_gads[MYGAD_STRING2]:=(gad:=CreateGadgetA(STRING_KIND, gad, ng, + [GTST_STRING, 'TAB or Shift-TAB', + GTST_MAXCHARS, 50, + GT_UNDERSCORE, "_", + NIL])) + + ng.topedge := ng.topedge+20 + ng.gadgettext := '_Third:' + ng.gadgetid := MYGAD_STRING3 + my_gads[MYGAD_STRING3]:=(gad:=CreateGadgetA(STRING_KIND, gad, ng, + [GTST_STRING, 'To see what happens!', + GTST_MAXCHARS, 50, + GT_UNDERSCORE, "_", + NIL])) + + ng.leftedge := 50 + ng.topedge := 20 + ng.width := 100 + ng.height := 12 + ng.gadgettext := '_Click Here' + ng.gadgetid := MYGAD_BUTTON + ng.flags := 0 + gad:=CreateGadgetA(BUTTON_KIND, gad, ng, + [GT_UNDERSCORE, "_", NIL]) +ENDPROC gad + +-> Standard message handling loop with GadTools message handling functions +-> used (Gt_GetIMsg() and Gt_ReplyIMsg()). +-> E-Note: slider_level is not a 'PTR TO INT', but 'PTR TO LONG' +PROC process_window_events(mywin:PTR TO window, slider_level:PTR TO LONG, + my_gads:PTR TO LONG) + DEF imsg:PTR TO intuimessage, imsgClass, imsgCode, gad, terminated=FALSE + REPEAT + Wait(Shl(1, mywin.userport.sigbit)) + + -> Gt_GetIMsg() returns an IntuiMessage with more friendly information for + -> complex gadget classes. Use it wherever you get IntuiMessages where + -> using GadTools gadgets. + WHILE (terminated=FALSE) AND (imsg:=Gt_GetIMsg(mywin.userport)) + -> Presuming a gadget, of course, but no harm... Only dereference this + -> value (gad) where the Class specifies that it is a gadget event. + gad:=imsg.iaddress + + imsgClass:=imsg.class + imsgCode:=imsg.code + + -> Use the toolkit message-replying function here... + Gt_ReplyIMsg(imsg) + + SELECT imsgClass + -> --- WARNING --- WARNING --- WARNING --- WARNING --- WARNING --- + -> GadTools puts the gadget address into IAddress of IDCMP_MOUSEMOVE + -> messages. This is NOT true for standard Intuition messages, + -> but is an added feature of GadTools. + CASE IDCMP_GADGETDOWN + handleGadgetEvent(mywin, gad, imsgCode, slider_level, my_gads) + CASE IDCMP_MOUSEMOVE + handleGadgetEvent(mywin, gad, imsgCode, slider_level, my_gads) + CASE IDCMP_GADGETUP + handleGadgetEvent(mywin, gad, imsgCode, slider_level, my_gads) + + CASE IDCMP_VANILLAKEY + handleVanillaKey(mywin, imsgCode, slider_level, my_gads) + CASE IDCMP_CLOSEWINDOW + terminated:=TRUE + CASE IDCMP_REFRESHWINDOW + -> With GadTools, the application must use Gt_BeginRefresh() + -> where it would normally have used BeginRefresh() + Gt_BeginRefresh(mywin) + Gt_EndRefresh(mywin, TRUE) + ENDSELECT + ENDWHILE + UNTIL terminated +ENDPROC + +-> Prepare for using GadTools, set up gadgets and open window. +-> Clean up and when done or on error. +PROC gadtoolsWindow() HANDLE + DEF font=NIL, mysc=NIL:PTR TO screen, mywin=NIL, glist=NIL, + my_gads[4]:ARRAY OF LONG, vi, slider_level=5, topborder + -> Open topaz 8 font, so we can be sure it's openable when we later + -> set ng.textattr to Topaz80: + topaz80:=['topaz.font', 8, 0, 0]:textattr + font:=OpenFont(topaz80) + mysc:=LockPubScreen(NIL) + vi:=GetVisualInfoA(mysc, [NIL]) + + -> Here is how we can figure out ahead of time how tall the window's + -> title bar will be: + topborder:=mysc.wbortop+mysc.font.ysize+1 + + createAllGadgets({glist}, vi, topborder, slider_level, my_gads) + + mywin:=OpenWindowTagList(NIL, + [WA_TITLE, 'GadTools Gadget Demo', + WA_GADGETS, glist, WA_AUTOADJUST, TRUE, + WA_WIDTH, 400, WA_MINWIDTH, 50, + WA_INNERHEIGHT, 140, WA_MINHEIGHT, 50, + WA_DRAGBAR, TRUE, WA_DEPTHGADGET, TRUE, + WA_ACTIVATE, TRUE, WA_CLOSEGADGET, TRUE, + WA_SIZEGADGET, TRUE, WA_SIMPLEREFRESH, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_REFRESHWINDOW OR + IDCMP_VANILLAKEY OR SLIDERIDCMP OR + STRINGIDCMP OR BUTTONIDCMP, + WA_PUBSCREEN, mysc, + NIL]) + -> After window is open, gadgets must be refreshed with a call to the + -> GadTools refresh window function. + Gt_RefreshWindow(mywin, NIL) + + process_window_events(mywin, {slider_level}, my_gads) + +EXCEPT DO + IF mywin THEN CloseWindow(mywin) + -> FreeGadgets() even if createAllGadgets() fails, as some of the gadgets may + -> have been created... If glist is NIL then FreeGadgets() will do nothing. + FreeGadgets(glist) + IF vi THEN FreeVisualInfo(vi) + IF mysc THEN UnlockPubScreen(mysc, NIL) + IF font THEN CloseFont(font) + ReThrow() -> E-Note: pass on exception if it was an error +ENDPROC + +-> Open all libraries and run. Clean up when finished or on error.. +PROC main() HANDLE + KickVersion(37) + gadtoolsbase:=OpenLibrary('gadtools.library', 37) + gadtoolsWindow() +EXCEPT DO + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + SELECT exception + CASE ERR_FONT; WriteF('Error: Failed to open Topaz 80\n') + CASE ERR_GAD; WriteF('Error: createAllGadgets() failed\n') + CASE ERR_KICK; WriteF('Error: Requires V37\n') + CASE ERR_LIB; WriteF('Error: Requires V37 gadtools.library\n') + CASE ERR_PUB; WriteF('Error: Couldn''t lock default public screen\n') + CASE ERR_VIS; WriteF('Error: GetVisualInfoA() failed\n') + CASE ERR_WIN; WriteF('Error: OpenWindow() failed\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsmenu.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsmenu.e new file mode 100644 index 0000000..4e533e5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/gadtoolsmenu.e @@ -0,0 +1,98 @@ +-> gadtoolsmenu.e +-> Example showing the basic usage of the menu system with a window. +-> Menu layout is done with GadTools, as is recommended for applications. + +OPT PREPROCESS + +MODULE 'gadtools', + 'intuition/intuition', + 'libraries/gadtools' + +ENUM ERR_NONE, ERR_LIB, ERR_MENU, ERR_VIS, ERR_WIN + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_MENU IF CreateMenusA()=NIL, + ERR_VIS IF GetVisualInfoA()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +-> E-Note: used to convert an INT to unsigned +#define UNSIGNED(x) ((x) AND $FFFF) + +-> Watch the menus and wait for the user to select the close gadget or quit +-> from the menus. +PROC handle_window_events(win, menuStrip) + DEF done=FALSE, menuNumber, menuNum, itemNum, subNum, + item:PTR TO menuitem, class + REPEAT + -> E-Note: we can use WaitIMessage in this example + class:=WaitIMessage(win) + SELECT class + CASE IDCMP_CLOSEWINDOW + done:=TRUE + CASE IDCMP_MENUPICK + -> E-Note: convert message code to an unsigned INT + menuNumber:=UNSIGNED(MsgCode()) + WHILE (menuNumber<>MENUNULL) AND (done=FALSE) + item:=ItemAddress(menuStrip, menuNumber) + + -> Process the item here! + menuNum:=MENUNUM(menuNumber) + itemNum:=ITEMNUM(menuNumber) + subNum:=SUBNUM(menuNumber) + + -> Stop if quit is selected + IF (menuNum=0) AND (itemNum=5) THEN done:=TRUE + + -> E-Note: convert item.nextselect to an unsigned INT + menuNumber:=UNSIGNED(item.nextselect) + ENDWHILE + ENDSELECT + UNTIL done +ENDPROC + +-> Open all of the required libraries and set-up the menus +PROC main() HANDLE + DEF win=NIL:PTR TO window, my_VisualInfo=NIL, menuStrip=NIL + gadtoolsbase:=OpenLibrary('gadtools.library', 37) + win:=OpenWindowTagList(NIL, [WA_WIDTH, 400, WA_ACTIVATE, TRUE, + WA_HEIGHT, 100, WA_CLOSEGADGET, TRUE, + WA_TITLE, 'Menu Test Window', + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_MENUPICK, + NIL]) + my_VisualInfo:=GetVisualInfoA(win.wscreen, [NIL]) + menuStrip:=CreateMenusA([NM_TITLE, 0, 'Project', 0, 0, 0, 0, + NM_ITEM, 0, 'Open...', 'O', 0, 0, 0, + NM_ITEM, 0, 'Save', 'S', 0, 0, 0, + NM_ITEM, 0, NM_BARLABEL, 0, 0, 0, 0, + NM_ITEM, 0, 'Print', 0, 0, 0, 0, + NM_SUB, 0, 'Draft', 0, 0, 0, 0, + NM_SUB, 0, 'NLQ', 0, 0, 0, 0, + NM_ITEM, 0, NM_BARLABEL, 0, 0, 0, 0, + NM_ITEM, 0, 'Quit...', 'Q', 0, 0, 0, + NM_TITLE, 0, 'Edit', 0, 0, 0, 0, + NM_ITEM, 0, 'Cut', 'X', 0, 0, 0, + NM_ITEM, 0, 'Copy', 'C', 0, 0, 0, + NM_ITEM, 0, 'Paste', 'V', 0, 0, 0, + NM_ITEM, 0, NM_BARLABEL, 0, 0, 0, 0, + NM_ITEM, 0, 'Undo', 'Z', 0, 0, 0, + NM_END, 0, NIL, 0, 0, 0, 0]:newmenu, + [NIL]) + IF LayoutMenusA(menuStrip, my_VisualInfo, [NIL]) + IF SetMenuStrip(win, menuStrip) + handle_window_events(win, menuStrip) + + ClearMenuStrip(win) + ENDIF + FreeMenus(menuStrip) + ENDIF +EXCEPT DO + IF my_VisualInfo THEN FreeVisualInfo(my_VisualInfo) + IF win THEN CloseWindow(win) + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + SELECT exception + CASE ERR_LIB; WriteF('Error: Could not open gadtools.library\n') + CASE ERR_MENU; WriteF('Error: Could not create menu\n') + CASE ERR_VIS; WriteF('Error: Could not get visual info\n') + CASE ERR_WIN; WriteF('Error: Could not open window\n') + ENDSELECT +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/simplegtgadget.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/simplegtgadget.e new file mode 100644 index 0000000..f497913 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/GadTools/simplegtgadget.e @@ -0,0 +1,103 @@ +-> simplegtgadget.e - Simple example of a GadTools gadget. + +OPT OSVERSION=37 + +MODULE 'gadtools', + 'exec/ports', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens', + 'libraries/gadtools' + +ENUM ERR_NONE, ERR_GAD, ERR_LIB, ERR_PUB, ERR_VIS, ERR_WIN + +RAISE ERR_GAD IF CreateGadgetA()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PUB IF LockPubScreen()=NIL, + ERR_VIS IF GetVisualInfoA()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST MYGAD_BUTTON=4 + +-> Open all libraries and run. Clean up when finished or on error.. +PROC main() HANDLE + gadtoolsbase:=OpenLibrary('gadtools.library', 37) + gadtoolsWindow() +EXCEPT DO + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + SELECT exception + CASE ERR_GAD; WriteF('Error: Could not create gadget\n') + CASE ERR_LIB; WriteF('Error: Could not open gadtools.library\n') + CASE ERR_PUB; WriteF('Error: Could not lock public screen\n') + CASE ERR_VIS; WriteF('Error: Could not get visual info\n') + CASE ERR_WIN; WriteF('Error: Could not open window\n') + ENDSELECT +ENDPROC + +-> Prepare for using GadTools, set up gadgets and open window. +-> Clean up and when done or on error. +PROC gadtoolsWindow() HANDLE + DEF mysc=NIL:PTR TO screen, mywin=NIL, glist=NIL, gad, vi=NIL + mysc:=LockPubScreen(NIL) + vi:=GetVisualInfoA(mysc, [NIL]) + -> GadTools gadgets require this step to be taken + gad:=CreateContext({glist}) + + -> Create a button gadget centered below the window title + gad:=CreateGadgetA(BUTTON_KIND, gad, + [150, (20+mysc.wbortop+mysc.font.ysize+1), + 100, 12, + 'Click Here', ['topaz.font', 8, 0, 0]:textattr, + MYGAD_BUTTON, 0, + vi, NIL]:newgadget, + [NIL]) + mywin:=OpenWindowTagList(NIL, + [WA_TITLE, 'GadTools Gadget Demo', + WA_GADGETS, glist, WA_AUTOADJUST, TRUE, + WA_WIDTH, 400, WA_INNERHEIGHT, 100, + WA_DRAGBAR, TRUE, WA_DEPTHGADGET, TRUE, + WA_ACTIVATE, TRUE, WA_CLOSEGADGET, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW OR + IDCMP_REFRESHWINDOW OR BUTTONIDCMP, + WA_PUBSCREEN, mysc, + NIL]) + Gt_RefreshWindow(mywin, NIL) + process_window_events(mywin) +EXCEPT DO + IF mywin THEN CloseWindow(mywin) + -> FreeGadgets() must be called after the context has been created. + -> It does nothing if glist is NIL + FreeGadgets(glist) + IF vi THEN FreeVisualInfo(vi) + IF mysc THEN UnlockPubScreen(NIL, mysc) + ReThrow() -> E-Note: pass on exception if it is an error +ENDPROC + +-> Standard message handling loop with GadTools message handling functions +-> used (Gt_GetIMsg() and Gt_ReplyIMsg()). +PROC process_window_events(mywin:PTR TO window) + DEF imsg:PTR TO intuimessage, gad:PTR TO gadget, terminated=FALSE, class + REPEAT + Wait(Shl(1, mywin.userport.sigbit)) + + -> Use Gt_GetIMsg() and Gt_ReplyIMsg() for handling IntuiMessages + -> with GadTools gadgets. + WHILE (terminated=FALSE) AND (imsg:=Gt_GetIMsg(mywin.userport)) + -> Gt_ReplyIMsg() at end of loop + class:=imsg.class + SELECT class + CASE IDCMP_GADGETUP -> Buttons only report GADGETUP + gad:=imsg.iaddress + IF gad.gadgetid=MYGAD_BUTTON THEN WriteF('Button was pressed\n') + CASE IDCMP_CLOSEWINDOW + terminated:=TRUE + CASE IDCMP_REFRESHWINDOW + -> This handling is REQUIRED with GadTools. + Gt_BeginRefresh(mywin) + Gt_EndRefresh(mywin, TRUE) + ENDSELECT + -> Use the toolkit message-replying function here... + Gt_ReplyIMsg(imsg) + ENDWHILE + UNTIL terminated +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Gameport/Absolute_Joystick.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Gameport/Absolute_Joystick.e new file mode 100644 index 0000000..1a1f008 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Gameport/Absolute_Joystick.e @@ -0,0 +1,291 @@ +-> Absolute_Joystick.e - Gameport device absolute joystick example + +->>> Header (globals) +MODULE 'amigalib/ports', + 'amigalib/io', + 'devices/gameport', + 'devices/inputevent', + 'devices/timer', + 'exec/execbase', + 'exec/io', + 'exec/nodes', + 'exec/ports' + +ENUM ERR_NONE, ERR_DEV, ERR_IO, ERR_PORT + +RAISE ERR_DEV IF OpenDevice()<>0 + +CONST JOY_X_DELTA=1, JOY_Y_DELTA=1, TIMEOUT_SECONDS=10 + +DEF exec:PTR TO execbase +->>> + +->>> PROC printInstructions() +-> Routine to print out some information for the user. +PROC printInstructions() + WriteF('\n >>> gameport.device Absolute Joystick Demo <<<\n\n') + + IF exec.vblankfrequency=60 + WriteF(' Running on NTSC system (60 Hz).\n') + ELSEIF exec.vblankfrequency=50 + WriteF(' Running on PAL system (50 Hz).\n') + ENDIF + + WriteF(' Attach joystick to rear connector (A3000) and (A1000).\n' + + ' Attach joystick to right connector (A2000).\n' + + ' Attach joystick to left connector (A500).\n' + + ' Then move joystick and click its button(s).\n\n' + + ' To EXIT program press and release fire button 3 consecutive ' + + 'times.\n' + + ' The program also exits if no activity occurs for 1 minute.\n\n') +ENDPROC +->>> + +->>> PROC check_move(game_event:PTR TO inputevent) +-> Print out information on the event received. +PROC check_move(game_event:PTR TO inputevent) + DEF xmove, ymove, timeout=FALSE + xmove:=game_event.x + ymove:=game_event.y + + IF xmove=1 + IF ymove=1 + WriteF('RIGHT DOWN\n') + ELSEIF ymove=0 + WriteF('RIGHT\n') + ELSEIF ymove=-1 + WriteF('RIGHT UP\n') + ELSE + WriteF('UNKNOWN Y\n') + ENDIF + ELSEIF xmove=-1 + IF ymove=1 + WriteF('LEFT DOWN\n') + ELSEIF ymove=0 + WriteF('LEFT\n') + ELSEIF ymove=-1 + WriteF('LEFT UP\n') + ELSE + WriteF('UNKNOWN Y\n') + ENDIF + ELSEIF xmove=0 + IF ymove=1 + WriteF('DOWN\n') + ELSEIF ymove=0 + -> Note that 0,0 can be a timeout, or a direction release. + IF game_event.timestamp.secs >= (exec.vblankfrequency*TIMEOUT_SECONDS) + -> Under 1.3 (V34) and earlier versions of the Amiga OS, the + -> timestamp.secs field used in the IF statement above is not + -> correctly filled in. Therefore, this program cannot tell the + -> difference between a release event and a timeout under 1.3 (release + -> events will be reported as timeouts). + WriteF('TIMEOUT\n') + timeout:=TRUE + ELSE + WriteF('RELEASE\n') + ENDIF + ELSEIF ymove=-1 + WriteF('UP\n') + ELSE + WriteF('UNKNOWN Y\n') + ENDIF + ELSE + WriteF('UNKNOWN X ') + IF ymove=1 + WriteF('unknown action\n') + ELSEIF ymove=0 + WriteF('unknown action\n') + ELSEIF ymove=-1 + WriteF('unknown action\n') + ELSE + WriteF('UNKNOWN Y\n') + ENDIF + ENDIF +ENDPROC timeout +->>> + +->>> PROC send_read_request(game_event, game_io_msg:PTR TO iostd) +-> Send a request to the gameport to read an event. +PROC send_read_request(game_event, game_io_msg:PTR TO iostd) + game_io_msg.command:=GPD_READEVENT + game_io_msg.flags:=0 + game_io_msg.data:=game_event + game_io_msg.length:=SIZEOF inputevent + SendIO(game_io_msg) -> Asynchronous - message will return later +ENDPROC +->>> + +->>> PROC processEvents(game_io_msg:PTR TO iostd, game_msg_port:PTR TO mp) +-> Simple loop to process gameport events. +PROC processEvents(game_io_msg:PTR TO iostd, game_msg_port:PTR TO mp) + DEF timeout, timeouts, button_count, not_finished, code, + game_event:inputevent -> Where input event will be stored + -> From now on, just read input events into the event buffer, + -> one at a time. READEVENT waits for the preset conditions. + timeouts:=0 + button_count:=0 + not_finished:=TRUE + + WHILE (timeouts<6) AND not_finished + -> Send the read request + send_read_request(game_event, game_io_msg) + + -> Wait for joystick action + Wait(Shl(1, game_msg_port.sigbit)) + WHILE NIL<>GetMsg(game_msg_port) + timeout:=FALSE + code:=game_event.code + SELECT code + CASE IECODE_LBUTTON + WriteF(' FIRE BUTTON PRESSED \n') + CASE IECODE_LBUTTON OR IECODE_UP_PREFIX + WriteF(' FIRE BUTTON RELEASED \n') + button_count++ + IF 3=button_count THEN not_finished:=FALSE + CASE IECODE_RBUTTON + WriteF(' ALT BUTTON PRESSED \n') + button_count:=0 + CASE IECODE_RBUTTON OR IECODE_UP_PREFIX + WriteF(' ALT BUTTON RELEASED \n') + button_count:=0 + CASE IECODE_NOBUTTON + -> Check for change in position + timeout:=check_move(game_event) + button_count:=0 + DEFAULT + ENDSELECT + + IF timeout + INC timeouts + ELSE + timeouts:=0 + ENDIF + ENDWHILE + ENDWHILE +ENDPROC +->>> + +->>> PROC set_controller_type(type, game_io_msg:PTR TO iostd) +-> Allocate the controller if it is available. You allocate the controller by +-> setting its type to something other than GPCT_NOCONTROLLER. Before you +-> allocate the thing you need to check if anyone else is using it (it is free +-> if it is set to GPCT_NOCONTROLLER). +PROC set_controller_type(type, game_io_msg:PTR TO iostd) + DEF success=FALSE, controller_type_addr + controller_type_addr:=[0]:CHAR + -> Begin critical section. + -> We need to be sure that between the time we check that the controller is + -> available and the time we allocate it, no one else steals it. + Forbid() + + game_io_msg.command:=GPD_ASKCTYPE -> Enquire current status + game_io_msg.flags:=IOF_QUICK + game_io_msg.data:=controller_type_addr -> Put answer in here + game_io_msg.length:=1 + DoIO(game_io_msg) + + -> No one is using this device unit, let's claim it + IF controller_type_addr[]=GPCT_NOCONTROLLER + game_io_msg.command:=GPD_SETCTYPE + game_io_msg.flags:=IOF_QUICK + game_io_msg.data:=[type]:CHAR + game_io_msg.length:=1 + DoIO( game_io_msg) + success:=TRUE + ENDIF + + Permit() -> Critical section end +ENDPROC success +->>> + +->>> PROC set_trigger_conditions(gpt:PTR TO gameporttrigger, game_io_msg:...) +-> Tell the gameport when to trigger. +PROC set_trigger_conditions(gpt:PTR TO gameporttrigger, + game_io_msg:PTR TO iostd) + -> Trigger on all joystick key transitions + gpt.keys:=GPTF_UPKEYS OR GPTF_DOWNKEYS + gpt.xdelta:=JOY_X_DELTA + gpt.ydelta:=JOY_Y_DELTA + -> Timeout trigger every TIMEOUT_SECONDS second(s) + gpt.timeout:=exec.vblankfrequency*TIMEOUT_SECONDS + + game_io_msg.command:=GPD_SETTRIGGER + game_io_msg.flags:=IOF_QUICK + game_io_msg.data:=gpt + game_io_msg.length:=SIZEOF gameporttrigger + DoIO(game_io_msg) +ENDPROC +->>> + +->>> PROC flush_buffer(game_io_msg:PTR TO iostd) +-> Clear the buffer. Do this before you begin to be sure you start in a known +-> state. +PROC flush_buffer(game_io_msg:PTR TO iostd) + game_io_msg.command:=CMD_CLEAR + game_io_msg.flags:=IOF_QUICK + game_io_msg.data:=NIL + game_io_msg.length:=0 + DoIO(game_io_msg) +ENDPROC +->>> + +->>> PROC free_gp_unit(game_io_msg:PTR TO iostd) +-> Free the unit by setting its type back to GPCT_NOCONTROLLER. +PROC free_gp_unit(game_io_msg:PTR TO iostd) + DEF type=GPCT_NOCONTROLLER + game_io_msg.command:=GPD_SETCTYPE + game_io_msg.flags:=IOF_QUICK + game_io_msg.data:=[type]:CHAR + game_io_msg.length:=1; + DoIO(game_io_msg) +ENDPROC +->>> + +->>> PROC main() +-> Allocate everything and go. On failure, free any resources that have been +-> allocated. +PROC main() HANDLE + DEF joytrigger:gameporttrigger, game_io_msg=NIL:PTR TO iostd, + game_msg_port=NIL, open_dev=FALSE + -> E-Note: get the right type for exec + exec:=execbase + -> Create port for gameport device communications + IF NIL=(game_msg_port:=createPort('RKM_game_port', 0)) + Raise(ERR_PORT) + ENDIF + -> Create message block for device IO + IF NIL=(game_io_msg:=createExtIO(game_msg_port, SIZEOF iostd)) + Raise(ERR_IO) + ENDIF + + game_io_msg.mn.ln.type:=NT_UNKNOWN + -> Open the right/back (unit 1, number 2) gameport.device unit + OpenDevice('gameport.device', 1, game_io_msg, 0) + open_dev:=TRUE + -> Set controller type to joystick + IF set_controller_type(GPCT_ABSJOYSTICK, game_io_msg) + -> Specify the trigger conditions + set_trigger_conditions(joytrigger, game_io_msg) + + printInstructions() + + -> Clear device buffer to start from a known state. + -> There might still be events left. + flush_buffer(game_io_msg) + + processEvents(game_io_msg, game_msg_port) + + -> Free gameport unit so other applications can use it! + free_gp_unit(game_io_msg) + ENDIF +EXCEPT DO + IF open_dev THEN CloseDevice(game_io_msg) + IF game_io_msg THEN deleteExtIO(game_io_msg) + IF game_msg_port THEN deletePort(game_msg_port) + SELECT exception + CASE ERR_DEV; WriteF('Error: could not open gameport device\n') + CASE ERR_IO; WriteF('Error: could not create I/O\n') + CASE ERR_PORT; WriteF('Error: could not create port\n') + ENDSELECT +ENDPROC +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/clipping.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/clipping.e new file mode 100644 index 0000000..92c8a52 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/clipping.e @@ -0,0 +1,137 @@ +-> clipping.e + +->>> Header (globals) +MODULE 'layers', + 'graphics/gfx', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_LIB, ERR_WIN + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST MY_WIN_WIDTH=300, MY_WIN_HEIGHT=100 +->>> + +->>> PROC unclipWindow(win:PTR TO window) +-> Used to remove a clipping region installed by clipWindow() or +-> clipWindowToBorders(), disposing of the installed region and reinstalling +-> the region removed. +PROC unclipWindow(win:PTR TO window) + DEF old_region + -> Remove any old region by installing a NIL region, then dispose of the old + -> region if one was installed. + IF old_region:=InstallClipRegion(win.wlayer, NIL) + DisposeRegion(old_region) + ENDIF +ENDPROC +->>> + +->>> PROC clipWindow(win:PTR TO window, minX, minY, maxX, maxY) +-> Clip a window to a specified rectangle (given by upper left and lower right +-> corner). The removed region is returned so that it may be reinstalled +-> later. +PROC clipWindow(win:PTR TO window, minX, minY, maxX, maxY) + DEF new_region, my_rectangle + -> Set up the limits for the clip. + my_rectangle:=[minX, minY, maxX, maxY]:rectangle + -> Get a new region and OR in the limits. + IF new_region:=NewRegion() + IF OrRectRegion(new_region, my_rectangle)=FALSE + DisposeRegion(new_region) + new_region:=NIL + ENDIF + ENDIF +-> Install the new region, and return any existing region. If the above +-> allocation and region processing failed, then new_region will be NIL and +-> no clip region will be installed. +ENDPROC InstallClipRegion(win.wlayer, new_region) +->>> + +->>> PROC clipWindowToBorders(win:PTR TO window) +-> Clip a window to its borders. +-> The removed region is returned so that it may be re-installed later. +PROC clipWindowToBorders(win:PTR TO window) +ENDPROC clipWindow(win, win.borderleft, win.bordertop, + win.width-win.borderright-1, win.height-win.borderbottom-1) +->>> + +->>> PROC wait_for_close(win) +-> Wait for the user to select the close gadget. +PROC wait_for_close(win) + REPEAT -> E-Note: use built-in WaitIMessage() + UNTIL WaitIMessage(win)=IDCMP_CLOSEWINDOW +ENDPROC +->>> + +->>> PROC draw_in_window(win:PTR TO window, message) +-> Simple routine to blast all bits in a window with color three to show where +-> the window is clipped. After a delay, flush back to color zero and refresh +-> the window borders. +PROC draw_in_window(win:PTR TO window, message) + WriteF('\s...', message) + SetRast(win.rport, 3) + Delay(200) + SetRast(win.rport, 0) + RefreshWindowFrame(win) + WriteF('...done\n') +ENDPROC +->>> + +->>> PROC clip_test(win:PTR TO window) +-> Show drawing into an unclipped window, a window clipped to the borders and +-> a window clipped to a random rectangle. It is possible to clip more +-> complex shapes by AND'ing, OR'ing and exclusive-OR'ing regions and +-> rectangles to build a user clip region. +-> +-> This example assumes that old regions are not going to be re-used, so it +-> simply throws them away. +PROC clip_test(win) + DEF old_region + draw_in_window(win, 'Window with no clipping') + + -> If the application has never installed a user clip region, then + -> old_region will be NIL here. Otherwise, delete the old region (you + -> could save it and re-install it later...) + IF old_region:=clipWindowToBorders(win) + DisposeRegion(old_region) + ENDIF + draw_in_window(win, 'Window clipped to window borders') + unclipWindow(win) + + -> Here we know old_region will be NIL, as that is what we installed with + -> unclipWindow()... + IF old_region:=clipWindow(win, 20, 20, 100, 50) + DisposeRegion(old_region) + ENDIF + draw_in_window(win, 'Window clipped from (20,20) to (100,50)') + unclipWindow(win) + + wait_for_close(win) +ENDPROC +->>> + +->>> PROC main() +-> Open and close resources, call the test routine when ready. +PROC main() HANDLE + DEF win=NIL + KickVersion(37) + layersbase:=OpenLibrary('layers.library', 37) + win:=OpenWindowTagList(NIL, [WA_WIDTH, MY_WIN_WIDTH, + WA_HEIGHT, MY_WIN_HEIGHT, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_CLOSEGADGET, TRUE, + WA_DRAGBAR, TRUE, + WA_ACTIVATE, TRUE, + NIL]) + clip_test(win) +EXCEPT DO + IF win THEN CloseWindow(win) + IF layersbase THEN CloseLibrary(layersbase) + SELECT exception + CASE ERR_LIB; WriteF('Error: could not open layers.library V37+\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/layers.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/layers.e new file mode 100644 index 0000000..59670e6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Layers/layers.e @@ -0,0 +1,371 @@ +-> Layers.e + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'layers', + 'graphics/clip', + 'graphics/layers', + 'graphics/gfx', + 'graphics/gfxbase', + 'graphics/rastport', + 'graphics/view' + +ENUM ERR_NONE, ERR_BLYR, ERR_CMAP, ERR_LIB, ERR_LYR + +RAISE ERR_BLYR IF CreateBehindLayer()=NIL, + ERR_CMAP IF GetColorMap()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_LYR IF NewLayerInfo()=NIL + +CONST L_DELAY=100, S_DELAY=50, DUMMY=0 + +ENUM RED_PEN=1, GREEN_PEN, BLUE_PEN + +CONST SCREEN_D=2, SCREEN_W=320, SCREEN_H=200 + +-> The starting size of example layers, offsets are used for placement. +CONST W_H=50, W_T=5, W_W=80 +CONST W_B=W_T+W_H-1 +CONST SWH=SCREEN_W/2, WWH=W_W/2 +CONST W_L=SWH-WWH +CONST W_R=W_L+W_W-1 + +-> Size of the superbitmap. +CONST SUPER_H=SCREEN_H, SUPER_W=SCREEN_W + +-> Starting size of the message layer. +CONST M_H=10, M_W=SCREEN_W, M_L=0 +CONST M_T=SCREEN_H-M_H +CONST M_B=M_T+M_H-1 +CONST M_R=M_L+M_W-1 + +DEF theLayerFlags:PTR TO LONG, colourtable:PTR TO INT +->>> + +->>> PROC myLabelLayer(layer:PTR TO layer, colour, string) +-> Clear the layer THEN draw in a text string. +PROC myLabelLayer(layer:PTR TO layer, colour, string) + -> Fill layer with colour + SetRast(layer.rp, colour) + + -> Set up for writing text into layer + SetDrMd(layer.rp, RP_JAM1) + SetAPen(layer.rp, 0) + Move(layer.rp, 5, 7) + + -> Write into layer + Text(layer.rp, string, StrLen(string)) +ENDPROC +->>> + +->>> PROC pMessage(layer, string) +-> Write a message into a layer with a delay. +PROC pMessage(layer, string) + Delay(S_DELAY) + myLabelLayer(layer, GREEN_PEN, string) +ENDPROC +->>> + +->>> PROC error(layer, string) +-> Write an error message into a layer with a delay. +PROC error(layer, string) + myLabelLayer(layer, RED_PEN, string) + Delay(L_DELAY) +ENDPROC +->>> + +->>> PROC doLayers(msgLayer, layer_array:PTR TO LONG) +-> Do some layers manipulations to demonstrate their abilities. +PROC doLayers(msgLayer, layer_array:PTR TO LONG) + DEF ktr, ktr_2, tlayer:PTR TO layer + + pMessage(msgLayer, 'Label all Layers') + myLabelLayer(layer_array[0], RED_PEN, 'SUPER') + myLabelLayer(layer_array[1], GREEN_PEN, 'Smart') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + pMessage(msgLayer, 'MoveLayer 1 InFrontOf 0') + IF FALSE=MoveLayerInFrontOf(layer_array[1], layer_array[0]) + error(msgLayer, 'MoveLayerInFrontOf() failed.') + ENDIF + + pMessage(msgLayer, 'MoveLayer 2 InFrontOf 1') + IF FALSE=MoveLayerInFrontOf(layer_array[2], layer_array[1]) + error(msgLayer, 'MoveLayerInFrontOf() failed.') + ENDIF + + pMessage(msgLayer, 'Refresh Simple Refresh Layer') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + pMessage(msgLayer, 'Incrementally MoveLayers...') + FOR ktr:=0 TO 29 + IF FALSE=MoveLayer(DUMMY, layer_array[1], -1, 0) + error(msgLayer, 'MoveLayer() failed.') + ENDIF + IF FALSE=MoveLayer(DUMMY, layer_array[2], -2, 0) + error(msgLayer, 'MoveLayer() failed.') + ENDIF + ENDFOR + + pMessage(msgLayer, 'Refresh Simple Refresh Layer') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + pMessage(msgLayer, 'Make Layer 0 the UpfrontLayer') + IF FALSE=UpfrontLayer(DUMMY, layer_array[0]) + error(msgLayer, 'UpfrontLayer() failed.') + ENDIF + + pMessage(msgLayer, 'Make Layer 2 the BehindLayer') + IF FALSE=BehindLayer(DUMMY, layer_array[2]) + error(msgLayer, 'BehindLayer() failed.') + ENDIF + + pMessage(msgLayer, 'Incrementally MoveLayers again...') + FOR ktr:=0 TO 29 + IF FALSE=MoveLayer(DUMMY, layer_array[1], 0, 1) + error(msgLayer, 'MoveLayer() failed.') + ENDIF + IF FALSE=MoveLayer(DUMMY, layer_array[2], 0, 2) + error(msgLayer, 'MoveLayer() failed.') + ENDIF + ENDFOR + + pMessage(msgLayer, 'Refresh Simple Refresh Layer') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + pMessage(msgLayer, 'Big MoveLayer') + FOR ktr:=0 TO 2 + tlayer:=layer_array[ktr] + IF FALSE=MoveLayer(DUMMY, tlayer, -tlayer.minx, 0) + error(msgLayer, 'MoveLayer() failed.') + ENDIF + ENDFOR + + pMessage(msgLayer, 'Incrementally increase size') + FOR ktr:=0 TO 4 + FOR ktr_2:=0 TO 2 + IF FALSE=SizeLayer(DUMMY, layer_array[ktr_2], 1, 1) + error(msgLayer, 'SizeLayer() failed.') + ENDIF + ENDFOR + ENDFOR + + pMessage(msgLayer, 'Refresh Smart Refresh Layer') + myLabelLayer(layer_array[1], GREEN_PEN, 'Smart') + pMessage(msgLayer, 'Refresh Simple Refresh Layer') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + pMessage(msgLayer, 'Big SizeLayer') + FOR ktr:=0 TO 2 + tlayer:=layer_array[ktr] + IF FALSE=SizeLayer(DUMMY, tlayer, SCREEN_W-tlayer.maxx-1, 0) + error(msgLayer, 'SizeLayer() failed.') + ENDIF + ENDFOR + + pMessage(msgLayer, 'Refresh Smart Refresh Layer') + myLabelLayer(layer_array[1], GREEN_PEN, 'Smart') + pMessage(msgLayer, 'Refresh Simple Refresh Layer') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + pMessage(msgLayer, 'ScrollLayer down') + FOR ktr:=0 TO 29 + FOR ktr_2:=0 TO 2 + ScrollLayer(DUMMY, layer_array[ktr_2], 0, -1) + ENDFOR + ENDFOR + + pMessage(msgLayer, 'Refresh Smart Refresh Layer') + myLabelLayer(layer_array[1], GREEN_PEN, 'Smart') + pMessage(msgLayer, 'Refresh Simple Refresh Layer') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + pMessage(msgLayer, 'ScrollLayer up') + FOR ktr:=0 TO 29 + FOR ktr_2:=0 TO 2 + ScrollLayer(DUMMY, layer_array[ktr_2], 0, 1) + ENDFOR + ENDFOR + + pMessage(msgLayer, 'Refresh Smart Refresh Layer') + myLabelLayer(layer_array[1], GREEN_PEN, 'Smart') + pMessage(msgLayer, 'Refresh Simple Refresh Layer') + myLabelLayer(layer_array[2], BLUE_PEN, 'Simple') + + Delay(L_DELAY) +ENDPROC +->>> + +->>> PROC disposeLayers(msgLayer, layer_array:PTR TO LONG) +-> Delete the layer array created by allocLayers(). +PROC disposeLayers(msgLayer, layer_array:PTR TO LONG) + DEF ktr + FOR ktr:=0 TO 2 + IF layer_array[ktr] + IF FALSE=DeleteLayer(DUMMY, layer_array[ktr]) + error(msgLayer, 'Error deleting layer') + ENDIF + ENDIF + ENDFOR +ENDPROC +->>> + +->>> PROC allocLayers(msgLayer,layer_array,super_bitmap,theLayerInfo,theBitMap) +-> Create some hard-coded layers. The first must be SUPER-bitmap, with the +-> bitmap passed as an argument. The others must not be super-bitmap. The +-> pointers to the created layers are returned in layer_array. +-> +-> Return FALSE on failure. On a FALSE return, the layers are properly +-> cleaned up. +PROC allocLayers(msgLayer, layer_array:PTR TO LONG, super_bitmap, + theLayerInfo, theBitMap) HANDLE + DEF ktr, tlayer:PTR TO layer + FOR ktr:=0 TO 2 + pMessage(msgLayer, 'Create BehindLayer') + IF ktr=0 + tlayer:=CreateBehindLayer(theLayerInfo, theBitMap, + W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30), + theLayerFlags[ktr], super_bitmap) + ELSE + tlayer:=CreateBehindLayer(theLayerInfo, theBitMap, + W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30), + theLayerFlags[ktr], NIL) + ENDIF + + pMessage(msgLayer, 'Fill the RastPort') + SetRast(tlayer.rp, ktr+1) + layer_array[ktr]:=tlayer + ENDFOR +EXCEPT + disposeLayers(msgLayer, layer_array) + ReThrow() +ENDPROC +->>> + +->>> PROC disposeBitMap(bitmap:PTR TO bitmap, depth, width, height) +-> Free the bitmap and all bitplanes created by allocBitMap(). +PROC disposeBitMap(bitmap:PTR TO bitmap, depth, width, height) + DEF ktr + IF bitmap + FOR ktr:=0 TO depth-1 + IF bitmap.planes[ktr] THEN FreeRaster(bitmap.planes[ktr], width, height) + ENDFOR + Dispose(bitmap) + ENDIF +ENDPROC +->>> + +->>> PROC allocBitMap(depth, width, height) +-> Allocate and initialize a bitmap structure. +PROC allocBitMap(depth, width, height) HANDLE + DEF ktr, bitmap=NIL:PTR TO bitmap + NEW bitmap + InitBitMap(bitmap, depth, width, height) + + FOR ktr:=0 TO depth-1 + bitmap.planes[ktr]:=AllocRaster(width, height) + BltClear(bitmap.planes[ktr], RASSIZE(width, height), 1) + ENDFOR +EXCEPT + disposeBitMap(bitmap, depth, width, height) + ReThrow() +ENDPROC bitmap +->>> + +->>> PROC startLayers(theLayerInfo, theBitMap) +-> Set up to run the layers example, doLayers(). Clean up when done. +PROC startLayers(theLayerInfo, theBitMap) HANDLE + DEF msgLayer=NIL, theSuperBitMap=NIL, theLayers=NIL + theLayers:=[NIL, NIL, NIL]:LONG + IF msgLayer:=CreateUpfrontLayer(theLayerInfo, theBitMap, + M_L, M_T, M_R, M_B, LAYERSMART, NIL) + pMessage(msgLayer, 'Setting up Layers') + theSuperBitMap:=allocBitMap(SCREEN_D, SUPER_W, SUPER_H) + allocLayers(msgLayer, theLayers, theSuperBitMap, theLayerInfo, theBitMap) + doLayers(msgLayer, theLayers) + ENDIF +EXCEPT DO + disposeLayers(msgLayer, theLayers) + disposeBitMap(theSuperBitMap, SCREEN_D, SUPER_W, SUPER_H) + IF msgLayer + IF FALSE=DeleteLayer(DUMMY, msgLayer) + error(msgLayer, 'Error deleting layer') + ENDIF + ENDIF +ENDPROC +->>> + +->>> PROC runNewView() +-> Set up a low-level graphics display for layers to work on. Layers should +-> not be built directly on Intuition screens, use a low-level graphics view. +-> If you need mouse or other events for the layers display, you have to get +-> them directly from the input device. The only supported method of using +-> layers library calls with Intuition (other than the InstallClipRegion() +-> call) is through Intuition windows. +-> +-> See graphics primitives chapter for details on creating and using the +-> low-level graphics calls. +PROC runNewView() HANDLE + DEF theView:view, oldview:PTR TO view, theViewPort:viewport, + theRasInfo, theColourMap=NIL:PTR TO colormap, + theLayerInfo=NIL:PTR TO layer_info, theBitMap=NIL:PTR TO bitmap, + colourpalette:PTR TO INT, ktr, gfx:PTR TO gfxbase + + -> E-Note: get the right type... + gfx:=gfxbase + -> Save current view, to be restored when done + IF oldview:=gfx.actiview + -> Get a LayerInfo structure + theLayerInfo:=NewLayerInfo() + theColourMap:=GetColorMap(4) + colourpalette:=theColourMap.colortable; + FOR ktr:=0 TO 3 DO colourpalette[]++:=colourtable[ktr] + + theBitMap:=allocBitMap(SCREEN_D, SCREEN_W, SCREEN_H) + InitView(theView) + InitVPort(theViewPort) + + theView.viewport:=theViewPort + + theRasInfo:=[NIL, theBitMap, 0, 0]:rasinfo + + theViewPort.dwidth:=SCREEN_W; theViewPort.dheight:=SCREEN_H + theViewPort.rasinfo:=theRasInfo; theViewPort.colormap:=theColourMap + + MakeVPort(theView, theViewPort); MrgCop(theView); LoadView(theView) + WaitTOF() + + startLayers(theLayerInfo, theBitMap) + + -> Put back the old view, wait for it to become active before freeing any + -> of our display + LoadView(oldview) + WaitTOF() + + -> Free dynamically created structures + FreeVPortCopLists(theViewPort) + FreeCprList(theView.lofcprlist) + ENDIF +EXCEPT DO + IF theBitMap THEN disposeBitMap(theBitMap, SCREEN_D, SCREEN_W, SCREEN_H) + IF theColourMap THEN FreeColorMap(theColourMap) + IF theLayerInfo THEN DisposeLayerInfo(theLayerInfo) + ReThrow() +ENDPROC +->>> + +->>> PROC main() +-> Open the libraries used by the example. Clean up when done. +PROC main() HANDLE + -> Global constant data for initialising the layers. + theLayerFlags:=[LAYERSUPER, LAYERSMART, LAYERSIMPLE]:LONG + colourtable:=[$000, $F44, $4F4, $44F]:INT + + layersbase:=OpenLibrary('layers.library', 33) + runNewView() +EXCEPT DO + IF layersbase THEN CloseLibrary(layersbase) +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/RGBBoxes.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/RGBBoxes.e new file mode 100644 index 0000000..78a46ea --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/RGBBoxes.e @@ -0,0 +1,199 @@ +-> RGBBoxes.e - Simple ViewPort example -- works with 1.3 and Release 2 + +->>> Header (globals) +MODULE 'dos/dos', + 'exec/libraries', + 'graphics/displayinfo', + 'graphics/gfx', + 'graphics/gfxbase', + 'graphics/gfxnodes', + 'graphics/modeid', + 'graphics/videocontrol', + 'graphics/view' + +ENUM ERR_NONE, ERR_COLMAP, ERR_FINDDISP, ERR_GETDISP, ERR_GFXNEW, ERR_MONI, + ERR_RAST, ERR_VIDEO + +RAISE ERR_COLMAP IF GetColorMap()=NIL, + ERR_FINDDISP IF FindDisplayInfo()=NIL, + ERR_GETDISP IF GetDisplayInfoData()=0, + ERR_GFXNEW IF GfxNew()=NIL, + ERR_MONI IF OpenMonitor()=NIL, + ERR_RAST IF AllocRaster()=NIL, + ERR_VIDEO IF VideoControl()<>NIL + +-> The number of bitplanes, and the nominal width and height used in 1.3. +CONST DEPTH=2, WIDTH=640, HEIGHT=400 + +-> RGB values for the four colours used +CONST BLACK=$000, RED=$f00, GREEN=$0f0, BLUE=$00f + +DEF bitMap:bitmap, + displaymem=NIL -> Pointer for writing to BitMap memory +->>> + +->>> PROC main() +PROC main() HANDLE + -> E-Note: a lot of the globals are really local to main() + DEF view:view, oldview=NIL, viewPort:viewport, cm=NIL:PTR TO colormap, + vextra=NIL:PTR TO viewextra, vpextra=NIL:PTR TO viewportextra, + monspec=NIL, dimquery:dimensioninfo, depth, box, rasInfo:rasinfo, + modeID, colortable, boxoffsets:PTR TO INT, gfx:PTR TO gfxbase + gfx:=gfxbase -> E-Note: get the right type for gfxbase + + -> Set the plane pointers to NIL so the handler will know if they are used. + -> E-Note: this needs to be done *before* anything that may go wrong + FOR depth:=0 TO DEPTH-1 DO bitMap.planes[depth]:=NIL + + -> Example steals the screen from Intuition if Intuition is around. + oldview:=gfx.actiview -> Save current View to restore later. + + InitView(view) -> Initialise the View and set view.modes. + -> This is the old 1.3 way (only V_LACE counts). + view.modes:=view.modes OR V_LACE + + IF gfx.lib.version>=36 + -> Form the ModeID from values in 'graphics/displayinfo' + modeID:=DEFAULT_MONITOR_ID OR HIRESLACE_KEY + + -> Make the viewextra object + vextra:=GfxNew(VIEW_EXTRA_TYPE) + -> Attach the ViewExtra to the View + GfxAssociate(view, vextra) + view.modes:=view.modes OR EXTEND_VSTRUCT + + -> Create and attach a MonitorSpec to the ViewExtra + monspec:=OpenMonitor(NIL, modeID) + vextra.monitor:=monspec + ENDIF + + -> Initialise the BitMap for RasInfo. + InitBitMap(bitMap, DEPTH, WIDTH, HEIGHT) + + -> Allocate space for BitMap + FOR depth:=0 TO DEPTH-1 DO bitMap.planes[depth]:=AllocRaster(WIDTH, HEIGHT) + + -> Initialise the RasInfo. + rasInfo:=[NIL, bitMap, 0, 0]:rasinfo + + InitVPort(viewPort) -> Initialise the ViewPort. + view.viewport:=viewPort -> Link the ViewPort into the View. + viewPort.rasinfo:=rasInfo + viewPort.dwidth:=WIDTH + viewPort.dheight:=HEIGHT + + -> Set the display mode the old-fashioned way + viewPort.modes:=V_HIRES OR V_LACE + + IF gfx.lib.version>=36 + -> Make a ViewPortExtra and get ready to attach it + vpextra:=GfxNew(VIEWPORT_EXTRA_TYPE) + + -> Initialise the DisplayClip field of the ViewPortExtra + GetDisplayInfoData(NIL, dimquery, SIZEOF dimensioninfo, DTAG_DIMS, modeID) + CopyMem(dimquery.nominal, vpextra.displayclip, SIZEOF rectangle) + -> E-Note: FindDisplayInfo in a the tag-list later + + -> This is for backwards compatibility with, for example, a 1.3 screen + -> saver utility that looks at the Modes field. + viewPort.modes:=modeID AND $0000FFFF + ENDIF + + -> Initialize the ColorMap. + -> 2 planes deep, so 4 entries (2 raised to the #_planes power). + cm:=GetColorMap(4) + + IF gfx.lib.version>=36 + -> Attach the color map and Release 2 extended structures + VideoControl(cm, [VTAG_ATTACH_CM_SET, viewPort, + VTAG_VIEWPORTEXTRA_SET, vpextra, + VTAG_NORMAL_DISP_SET, FindDisplayInfo(modeID), + NIL]) + ELSE + -> Attach the ColorMap, old 1.3-style + viewPort.colormap:=cm + ENDIF + + colortable:=[BLACK, RED, GREEN, BLUE]:INT + -> Change colors to those in colortable. + LoadRGB4(viewPort, colortable, 4) + + MakeVPort(view, viewPort) -> Construct preliminary Copper instruction list. + + -> Merge preliminary lists into a real Copper list in the view object + MrgCop(view) + + -> Clear the ViewPort + FOR depth:=0 TO DEPTH-1 + displaymem:=bitMap.planes[depth] + BltClear(displaymem, bitMap.bytesperrow*bitMap.rows, 1) + ENDFOR + + LoadView(view) + + boxoffsets:=[802, 2010, 3218]:INT + -> Now fill some boxes so that user can see something. + -> Always draw into both planes to assure true colors. + FOR box:=1 TO 3 -> Three boxes; red, green and blue. + FOR depth:=0 TO DEPTH-1 -> Two planes + displaymem:=bitMap.planes[depth]+boxoffsets[box-1] + drawFilledBox(box, depth) + ENDFOR + ENDFOR + + Delay(10*TICKS_PER_SECOND) -> Pause for 10 seconds. + LoadView(oldview) -> Put back the old View. + WaitTOF() -> Wait until the View is being rendered to free memory. + + -> Deallocate the hardware Copper list created by MrgCopy(). Since this is + -> interlace, also check for a short frame copper list to free. + FreeCprList(view.lofcprlist) + IF view.shfcprlist THEN FreeCprList(view.shfcprlist) + + -> Free all intermediate Copper lists created by MakeVPort(). + FreeVPortCopLists(viewPort) + +EXCEPT DO + -> Free the color map created by GetColorMap() + IF cm THEN FreeColorMap(cm) + -> Free the ViewPortExtra created by GfxNew() + IF vpextra THEN GfxFree(vpextra) + -> Free the BitPlanes drawing area. + FOR depth:=0 TO DEPTH-1 + IF bitMap.planes[depth] THEN FreeRaster(bitMap.planes[depth], WIDTH, HEIGHT) + ENDFOR + -> Free the MonitorSpec created with OpenMonitor(). + IF monspec THEN CloseMonitor(monspec) + -> Free the ViewExtra created with GfxNew(). + IF vextra THEN GfxFree(vextra) + SELECT exception + CASE ERR_COLMAP; WriteF('Could not get ColorMap\n') + CASE ERR_FINDDISP; WriteF('Could not get DisplayInfo\n') + CASE ERR_GETDISP; WriteF('Could not get DimensionInfo\n') + CASE ERR_GFXNEW; WriteF('Could not get ViewExtra/ViewPortExtra\n') + CASE ERR_MONI; WriteF('Could not get MonitorSpec\n') + CASE ERR_RAST; WriteF('Could not get BitPlanes\n') + CASE ERR_VIDEO; WriteF('Could not attach extended structures\n') + ENDSELECT +ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK +->>> + +->>> PROC drawFilledBox(fillcolor, plane) +-> Create a WIDTH/2 by HEIGHT/2 box of color "fillcolor" into the given plane +PROC drawFilledBox(fillcolor, plane) + DEF value, boxHeight, boxWidth, width + + -> Divide (WIDTH/2) by eight because each CHAR that is written stuffs eight + -> bits into the BitMap. + boxWidth:=(WIDTH/2)/8 + + value:=IF fillcolor AND Shl(1, plane) THEN $FF ELSE 0 + + -> E-Note: slightly re-expressed to read a lot better... + FOR boxHeight:=1 TO HEIGHT/2 + FOR width:=1 TO boxWidth DO displaymem[]++:=value + displaymem:=displaymem+(bitMap.bytesperrow-boxWidth) + ENDFOR +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/WBClone.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/WBClone.e new file mode 100644 index 0000000..a29a59d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/WBClone.e @@ -0,0 +1,294 @@ +-> WBClone.e - Clone the Workbench using graphics calls + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'exec/memory', + 'graphics/displayinfo', + 'graphics/gfx', + 'graphics/gfxnodes', + 'graphics/monitor', + 'graphics/rastport', + 'graphics/view', + 'graphics/videocontrol', + 'intuition/intuitionbase', + 'intuition/screens' + +ENUM ERR_NONE, ERR_CMAP, ERR_DINFO, ERR_GFXNEW, ERR_KICK, ERR_MONI + +RAISE ERR_CMAP IF GetColorMap()=NIL, + ERR_DINFO IF GetDisplayInfoData()=NIL, + ERR_GFXNEW IF GfxNew()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_MONI IF OpenMonitor()=NIL + +#define INTUITIONNAME 'intuition.library' +->>> + +->>> PROC destroyView(view:PTR TO view) +-> Close and free everything to do with the View +PROC destroyView(view:PTR TO view) + DEF ve:PTR TO viewextra + IF view + IF ve:=GfxLookUp(view) + IF ve.monitor THEN CloseMonitor(ve.monitor) + GfxFree(ve) + ENDIF + + -> Free up the copper lists + IF view.lofcprlist THEN FreeCprList(view.lofcprlist) + IF view.shfcprlist THEN FreeCprList(view.shfcprlist) + + Dispose(view) + ENDIF +ENDPROC +->>> + +->>> PROC dupView(v:PTR TO view, modeID) +-> Duplicate the View +PROC dupView(v:PTR TO view, modeID) HANDLE + -> Allocate and init a view OBJECT. Also, get a viewextra OBJECT and + -> attach the monitor type to the View. + DEF view=NIL:PTR TO view, ve=NIL:PTR TO viewextra, + mspc=NIL:PTR TO monitorspec + view:=NewM(SIZEOF view, MEMF_CLEAR OR MEMF_PUBLIC) + ve:=GfxNew(VIEW_EXTRA_TYPE) + mspc:=OpenMonitor(NIL, modeID) + InitView(view) + view.dyoffset:=v.dyoffset + view.dxoffset:=v.dxoffset + view.modes:=v.modes + GfxAssociate(view, ve) + ve.monitor:=mspc + RETURN view +EXCEPT + -> E-Note: C version is wrong; failure may happen before attaching to view + IF mspc THEN CloseMonitor(mspc) + IF ve THEN GfxFree(ve) + IF view THEN Dispose(view) + ReThrow() -> E-Note: pass on exception if it was an error +ENDPROC +->>> + +->>> PROC destroyViewPort(vp:PTR TO viewport) +-> Close and free everything to do with the viewport +PROC destroyViewPort(vp:PTR TO viewport) + DEF cm:PTR TO colormap, ti:PTR TO LONG + IF vp + -> Find the ViewPort's ColorMap. From that use VideoControl to get the + -> ViewPortExtra, and free it. + -> Then free the ColorMap, and finally the ViewPort itself. + IF cm:=vp.colormap + -> E-Note: ti[1] will be filled in by the call to VideoControl + IF VideoControl(cm, ti:=[VTAG_VIEWPORTEXTRA_GET, NIL, NIL])=NIL + GfxFree(ti[1]) + ELSE + WriteF('VideoControl error in destroyViewPort()\n') + ENDIF + + FreeColorMap(cm) + ELSE + WriteF('Could not free the ColorMap\n') + ENDIF + + FreeVPortCopLists(vp) + + Dispose(vp) + ENDIF +ENDPROC +->>> + +->>> PROC dupViewPort(vp:PTR TO viewport, modeID) +CONST COLOURS=32 -> E-Note: this is a bit out of date... + +-> Duplicate the ViewPort +PROC dupViewPort(vp:PTR TO viewport, modeID) HANDLE + -> Allocate and initialise a ViewPort. Copy the ViewPort width and heights, + -> offsets, and modes values. Allocate and initialise a ColorMap. + -> + -> Also, allocate a ViewPortExtra, and copy the TextOScan values of the + -> ModeID from the database into the ViewPortExtra. + DEF myvp=NIL:PTR TO viewport, vpe=NIL:PTR TO viewportextra, + cm=NIL:PTR TO colormap, query:dimensioninfo, colour, c + myvp:=NewM(SIZEOF viewport, MEMF_CLEAR OR MEMF_PUBLIC) + vpe:=GfxNew(VIEWPORT_EXTRA_TYPE) + cm:=GetColorMap(COLOURS) -> E-Note: use the constant that's been defined! + GetDisplayInfoData(NIL, query, SIZEOF dimensioninfo, DTAG_DIMS, modeID) + InitVPort(myvp) + + -> Duplicate the viewport object + myvp.dwidth:=vp.dwidth + myvp.dheight:=vp.dheight + myvp.dxoffset:=vp.dxoffset + myvp.dyoffset:=vp.dyoffset + myvp.modes:=vp.modes + myvp.spritepriorities:=vp.spritepriorities + myvp.extendedmodes:=vp.extendedmodes + + -> Duplicate the Overscan values + CopyMem(query.txtoscan, vpe.displayclip, SIZEOF rectangle) + + -> Attach everything together + IF VideoControl(cm, [VTAG_ATTACH_CM_SET, myvp, + VTAG_VIEWPORTEXTRA_SET, vpe, + VTAG_NORMAL_DISP_SET, FindDisplayInfo(modeID), + NIL]) + WriteF('VideoControl error in duplicateViewPort()\n') + ENDIF + + -> Copy the colours from the Workbench + FOR c:=0 TO COLOURS-1 + IF -1<>(colour:=GetRGB4(vp.colormap, c)) + SetRGB4CM(cm, c, Shr(colour, 8), Shr(colour, 4) AND $F, colour AND $F) + ENDIF + ENDFOR + RETURN myvp +EXCEPT + -> E-Note: C version is wrong; failure may happen before attaching to myvp + IF cm THEN FreeColorMap(cm) + IF vpe THEN GfxFree(vpe) + IF myvp THEN Dispose(myvp) + ReThrow() -> E-Note: pass on exception if an error +ENDPROC +->>> + +->>> PROC destroyBitMap(mybm:PTR TO bitmap, width, height, depth) +-> Close and free everything to do with the BitMap +PROC destroyBitMap(mybm:PTR TO bitmap, width, height, depth) + DEF i + IF mybm + FOR i:=0 TO depth-1 + IF mybm.planes[i] THEN FreeRaster(mybm.planes[i], width, height) + ENDFOR + Dispose(mybm) + ENDIF +ENDPROC +->>> + +->>> PROC createBitMap(width, height, depth) +-> Create the BitMap +PROC createBitMap(width, height, depth) HANDLE + -> Allocate a bitmap OBJECT, initialise it and allocate each plane. + DEF mybm:PTR TO bitmap, i + mybm:=NewM(SIZEOF bitmap, MEMF_CLEAR OR MEMF_PUBLIC) + InitBitMap(mybm, depth, width, height) + FOR i:=0 TO depth-1 + mybm.planes[i]:=AllocRaster(width, height) + ENDFOR + RETURN mybm +EXCEPT + -> E-Note: hey! the C version is OK this time! + destroyBitMap(mybm, width, height, depth) + ReThrow() -> E-Note: pass on exception if an error +ENDPROC +->>> + +->>> PROC showView(view, vp, bm, width, height) +-> Assemble and display the View +PROC showView(view:PTR TO view, vp:PTR TO viewport, bm:PTR TO bitmap, + width, height) HANDLE + -> Attach the BitMap to the ViewPort via a RasInfo. Attach the ViewPort to + -> the View. Clear the BitMap, and draw into it by attaching the BitMap to + -> a RastPort. Then MakeVPort(), MrgCop() and LoadView(). + -> Just wait for the user to press before returning. + DEF rp=NIL:PTR TO rastport, ri=NIL:PTR TO rasinfo + rp:=NewM(SIZEOF rastport, MEMF_CLEAR OR MEMF_PUBLIC) + ri:=NewM(SIZEOF rasinfo, MEMF_CLEAR OR MEMF_PUBLIC) + InitRastPort(rp) + rp.bitmap:=bm + ri.bitmap:=bm + vp.rasinfo:=ri + view.viewport:=vp + + -> Render + SetRast(rp, 0) -> Clear the background + SetAPen(rp, Shl(1, bm.depth)-1) -> Use the last pen + Move(rp, 0, 0) + Draw(rp, width, 0) + Draw(rp, width, height) + Draw(rp, 0, height) + Draw(rp, 0, 0) + + -> Display it + MakeVPort(view, vp) + MrgCop(view) + LoadView(view) + + -> E-Note: make this work even under Workbench + WriteF(''); Inp(IF stdin THEN stdin ELSE stdout) + + -> Bring back the system + RethinkDisplay() +EXCEPT DO + IF ri THEN Dispose(ri) + IF rp THEN Dispose(rp) + ReThrow() -> E-Note: pass on exception if an error +ENDPROC +->>> + +->>> PROC main() +-> Clone the Workbench View using Graphics Library calls. +PROC main() HANDLE + DEF wb=NIL:PTR TO screen, myview=NIL, myvp=NIL, mybm=NIL, + modeID, ibaseLock=NIL, intuition:PTR TO intuitionbase + + KickVersion(37) -> E-Note: requires V37 + + -> To clone the Workbench using graphics calls involves duplicating the + -> Workbench ViewPort, ViewPort mode, and Intuition's View. This also + -> involves duplicating the DisplayClip for the overscan value, the colours, + -> and the View position. + -> + -> When this is all done, the View, ViewPort, ColorMap and BitMap (and + -> ViewPortExtra, ViewExtra and RasInfo) all have to be linked together, and + -> the copperlists made to create the display. + -> + -> This is not as difficult as it sounds (trust me!) + + -> First, lock the Workbench screen, so no changes can be made to it while + -> we are duplicating it. + wb:=LockPubScreen('Workbench') + + -> Find the Workbench's ModeID. This is a 32-bit number that identifies the + -> monitor type, and the display mode of that monitor. + modeID:=GetVPModeID(wb.viewport) + + -> We need to duplicate Intuition's View structure, so lock IntuitionBase to + -> prevent the View changing under our feet. + ibaseLock:=LockIBase(0) + intuition:=intuitionbase -> E-Note: get the right type for intuitionbase + myview:=dupView(intuition.viewlord, modeID) + + -> The View has been cloned, so we don't need to keep it locked. + UnlockIBase(ibaseLock) + ibaseLock:=NIL -> E-Note: set to NIL so we don't Unlock it again + + -> Now duplicate the Workbench's ViewPort. Remember, we still have the + -> Workbench locked. + myvp:=dupViewPort(wb.viewport, modeID) + + -> Create a BitMap to render into. This will be of the same dimensions + -> as the Workbench. + mybm:=createBitMap(wb.width, wb.height, wb.bitmap.depth) + + -> Now we have everything copied, show something + showView(myview, myvp, mybm, wb.width-1, wb.height-1) + +EXCEPT DO + -> Free up everything we may have allocated or still have locked + IF mybm THEN destroyBitMap(mybm, wb.width, wb.height, wb.bitmap.depth) + IF myvp THEN destroyViewPort(myvp) + IF myview THEN destroyView(myview) + IF ibaseLock THEN UnlockIBase(ibaseLock) + IF wb THEN UnlockPubScreen(NIL, wb) + SELECT exception + CASE ERR_CMAP; WriteF('Could not get ColorMap\n') + CASE ERR_DINFO; WriteF('Display database error\n') + CASE ERR_GFXNEW; WriteF('Could not get the View-/ViewPort- Extra\n') + CASE ERR_KICK; WriteF('Requires at least V37\n') + CASE ERR_MONI; WriteF('Could not open monitor\n') + CASE "MEM"; WriteF('Ran out of memory\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/genlockdemo.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/genlockdemo.e new file mode 100644 index 0000000..48c7b80 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/genlockdemo.e @@ -0,0 +1,403 @@ +-> genlockdemo.e - Genlock VideoControl example. + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'gadtools', + 'exec/libraries', + 'graphics/displayinfo', + 'graphics/gfxbase', + 'graphics/modeid', + 'graphics/text', + 'graphics/videocontrol', + 'graphics/view', + 'intuition/intuition', + 'intuition/screens', + 'libraries/gadtools', + 'utility/tagitem' + +ENUM ERR_NONE, ERR_CTXT, ERR_ECS, ERR_GAD, ERR_KICK, ERR_LIB, ERR_SCRN, + ERR_VIS, ERR_WIN + +RAISE ERR_CTXT IF CreateContext()=NIL, + ERR_GAD IF CreateGadgetA()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_VIS IF GetVisualInfoA()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL, + "MEM" IF String()=NIL + +-> 'libraries/gadtools' does not define a library name. +#define GADTOOLSNAME 'gadtools.library' + +-> Some gadget ID's +ENUM BORDERBLANK_ID=16, BORDERNOTRANS_ID, BITPLANEKEY_ID, CHROMAPLANE_ID, + CHROMAKEY_ID + +-> E-Note: get the right type to use gfxbase +DEF gfx:PTR TO gfxbase +->>> + +->>> PROC main() +PROC main() HANDLE + DEF genscreen=NIL:PTR TO screen, controlwindow=NIL:PTR TO window, + glist=NIL, gadget:PTR TO gadget, hitgadget:PTR TO gadget, + vp:PTR TO viewport, viewlord:PTR TO view, vi=NIL, ng:PTR TO newgadget, + -> E-Note: C version is over-cautious about the size of vtags + imsg:PTR TO intuimessage, vtags[22]:ARRAY OF tagitem, + gadgetPtrs[21]:ARRAY OF LONG, iclass, icode, i, j, abort=FALSE, isPAL, + gfx:PTR TO gfxbase + gfx:=gfxbase -> E-Note: set-up correct typed gfxbase + KickVersion(37) + gadtoolsbase:=OpenLibrary(GADTOOLSNAME, 37) + IF 0=(gfx.chiprevbits0 AND GFXF_HR_DENISE) THEN Raise(ERR_ECS) + -> Check if the user happens to prefer PAL or if this is a true PAL system. + isPAL:=checkPAL('Workbench') + + -> Open a 'standard' HIRES screen. + genscreen:=OpenScreenTagList(NIL, + -> Give me 3D look window (I'll use a quiet screen). + [SA_PENS, [0, 1, 1, 2, 1, 3, 1, 0, 3, -1]:INT, + SA_DISPLAYID, HIRES_KEY, + SA_DEPTH, 4, + -> Give me a lot of border. + SA_WIDTH, 640, + SA_HEIGHT, IF isPAL THEN 256 ELSE 200, + SA_OVERSCAN, 0, + -> Hold the titlebar, please. + SA_QUIET, TRUE, + -> Give me a sysfont 1 as default rastport font. + SA_SYSFONT, 1, + NIL]) + -> Blast some colourbars in screen's rastport, leave some colour 0 gaps. + j:=0 + FOR i:=0 TO 15 + SetAPen(genscreen.rastport, i) + RectFill(genscreen.rastport, j+1, 0, j+30, IF isPAL THEN 255 ELSE 199) + j:=j+40 + ENDFOR + -> A line to show where borders start. + SetAPen(genscreen.rastport, 5) + Move(genscreen.rastport, 0, 0) + Draw(genscreen.rastport, genscreen.width-1, 0) + Draw(genscreen.rastport, genscreen.width-1, genscreen.height-1) + Draw(genscreen.rastport, 0, genscreen.height-1) + Draw(genscreen.rastport, 0, 0) + + -> Open a restricted window, no dragging or sizing, just closing (don't + -> want to refresh screen). + controlwindow:=OpenWindowTagList(NIL, + [WA_TITLE, 'VideoControl', + WA_LEFT, 210, + WA_TOP, 20, + WA_WIDTH, 220, + WA_HEIGHT, 150, + WA_CUSTOMSCREEN, genscreen, + WA_FLAGS, WFLG_CLOSEGADGET OR WFLG_ACTIVATE OR + WFLG_NOCAREREFRESH, + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_GADGETUP, + NIL]) + -> OK, got a window, lets make some gadgets. + vi:=GetVisualInfoA(genscreen, [NIL]) + gadget:=CreateContext({glist}) + ng:=[controlwindow.borderleft+120, controlwindow.bordertop+2, + 12, 12, + -> Just a demo, set everything to topaz 80. + 'BORDERBLANK', ['topaz.font', 8, 0, 0]:textattr, + BORDERBLANK_ID, PLACETEXT_LEFT OR NG_HIGHLABEL, + vi, NIL]:newgadget + -> E-Note: the C version fails to check the return value of every single one + -> of the calls to CreateGadgetA(), which is fatal since "gadget" is + -> dereferenced as "gadget.height" (we are using automatic exceptions) + gadget:=CreateGadgetA(CHECKBOX_KIND, gadget, ng, [NIL]) + gadgetPtrs[BORDERBLANK_ID]:=gadget + + ng.topedge:=ng.topedge+gadget.height+2 + ng.gadgettext:='BORDERNOTRANS' + ng.gadgetid:=BORDERNOTRANS_ID + gadget:=CreateGadgetA(CHECKBOX_KIND, gadget, ng, [NIL]) + gadgetPtrs[BORDERNOTRANS_ID]:=gadget + + ng.topedge:=ng.topedge+gadget.height+2 + ng.gadgettext:='CHROMAKEY' + ng.gadgetid:=CHROMAKEY_ID + gadget:=CreateGadgetA(CHECKBOX_KIND, gadget, ng, [NIL]) + gadgetPtrs[CHROMAKEY_ID]:=gadget + + ng.topedge:=ng.topedge+gadget.height+2 + ng.gadgettext:='BITPLANEKEY' + ng.gadgetid:=BITPLANEKEY_ID + gadget:=CreateGadgetA(CHECKBOX_KIND, gadget, ng, [NIL]) + gadgetPtrs[BITPLANEKEY_ID]:=gadget + + ng.topedge:=ng.topedge+gadget.height+2 + ng.width:=90 + ng.gadgettext:='CHROMAPLANE' + ng.gadgetid:=CHROMAPLANE_ID + gadget:=CreateGadgetA(CYCLE_KIND, gadget, ng, + [GTCY_LABELS, ['Plane 0', 'Plane 1', 'Plane 2', 'Plane 3', NIL], + NIL]) + gadgetPtrs[CHROMAPLANE_ID]:=gadget + + ng.topedge:=ng.topedge+gadget.height+20 + ng.width:=12 + ng.flags:=PLACETEXT_ABOVE OR NG_HIGHLABEL + FOR j:=0 TO 1 + FOR i:=0 TO 7 + ng.leftedge:=controlwindow.borderleft+2+(i*gadget.width) + -> E-Note: we can let E clear up all the E-strings we make + ng.gadgettext:=StringF(String(3), '\d', i+(j*8)) + ng.gadgetid:=i+(j*8) + gadget:=CreateGadgetA(CHECKBOX_KIND, gadget, ng, [NIL]) + -> E-Note: C version gets the index wrong + gadgetPtrs[i+(j*8)]:=gadget + ENDFOR + ng.topedge:=ng.topedge+gadget.height + ng.flags:=PLACETEXT_BELOW OR NG_HIGHLABEL + ENDFOR + + AddGList(controlwindow, glist, -1, -1, NIL) + RefreshGList(glist, controlwindow, NIL, -1) + Gt_RefreshWindow(controlwindow, NIL) + + -> Finally, a window with some gadgets... + -> + -> Get the current genlock state. Obviously I already know what the settings + -> will be (all off), since I opened the screen myself. Do it just to show + -> how to get them. + vp:=genscreen.viewport + + -> Is borderblanking on? + vtags[0].tag:=VTAG_BORDERBLANK_GET + vtags[0].data:=NIL + + -> Is bordertransparent set? + vtags[1].tag:=VTAG_BORDERNOTRANS_GET + vtags[1].data:=NIL + + -> Key on bitplane? + vtags[2].tag:=VTAG_BITPLANEKEY_GET + vtags[2].data:=NIL + + -> Get plane which is used to key on + vtags[3].tag:=VTAG_CHROMA_PLANE_GET + vtags[3].data:=NIL + + -> Chromakey overlay on? + vtags[4].tag:=VTAG_CHROMAKEY_GET + vtags[4].data:=NIL + + FOR i:=0 TO 15 + -> Find out which colours overlay + vtags[i+5].tag:=VTAG_CHROMA_PEN_GET + vtags[i+5].data:=i + ENDFOR + + -> Indicate end of tag array + vtags[21].tag:=VTAG_END_CM + vtags[21].data:=NIL + + -> And send the commands. On return the Tags themselves will indicate the + -> genlock settings for this ViewPort's ColorMap. + VideoControl(vp.colormap, vtags) + + -> And initialise the gadgets, according to genlock settings. + + IF vtags[0].tag=VTAG_BORDERBLANK_SET + Gt_SetGadgetAttrsA(gadgetPtrs[BORDERBLANK_ID], controlwindow, NIL, + [GTCB_CHECKED, TRUE, NIL]) + ENDIF + IF vtags[1].tag=VTAG_BORDERNOTRANS_SET + Gt_SetGadgetAttrsA(gadgetPtrs[BORDERNOTRANS_ID], controlwindow, NIL, + [GTCB_CHECKED, TRUE, NIL]) + ENDIF + IF vtags[2].tag=VTAG_BITPLANEKEY_SET + Gt_SetGadgetAttrsA(gadgetPtrs[BITPLANEKEY_ID], controlwindow, NIL, + [GTCB_CHECKED, TRUE, NIL]) + ENDIF + IF vtags[3].tag=VTAG_CHROMA_PLANE_SET + Gt_SetGadgetAttrsA(gadgetPtrs[CHROMAPLANE_ID], controlwindow, NIL, + [GTCY_ACTIVE, vtags[3].data, NIL]) + ENDIF + IF vtags[4].tag=VTAG_CHROMAKEY_SET + Gt_SetGadgetAttrsA(gadgetPtrs[CHROMAKEY_ID], controlwindow, NIL, + [GTCB_CHECKED, TRUE, NIL]) + ENDIF + FOR i:=0 TO 15 + IF vtags[i+5].tag=VTAG_CHROMA_PEN_SET + -> E-Note: C version fails to terminate the tag list! + Gt_SetGadgetAttrsA(gadgetPtrs[i], controlwindow, NIL, + [GTCB_CHECKED, TRUE, NIL]) + ENDIF + ENDFOR + + -> Will only send single commands from here on. + vtags[1].tag:=VTAG_END_CM + + -> Get user input. + REPEAT + WaitPort(controlwindow.userport) + WHILE imsg:=Gt_GetIMsg(controlwindow.userport) + iclass:=imsg.class + icode:=imsg.code + hitgadget:=imsg.iaddress + Gt_ReplyIMsg(imsg) + + -> E-Note: C version uses obsolete tags + SELECT iclass + CASE IDCMP_GADGETUP + IF hitgadget.gadgetid < 16 + IF hitgadget.flags AND GFLG_SELECTED + -> Set colour key + vtags[0].tag:=VTAG_CHROMA_PEN_SET + ELSE + -> Clear colour key + vtags[0].tag:=VTAG_CHROMA_PEN_CLR + ENDIF + ELSE + i:=hitgadget.gadgetid + SELECT i + CASE BORDERBLANK_ID + IF hitgadget.flags AND GFLG_SELECTED + -> Set border blanking on + vtags[0].tag:=VTAG_BORDERBLANK_SET + ELSE + -> Turn border blanking off + vtags[0].tag:=VTAG_BORDERBLANK_CLR + ENDIF + CASE BORDERNOTRANS_ID + IF hitgadget.flags AND GFLG_SELECTED + -> Set border transparency on + vtags[0].tag:=VTAG_BORDERNOTRANS_SET + ELSE + -> Turn border transparency off + vtags[0].tag:=VTAG_BORDERNOTRANS_CLR + ENDIF + CASE BITPLANEKEY_ID + IF hitgadget.flags AND GFLG_SELECTED + -> Key on current selected bitplane (chromaplane) + vtags[0].tag:=VTAG_BITPLANEKEY_SET + ELSE + -> Turn bitplane keying off + vtags[0].tag:=VTAG_BITPLANEKEY_CLR + ENDIF + CASE BITPLANEKEY_ID + IF hitgadget.flags AND GFLG_SELECTED + -> Key on current selected bitplane (chromaplane) + vtags[0].tag:=VTAG_BITPLANEKEY_SET + ELSE + -> Turn bitplane keying off + vtags[0].tag:=VTAG_BITPLANEKEY_CLR + ENDIF + CASE CHROMAPLANE_ID + -> Set plane to key on + vtags[0].tag:=VTAG_CHROMA_PLANE_SET + vtags[0].data:=icode + CASE BITPLANEKEY_ID + IF hitgadget.flags AND GFLG_SELECTED + -> Key on current selected bitplane (chromaplane) + vtags[0].tag:=VTAG_BITPLANEKEY_SET + ELSE + -> Turn bitplane keying off + vtags[0].tag:=VTAG_BITPLANEKEY_CLR + ENDIF + CASE CHROMAKEY_ID + IF hitgadget.flags AND GFLG_SELECTED + -> Set chromakey overlay on + vtags[0].tag:=VTAG_CHROMAKEY_SET + ELSE + -> Turn chromakey overlay off + vtags[0].tag:=VTAG_CHROMAKEY_CLR + ENDIF + ENDSELECT + ENDIF + + -> Send video command. + VideoControl(vp.colormap, vtags) + -> Get the View for this genlock screen. + viewlord:=ViewAddress() + -> And remake the ViewPort. + MakeVPort(viewlord, vp) + MrgCop(viewlord) + LoadView(viewlord) + + CASE IDCMP_CLOSEWINDOW + -> Get out of here. + abort:=TRUE + ENDSELECT + ENDWHILE + UNTIL abort + + RemoveGList(controlwindow, glist, -1) + +EXCEPT DO + -> E-Note: works even if glist=NIL + FreeGadgets(glist) + IF vi THEN FreeVisualInfo(vi) + IF controlwindow THEN CloseWindow(controlwindow) + IF genscreen THEN CloseScreen(genscreen) + -> E-Note: the E-strings used for gadget text will be freed automatically + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + imsg:=NIL -> E-Note: get ready to receive a possible error message + SELECT exception + CASE ERR_CTXT; imsg:='Can''t create gadget context' + CASE ERR_ECS; imsg:='Requires ECS' + CASE ERR_GAD; imsg:='Can''t create gadget' + CASE ERR_KICK; imsg:='Requires V37' + CASE ERR_LIB; imsg:='Unable to open gadtools.library' + CASE ERR_SCRN; imsg:='Can''t open screen' + CASE ERR_VIS; imsg:='Can''t get visual info' + CASE ERR_WIN; imsg:='Can''t open window' + CASE "MEM"; imsg:='Out of memory' + ENDSELECT + IF imsg THEN EasyRequestArgs(NIL, [SIZEOF easystruct, 0, 'GenlockDemo', + '\s', 'Continue']:easystruct, + NIL, [imsg]) +ENDPROC +->>> + +->>> PROC checkPAL(screenname) +-> Generic routine to check for a PAL System. CheckPAL returns TRUE, if the +-> videomode of the specified public screen (or default videmode) is PAL. If +-> the screenname is NIL, the default public screen will be used. +PROC checkPAL(screenname) + DEF screen:PTR TO screen, modeID=LORES_KEY, displayinfo:displayinfo, isPAL + IF gfx.lib.version>=36 + -> We got V36, so lets use the new calls to find out what kind of videomode + -> the user (hopefully) prefers. + IF screen:=LockPubScreen(screenname) + -> Use graphics.library/GetVPModeID() to get the ModeID of the specified + -> screen. Will use the default public screen (Workbench most of the + -> time) if NIL. It is _very_ unlikely that this would be invalid, heck + -> it's impossible. + IF INVALID_ID<>(modeID:=GetVPModeID(screen.viewport)) + -> If the screen is in VGA mode, we can't tell whether the system is PAL + -> or NTSC. So to be foolproof we fall back to the displayinfo of the + -> default.monitor by inquiring about just the LORES_KEY displaymode if + -> we don't know. The default.monitor reflects the initial video setup + -> of the system, thus is an alias for either ntsc.monitor or + -> pal.monitor. We only use the displaymode of the specified public + -> screen if it's display mode is PAL or NTSC and NOT the default. + IF ((modeID AND MONITOR_ID_MASK)<>NTSC_MONITOR_ID) AND + ((modeID AND MONITOR_ID_MASK)<>PAL_MONITOR_ID) + modeID:=LORES_KEY + ENDIF + ENDIF + UnlockPubScreen(NIL, screen) + ENDIF + -> If fails modeID=LORES_KEY. Can't lock screen, so fall back on + -> default monitor. + IF GetDisplayInfoData(NIL, displayinfo, SIZEOF displayinfo, + DTAG_DISP, modeID) + -> Currently the default monitor is always either PAL or NTSC. + isPAL:=displayinfo.propertyflags AND DIPF_IS_PAL + ENDIF + ELSE + -> < V36. The enhancements to the videosystem in V36 cannot be better + -> expressed than with the simple way to determine PAL in V34. + isPAL:=gfx.displayflags AND PAL + ENDIF +ENDPROC isPAL +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/usercopperexample.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/usercopperexample.e new file mode 100644 index 0000000..547e082 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Primitives/usercopperexample.e @@ -0,0 +1,135 @@ +-> UserCopperExample.e - User Copper List Example + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'dos/dos', + 'exec/memory', + 'graphics/copper', + 'graphics/gfxmacros', + 'graphics/text', + 'graphics/videocontrol', + 'graphics/view', + 'hardware/custom', + 'intuition/intuition', + 'intuition/preferences', + 'intuition/screens' + +ENUM ERR_NONE, ERR_KICK, ERR_SCRN, ERR_WIN + +RAISE ERR_KICK IF KickVersion()=FALSE, + ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL, + "MEM" IF AllocMem()=NIL + +DEF screen=NIL:PTR TO screen, window=NIL:PTR TO window, + -> E-Note: set-up custom + custom=CUSTOMADDR:PTR TO custom +->>> + +->>> PROC main() +PROC main() HANDLE + DEF ret_val=RETURN_OK, viewPort:PTR TO viewport + -> Open a screen and a window + openAll() + -> Create and attach the user Copper list. + loadCopper() + -> Wait until the user clicks in the close gadget. + REPEAT + UNTIL WaitIMessage(window)=IDCMP_CLOSEWINDOW +EXCEPT DO + IF window + viewPort:=ViewPortAddress(window) + IF viewPort.ucopins + -> Free the memory allocated for the Copper list. + FreeVPortCopLists(viewPort) + RemakeDisplay() + ENDIF + CloseWindow(window) + ENDIF + IF screen THEN CloseScreen(screen) + SELECT exception + CASE ERR_KICK; WriteF('Error: requires V37\n') + ret_val:=ERROR_INVALID_RESIDENT_LIBRARY + CASE ERR_SCRN; WriteF('Error: failed to open screen\n') + ret_val:=ERROR_NO_FREE_STORE + CASE ERR_WIN; WriteF('Error: failed to open window\n') + ret_val:=ERROR_NO_FREE_STORE + CASE "MEM"; WriteF('Error: ran out of memory\n') + ret_val:=ERROR_NO_FREE_STORE + ENDSELECT +ENDPROC ret_val +->>> + +->>> PROC openAll() +CONST MY_WA_WIDTH=270 -> Width of window. + +-> Opens screen and window +-> E-Note: any exception raised here will be handled by the caller +PROC openAll() + KickVersion(37) + screen:=OpenScreenTagList(NIL, + [SA_OVERSCAN, OSCAN_STANDARD, + SA_TITLE, 'User Copper List Example', + SA_FONT, ['topaz.font', TOPAZ_SIXTY, 0, 0]:textattr, + NIL]) + -> E-Note: C version uses obsolete tags, and in fact used an IDCMP flag, + -> INACTIVEWINDOW, with WA_FLAGS (I guess they meant WFLG_ACTIVATE) + window:=OpenWindowTagList(NIL, + [WA_CUSTOMSCREEN, screen, + WA_TITLE, '<- Click here to quit.', + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_FLAGS, WFLG_DRAGBAR OR WFLG_CLOSEGADGET OR + WFLG_ACTIVATE, + WA_LEFT, (screen.width-MY_WA_WIDTH)/2, + WA_TOP, screen.height/2, + WA_HEIGHT, screen.font.ysize+3, + WA_WIDTH, MY_WA_WIDTH, + NIL]) +ENDPROC +->>> + +->>> PROC loadCopper() +CONST NUMCOLORS=32 + +-> Creates a Copper list program and adds it to the system +-> E-Note: again, any exception raised here will be handled by the caller +PROC loadCopper() + DEF i, scanlines_per_color, viewPort:PTR TO viewport, uCopList, + spectrum:PTR TO INT + -> Allocate memory for the Copper list. + -> Make certain that the initial memory is cleared. + -> E-Note: we *have* to use AllocMem() since FreeVPortCopLists() is used + uCopList:=AllocMem(SIZEOF ucoplist, MEMF_PUBLIC OR MEMF_CLEAR) + + -> Initialise the Copper list buffer. + CINIT(uCopList, NUMCOLORS) + + scanlines_per_color:=screen.height/NUMCOLORS + + spectrum:=[$0604, $0605, $0606, $0607, $0617, $0618, $0619, $0629, + $072a, $073b, $074b, $074c, $075d, $076e, $077e, $088f, + $07af, $06cf, $05ff, $04fb, $04f7, $03f3, $07f2, $0bf1, + $0ff0, $0fc0, $0ea0, $0e80, $0e60, $0d40, $0d20, $0d00]:INT + -> Load in each color. + FOR i:=0 TO NUMCOLORS-1 + CWAIT(uCopList, i*scanlines_per_color, 0) + -> E-Note: hard to use CMOVE() due to use of {}, which CMOVEA() eliminates + -> E-Note: use the offset constant COLOR plus n*SIZEOF INT for n-th color + CMOVEA(uCopList, CUSTOMADDR+COLOR+0, spectrum[i]) + ENDFOR + + CEND(uCopList) -> End the Copper list. + + viewPort:=ViewPortAddress(window) -> Get a pointer to the ViewPort. + Forbid() -> Forbid task switching while changing the Copper list. + viewPort.ucopins:=uCopList + Permit() -> Permit task switching again. + + -> Enable user Copper list clipping this ViewPort. + VideoControl(viewPort.colormap, [VTAG_USERCLIP_SET, NIL, NIL]) + + RethinkDisplay() -> Display the new Copper list. +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/animtools.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/animtools.e new file mode 100644 index 0000000..a517d95 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/animtools.e @@ -0,0 +1,356 @@ +-> animtools.e +-> +-> This file is a collection of tools which are used with the VSprite, Bob and +-> Animation system software. It is intended as a useful EXAMPLE, and while it +-> shows what must be done, it is not the only way to do it. If Not Enough +-> Memory, or error return, each cleans up after itself before returning. +-> NOTE that these routines assume a very specific structure to the GEL lists. +-> Make sure that you use the correct pairs together +-> (i.e., makeOb()/freeOb()) + +->>> Header (globals) +OPT MODULE, PREPROCESS +OPT EXPORT + +MODULE 'exec/memory', + 'graphics/gels', + 'graphics/gfx', + 'graphics/rastport' + +-> 'intuition/intuitionbase' does not define a library name. +#define INTUITIONNAME 'intuition.library' + +-> These objects are used by the functions below to allow for an easier +-> interface to the animation system. +->>> + +->>> OBJECT newVSprite +-> Object to hold information for a new VSprite. +OBJECT newVSprite + image:PTR TO INT -> Image data for the VSprite + colorSet:PTR TO INT -> Colour array for the VSprite + wordWidth:INT -> Width in words + lineHeight:INT -> Height in lines + imageDepth:INT -> Depth of the image + x:INT -> Initial x position + y:INT -> Initial y position + flags:INT -> VSprite flags + hitMask:INT -> Hit mask + meMask:INT -> Me mask +ENDOBJECT +->>> + +->>> OBJECT newBob +-> Object to hold information for a new Bob. +OBJECT newBob + image:PTR TO INT -> Image data FOR the Bob + wordWidth:INT -> Width in words + lineHeight:INT -> Height in lines + imageDepth:INT -> Depth of the image + planePick:INT -> Planes that get image data + planeOnOff:INT -> Unused planes to turn on + bFlags:INT -> Bob flags + dBuf:INT -> 1=double buf, 0=not + rasDepth:INT -> Depth of the raster + x:INT -> Initial x position + y:INT -> Initial y position + hitMask:INT -> Hit mask + meMask:INT -> Me mask +ENDOBJECT +->>> + +->>> OBJECT newAnimComp +-> Object to hold information for a new animation component. +OBJECT newAnimComp + routine:LONG -> Routine called when Comp IS displayed + xt:INT -> Initial delta offset position + yt:INT + time:INT -> Initial timer value + cFlags:INT -> Flags for the Comp +ENDOBJECT +->>> + +->>> OBJECT newAnimSeq +-> Object to hold information for a new animation sequence. +OBJECT newAnimSeq + headOb:PTR TO ao -> Common head of object + images:PTR TO INT -> Array of Comp image data + xt:PTR TO INT -> Arrays of initial offsets + yt:PTR TO INT + times:PTR TO INT -> Array of initial timer values + routines:PTR TO LONG -> Array of functions called when Comp is drawn + cFlags:INT -> Flags for the Comp + count:INT -> Number of Comps in sequence (= arrays size) + singleImage:INT -> One (or count) images +ENDOBJECT +->>> + +->>> PROC setupGelSys(rPort:PTR TO rastport, reserved) HANDLE +-> Setup the GELs system. After this call is made you can use VSprites, Bobs, +-> AnimComps and AnimObs. Note that this links the GelsInfo structure into the +-> RastPort, and calls InitGels(). It uses information in your rastport +-> object to establish boundary collision defaults at the outer edges of the +-> raster. This routine sets up for everything - collision detection and all. +-> You must already have run LoadView before ReadyGelSys is called. +PROC setupGelSys(rPort:PTR TO rastport, reserved) HANDLE + DEF gInfo=NIL:PTR TO gelsinfo, vsHead=NIL:PTR TO vs, vsTail=NIL:PTR TO vs + NEW gInfo, vsHead, vsTail + NEW gInfo.nextline[8], gInfo.lastcolor[8], gInfo.collhandler + gInfo.sprrsrvd:=reserved + -> Set left- and top-most to 1 to better keep items inside the display + -> boundaries. + gInfo.leftmost:=1; gInfo.topmost:=1 + gInfo.rightmost:=(rPort.bitmap.bytesperrow*8)-1 + gInfo.bottommost:=rPort.bitmap.rows-1 + rPort.gelsinfo:=gInfo + InitGels(vsHead, vsTail, gInfo) +EXCEPT + IF gInfo THEN END gInfo.nextline[8], gInfo.lastcolor[8], gInfo.collhandler + END gInfo, vsHead, vsTail + ReThrow() +ENDPROC gInfo +->>> + +->>> PROC cleanupGelSys(gInfo:PTR TO gelsinfo, rPort:PTR TO rastport) +-> Free all of the stuff allocated by setupGelSys(). Only call this routine if +-> setupGelSys() returned successfully. The GelsInfo structure IS the one +-> returned by setupGelSys(). It also unlinks the GelsInfo from the RastPort. +PROC cleanupGelSys(gInfo:PTR TO gelsinfo, rPort:PTR TO rastport) + rPort.gelsinfo:=NIL + END gInfo.nextline[8], gInfo.lastcolor[8], gInfo.collhandler, + gInfo.gelhead, gInfo.geltail + END gInfo +ENDPROC +->>> + +->>> PROC makeVSprite(nVSprite:PTR TO newVSprite) HANDLE +-> Create a VSprite from the information given in nVSprite. Use freeVSprite() +-> to free this GEL. +PROC makeVSprite(nVSprite:PTR TO newVSprite) HANDLE + DEF vsprite=NIL:PTR TO vs, line_size, plane_size + line_size:=SIZEOF INT * nVSprite.wordWidth + plane_size:=line_size * nVSprite.lineHeight + NEW vsprite + vsprite.borderline := NewM(line_size, MEMF_CHIP) + vsprite.collmask := NewM(plane_size, MEMF_CHIP) + vsprite.y := nVSprite.y + vsprite.x := nVSprite.x + vsprite.vsflags := nVSprite.flags + vsprite.width := nVSprite.wordWidth + vsprite.depth := nVSprite.imageDepth + vsprite.height := nVSprite.lineHeight + vsprite.memask := nVSprite.meMask + vsprite.hitmask := nVSprite.hitMask + vsprite.imagedata := nVSprite.image + vsprite.sprcolors := nVSprite.colorSet + vsprite.planepick := 0 + vsprite.planeonoff := 0 + InitMasks(vsprite) +EXCEPT + IF vsprite + Dispose(vsprite.borderline) + Dispose(vsprite.collmask) + ENDIF + END vsprite + ReThrow() +ENDPROC vsprite +->>> + +->>> PROC makeBob(nBob:PTR TO newBob) HANDLE +-> Create a Bob from the information given in nBob. Use freeBob() to free this +-> GEL. A VSprite is created for this bob. This routine properly allocates +-> all double buffered information if it is required. +PROC makeBob(nBob:PTR TO newBob) HANDLE + DEF bob=NIL:PTR TO bob, vsprite=NIL:PTR TO vs, rassize + rassize:=SIZEOF INT * nBob.wordWidth * nBob.lineHeight * nBob.rasDepth + NEW bob + bob.savebuffer:=NewM(rassize, MEMF_CHIP) + vsprite:=makeVSprite([nBob.image, NIL, nBob.wordWidth, nBob.lineHeight, + nBob.imageDepth, nBob.x, nBob.y, nBob.bFlags, + nBob.hitMask, nBob.meMask]:newVSprite) + vsprite.planepick:=nBob.planePick + vsprite.planeonoff:=nBob.planeOnOff + vsprite.vsbob:=bob + bob.bobvsprite:=vsprite + bob.imageshadow:=vsprite.collmask + bob.bobflags:=0 + bob.before:=NIL + bob.after:=NIL + bob.bobcomp:=NIL + + IF nBob.dBuf + NEW bob.dbuffer + bob.dbuffer.bufbuffer:=NewM(rassize, MEMF_CHIP) + ELSE + bob.dbuffer:=NIL + ENDIF +EXCEPT + IF vsprite THEN freeVSprite(vsprite) + IF bob + IF bob.dbuffer THEN Dispose(bob.dbuffer.bufbuffer) + END bob.dbuffer + Dispose(bob.savebuffer) + ENDIF + END bob + ReThrow() +ENDPROC bob +->>> + +->>> PROC makeComp(nBob:PTR TO newBob, nAnimComp:PTR TO newAnimComp) HANDLE +-> Create a Animation Component from the information given in nAnimComp and +-> nBob. Use freeComp() to free this GEL. makeComp() calls makeBob(), and +-> links the Bob into an AnimComp. +PROC makeComp(nBob:PTR TO newBob, nAnimComp:PTR TO newAnimComp) HANDLE + DEF compBob=NIL:PTR TO bob, aComp=NIL:PTR TO ac + NEW aComp + compBob:=makeBob(nBob) + compBob.before:=NIL + compBob.after:=NIL + compBob.bobcomp:=aComp -> Link 'em up + aComp.animbob := compBob + aComp.timeset := nAnimComp.time -> Number of ticks active + aComp.ytrans := nAnimComp.yt -> Offset relative to HeadOb + aComp.xtrans := nAnimComp.xt + aComp.animcroutine := nAnimComp.routine + aComp.compflags := nAnimComp.cFlags + aComp.timer := 0 + aComp.prevseq := NIL + aComp.nextseq := NIL + aComp.prevcomp := NIL + aComp.nextcomp := NIL + aComp.headob := NIL +EXCEPT + -> E-Note: Don't need to freeBob(compBob)... + END aComp + ReThrow() +ENDPROC aComp +->>> + +->>> PROC makeSeq(nBob:PTR TO newBob, nAnimSeq:PTR TO newAnimSeq) HANDLE +-> Create an Animation Sequence from the information given in nAnimSeq and +-> nBob. Use freeSeq() to free this GEL. This routine creates a linked list +-> of animation components which make up the animation sequence. It links them +-> all up, making a circular list of the prevseq and nextseq pointers. That is +-> to say, the first component of the sequence's prevseq points to the last +-> component; the last component of the sequence's nextseq points back to the +-> first component. If dbuf is on, the underlying Bobs will be set up for +-> double buffering. If singleImage is non-zero, the 'images' pointer is +-> assumed to point to an array of only one image, instead of an array of +-> 'count' images, and all Bobs will use the same image. +PROC makeSeq(nBob:PTR TO newBob, nAnimSeq:PTR TO newAnimSeq) HANDLE + DEF seq, firstCompInSeq=NIL:PTR TO ac, seqComp=NIL:PTR TO ac, + lastCompMade=NIL:PTR TO ac, image_size, nAnimComp:newAnimComp + -> Get the initial image. This is the only image that is used if + -> nAnimSeq.singleImage is non-zero. + nBob.image:=nAnimSeq.images + image_size:=nBob.lineHeight * nBob.imageDepth * nBob.wordWidth + + -> For each comp in the sequence + FOR seq:=0 TO nAnimSeq.count-1 + nAnimComp.xt := nAnimSeq.xt[seq] + nAnimComp.yt := nAnimSeq.yt[seq] + nAnimComp.time := nAnimSeq.times[seq] + nAnimComp.routine := nAnimSeq.routines[seq] + nAnimComp.cFlags := nAnimSeq.cFlags + seqComp:=makeComp(nBob, nAnimComp) + seqComp.headob:=nAnimSeq.headOb + -> Make a note of where the first component is. + IF firstCompInSeq=NIL THEN firstCompInSeq:=seqComp + -> Link the component into the list + IF lastCompMade<>NIL THEN lastCompMade.nextseq:=seqComp + seqComp.nextseq:=NIL + seqComp.prevseq:=lastCompMade + lastCompMade:=seqComp + -> If nAnimSeq.singleImage is zero, the image array has nAnimSeq.count + -> images. + IF nAnimSeq.singleImage=0 + -> E-Note: image_size is in INTs so multiply up first + nBob.image:=nBob.image+(image_size*SIZEOF INT) + ENDIF + ENDFOR + -> On the last component in the sequence, set Next/Prev to make the linked + -> list a loop of components. + lastCompMade.nextseq:=firstCompInSeq + firstCompInSeq.prevseq:=lastCompMade +EXCEPT + IF firstCompInSeq THEN freeSeq(firstCompInSeq, nBob.rasDepth) + ReThrow() +ENDPROC firstCompInSeq +->>> + +->>> PROC freeVSprite(vsprite:PTR TO vs) +-> Free the data created by makeVSprite(). Assumes images deallocated +-> elsewhere. +PROC freeVSprite(vsprite:PTR TO vs) + DEF line_size, plane_size + line_size:=SIZEOF INT * vsprite.width + plane_size:=line_size * vsprite.height + Dispose(vsprite.borderline) + Dispose(vsprite.collmask) + END vsprite +ENDPROC +->>> + +->>> PROC freeBob(bob:PTR TO bob, rasdepth) +-> Free the data created by makeBob(). It's important that rasdepth match the +-> depth you passed to makeBob() when this GEL was made. Assumes images +-> deallocated elsewhere. +PROC freeBob(bob:PTR TO bob, rasdepth) + DEF rassize + rassize:=SIZEOF INT * bob.bobvsprite.width * bob.bobvsprite.height * rasdepth + IF bob.dbuffer THEN Dispose(bob.dbuffer.bufbuffer) + END bob.dbuffer + Dispose(bob.savebuffer) + freeVSprite(bob.bobvsprite) + END bob +ENDPROC +->>> + +->>> PROC freeComp(myComp:PTR TO ac, rasdepth) +-> Free the data created by makeComp(). It's important that rasdepth match +-> the depth you passed to makeComp() when this GEL was made. Assumes images +-> deallocated elsewhere. +PROC freeComp(myComp:PTR TO ac, rasdepth) + freeBob(myComp.animbob, rasdepth) + END myComp +ENDPROC +->>> + +->>> PROC freeSeq(headComp:PTR TO ac, rasdepth) +-> Free the data created by makeSeq(). Complementary to makeSeq(), this +-> routine goes through the nextseq pointers and frees the Comps. This routine +-> only goes forward through the list, and so it must be passed the first +-> component in the sequence, or the sequence must be circular (which is +-> guaranteed if you use makeSeq()). It's important that rasdepth match the +-> depth you passed to makeSeq() when this GEL was made. Assumes images +-> deallocated elsewhere! +PROC freeSeq(headComp:PTR TO ac, rasdepth) + DEF curComp:PTR TO ac, nextComp + -> Break the nextseq loop, so we get a NIL at the end of the list. + headComp.prevseq.nextseq:=NIL + + curComp:=headComp -> Get the start of the list + WHILE curComp<>NIL + nextComp:=curComp.nextseq + freeComp(curComp, rasdepth) + curComp:=nextComp + ENDWHILE +ENDPROC +->>> + +->>> PROC freeOb(headOb:PTR TO ao, rasdepth) +-> Free an animation object (list of sequences). freeOb() goes through the +-> nextcomp pointers, starting at the AnimOb's headcomp, and frees every +-> sequence. It only goes forward. It then frees the Object itself. Assumes +-> images deallocated elsewhere! +PROC freeOb(headOb:PTR TO ao, rasdepth) + DEF curSeq:PTR TO ac, nextSeq + curSeq:=headOb.headcomp -> Get the start of the list + WHILE curSeq<>NIL + nextSeq:=curSeq.nextcomp + freeSeq(curSeq, rasdepth) + curSeq:=nextSeq + ENDWHILE + END headOb +ENDPROC +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/animtools.m b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/animtools.m new file mode 100644 index 0000000000000000000000000000000000000000..b01b027b0e05cc7c8cacae1566ed6e19002be9bf GIT binary patch literal 4640 zcmai1O>A3L7Cv^2^Yr>;d8{aktf)0nL|t&|Fq#FGDwKu-4r=U(P-Yg4S|@o)tojef zp$V%8La6En!~%863UvXfLM%XH(QH_tS#-s!q9Y-uS!9MTEMy^1-+brX`>tPXR}<-6 z-+S)4=l8qkzP!9#x=2qEkpuGXVURyt#xbI?)5Xhvr||F;HR-tpzb9i?#!f!x-vNCC zx_zeP-?{Jy{c)z?e{*Kpzg^g)XNup^814P-BR+@qi=lOQVBKk2zud@EAd#v0y{8w* zZd$(%a}zkbFd&)A%#p>Xl3p{yzt1nwq?x5NHF7fB6q`>L?jH2WTJ^Ndl-bErv~bt( zr!#YYkN4ok1Z2B2HNP_py}7FYkK$MUjWbse^A*H;#lLfv=zEsmBHCoVnJn2`Q+W!- zbbaL`-dVg&ww6dJ2@_vmBB3QxTa$S*vG(^7D{Q4?PvsbUi(kU-oZr=am21WCg5Mdz z???_^)^_Oub&G#5?iMc->WsK86*sc>gjmQ?v53UTSVRJ`h{T9kWIv_%qdHdOH}hd3 zs`ukh*pH*`&TuZsX_AU3jNM_pMqUr_+GI=CpR;5Y4h{~0*bZk+^K8uE~wTz7CZag$k1(imfW`cf#%6CUr zwTtWsMl#8~+z{k7R=8{C@z5MqGJIs(%uxq3N43p-Dl|{?9G%q8Sm-O$q&l&*K|XresXYn2^zt(U#GA`U+8=%G5jJT5wO+SkQRk8f%Wm6gcNl&#uP8U%0lI zb0%JR~Jy~SsMzO-1z&A%c7`n| z3@aSzzH2bt?e|x7h2SlHB8KVr0K>@7u~#&YZifo~t}6%)IuoI6hpIFgs-E0)V7A{u za37^R0J+e@ohaxRz_sQ`moeQTsGmlRt~Q^HiYMGbQf8*=uHJF>lV=JiJUcm1yNuLs z#H(hq7<#4rLz6}IMbeQkl1HWA{LXVF+~A=vlgOEWX;a`N59;h$F}6Ii=0S)vFD7~i?c55B}eSx zJ4W^0r76>YKL;i(dAIm9_wx>CnX|e{*ufe%cFuo< zyO6*y-ZuXcBvh4Hmbs7gxs=FbB@s{aeT9};tR3lpbN(T|Z=y4lIdyQr>oZIB4D@=R=Q9{0H)+GF$_<-9>KE#jn%3j6&No+^txDU4fc+_CBdioD*wI{v zwe@A9-?NP0VexvOomj8B<@#>(Rkymjzk|)l5!+=|z}-@Pvyp49G+J$}cHDMIjz!@g z>r0A6uI28yt#{lFa4hx@PGfq)GWrs02%{e^S?r;birp~Y#W~tQM~P?TTr@h8+irQI z6jmd)R^7MR)?*`=V!46*iajN1eZrFdAr2+_+2uXo=jfwflY<%6-RqooeF)VgWuI6s zR&L{qSe@KSL$*OXTY6Wf2CU9 zVm(B0tkdg_-8vt~|L{?o-l^2Ls_qioVjk`&2;Sl^?5zR``$gIUOT-`<6Tj3vE`BLH z7W>6Q;)NaZf-MI&ES(WmAC8A4ZWRx-UvIQF{#w~!EGv)WRfJb?D_h$VghXM`D?n-6-T5!@4PN`nn++>#cl~_BTo#e*iuG(cCDIlw_H44te9-rjd}M zr1;9!Pi+QZU{5CoJfA$~`4oIUL5Zc}8<&^fSSl5Z7nWb bob.e - Simple Bob example + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'dos/dos', + 'exec/memory', + 'exec/ports', + 'graphics/gels', + 'intuition/intuition', + 'intuition/screens', + '*animtools' + +ENUM ERR_NONE, ERR_KICK, ERR_WIN + +RAISE ERR_KICK IF KickVersion()=FALSE, + ERR_WIN IF OpenWindow()=NIL + +CONST GEL_SIZE=4 + +DEF bob_data1, bob_data2, myNewBob:PTR TO newBob +->>> + +->>> PROC bobDrawGList(rport, vport) +-> Draw the Bobs into the RastPort. +PROC bobDrawGList(rport, vport) + SortGList(rport) + DrawGList(rport, vport) + -> If the GelsList includes true VSprites, MrgCop() and LoadView() here + WaitTOF() +ENDPROC +->>> + +->>> PROC process_window(win:PTR TO window, myBob:PTR TO bob) +-> Process window and dynamically change bob: Get messages. Go away on +-> IDCMP_CLOSEWINDOW. Update and redisplay bob on IDCMP_INTUITICKS. Wait for +-> more messages. +PROC process_window(win:PTR TO window, myBob:PTR TO bob) + DEF msg:PTR TO intuimessage + LOOP + Wait(Shl(1, win.userport.sigbit)) + WHILE msg:=GetMsg(win.userport) + -> Only IDCMP_CLOSEWINDOW AND IDCMP_INTUITICKS are active + IF msg.class=IDCMP_CLOSEWINDOW + ReplyMsg(msg) + RETURN + ENDIF + -> Must be IDCMP_INTUITICKS: change x and y values on the fly. Note: do + -> not have to add window offset, Bob is relative to the window (sprite + -> relative to screen). + myBob.bobvsprite.x:=msg.mousex+20 + myBob.bobvsprite.y:=msg.mousey+1 + ReplyMsg(msg) + ENDWHILE + -> After getting a message, change image data on the fly + myBob.bobvsprite.imagedata:=IF myBob.bobvsprite.imagedata=bob_data1 THEN + bob_data2 ELSE bob_data1 + InitMasks(myBob.bobvsprite) -> Set up masks for new image + bobDrawGList(win.rport, ViewPortAddress(win)) + ENDLOOP +ENDPROC +->>> + +->>> PROC do_Bob(win:PTR TO window) +-> Working with the Bob: setup the GEL system, and get a new Bob (makeBob()). +-> Add the bob to the system and display. Use the Bob. When done, remove the +-> Bob and update the display without the bob. Cleanup everything. +PROC do_Bob(win:PTR TO window) HANDLE + DEF myBob=NIL, my_ginfo=NIL + my_ginfo:=setupGelSys(win.rport, $03) + myBob:=makeBob(myNewBob) + AddBob(myBob, win.rport) + bobDrawGList(win.rport, ViewPortAddress(win)) + process_window(win, myBob) + RemBob(myBob) + bobDrawGList(win.rport, ViewPortAddress(win)) +EXCEPT DO + IF myBob THEN freeBob(myBob, myNewBob.rasDepth) + IF my_ginfo THEN cleanupGelSys(my_ginfo, win.rport) + ReThrow() +ENDPROC +->>> + +->>> PROC main() +PROC main() HANDLE + DEF win=NIL + KickVersion(37) + -> E-Note: set-up global data + -> Bob data - two sets that are alternated between. Note that this data is + -> at the resolution of the screen. + bob_data1:=copyListToChip([$FFFF0003, $FFF00003, $FFF00003, $FFFF0003, + $3FFFFFFC, $3FF00FFC, $3FF00FFC, $3FFFFFFC]) + bob_data2:=copyListToChip([$C000FFFF, $C0000FFF, $C0000FFF, $C000FFFF, + $3FFFFFFC, $3FF00FFC, $3FF00FFC, $3FFFFFFC]) + -> Data for the new Bob object defined in animtools.m + myNewBob:=[bob_data2, 2, GEL_SIZE, + 2, 3, 0, VSF_SAVEBACK OR VSF_OVERLAY, + 0, 8, 160, 100, 0, 0]:newBob + win:=OpenWindow([80, 20, 400, 150, -1, -1, + IDCMP_CLOSEWINDOW OR IDCMP_INTUITICKS, + WFLG_ACTIVATE OR WFLG_CLOSEGADGET OR WFLG_DEPTHGADGET OR + WFLG_RMBTRAP, + NIL, NIL, 'Bob', NIL, NIL, 0, 0, 0, 0, WBENCHSCREEN]:nw) + do_Bob(win) +EXCEPT DO + IF win THEN CloseWindow(win) + SELECT exception + CASE ERR_KICK; WriteF('Error: requires V37\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK +->>> + +->>> PROC copyListToChip(data) +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/collide.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/collide.e new file mode 100644 index 0000000..8662528 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/collide.e @@ -0,0 +1,514 @@ +-> collide.e - An example of collision detection between objects and between +-> the border. + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'dos/dos', + 'exec/memory', + 'graphics/collide', + 'graphics/gels', + 'graphics/gfx', + 'graphics/rastport', + 'graphics/view', + 'intuition/intuition', + 'intuition/screens', + 'other/ecode', + '*animtools' + +ENUM ERR_NONE, ERR_RAST, ERR_SCRN, ERR_WIN + +RAISE ERR_RAST IF AllocRaster()=NIL, + ERR_SCRN IF OpenScreen()=NIL, + ERR_WIN IF OpenWindow()=NIL + +CONST RBMWIDTH=320, RBMHEIGHT=200, RBMDEPTH=4 + +-> These give the number of frames (COUNT), size (HEIGHT, WIDTH, DEPTH), and +-> word width (WWIDTH) of the animated object. +CONST BOING_COUNT=6, BOING_HEIGHT=25, BOING_WIDTH=32, BOING_DEPTH=1 +CONST BOING_WWIDTH=BOING_WIDTH+15/16 + +-> These are the IDs for the system to use for the three objects. These +-> numbers will be used for the collision detection system. +-> +-> Do not use zero (0), as it is reserved by the collision system for border +-> hits (see 'graphics/collide', BORDERHIT). +ENUM BOING_1=2, BOING_2, BOING_3 + +DEF ns:PTR TO ns, nw:PTR TO nw, boing3Times:PTR TO INT, + boing3YTranses:PTR TO INT, boing3XTranses:PTR TO INT, + boing3CRoutines:PTR TO LONG, boing3Image:PTR TO LONG, + newBoingBob:PTR TO newBob, newBoingSeq:PTR TO newAnimSeq + +-> E-Note: this is the static variable from setupBitMaps(). +DEF myBitMaps[2]:ARRAY OF LONG +->>> + +->>> PROC setupGlobals() +PROC setupGlobals() + ns:=[0, 0, 320, 200, 2, 0, 1, NIL, + CUSTOMSCREEN, NIL, 'Collision with AnimObs', NIL, NIL]:ns + nw:=[50, 50, 220, 100, -1, -1, IDCMP_CLOSEWINDOW, + WFLG_CLOSEGADGET OR WFLG_RMBTRAP, NIL, NIL, 'Close Window to Stop', + NIL, NIL, 150, 100, 150, 100, CUSTOMSCREEN]:nw + -> These are the number of counts that each frame is displayed. They are + -> all one, so each frame is displayed once then the animation system will + -> move on to the next in the sequence. + boing3Times:=[1, 1, 1, 1, 1, 1]:INT + -> These are all set to zero as we do not want anything added to the X and Y + -> positions using ring motion control. All movement is done using the + -> acceleration and velocity values. + boing3YTranses:=[0, 0, 0, 0, 0, 0]:INT + boing3XTranses:=[0, 0, 0, 0, 0, 0]:INT + -> No special routines to call when each anim comp is displayed. + boing3CRoutines:=[NIL, NIL, NIL, NIL, NIL, NIL]:LONG + boing3Image:=copyListToChip( + -> ----- bitmap Boing, frame 0: w = 32, h = 25 ------ + [$00230000, $004E3000, $00E33A00, $03C3C900, + $07878780, $108F8700, $31F78790, $61F04790, + $63E0FB90, $43E0F848, $3BC0F870, $3801F870, + $383DF070, $387E1070, $387C0EE0, $D87C1F10, + $467C1E10, $479C1E30, $67873E20, $0787CC60, + $0F0F8700, $048F0E00, $02771C00, $0161D800, + $00272000, + -> ----- bitmap Boing, frame 1: w = 32, h = 25 ------ + $00318000, $01071800, $00F01900, $09E1EC80, + $13C1E340, $1803E380, $387BC390, $30F801D0, + $70F83DC0, $E1F03E08, $9DF07C30, $9E307C30, + $9E1C7C30, $1C1F9C30, $1C1F0630, $7C1F0780, + $623F0798, $63DE0F10, $23C10F20, $33C3EE20, + $0BC3C380, $0647C700, $023F8E00, $0130F800, + $00338000, + -> ----- bitmap Boing, frame 2: w = 32, h = 25 ------ + $0019C000, $01038800, $02788D00, $0CF0FE80, + $11F0F140, $0E60F1E0, $1C39F0C0, $1C3E30C0, + $387E0CE0, $F87C1F28, $8C7C1F18, $8F3C1F18, + $8F061E18, $8F07DE18, $8F07C018, $6E0FC1C0, + $300F83C8, $31EF8390, $31F08780, $11E0F720, + $11E1F1C0, $0B61E300, $071BC600, $01386C00, + $00318000, + -> ----- bitmap Boing, frame 3: w = 32, h = 25 ------ + $001CE000, $01B1CC00, $031CC500, $0C3C3680, + $18787840, $2F7078E0, $0E087860, $1E0FB860, + $1C1F0460, $BC1F07B0, $C43F0788, $C7FE0788, + $C7C00F88, $C781EF88, $C783F118, $2783E0E8, + $3983E1E0, $3863E1C0, $1878C1C0, $38783380, + $10F078C0, $0B70F180, $0588E200, $009E2400, + $0018C000, + -> ----- bitmap Boing, frame 4: w = 32, h = 25 ------ + $000E6000, $00F8E400, $030FE600, $061E1300, + $0C3E1C80, $27FC1C60, $07843C60, $4F07FE20, + $8F07C230, $1E0FC1F0, $620F83C8, $61CF83C8, + $61E183C8, $63E063C8, $63E0F9C8, $03E0F878, + $1DC0F860, $1C21F0E0, $5C3EF0C0, $0C3C11C0, + $143C3C40, $09B83880, $05C07000, $00CF0400, + $000C6000, + -> ----- bitmap Boing, frame 5: w = 32, h = 25 ------ + $00262000, $00FC7400, $01877200, $030F0100, + $0E0F0E80, $319F0E00, $23C60F30, $63C1CF30, + $4781F310, $0783E0D0, $7383E0E0, $70C3E0E0, + $70F9E1E0, $70F821E0, $70F83FE0, $91F03E38, + $4FF07C30, $4E107C60, $4E0F7860, $2E1F08C0, + $0E1E0E00, $049E1C80, $00E43800, $00C79000, + $000E6000]) + -> These objects contain the initialisation data for the animation sequence. + newBoingBob:=[NIL, BOING_WWIDTH, BOING_HEIGHT, BOING_DEPTH, $2, $0, + VSF_SAVEBACK OR VSF_OVERLAY, 0, RBMDEPTH, 0, 0, 0, 0]:newBob + newBoingSeq:=[NIL, boing3Image, boing3XTranses, boing3YTranses, + boing3Times, boing3CRoutines, 0, BOING_COUNT, 0]:newAnimSeq +ENDPROC +->>> + +->>> PROC setupBoing(dbufing) +-> Make a new animation object. Since all of the boing balls use the same +-> underlying data, the initalisation structures are hard-coded into the +-> routine (newBoingBob and newBoingSeq.) +-> +-> Return a pointer to the object if successful. +PROC setupBoing(dbufing) HANDLE + DEF bngOb=NIL:PTR TO ao, bngComp:PTR TO ac + NEW bngOb + newBoingBob.dBuf:=dbufing -> Double-buffer status + newBoingSeq.headOb:=bngOb -> Pass down head object + + bngComp:=makeSeq(newBoingBob, newBoingSeq) + -> The head comp is the one that is returned by makeSeq() + bngOb.headcomp:=bngComp +EXCEPT + IF bngOb THEN END bngOb + ReThrow() +ENDPROC bngOb +->>> + +->>> PROC runAnimation(win:PTR TO window, dbufing, animKey, myBitMaps) +-> A simple message handling LOOP that also draws the successive frames. +PROC runAnimation(win:PTR TO window, dbufing, animKey, myBitMaps) + DEF intuiMsg:PTR TO intuimessage, toggleFrame + -> toggleFrame is used to keep track of which frame of the double buffered + -> screen we are currently displaying. The variable must exist for the life + -> of the displayed objects, so it is defined here. + toggleFrame:=0 + + -> End the loop on a IDCMP_CLOSEWINDOW event. + LOOP + -> Draw the gels, then check for messages. Check the messages after each + -> display so we get a quick response. + drawGels(win, animKey, dbufing, {toggleFrame}, myBitMaps) + + -> Quit on a Control-C + -> E-Note: use built-in check + IF CtrlC() THEN RETURN + + -> Check for a IDCMP_CLOSEWINDOW event, die if found + WHILE intuiMsg:=GetMsg(win.userport) + IF intuiMsg.class=IDCMP_CLOSEWINDOW + ReplyMsg(intuiMsg) + RETURN + ENDIF + ReplyMsg(intuiMsg) + ENDWHILE + ENDLOOP +ENDPROC +->>> + +->>> PROC setupPlanes(bitMap:PTR TO bitmap, depth, width, height) +-> Called only for double-buffered displays. Allocate and clear each +-> bit-plane in a bitmap structure. Clean-up on failure. +PROC setupPlanes(bitMap:PTR TO bitmap, depth, width, height) HANDLE + DEF plane_num + FOR plane_num:=0 TO depth-1 + bitMap.planes[plane_num]:=AllocRaster(width, height) + BltClear(bitMap.planes[plane_num], (width/8)*height, 1) + ENDFOR +EXCEPT + freePlanes(bitMap, depth, width, height) + ReThrow() +ENDPROC +->>> + +->>> PROC setupBitMaps(depth, width, height) +-> Allocate the two bitmaps for a double-buffered display. Routine only +-> called when the display is double-buffered. +PROC setupBitMaps(depth, width, height) HANDLE + DEF p=NIL:PTR TO bitmap, q=NIL:PTR TO bitmap + -> Allocate the two bitmap objects. These do not have to be in CHIP. + -> E-Note: use p and q to get correct type. + myBitMaps[0]:=NEW p + myBitMaps[1]:=NEW q + -> Initialise the bitmaps to the correct size. + InitBitMap(p, depth, width, height) + InitBitMap(q, depth, width, height) + -> Allocate and initialise the bit-planes for the bitmaps. + setupPlanes(p, depth, width, height) + setupPlanes(q, depth, width, height) +EXCEPT + IF p + freePlanes(p, depth, width, height) + END p + ENDIF + IF q + freePlanes(q, depth, width, height) + END q + ENDIF + ReThrow() +ENDPROC myBitMaps +->>> + +->>> PROC freePlanes(bitMap:PTR TO bitmap, depth, width, height) +-> Free all of the bit-planes in a bitmap structure. +PROC freePlanes(bitMap:PTR TO bitmap, depth, width, height) + DEF plane_num + FOR plane_num:=0 TO depth-1 + IF bitMap.planes[plane_num] + FreeRaster(bitMap.planes[plane_num], width, height) + ENDIF + ENDFOR +ENDPROC +->>> + +->>> PROC freeBitMaps(myBitMaps:PTR TO LONG, depth, width, height) +-> Free the two bitmaps from the double buffered display. The bit-planes are +-> freed first, then the bitmap objects. +PROC freeBitMaps(myBitMaps:PTR TO LONG, depth, width, height) + freePlanes(myBitMaps[0], depth, width, height) + freePlanes(myBitMaps[1], depth, width, height) + END myBitMaps[2] +ENDPROC +->>> + +->>> PROC setupDisplay(win:PTR TO LONG, dbufing, myBitMaps:PTR TO LONG) +-> Open the screen and the window for the display. +-> +-> If using double buffered display, assume the bitmaps have been opened and +-> correctly set-up. +PROC setupDisplay(win:PTR TO LONG, dbufing, myBitMaps:PTR TO LONG) HANDLE + DEF gInfo, screen=NIL, wp=NIL:PTR TO window + -> If double-buffered, set-up the new screen structure for custom bitmap. + IF dbufing + ns.type:=ns.type OR CUSTOMBITMAP + ns.custombitmap:=myBitMaps[0] + ENDIF + + -> Open everything. Check for failure. + screen:=OpenScreen(ns) + nw.screen:=screen + -> E-Note: use wp to get the right type + win[]:=(wp:=OpenWindow(nw)) + IF dbufing + -> We are double buffered. Set the rastport for it. + wp.wscreen.rastport.flags:=RPF_DBUFFER + + -> This copies the Intuition display (close gadget) to the second bitmap + -> so the display does not flash when we change between them. + wp.wscreen.rastport.bitmap:=myBitMaps[1] + BltBitMapRastPort(myBitMaps[0], 0, 0, wp.wscreen.rastport, + 0, 0, RBMWIDTH, RBMHEIGHT, $C0) + wp.wscreen.rastport.bitmap:=myBitMaps[0] + ENDIF + + -> Ready the gel system for accepting objects. This is only done once for + -> each rastport in use. + gInfo:=setupGelSys(wp.wscreen.rastport, $03) +EXCEPT + IF wp THEN CloseWindow(wp) + IF screen THEN CloseScreen(screen) + ReThrow() +ENDPROC gInfo +->>> + +->>> PROC drawGels(win:..., animKey, dbufing, toggleFrame:..., myBitMaps:...) +-> Handle the update of the display. Animate the simulation and check for +-> collisions. If the screen is double buffered, swap the bit map as +-> required. +-> E-Note: toggleFrame is PTR TO LONG since '{toggle}' was used. +PROC drawGels(win:PTR TO window, animKey, dbufing, + toggleFrame:PTR TO LONG, myBitMaps:PTR TO LONG) + -> Do the required animation stuff. You must sort both after the animate + -> call and after the collision call. + Animate(animKey, win.wscreen.rastport) + SortGList(win.wscreen.rastport) + + DoCollision(win.wscreen.rastport) + SortGList(win.wscreen.rastport) + + -> Toggle if double buffered + IF dbufing + win.wscreen.viewport.rasinfo.bitmap:=myBitMaps[toggleFrame[]] + ENDIF + + -> Draw the new position of the gels into the screen. + DrawGList(win.wscreen.rastport, win.wscreen.viewport) + + -> If using a double buffered display, you have a more complicated update + -> procedure. If not then simply use WaitTOF(). + IF dbufing + MakeScreen(win.wscreen) + RethinkDisplay() + toggleFrame[]:=1-toggleFrame[] + win.wscreen.rastport.bitmap:=myBitMaps[toggleFrame[]] + ELSE + WaitTOF() + ENDIF +ENDPROC +->>> + +->>> PROC bounceWall(vs1:PTR TO vs, borderflags) +-> Handle bouncing the animation objects off the walls. +PROC bounceWall(vs1:PTR TO vs, borderflags) + DEF ob:PTR TO ao + -> Get a pointer to the object from the sprite pointer. + ob:=vs1.vsbob.bobcomp.headob + + -> Check for hits and act appropriately. For right and left, reverse the x + -> velocity if the object is moving towards the wall (it may have already + -> reversed but still be in contact with the wall). For the bottom and top + -> you also have to subtract out the velocity. + IF ((borderflags AND RIGHTHIT) AND (ob.xvel>0)) OR + ((borderflags AND LEFTHIT) AND (ob.xvel<0)) + ob.xvel:=-ob.xvel + ELSEIF ((borderflags AND TOPHIT) AND (ob.yvel<0)) OR + ((borderflags AND BOTTOMHIT) AND (ob.yvel>0)) + ob.yvel:=ob.yvel-ob.yaccel + ob.yvel:=-ob.yvel + ENDIF +ENDPROC +->>> + +->>> PROC hit_routine(vs1:PTR TO vs, vs2:PTR TO vs) +-> Handle the collision between two animation objects. This routine simulates +-> objects bouncing off of each other. This does not do a very good job of +-> it, it does not take into account the angle of the collision or real +-> physics. If anyone wants to fix it, please feel free. +-> +-> The call to DoCollision() causes a call back to this routine when two +-> animation objects overlap. +PROC hit_routine(vs1:PTR TO vs, vs2:PTR TO vs) + DEF vel1, vel2, ob1:PTR TO ao, ob2:PTR TO ao + -> Get pointers to the objects from the sprite pointers. + ob1:=vs1.vsbob.bobcomp.headob + ob2:=vs2.vsbob.bobcomp.headob + + -> Check that the bob is not being removed! This is due to a 1.3 bug where + -> all bobs are tested for collision, even the ones that are in the process + -> of being removed. See text for more information. + -> + -> Bobs are moved to a very large negative position as they are being + -> removed. If the BOBSAWAY flag is set, then both bobs in the collision + -> are in the process of being removed--don't do anything in the collision + -> routine. + IF 0=(vs1.vsbob.bobflags AND BF_BOBSAWAY) + -> Cache the velocity values. + -> Do the X values first (order is not important). + vel1:=ob1.xvel + vel2:=ob2.xvel + + -> If the two objects are moving in the opposite direction (X component) + -> then negate the velocities, else swap the velocities. + IF ((vel1>0) AND (vel2<0)) OR ((vel1<0) AND (vel2>0)) + ob1.xvel:=-vel1 + ob2.xvel:=-vel2 + ELSE + ob1.xvel:=vel2 + ob2.xvel:=vel1 + ENDIF + + -> Cache the velocity values. + -> Do the Y values second (order is not important). + vel1:=ob1.yvel + vel2:=ob2.yvel + + -> If the two objects are moving in the opposite direction (Y component) + -> then negate the velocities, else swap the velocities. + IF ((vel1>0) AND (vel2<0)) OR ((vel1<0) AND (vel2>0)) + ob1.yvel:=-vel1 + ob2.yvel:=-vel2 + ELSE + ob1.yvel:=vel2 + ob2.yvel:=vel1 + ENDIF + ENDIF +ENDPROC +->>> + +->>> PROC main() +-> Run a double buffered display if the user puts any arguments on the command +-> line. +-> +-> Set-up the display, set-up the animation system and the objects, set-up +-> collisions between objects and against walls, and run the thing. +-> +-> Clean-up and close resources when done. +PROC main() HANDLE + DEF myBitMaps:PTR TO LONG, boingOb=NIL:PTR TO ao, boing2Ob=NIL:PTR TO ao, + boing3Ob=NIL:PTR TO ao, win=NIL:PTR TO window, gInfo=NIL, animKey, + dbufing=0, hitcode + -> E-Note: set-up global data + setupGlobals() + -> If any arguments, use double-buffering + IF arg THEN IF arg[] THEN dbufing:=1 + WriteF(IF dbufing THEN + 'Double buffering - no args means single buffered\n' ELSE + 'Single buffering - supply any arguments to do double buffering\n') + -> Note that setupBitMaps() will only be called if we are double buffering. + IF dbufing THEN myBitMaps:=setupBitMaps(RBMDEPTH, RBMWIDTH, RBMHEIGHT) + gInfo:=setupDisplay({win}, dbufing, myBitMaps) + -> You have to initialise the animation key before you use it. + InitAnimate({animKey}) + + -> Set-up the first boing ball. All of these use the same data, hard coded + -> into setupBoing(). Change the colour by changing planePick. Set the ID + -> of the ball (meMask) to BOING_1. hitMask = $FF means that it will + -> collide with everything. + newBoingBob.planePick:=$2 + newBoingBob.meMask:=Shl(1, BOING_1) + newBoingBob.hitMask:=$FF + boingOb:=setupBoing(dbufing) + + -> Pick an initial position, velocity and acceleration and add the OBJECT to + -> the system. NOTE that the Y-velocity and X-acceleration are not set + -> (they default to zero.) This means that the objects will maintain a + -> constant movement to the left or right, and will rely on the Y + -> accelleration for the downward movement. The collision routines change + -> these values, producing bouncing off of walls and other objects. + -> + -> NOTE: ANFRACSIZE is a value that shifts animation constants past an + -> internal decimal point. If you do not do this, then the values will only + -> be some fraction of what you expect. See the text of the Animation + -> chapter. + boingOb.any:=Shl(10, ANFRACSIZE) + boingOb.anx:=Shl(250, ANFRACSIZE) + boingOb.xvel:=-Shl(3, ANFRACSIZE) + boingOb.yaccel:=35 + AddAnimOb(boingOb, {animKey}, win.wscreen.rastport) + + -> Do the second object--see above comments. + newBoingBob.planePick:=$1 + newBoingBob.meMask:=Shl(1, BOING_2) + newBoingBob.hitMask:=$FF + boing2Ob:=setupBoing(dbufing) + boing2Ob.any:=Shl(50, ANFRACSIZE) + boing2Ob.anx:=Shl(50, ANFRACSIZE) + boing2Ob.xvel:=Shl(2, ANFRACSIZE) + boing2Ob.yaccel:=35 + AddAnimOb(boing2Ob, {animKey}, win.wscreen.rastport) + + -> Do the third object--see above comments. + -> Here we also use planeOnOff to change the colour. + newBoingBob.planePick:=$1 + newBoingBob.planeOnOff:=$2 + newBoingBob.meMask:=Shl(1, BOING_3) + newBoingBob.hitMask:=$FF + boing3Ob:=setupBoing(dbufing) + boing3Ob.any:=Shl(80, ANFRACSIZE) + boing3Ob.anx:=Shl(150, ANFRACSIZE) + boing3Ob.xvel:=Shl(1, ANFRACSIZE) + boing3Ob.yaccel:=35 + AddAnimOb(boing3Ob, {animKey}, win.wscreen.rastport) + + -> Set up the collisions between boing balls. + -> NOTE that they all call the same routine. + -> E-Note: wrap hit_routine() so it can be used as a collision function (the + -> function is simple enough not to need the full register + -> preservation of eCodeCollision(), so eCodeSwapArgs() is used). + hitcode:=eCodeSwapArgs({hit_routine}) + SetCollision(BOING_1, hitcode, gInfo) + SetCollision(BOING_2, hitcode, gInfo) + SetCollision(BOING_3, hitcode, gInfo) + + -> Set the collisions with the walls. + -> E-Note: see above comment about eCodeXXX(). + SetCollision(BORDERHIT, eCodeSwapArgs({bounceWall}), gInfo) + + -> Everything set-up... Run the animation. + runAnimation(win, dbufing, {animKey}, myBitMaps) + + -> Done.. Free-up everything and clean up the mess. +EXCEPT DO + IF boing3Ob THEN freeOb(boing3Ob, RBMDEPTH) + IF boing2Ob THEN freeOb(boing2Ob, RBMDEPTH) + IF boingOb THEN freeOb(boingOb, RBMDEPTH) + IF gInfo THEN cleanupGelSys(gInfo, win.wscreen.rastport) + IF win THEN CloseWindow(win) + -> E-Note: C version does not do this safely... + IF nw.screen THEN CloseScreen(nw.screen) + IF dbufing THEN freeBitMaps(myBitMaps, RBMDEPTH, RBMWIDTH, RBMHEIGHT) + SELECT exception + CASE ERR_RAST; WriteF('Error: could not allocate raster\n') + CASE ERR_SCRN; WriteF('Error: could not open screen\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK +->>> + +->>> PROC copyListToChip(data) +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/ssprite.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/ssprite.e new file mode 100644 index 0000000..a7d1745 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/ssprite.e @@ -0,0 +1,103 @@ +-> ssprite.e - Simple Sprite example + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'dos/dos', + 'exec/memory', + 'graphics/gfx', + 'graphics/gfxmacros', + 'graphics/sprite', + 'graphics/view', + 'hardware/custom', + 'hardware/dmabits', + 'intuition/screens' + +ENUM ERR_NONE, ERR_KICK, ERR_SCRN, ERR_SPRT + +RAISE ERR_KICK IF KickVersion()=FALSE, + ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_SPRT IF GetSprite()=-1 + +DEF sprite_data +->>> + +->>> PROC main() +PROC main() HANDLE + DEF sprite:simplesprite, viewport, sprite_num=-1, delta_move, ktr1, ktr2, + colour_reg, screen=NIL:PTR TO screen + KickVersion(37) + screen:=OpenScreenTagList(NIL, NIL) + viewport:=screen.viewport + sprite_num:=GetSprite(sprite, 2) + + -> Calculate the correct base colour register number, + -> set up the colour registers. + colour_reg:=16+((sprite_num AND $06)*2) + WriteF('colour_reg=\d\n', colour_reg) + SetRGB4(viewport, colour_reg+1, 12, 3, 8) + SetRGB4(viewport, colour_reg+2, 13, 13, 13) + SetRGB4(viewport, colour_reg+3, 4, 4, 15) + + sprite.x:=0 -> Initialise position and size info to match that shown in + sprite.y:=0 -> sprite_data so system knows layout of data later. + sprite.height:=9 + + -> E-Note: data is really a lot of LONGs + sprite_data:=copyListToChip([0, -> Position control + $ffff0000, -> Image data line 1, color 1 + $ffff0000, -> Image data line 2, color 1 + $0000ffff, -> Image data line 3, color 2 + $0000ffff, -> Image data line 4, color 2 + $00000000, -> Image data line 5, transparent + $0000ffff, -> Image data line 6, color 2 + $0000ffff, -> Image data line 7, color 2 + $ffffffff, -> Image data line 8, color 3 + $ffffffff, -> Image data line 9, color 3 + 0]) -> Reserved, must init to 0 + + -> Install sprite data and move sprite to start position. + ChangeSprite(viewport, sprite, sprite_data) + MoveSprite(viewport, sprite, 30, 0) + + -> Move the sprite back and forth. + delta_move:=1 + FOR ktr1:=0 TO 5 + FOR ktr2:=0 TO 99 + MoveSprite(viewport, sprite, sprite.x+delta_move, sprite.y+delta_move) + WaitTOF() -> One move per video frame. + + -> Show the effect of turning off sprite DMA. + IF ktr2=40 THEN OFF_SPRITE + IF ktr2=60 THEN ON_SPRITE + ENDFOR + delta_move:=-delta_move + ENDFOR + + -> Note: if you turn off the sprite at the wrong time (when it is being + -> displayed), the sprite will appear as a vertical bar on the screen. + -> To really get rid of the sprite, you must OFF_SPRITE while it is not + -> displayed. This is hard in a multi-tasking system (the solution is not + -> addressed in this program). + ON_SPRITE -> Just to be sure + +EXCEPT DO + IF sprite_num<>-1 THEN FreeSprite(sprite_num) + IF screen THEN CloseScreen(screen) + SELECT exception + CASE ERR_KICK; WriteF('Error: requires V37\n') + CASE ERR_SCRN; WriteF('Error: could not open screen\n') + CASE ERR_SPRT; WriteF('Error: could not allocate a new sprite\n') + ENDSELECT +ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK +->>> + +->>> PROC copyListToChip(data) +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/vsprite.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/vsprite.e new file mode 100644 index 0000000..95845ce --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Sprites_Bobs/vsprite.e @@ -0,0 +1,155 @@ +-> vsprite.e - Virtual Sprite example + +->>> Header (globals) +MODULE 'dos/dos', + 'exec/memory', + 'exec/ports', + 'graphics/collide', + 'graphics/gels', + 'graphics/rastport', + 'intuition/intuition', + 'intuition/screens', + 'other/ecode', + '*animtools' + +ENUM ERR_NONE, ERR_KICK, ERR_WIN + +RAISE ERR_KICK IF KickVersion()=FALSE, + ERR_WIN IF OpenWindow()=NIL + +CONST GEL_SIZE=4 + +-> VSprite data - there are two sets that are alternated between. Note that +-> this data is always displayed as low resolution. +DEF vsprite_data1, vsprite_data2, mySpriteColours, mySpriteAltColours +->>> + +->>> PROC vspriteDrawGList(win, myRPort) +-> Basic VSprite display subroutine +PROC vspriteDrawGList(win, myRPort) + SortGList(myRPort) + DrawGList(myRPort, ViewPortAddress(win)) + RethinkDisplay() +ENDPROC +->>> + +->>> PROC borderCheck(hitVSprite:PTR TO vs, borderflags) +-> Collision routine for vsprite hitting border. Note that when the collision +-> is VSprite to VSprite (or Bob to Bob, Bob to AnimOb, etc.), then the +-> parameters are both pointers to a VSprite. +PROC borderCheck(hitVSprite:PTR TO vs, borderflags) + IF borderflags AND RIGHTHIT + hitVSprite.sprcolors:=mySpriteAltColours + hitVSprite.vuserext:=-40 + ENDIF + IF borderflags AND LEFTHIT + hitVSprite.sprcolors:=mySpriteColours + hitVSprite.vuserext:=20 + ENDIF +ENDPROC +->>> + +->>> PROC process_window(win:PTR TO window, myRPort, myVSprite:PTR TO vs) +-> Process window and dynamically change vsprite. Get messages. Go away on +-> CLOSEWINDOW. Update and redisplay vsprite on INTUITICKS. Wait for more +-> messages. +PROC process_window(win:PTR TO window, myRPort, myVSprite:PTR TO vs) + DEF msg:PTR TO intuimessage + LOOP + Wait(Shl(1, win.userport.sigbit)) + WHILE NIL<>(msg:=GetMsg(win.userport)) + -> Only IDCMP_CLOSEWINDOW and IDCMP_INTUITICKS are active + IF msg.class=IDCMP_CLOSEWINDOW + ReplyMsg(msg) + RETURN + ENDIF + -> Must be an INTUITICKS: change x and y values on the fly. Note offset + -> by window left and top edge--sprite is relative to the screen, not + -> window. Divide the MouseY in half to adjust for Lores movement + -> increments on a Hires screen. + myVSprite.x:=win.leftedge+msg.mousex+myVSprite.vuserext + myVSprite.y:=win.topedge+(msg.mousey/2)+1 + ReplyMsg(msg) + ENDWHILE + -> Got a message, change image data on the fly + myVSprite.imagedata:=IF myVSprite.imagedata=vsprite_data1 THEN + vsprite_data2 ELSE vsprite_data1 + SortGList(myRPort) + DoCollision(myRPort) + vspriteDrawGList(win, myRPort) + ENDLOOP +ENDPROC +->>> + +->>> PROC do_VSprite(win, myRPort:PTR TO rastport) HANDLE +-> Working with the VSprite. Setup the GEL system and get a new VSprite +-> (makeVSprite()). Add VSprite to the system and display. Use the vsprite. +-> When done, remove VSprite and update the display without the VSprite. +-> Cleanup everything. +PROC do_VSprite(win, myRPort:PTR TO rastport) HANDLE + DEF myVSprite=NIL:PTR TO vs, my_ginfo=NIL + my_ginfo:=setupGelSys(myRPort, $FC) + myVSprite:=makeVSprite( + -> Image data, sprite colour array, word width (1 for true VSprite) + [vsprite_data1, mySpriteColours, 1, + -> Line height, image depth (2 for true VSprite), x, y position + GEL_SIZE, 2, 160, 100, + -> Flags (VSF_VSPRITE for true VSprite), hit mask and me mask + VSF_VSPRITE, Shl(1, BORDERHIT), 0]:newVSprite) + AddVSprite(myVSprite, myRPort) + vspriteDrawGList(win, myRPort) + myVSprite.vuserext:=20 + -> E-Note: wrap borderCheck function for use as collision routine + SetCollision(BORDERHIT, eCodeCollision({borderCheck}), myRPort.gelsinfo) + process_window(win, myRPort, myVSprite) + RemVSprite(myVSprite) +EXCEPT DO + IF myVSprite THEN freeVSprite(myVSprite) + IF my_ginfo + vspriteDrawGList(win, myRPort) + cleanupGelSys(my_ginfo, myRPort) + ENDIF + ReThrow() +ENDPROC +->>> + +->>> PROC main() HANDLE +-> Example VSprite program. First open a window. +PROC main() HANDLE + DEF win=NIL:PTR TO window, myRPort=NIL:PTR TO rastport + KickVersion(37) + NEW myRPort -> E-Note: allocate a zeroed rastport + -> E-Note: set-up global data + vsprite_data1:=copyListToChip([$7FFE80FF, $7C3E803F, $7C3E803F, $7FFE80FF, 0]) + vsprite_data2:=copyListToChip([$7FFEFF01, $7C3EFC01, $7C3EFC01, $7FFEFF01, 0]) + mySpriteColours:=[$0000, $00F0, $0F00]:INT + mySpriteAltColours:=[$000F, $0F00, $0FF0]:INT + win:=OpenWindow([80, 20, 400, 150, -1, -1, + IDCMP_CLOSEWINDOW OR IDCMP_INTUITICKS, + WFLG_ACTIVATE OR WFLG_CLOSEGADGET OR WFLG_DEPTHGADGET OR + WFLG_RMBTRAP OR WFLG_DRAGBAR, + NIL, NIL, 'VSprite', NIL, NIL, 0, 0, 0, 0, WBENCHSCREEN]:nw) + InitRastPort(myRPort) + -> Copy the window rastport + CopyMem(win.wscreen.rastport, myRPort, SIZEOF rastport) + do_VSprite(win, myRPort) +EXCEPT DO + IF win THEN CloseWindow(win) + END myRPort + SELECT exception + CASE ERR_KICK; WriteF('Error: requires V37\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK +->>> + +->>> PROC copyListToChip(data) +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/MeasureText.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/MeasureText.e new file mode 100644 index 0000000..5c70d11 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/MeasureText.e @@ -0,0 +1,190 @@ +-> MeasureText.e + +->>> Header (globals) +MODULE 'asl', + 'diskfont', + 'graphics/rastport', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens', + 'libraries/asl', + 'other/split' + +ENUM ERR_NONE, ERR_ARGS, ERR_ASL, ERR_FONT, ERR_KICK, ERR_LIB, ERR_OPEN, + ERR_READ, ERR_WIN + +RAISE ERR_ASL IF AllocAslRequest()=NIL, + ERR_FONT IF OpenDiskFont()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_OPEN IF Open()=NIL, + ERR_READ IF Read()<0, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST BUFSIZE=32000 -> E-Note: 32768 is too big for a static ARRAY + +DEF buffer[BUFSIZE]:ARRAY, myfile=NIL, wtbarheight, + fr=NIL:PTR TO fontrequester, myfont=NIL:PTR TO textfont, + w=NIL:PTR TO window, myrp:PTR TO rastport +->>> + +->>> PROC main() +PROC main() HANDLE + DEF arglist:PTR TO LONG + KickVersion(37) -> Run only on 2.0 machines + -> E-Note: use argSplit() to get argv-like list (minus command name) + IF NIL=(arglist:=argSplit()) THEN Raise(ERR_ARGS) + IF ListLen(arglist)=1 -> E-Note: replaces 'argc==2' + myfile:=Open(arglist[0], OLDFILE) -> Open the file to print out. + diskfontbase:=OpenLibrary('diskfont.library', 37) + aslbase:=OpenLibrary('asl.library', 37) + fr:=AllocAslRequest(ASL_FONTREQUEST, -> Open an ASL font requester. + -> Supply initial values for requester + [ASL_FONTNAME, 'topaz.font', + ASL_FONTHEIGHT, 11, + ASL_FONTSTYLES, FSF_BOLD OR FSF_ITALIC, + ASL_FRONTPEN, 1, + ASL_BACKPEN, 0, + + -> Give us all the gadgetry + ASL_FUNCFLAGS, FONF_FRONTCOLOR OR FONF_BACKCOLOR OR + FONF_DRAWMODE OR FONF_STYLES, + NIL]) + -> Pop up the requester + IF AslRequest(fr, NIL) + -> Extract the font and display attributes from the fontrequest. + myfont:=OpenDiskFont([fr.attr.name, fr.attr.ysize, + fr.attr.style, fr.attr.flags]:textattr) + w:=OpenWindowTagList(NIL, [WA_SIZEGADGET, TRUE, + WA_MINWIDTH, 200, + WA_MINHEIGHT, 200, + WA_DRAGBAR, TRUE, + WA_DEPTHGADGET, TRUE, + WA_TITLE, arglist[0], + NIL]) + myrp:=w.rport + -> Figure out where the baseline of the uppermost line should be. + wtbarheight:=w.wscreen.barheight+myfont.baseline+2 + + -> Set the font and add software styling to the text if I asked for it + -> in OpenFont() and didn't get it. Because most Amiga fonts do not + -> have styling built into them (with the exception of the CG outline + -> fonts), if the user selected some kind of styling for the text, it + -> will to be added algorithmically by calling SetSoftStyle(). + SetFont(myrp, myfont) + SetSoftStyle(myrp, Eor(fr.attr.style, myfont.style), + FSF_BOLD OR FSF_UNDERLINED OR FSF_ITALIC) + SetDrMd(myrp, fr.drawmode) + SetAPen(myrp, fr.frontpen) + SetBPen(myrp, fr.backpen) + Move(myrp, w.wscreen.wborleft, wtbarheight) + + mainLoop() + + -> Short delay to allow user to see the text before it goes away. + Delay(25) + ELSE + WriteF('Request Cancelled\n') + ENDIF + ELSE + WriteF('Template: MeasureText \n') + ENDIF +EXCEPT DO + IF w THEN CloseWindow(w) + IF myfont THEN CloseFont(myfont) + IF fr THEN FreeAslRequest(fr) + IF aslbase THEN CloseLibrary(aslbase) + IF diskfontbase THEN CloseLibrary(diskfontbase) + IF myfile THEN Close(myfile) + SELECT exception + CASE ERR_ARGS; WriteF('Error: ran out of memory splitting arguments\n') + CASE ERR_ASL; WriteF('Error: could not allocate ASL request\n') + CASE ERR_FONT; WriteF('Error: could not open font\n') + CASE ERR_KICK; WriteF('Error: requires V37+\n') + CASE ERR_LIB; WriteF('Error: could not open required library\n') + CASE ERR_OPEN; WriteF('Error: could not open file\n') + CASE ERR_READ; WriteF('Error: Read() failed on file\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + ENDSELECT +ENDPROC +->>> + +->>> PROC mainLoop() +PROC mainLoop() + DEF resulttextent:textextent, fit, actual, count, printable, crrts, aok=TRUE + -> While there's something to read, fill the buffer. + WHILE (actual:=Read(myfile, buffer, BUFSIZE)) AND aok + count:=0 + + WHILE count Skip non-printable characters, but account for newline characters. + WHILE ((buffer[count] < myfont.lochar) OR + (buffer[count] > myfont.hichar)) AND (count < actual) + -> Is this character a newline? If it is, bump up the newline count. + IF buffer[count]=$0A THEN INC crrts + INC count + ENDWHILE + + IF crrts>0 -> If there were any newlines, be sure to display them. + Move(myrp, w.borderleft, myrp.cp_y+(crrts*(myfont.ysize+1))) + eop() -> Did we go past the end of the page? + ENDIF + + printable:=count + -> Find the next non-printables. + WHILE (buffer[printable] >= myfont.lochar) AND + (buffer[printable] <= myfont.hichar) AND (printable < actual) + INC printable + ENDWHILE + -> Print the string of printable characters wrapping lines to the + -> beginning of the next line as needed. + WHILE count How many characters in the current string of printable characters + -> will fit between the rastport's current X position and the edge of + -> the window? + fit:=TextFit(myrp, buffer+count, + printable-count, resulttextent, + NIL, 1, + w.width-(myrp.cp_x+w.borderleft+w.borderright), + myfont.ysize+1) + IF fit=0 + -> Nothing else fits on this line, need to wrap to the next line + Move(myrp, w.borderleft, myrp.cp_y+myfont.ysize+1) + ELSE + Text(myrp, buffer+count, fit) + count:=count+fit + ENDIF + eop() + ENDWHILE + + IF CtrlC() -> Did the user hit Ctrl-C? + aok:=FALSE + WriteF('Ctrl-C Break\n') + count:=BUFSIZE+1 + ENDIF + ENDWHILE + ENDWHILE +ENDPROC +->>> + +->>> PROC eop() +PROC eop() + -> If we reached the page bottom, clear the rastport and move to the top. + IF myrp.cp_y > (w.height-(w.borderbottom+2)) + Delay(25) + SetAPen(myrp, 0) + RectFill(myrp, w.borderleft, w.bordertop, w.width-(w.borderright+1), + w.height-(w.borderbottom+1)) + SetAPen(myrp, 1) + Move(myrp, w.borderleft+1, wtbarheight) + SetAPen(myrp, fr.frontpen) + ENDIF +ENDPROC +->>> + +->>> Version string +vers: + CHAR 0, '$VER: MeasureText 37.1', 0 +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/availfonts.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/availfonts.e new file mode 100644 index 0000000..227ee4e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/availfonts.e @@ -0,0 +1,272 @@ +-> AvailFonts.e + +->>> Header (globals) +MODULE 'diskfont', + 'layers', + 'utility', + 'exec/nodes', + 'exec/ports', + 'graphics/rastport', + 'graphics/gfx', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens', + 'libraries/diskfont' + +ENUM ERR_NONE, ERR_DRAW, ERR_LIB, ERR_REGN, ERR_WIN + +RAISE ERR_DRAW IF GetScreenDrawInfo()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_REGN IF NewRegion()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +OBJECT stringobj + string + charcount + stringwidth +ENDOBJECT + +DEF alphabetstring, fname:stringobj, fheight:stringobj, xDPI:stringobj, + yDPI:stringobj, entrynum:stringobj +DEF mywin=NIL:PTR TO window, mycliprp, myrp:rastport +DEF myrect:rectangle, new_region=NIL, old_region +DEF mydrawinfo=NIL:PTR TO drawinfo, afh=NIL:PTR TO afh, fontheight, + alphabetcharcount, stringwidth +->>> + +->>> PROC main() +PROC main() HANDLE + DEF defaultfont=NIL, defaultfontattr, afsize, afshortage, cliprectside + -> E-Note: use the STRLEN short-cut to get string lengths. + alphabetstring:='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + alphabetcharcount:=STRLEN + defaultfontattr:=['topaz.font', 9, 0, 0]:textattr + fname.string:='Font Name: '; fname.charcount:=STRLEN + fheight.string:='Font Height: '; fheight.charcount:=STRLEN + xDPI.string:='X DPI: '; xDPI.charcount:=STRLEN + yDPI.string:='Y DPI: '; yDPI.charcount:=STRLEN + entrynum.string:='Entry #: '; entrynum.charcount:=STRLEN + KickVersion(37) + diskfontbase:=OpenLibrary('diskfont.library', 37) + layersbase:=OpenLibrary('layers.library', 37) + utilitybase:=OpenLibrary('utility.library', 37) + mywin:=OpenWindowTagList(NIL, [WA_SMARTREFRESH, TRUE, -> Open that window. + WA_SIZEGADGET, FALSE, + WA_CLOSEGADGET, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_DRAGBAR, TRUE, + WA_DEPTHGADGET, TRUE, + WA_TITLE, 'AvailFonts() example', + NIL]) + -> An object copy: clone my window's rastport. This rastport will be used + -> to render the font specs, not the actual font sample. + CopyMem(mywin.rport, myrp, SIZEOF rastport) + mydrawinfo:=GetScreenDrawInfo(mywin.wscreen) + SetFont(myrp, mydrawinfo.font) + + myrect.minx:=mywin.borderleft -> LAYOUT THE WINDOW + myrect.miny:=mywin.bordertop + myrect.maxx:=mywin.width-(mywin.borderright+1) + myrect.maxy:=mywin.height-(mywin.borderbottom+1) + + cliprectside:=(myrect.maxx-myrect.minx)/20 + + fontheight:=myrp.font.ysize+2 + -> If the default screen font is more than one-sixth the size of the window, + -> use topaz-9. + IF fontheight>((myrect.maxy-myrect.miny)/6) + defaultfont:=OpenFont(defaultfontattr) + SetFont(myrp, defaultfont) + fontheight:=myrp.font.ysize+2 + ENDIF + + fname.stringwidth:=TextLength(myrp, fname.string, fname.charcount) + fheight.stringwidth:=TextLength(myrp, fheight.string, fheight.charcount) + xDPI.stringwidth:=TextLength(myrp, xDPI.string, xDPI.charcount) + yDPI.stringwidth:=TextLength(myrp, yDPI.string, yDPI.charcount) + entrynum.stringwidth:=TextLength(myrp, entrynum.string, entrynum.charcount) + + -> What is the largest string length? + stringwidth:=Max(Max(Max(Max(fname.stringwidth, fheight.stringwidth), + xDPI.stringwidth), yDPI.stringwidth), entrynum.stringwidth) + stringwidth:=stringwidth+mywin.borderleft + + -> If the stringwidth is more than half the viewing area, quit because the + -> font is just too big. + IF stringwidth<((myrect.maxx-myrect.minx)/2) + SetAPen(myrp, mydrawinfo.pens[TEXTPEN]) + SetDrMd(myrp, RP_JAM2) + + Move(myrp, myrect.minx+8+stringwidth-fname.stringwidth, + myrect.miny+4+myrp.font.baseline) + Text(myrp, fname.string, fname.charcount) + + Move(myrp, myrect.minx+8+stringwidth-fheight.stringwidth, + myrp.cp_y+fontheight) + Text(myrp, fheight.string, fheight.charcount) + + Move(myrp, myrect.minx+8+stringwidth-xDPI.stringwidth, + myrp.cp_y+fontheight) + Text(myrp, xDPI.string, xDPI.charcount) + + Move(myrp, myrect.minx+8+stringwidth-yDPI.stringwidth, + myrp.cp_y+fontheight) + Text(myrp, yDPI.string, yDPI.charcount) + + Move(myrp, myrect.minx+8+stringwidth-entrynum.stringwidth, + myrp.cp_y+fontheight) + Text(myrp, entrynum.string, entrynum.charcount) + + myrect.minx:=myrect.minx+cliprectside + myrect.maxx:=myrect.maxx-cliprectside + myrect.miny:=myrect.miny+(5*fontheight)+8 + myrect.maxy:=myrect.maxy-8 + + -> Draw a box around the cliprect + SetAPen(myrp, mydrawinfo.pens[SHINEPEN]) + Move(myrp, myrect.minx-1, myrect.maxy+1) + Draw(myrp, myrect.maxx+1, myrect.maxy+1) + Draw(myrp, myrect.maxx+1, myrect.miny-1) + + SetAPen(myrp, mydrawinfo.pens[SHADOWPEN]) + Draw(myrp, myrect.minx-1, myrect.miny-1) + Draw(myrp, myrect.minx-1, myrect.maxy) + + SetAPen(myrp, mydrawinfo.pens[TEXTPEN]) + -> Fill up a buffer with a LIST of the available fonts. + afsize:=AvailFonts(afh, 0, + AFF_MEMORY OR AFF_DISK OR AFF_SCALED OR AFF_TAGGED) + REPEAT + afh:=NewR(afsize) + afshortage:=AvailFonts(afh, afsize, + AFF_MEMORY OR AFF_DISK OR AFF_SCALED OR AFF_TAGGED) + IF afshortage + Dispose(afh) + afsize:=afsize+afshortage + afh:=-1 + ENDIF + UNTIL afshortage=0 + + -> This is for the layers.library clipping region that gets attached to + -> the window. This prevents the application from unnecessarily rendering + -> beyond the bounds of the inner part of the window. For more information + -> on clipping, see the Layers chapter of the RKRM. + new_region:=NewRegion() -> More layers stuff + IF OrRectRegion(new_region, myrect) -> Even more layers stuff + -> Obtain a pointer to the window's rastport and set up some of the + -> rastport attributes. This example obtains the text pen for the + -> window's screen using the GetScreenDrawInfo() function. + mycliprp:=mywin.rport + SetAPen(mycliprp, mydrawinfo.pens[TEXTPEN]) + mainLoop() + ENDIF + ENDIF +EXCEPT DO + IF new_region THEN DisposeRegion(new_region) + IF afh THEN Dispose(afh) + -> E-Note: C version forgets to CloseFont() + IF defaultfont THEN CloseFont(defaultfont) + IF mydrawinfo THEN FreeScreenDrawInfo(mywin.wscreen, mydrawinfo) + IF mywin THEN CloseWindow(mywin) + IF utilitybase THEN CloseLibrary(utilitybase) + IF layersbase THEN CloseLibrary(layersbase) + IF diskfontbase THEN CloseLibrary(diskfontbase) + SELECT exception + CASE ERR_DRAW; WriteF('Error: could not get drawinfo from screen\n') + CASE ERR_LIB; WriteF('Error: could not open required library\n') + CASE ERR_REGN; WriteF('Error: could not allocate new region\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC +->>> + +->>> PROC mainLoop() +PROC mainLoop() + DEF x, mymsg:PTR TO intuimessage, aok=TRUE, afont:PTR TO taf, + myfont:PTR TO textfont, buf[8]:STRING, dpi + + -> E-Note: task data not needed since we can use CtrlC() + afont:=afh+SIZEOF afh + + FOR x:=0 TO afh.numentries-1 + IF aok + IF myfont:=OpenDiskFont(afont.attr) + -> Print the TextFont attributes. + SetAPen(myrp, mydrawinfo.pens[BACKGROUNDPEN]) + RectFill(myrp, stringwidth, mywin.bordertop+4, + mywin.width-(mywin.borderright+1), myrect.miny-2) + + SetAPen(myrp, mydrawinfo.pens[TEXTPEN]) + Move(myrp, stringwidth+mywin.borderleft, + mywin.bordertop+4+myrp.font.baseline) + Text(myrp, myfont.mn.ln.name, StrLen(myfont.mn.ln.name)) + + -> Print the font's Y Size. + Move(myrp, stringwidth+mywin.borderleft, myrp.cp_y+fontheight) + StringF(buf, '\d', myfont.ysize) + Text(myrp, buf, StrLen(buf)) + + -> Print the X DPI + Move(myrp, stringwidth+mywin.borderleft, myrp.cp_y+fontheight) + dpi:=GetTagData(TA_DEVICEDPI, 0, + myfont.mn.replyport::textfontextension.tags) + IF dpi + StringF(buf, '\d', Shr(dpi AND $FFFF0000, 16)) + Text(myrp, buf, StrLen(buf)) + ELSE + Text(myrp, 'NIL', 3) + ENDIF + + -> Print the Y DPI + Move(myrp, stringwidth+mywin.borderleft, myrp.cp_y+fontheight) + IF dpi + StringF(buf, '\d', dpi AND $0000FFFF) + Text(myrp, buf, StrLen(buf)) + ELSE + Text(myrp, 'NIL', 3) + ENDIF + + -> Print the entrynum + Move(myrp, stringwidth+mywin.borderleft, myrp.cp_y+fontheight) + StringF(buf, '\d', x) + Text(myrp, buf, StrLen(buf)) + + SetFont(mycliprp, myfont) + -> Install clipping rectangle + old_region:=InstallClipRegion(mywin.wlayer, new_region) + + SetRast(mycliprp, mydrawinfo.pens[BACKGROUNDPEN]) + Move(mycliprp, myrect.minx, + myrect.maxy-(myfont.ysize-myfont.baseline)) + Text(mycliprp, alphabetstring, alphabetcharcount) + + Delay(100) + + -> Remove clipping rectangle + new_region:=InstallClipRegion(mywin.wlayer, old_region) + + WHILE mymsg:=GetMsg(mywin.userport) + aok:=FALSE + x:=afh.numentries + ReplyMsg(mymsg) + ENDWHILE + + -> Did the user hit Ctrl-C? + IF CtrlC() + aok:=FALSE + x:=afh.numentries + WriteF('Ctrl-C Break\n') + ENDIF + CloseFont(myfont) + ENDIF + ENDIF + afont++ + ENDFOR +ENDPROC +->>> + +->>> Version string +vers: + CHAR 0, '$VER: AvailFonts 36.3', 0 +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/cliptext.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/cliptext.e new file mode 100644 index 0000000..5f33170 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Graphics_Libraries/Text/cliptext.e @@ -0,0 +1,261 @@ +-> cliptext.e + +->>> Header (globals) +MODULE 'diskfont', + 'layers', + 'diskfont/diskfonttag', + 'dos/rdargs', + 'graphics/displayinfo', + 'graphics/gfx', + 'graphics/rastport', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens', + 'utility/tagitem' + +ENUM ERR_NONE, ERR_ARGS, ERR_FONT, ERR_KICK, ERR_LIB, ERR_OPEN, ERR_READ, + ERR_REGN, ERR_WIN + +RAISE ERR_ARGS IF ReadArgs()=NIL, + ERR_FONT IF OpenDiskFont()=NIL, + ERR_KICK IF KickVersion()=FALSE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_OPEN IF Open()=NIL, + ERR_READ IF Read()<0, + ERR_REGN IF NewRegion()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST BUFSIZE=4096 + +ENUM FONT_NAME, FONT_SIZE, FILE_NAME, JAM_MODE, XASP, YASP, NUM_ARGS + +CONST DEFAULTFONTSIZE=11, DEFAULTJAMMODE=0, DEFAULTXASP=0, DEFAULTYASP=0 + +DEF args:PTR TO LONG, tagitem[2]:ARRAY OF tagitem, buffer[BUFSIZE]:ARRAY, + myfile=NIL, mymsg:PTR TO intuimessage, mydrawinfo:PTR TO drawinfo, + mywin=NIL:PTR TO window, myrp:PTR TO rastport, + myfont=NIL:PTR TO textfont, myrectangle:rectangle, new_region=NIL +->>> + +->>> PROC main() +PROC main() HANDLE + DEF myrda=NIL:PTR TO rdargs, mydi:displayinfo, mymodeid, + mydefaultfontsize=DEFAULTFONTSIZE, + mydefaultJAMMode=DEFAULTJAMMODE, + mydefaultXASP=DEFAULTXASP, -> E-Note: C version fails to use these! + mydefaultYASP=DEFAULTYASP + args:=['topaz.font', {mydefaultfontsize}, 's:startup-sequence', + {mydefaultJAMMode}, {mydefaultXASP}, {mydefaultYASP}] + -> Run only on 2.0 machines + KickVersion(36) + -> dos.library standard command line parsing. See the dos.library Autodoc + myrda:=ReadArgs('FontName,FontSize/N,FileName,Jam/N,XASP/N,YASP/N\n', + args, NIL) + myfile:=Open(args[FILE_NAME], OLDFILE) -> Open the file to display. + diskfontbase:=OpenLibrary('diskfont.library', 36) -> Open the libraries. + layersbase:=OpenLibrary('layers.library', 36) + -> This application wants to hear about three things: 1) When the user + -> clicks the window's close gadget, 2) when the user starts to resize the + -> window, 3) and when the user has finished resizing the window. + mywin:=OpenWindowTagList(NIL, -> Open that window. + [WA_MINWIDTH, 100, + WA_MINHEIGHT, 100, + WA_SMARTREFRESH, TRUE, + WA_SIZEGADGET, TRUE, + WA_CLOSEGADGET, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_NEWSIZE OR + IDCMP_SIZEVERIFY, + WA_DRAGBAR, TRUE, + WA_DEPTHGADGET, TRUE, + WA_TITLE, args[FILE_NAME], + TAG_END]) + tagitem[0].tag:=OT_DEVICEDPI + + -> See if there is a non-zero value in the XASP or YASP fields. + -> Diskfont.library will get a divide by zero GURU if you give it a zero + -> XDPI or YDPI value. + -> If there is a zero value in one of them... + IF (Long(args[XASP])=0) OR (Long(args[YASP])=0) + -> ...use the aspect ratio of the current display as a default... + mymodeid:=GetVPModeID(mywin.wscreen.viewport) + IF GetDisplayInfoData(NIL, mydi, SIZEOF displayinfo, DTAG_DISP, mymodeid) + mydefaultXASP:=mydi.resolution.x + mydefaultYASP:=mydi.resolution.y + WriteF('XASP = \d YAsp = \d\n', mydefaultXASP, mydefaultYASP) + -> Notice that the X and Y get _swapped_ to keep the look of the font + -> glyphs the same using screens with different aspect ratios. + args[YASP]:={mydefaultXASP} + args[XASP]:={mydefaultYASP} + ELSE + -> ...unless something is preventing us from getting the screens + -> resolution. In that case, forget about the DPI tag. + tagitem[0].tag:=TAG_END + ENDIF + ENDIF + -> Here we have to put the X and Y DPI into the OT_DEVICEDPI tags data + -> field. THESE ARE NOT REAL X AND Y DPI VALUES FOR THIS FONT OR THE + -> DISPLAY. They only serve to supply the diskfont.library with values to + -> calculate the aspect ratio. The X value gets stored in the upper word of + -> the tag value and the Y DPI gets stored in the lower word. Because + -> ReadArgs() stores the _address_ of integers it gets from the command + -> line, you have to dereference the pointer it puts into the argument + -> array. + tagitem.data:=Shl(Long(args[XASP]), 16) OR Long(args[YASP]) + tagitem.tag:=TAG_END + + -> Set up myfont to match the font the user requested. + myfont:=OpenDiskFont([args[FONT_NAME], Long(args[FONT_SIZE]), + FSF_TAGGED, 0, tagitem]:ttextattr) -> Open that font. + -> This is for the layers.library clipping region that gets attached to the + -> window. This prevents the application from unnecessarily rendering + -> beyond the bounds of the inner part of the window. For now, you can + -> ignore the layers stuff if you are just interested in learning about + -> using text. For more information on clipping regions and layers, see the + -> Layers chapter of this manual. + myrectangle.minx:=mywin.borderleft + myrectangle.miny:=mywin.bordertop + myrectangle.maxx:=mywin.width-(mywin.borderright+1) + myrectangle.maxy:=mywin.height-(mywin.borderbottom+1) + + new_region:=NewRegion() + IF OrRectRegion(new_region, myrectangle) + InstallClipRegion(mywin.wlayer, new_region) + -> Obtain a pointer to the window's rastport and set up some of the + -> rastport attributes. This example obtains the text pen for the + -> window's screen using GetScreenDrawInfo(). + myrp:=mywin.rport + SetFont(myrp, myfont) + IF mydrawinfo:=GetScreenDrawInfo(mywin.wscreen) + SetAPen(myrp, mydrawinfo.pens[TEXTPEN]) + FreeScreenDrawInfo(mywin.wscreen, mydrawinfo) + ENDIF + SetDrMd(myrp, Long(args[JAM_MODE])) + + mainLoop() + ENDIF +EXCEPT DO + IF new_region THEN DisposeRegion(new_region) + IF myfont THEN CloseFont(myfont) + IF mywin THEN CloseWindow(mywin) + IF layersbase THEN CloseLibrary(layersbase) + IF diskfontbase THEN CloseLibrary(diskfontbase) + IF myfile THEN Close(myfile) + IF myrda THEN FreeArgs(myrda) + SELECT exception + CASE ERR_ARGS; WriteF('Error: ReadArgs() failed\n') + CASE ERR_FONT; WriteF('Error: could not open font\n') + CASE ERR_KICK; WriteF('Error: requires V36+\n') + CASE ERR_LIB; WriteF('Error: could not open required library\n') + CASE ERR_OPEN; WriteF('Error: could not open file\n') + CASE ERR_READ; WriteF('Error: Read() on the file failed\n') + CASE ERR_REGN; WriteF('Error: could not allocate region\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + ENDSELECT +ENDPROC +->>> + +->>> PROC mainLoop() +PROC mainLoop() + DEF count, actual, position, aok=TRUE, waitfornewsize=FALSE + -> E-Note: we don't need to find the task since we can use CtrlC() + Move(myrp, mywin.borderleft+1, mywin.bordertop+myfont.ysize+1) + + -> While there's something to read, fill the buffer + WHILE ((actual:=Read(myfile, buffer, BUFSIZE)) > 0) AND aok + position:=0 + count:=0 + + WHILE position<=actual + -> E-Note: logic swapped here... + IF waitfornewsize + WaitPort(mywin.userport) + ELSE + WHILE (buffer[count]>=myfont.lochar) AND + (buffer[count]<=myfont.hichar) AND (count<=actual) DO INC count + Text(myrp, buffer+position, count-position) + + WHILE ((buffer[count]myfont.hichar)) AND (count<=actual) + IF buffer[count]=$0A + Move(myrp, mywin.borderleft, myrp.cp_y+myfont.ysize+1) + ENDIF + INC count + ENDWHILE + position:=count + ENDIF + + WHILE mymsg:=GetMsg(mywin.userport) + -> The user clicked the close gadget. + IF mymsg.class=IDCMP_CLOSEWINDOW + aok:=FALSE + position:=actual+1 + ReplyMsg(mymsg) + -> The user picked up the window's sizing gagdet. + ELSEIF mymsg.class=IDCMP_SIZEVERIFY + -> When the user has picked up the window's sizing gadget when the + -> IDCMP_SIZEVERIFY flag is set, the application has to reply to + -> this message to tell Intuition to allow the user to move the + -> sizing gadget and resize the window. The reason for using this + -> here is because the user can resize the window while cliptext.e + -> is rendering text to the window. Cliptext.e has to stop + -> rendering text when it receives an IDCMP_SIZEVERIFY message. + -> + -> If this example had instead asked to hear about IDCMP events that + -> could take place between SIZEVERIFY and NEWSIZE events + -> (especially INTUITICKS), it should turn off those events here + -> using ModifyIDCMP(). + -> + -> After we allow the user to resize the window, we cannot write + -> into the window until the user has finished resizing it because + -> we need the window's new size to adjust the clipping area. + -> Specifically, we have to wait for an IDCMP_NEWSIZE message which + -> Intuition will send when the user lets go of the resize gadget. + -> For now, we set the waitfornewsize flag to stop rendering until + -> we get that NEWSIZE message. + waitfornewsize:=TRUE + WaitBlit() + -> The blitter is done, let the user resize the window + ReplyMsg(mymsg) + ELSE + ReplyMsg(mymsg) + waitfornewsize:=FALSE + -> The user has resized the window, so get the new window dimensions + -> and readjust the layers clipping region accordingly. + myrectangle.minx:=mywin.borderleft + myrectangle.miny:=mywin.bordertop + myrectangle.maxx:=mywin.width-(mywin.borderright+1) + myrectangle.maxy:=mywin.height-(mywin.borderbottom+1) + InstallClipRegion(mywin.wlayer, NIL) + ClearRegion(new_region) + IF OrRectRegion(new_region, myrectangle) + InstallClipRegion(mywin.wlayer, new_region) + ELSE + aok:=FALSE + position:=actual+1 + ENDIF + ENDIF + ENDWHILE + IF CtrlC() -> Check for user break. + aok:=FALSE + position:=actual+1 + ENDIF + + -> If we reached the bottom of the page, clear the rastport and move + -> back to the top. + IF myrp.cp_y>(mywin.height-(mywin.borderbottom+2)) + Delay(25) + + -> Set the entire rastport to colour zero. This will not include the + -> window borders because of the layers clipping. + SetRast(myrp, 0) + Move(myrp, mywin.borderleft+1, mywin.bordertop+myfont.ysize+1) + ENDIF + ENDWHILE + ENDWHILE +ENDPROC +->>> + +->>> Version string +vers: + CHAR 0, '$VER: cliptext 37.2', 0 +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/clipftxt.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/clipftxt.e new file mode 100644 index 0000000..6571927 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/clipftxt.e @@ -0,0 +1,166 @@ +-> clipftxt.e - Writes ASCII text to clipboard unit as FTXT +-> (All clipboard data must be IFF) +-> +-> Usage: clipftxt unitnumber +-> +-> To convert to an example of reading only, comment out #define WRITEREAD + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'iffparse', + 'libraries/iffparse', + 'other/split' + +ENUM ERR_NONE, ERR_ARGS, ERR_CLIP, ERR_IFF, ERR_LIB, ERR_OIFF, ERR_STOP, + ERR_USE, ERR_WRIT + +RAISE ERR_CLIP IF OpenClipboard()=NIL, + ERR_IFF IF AllocIFF()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_OIFF IF OpenIFF()<>0, + ERR_STOP IF StopChunk()<>FALSE + +-> Causes example to write FTXT first, then read it back. +-> Comment out to create a reader only +#define WRITEREAD + +-> E-Note: using argSplit() so one arg count is one less than C's argv +CONST MINARGS=1, RBUFSZ=512, ID_FTXT="FTXT", ID_CHRS="CHRS" + +DEF usage, errormsgs:PTR TO LONG, mytext +->>> + +->>> PROC main() +PROC main() HANDLE + DEF iff=NIL:PTR TO iffhandle, cn:PTR TO contextnode, error=0, unitnumber=0, + rlen, textlen, readbuf[RBUFSZ]:ARRAY, arglist:PTR TO LONG, going=TRUE + -> E-Note: set-up globals + usage:='Usage: clipftxt unitnumber (use zero for primary unit)\n' + -> Text error messages for possible IFFERR_#? returns from various IFF + -> routines. To get the index into this array, take your IFFERR code, + -> negate it, and subtract one. + -> idx = -error - 1; + errormsgs:=['End of file (not an error).', 'End of context (not an error).', + 'No lexical scope.', 'Insufficient memory.', + 'Stream read error.', 'Stream write error.', + 'Stream seek error.', 'File is corrupt.', 'IFF syntax error.', + 'Not an IFF file.', 'Required call-back hook missing.', + 'Return to client. You should never see this.']:LONG + mytext:='This FTXT written to clipboard by clipftxt example.\n' + textlen:=STRLEN + IF NIL=(arglist:=argSplit()) THEN Raise(ERR_ARGS) + -> If not enough args or "?", print usage + IF ListLen(arglist)<>MINARGS THEN Raise(ERR_USE) + IF arglist[][]="?" THEN Raise(ERR_USE) + unitnumber:=Val(arglist[]) + + iffparsebase:=OpenLibrary('iffparse.library', 0) + + -> Allocate IFF_File OBJECT + iff:=AllocIFF() + + -> Set up IFF_File for Clipboard I/O. + iff.stream:=OpenClipboard(unitnumber) + InitIFFasClip(iff) + WriteF('Opened clipboard unit \d\n', unitnumber) + + InitIFFasClip(iff) + +#ifdef WRITEREAD + + -> Start the IFF transaction. + OpenIFF(iff, IFFF_WRITE) + + -> Write our text to the clipboard as CHRS chunk in FORM FTXT + -> + -> First, write the FORM ID (FTXT) + IF FALSE=(error:=PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) + -> Now the CHRS chunk ID followed by the chunk data. We'll just write one + -> CHRS chunk. You could write more chunks. + IF FALSE=(error:=PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN)) + -> Now the actual data (the text) + IF WriteChunkBytes(iff, mytext, textlen)<>textlen + WriteF('Error writing CHRS data.\n') + error:=IFFERR_WRITE + ENDIF + ENDIF + IF FALSE=error THEN error:=PopChunk(iff) + ENDIF + IF FALSE=error THEN error:=PopChunk(iff) + + IF error THEN Raise(ERR_WRIT) + + WriteF('Wrote text to clipboard as FTXT\n') + + -> Now let's close it, then read it back. First close the write handle, then + -> close the clipboard. + CloseIFF(iff) + IF iff.stream THEN CloseClipboard(iff.stream) + iff.stream:=NIL -> E-Note: reinitialise it to NIL to help error trapping + + iff.stream:=OpenClipboard(unitnumber) + WriteF('Reopened clipboard unit \d\n', unitnumber) + +#endif -> WRITEREAD + + OpenIFF(iff, IFFF_READ) + + -> Tell iffparse we want to stop on FTXT CHRS chunks + StopChunk(iff, ID_FTXT, ID_CHRS) + + -> Find all of the FTXT CHRS chunks + -> E-Note: the going flag makes this easier to understand + WHILE going + error:=ParseIFF(iff, IFFPARSE_SCAN) + IF error=IFFERR_EOC -> Enter next context + ELSEIF error + going:=FALSE + ELSE + -> We only asked to stop at FTXT CHRS chunks. If no error we've hit a + -> stop chunk. Read the CHRS chunk data + cn:=CurrentChunk(iff) + + IF cn + IF (cn.type=ID_FTXT) AND (cn.id=ID_CHRS) + WriteF('CHRS chunk contains:\n') + WHILE (rlen:=ReadChunkBytes(iff, readbuf, RBUFSZ)) > 0 + -> E-Note: stdout is safe since WriteF() has been used above + Write(stdout, readbuf, rlen) + ENDWHILE + IF rlen<0 THEN error:=rlen + ENDIF + ENDIF + ENDIF + ENDWHILE + + IF error AND (error<>IFFERR_EOF) + WriteF('IFF read failed, error \d: \s\n', error, errormsgs[-error-1]) + ENDIF +EXCEPT DO + IF iff + -> Terminate the IFF transaction with the stream. Free all associated + -> structures. + CloseIFF(iff) + -> Close the clipboard stream + IF iff.stream THEN CloseClipboard(iff.stream) + -> Free the IFF_File structure itself. + FreeIFF(iff) + ENDIF + IF iffparsebase THEN CloseLibrary(iffparsebase) + SELECT exception + CASE ERR_CLIP; WriteF('Error: could not open clipboard\n') + CASE ERR_IFF; WriteF('Error: could not allocate IFF handle\n') + CASE ERR_LIB; WriteF('Error: could not open iffparse.library\n') + CASE ERR_OIFF; WriteF('Error: could not open IFF handle\n') + CASE ERR_USE; WriteF(usage) + CASE ERR_WRIT; WriteF('IFF write failed, error \d: \s\n', error, errormsgs[-error-1]) + ENDSELECT +ENDPROC +->>> + +->>> Version string +-> 2.0 Version string for c:Version to find +vers: + CHAR 0, '$VER: clipftxt 37.2', 0 +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/sift.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/sift.e new file mode 100644 index 0000000..4629055 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/IFFParse/sift.e @@ -0,0 +1,157 @@ +-> sift.e - Takes any IFF file and tells you what's in it. Verifies syntax +-> and all that cool stuff. +-> +-> Usage: sift -c ; For clipboard scanning +-> or sift ; For DOS file scanning +-> +-> Reads the specified stream and prints an IFFCheck-like listing of the +-> contents of the IFF file, if any. Stream is a DOS file for +-> argument, or is the clipboard's primary clip for -c. This program must be +-> run from a CLI. + +->>> Header (globals) +MODULE 'iffparse', + 'devices/clipboard', + 'libraries/iffparse', + 'other/split' + +ENUM ERR_NONE, ERR_ARGS, ERR_CLIP, ERR_IFF, ERR_LIB, ERR_OIFF, ERR_OPEN, + ERR_USE + +RAISE ERR_CLIP IF OpenClipboard()=NIL, + ERR_IFF IF AllocIFF()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_OIFF IF OpenIFF()<>0, + ERR_OPEN IF Open()=NIL + +-> E-Note: using argSplit() so one less argument than argv (no command name) +CONST MINARGS=1 + +DEF usage, errormsgs:PTR TO LONG +->>> + +->>> PROC main() +PROC main() HANDLE + DEF iff=NIL:PTR TO iffhandle, error, cbio, arglist:PTR TO LONG, going=TRUE + -> E-Note: set-up globals + usage:='Usage: sift IFFfilename (or -c for clipboard)\n' + -> Text error messages for possible IFFERR_#? returns from various IFF + -> routines. To get the index into this array, take your IFFERR code, + -> negate it, and subtract one. + -> idx = -error - 1; + errormsgs:=['End of file (not an error).', 'End of context (not an error).', + 'No lexical scope.', 'Insufficient memory.', + 'Stream read error.', 'Stream write error.', + 'Stream seek error.', 'File is corrupt.', 'IFF syntax error.', + 'Not an IFF file.', 'Required call-back hook missing.', + 'Return to client. You should never see this.']:LONG + IF NIL=(arglist:=argSplit()) THEN Raise(ERR_ARGS) + -> If not enough args or "?", print usage + IF ListLen(arglist)<>MINARGS THEN Raise(ERR_USE) + IF arglist[][]="?" THEN Raise(ERR_USE) + + -> Check to see if we are doing I/O to the Clipboard. + cbio:=(arglist[][]="-") AND (arglist[][1]="c") + + iffparsebase:=OpenLibrary('iffparse.library', 0) + + -> Allocate IFF_File OBJECT + iff:=AllocIFF() + + -> Internal support is provided for both AmigaDOS files, and the + -> clipboard.device. This bizarre 'IF' statement performs the appropriate + -> machinations for each case. + IF cbio + -> Set up IFF_File for Clipboard I/O. + iff.stream:=OpenClipboard(PRIMARY_CLIP) + InitIFFasClip(iff) + ELSE + -> Set up IFF_File for AmigaDOS I/O. + iff.stream:=Open(arglist[], OLDFILE) + InitIFFasDOS(iff) + ENDIF + + -> Start the IFF transaction. + OpenIFF(iff, IFFF_READ) + + -> E-Note: the going flag makes this easier to understand + WHILE going + -> The interesting bit. IFFPARSE_RAWSTEP permits us to have precision + -> monitoring of the parsing process, which is necessary if we wish to + -> print the structure of an IFF file. ParseIFF() with _RAWSTEP will + -> return the following things for the following reasons: + -> + -> Return code: Reason: + -> 0 Entered new context. + -> IFFERR_EOC About to leave a context. + -> IFFERR_EOF Encountered end-of-file. + -> A parsing error. + error:=ParseIFF(iff, IFFPARSE_RAWSTEP) + + -> Since we're only interested in when we enter a context, we 'discard' + -> end-of-context (_EOC) events. + IF error=IFFERR_EOC + ELSEIF error + -> Leave the loop if there is any other error. + going:=FALSE + ELSE + -> If we get here, error was zero. Print out the current state of + -> affairs. + printTopChunk(iff) + ENDIF + ENDWHILE + + -> If error was IFFERR_EOF, then the parser encountered the end of the file + -> without problems. Otherwise, we print a diagnostic. + IF error=IFFERR_EOF + WriteF('File scan complete.\n') + ELSE + WriteF('File scan aborted, error \d: \s\n', error, errormsgs[-error-1]) + ENDIF +EXCEPT DO + IF iff + -> Terminate the IFF transaction with the stream. + CloseIFF(iff) + -> Close the stream itself. + IF iff.stream + IF cbio THEN CloseClipboard(iff.stream) ELSE Close(iff.stream) + ENDIF + -> Free the IFF_File object itself. + FreeIFF(iff) + ENDIF + IF iffparsebase THEN CloseLibrary(iffparsebase) + SELECT exception + CASE ERR_CLIP; WriteF('Error: could not open clipboard\n') + CASE ERR_IFF; WriteF('Error: could not allocate IFF handle\n') + CASE ERR_LIB; WriteF('Error: could not open iffparse.library\n') + CASE ERR_OIFF; WriteF('Error: could not open IFF handle\n') + CASE ERR_OPEN; WriteF('Error: could not open file\n') + CASE ERR_USE; WriteF(usage) + ENDSELECT +ENDPROC +->>> + +->>> PROC printTopChunk(iff:PTR TO iffhandle) +PROC printTopChunk(iff:PTR TO iffhandle) + DEF top:PTR TO contextnode, i, idbuf[5]:ARRAY + -> Get a pointer to the context node describing the current context. + IF NIL=(top:=CurrentChunk(iff)) THEN RETURN + + -> Print a series of dots equivalent to the current nesting depth of chunks + -> processed so far. This will cause nested chunks to be printed out + -> indented. + FOR i:=iff.depth TO 1 STEP -1 DO WriteF('. ') + + -> Print out the current chunk's ID and size. + WriteF('\s \d ', IdtoStr(top.id, idbuf), top.size) + + -> Print the current chunk's type, with a newline. + WriteF('\s\n', IdtoStr(top.type, idbuf)) +ENDPROC +->>> + +->>> Version string +-> 2.0 Version string for c:Version to find +vers: + CHAR 0, '$VER: sift 37.1', 0 +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmbutclass.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmbutclass.e new file mode 100644 index 0000000..21b4fb6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmbutclass.e @@ -0,0 +1,345 @@ +-> RKMButClass.e - Example Boopsi gadget for RKRM:Libraries + +OPT PREPROCESS + +MODULE 'utility', + 'amigalib/boopsi', + 'tools/installhook', + 'devices/inputevent', + 'graphics/rastport', + 'intuition/cghooks', + 'intuition/classes', + 'intuition/classusr', + 'intuition/gadgetclass', + 'intuition/icclass', + 'intuition/imageclass', + 'intuition/intuition', + 'intuition/screens', + 'utility/tagitem' + +ENUM ERR_NONE, ERR_LIB, ERR_WIN + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +OBJECT butINST + midX, midY -> Coordinates of middle of gadget +ENDOBJECT + +CONST RKMBUT_PULSE=TAG_USER+1, + -> butINST has one flag: + ERASE_ONLY=1, -> Tells rendering routine to only erase the gadget, not + -> rerender a new one. This lets the gadget erase itself + -> before it rescales. + INTWIDTH=40, INTHEIGHT=20 + +DEF w=NIL:PTR TO window, rkmbutcl=NIL, + integer=NIL:PTR TO gadget, but=NIL:PTR TO gadget + +-> The main() function connects an rkmButClass object to a Boopsi integer +-> gadget, which displays the rkmButClass gadget's RKMBUT_PULSE value. The +-> code scales and move the gadget while it is in place. +PROC main() HANDLE + utilitybase:=OpenLibrary('utility.library', 37) + w:=OpenWindowTagList(NIL, + [WA_FLAGS, WFLG_DEPTHGADGET OR WFLG_DRAGBAR OR + WFLG_CLOSEGADGET OR WFLG_SIZEGADGET, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_WIDTH, 640, + WA_HEIGHT, 200, + NIL]) + WindowLimits(w, 450, 200, 640, 200) + IF rkmbutcl:=initRKMButGadClass() + integer:=NewObjectA(NIL, 'strgclass', + [GA_ID, 1, + GA_TOP, w.bordertop+5, + GA_LEFT, w.borderleft+5, + GA_WIDTH, INTWIDTH, + GA_HEIGHT, INTHEIGHT, + STRINGA_LONGVAL, 0, + STRINGA_MAXCHARS, 5, + NIL]) + but:=NewObjectA(rkmbutcl, NIL, + [GA_ID, 2, + GA_TOP, w.bordertop+5, + GA_LEFT, integer.leftedge+integer.width+5, + GA_WIDTH, INTWIDTH, + GA_HEIGHT, INTHEIGHT, + GA_PREVIOUS, integer, + ICA_MAP, [RKMBUT_PULSE, STRINGA_LONGVAL, NIL], + ICA_TARGET, integer, + NIL]) + + AddGList(w, integer, -1, -1, NIL) + RefreshGList(integer, w, NIL, -1) + + SetWindowTitles(w, '<-- Click to resize gadget Height', NIL) + mainLoop(NIL, 0) + + SetWindowTitles(w, '<-- Click to resize gadget Width', NIL) + mainLoop(GA_HEIGHT, 100) + + SetWindowTitles(w, '<-- Click to resize gadget Y position', NIL) + mainLoop(GA_WIDTH, 100) + + SetWindowTitles(w, '<-- Click to resize gadget X position', NIL) + mainLoop(GA_TOP, but.topedge+20) + + SetWindowTitles(w, '<-- Click to quit', NIL) + mainLoop(GA_LEFT, but.leftedge+20) + + RemoveGList(w, integer, -1) + ENDIF +EXCEPT DO + IF but THEN DisposeObject(but) + IF integer THEN DisposeObject(integer) + IF rkmbutcl THEN freeRKMButGadClass(rkmbutcl) + IF w THEN CloseWindow(w) + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ERR_LIB; WriteF('Error: Could not open utility.library\n') + CASE ERR_WIN; WriteF('Error: Could not open window\n') + ENDSELECT +ENDPROC + +PROC mainLoop(attr, value) + SetGadgetAttrsA(but, w, NIL, [attr, value, NIL]) + REPEAT + UNTIL WaitIMessage(w)=IDCMP_CLOSEWINDOW +ENDPROC + +-> Make the class and set up the dispatcher's hook +PROC initRKMButGadClass() + DEF cl:PTR TO iclass + IF cl:=MakeClass(NIL, 'gadgetclass', NIL, SIZEOF butINST, 0) + -> Initialise the dispatcher Hook. + -> E-Note: use installhook to set up the hook + installhook(cl.dispatcher, {dispatchRKMButGad}) + ENDIF +ENDPROC cl + +-> Free the class +PROC freeRKMButGadClass(cl) IS FreeClass(cl) + +-> The RKMBut class dispatcher +PROC dispatchRKMButGad(cl:PTR TO iclass, o, msg:PTR TO msg) + DEF inst:PTR TO butINST, retval=FALSE, g:PTR TO gadget, gpi:PTR TO gpinput, + ie:PTR TO inputevent, rp, x, y, w, h, tmp, gpmsg:gprender + -> E-Note: installhook makes sure A4 is set-up properly + tmp:=msg.methodid + SELECT tmp + CASE OM_NEW -> First, pass up to superclass + IF g:=doSuperMethodA(cl, o, msg) + -> Initialise local instance data + inst:=INST_DATA(cl, g) + inst.midX:=g.leftedge+(g.width/2) + inst.midY:=g.topedge+(g.height/2) + retval:=g + ENDIF + CASE GM_HITTEST -> Since this is a rectangular gadget this + -> method always returns GMR_GADGETHIT. + retval:=GMR_GADGETHIT + CASE GM_GOACTIVE + inst:=INST_DATA(cl, o) + + -> Only become active if the GM_GOACTIVE was triggered by direct user input. + IF msg::gpinput.ievent + -> This gadget is now active, change visual state to selected and render. + g:=o + g.flags:=g.flags OR GFLG_SELECTED + renderRKMBut(cl, o, msg) + retval:=GMR_MEACTIVE + ELSE + -> The GM_GOACTIVE was not triggered by direct user input. + retval:=GMR_NOREUSE + ENDIF + CASE GM_RENDER + retval:=renderRKMBut(cl, o, msg) + CASE GM_HANDLEINPUT + -> While it is active, this gadget sends its superclass an OM_NOTIFY pulse + -> for every IECLASS_TIMER event that goes by (about one every 10th of a + -> second). Any object that is connected to this gadget will get A LOT of + -> OM_UPDATE messages. + g:=o + gpi:=msg + ie:=gpi.ievent + + inst:=INST_DATA(cl, o) + + retval:=GMR_MEACTIVE + + IF ie.class=IECLASS_RAWMOUSE + tmp:=ie.code + SELECT tmp + CASE SELECTUP + -> The user let go of the gadget so return GMR_NOREUSE to deactivate + -> and to tell Intuition not to reuse this Input Event as we have + -> already processed it. If the user let go of the gadget while the + -> mouse was over it, mask GMR_VERIFY into the return value so Intuition + -> will send a Release Verify (GADGETUP). + IF (gpi.mousex < g.leftedge) OR + (gpi.mousex > (g.leftedge+g.width)) OR + (gpi.mousey < g.topedge) OR + (gpi.mousey > (g.topedge+g.height)) + retval:=GMR_NOREUSE OR GMR_VERIFY + ELSE + retval:=GMR_NOREUSE + ENDIF + + -> Since the gadget is going inactive, send a final notification to + -> the ICA_TARGET. + notifyPulse(cl, o, 0, inst.midX, msg) + CASE MENUDOWN + -> The user hit the menu button. Go inactive and let Intuition reuse + -> the menu button event so Intuition can pop up the menu bar. + retval:=GMR_REUSE + + -> Since the gadget is going inactive, send a final notification to + -> the ICA_TARGET. + notifyPulse(cl, o, 0, inst.midX, msg) + DEFAULT + retval:=GMR_MEACTIVE + ENDSELECT + ELSEIF ie.class=IECLASS_TIMER + -> If the gadget gets a timer event, it sends an interim OM_NOTIFY to + -> its superclass. + notifyPulse(cl, o, OPUF_INTERIM, inst.midX, gpi) + ENDIF + CASE GM_GOINACTIVE + -> Intuition said to go inactive. Clear the GFLG_SELECTED bit and render + -> using unselected imagery. + g:=o + g.flags:=g.flags AND Not(GFLG_SELECTED) + renderRKMBut(cl, o, msg) + CASE OM_SET + -> Although this class doesn't have settable attributes, this gadget class + -> does have scaleable imagery, so it needs to find out when its size and/or + -> position has changed so it can erase itself, THEN scale, and rerender. + IF FindTagItem(GA_WIDTH, msg::opset.attrlist) OR + FindTagItem(GA_HEIGHT, msg::opset.attrlist) OR + FindTagItem(GA_TOP, msg::opset.attrlist) OR + FindTagItem(GA_LEFT, msg::opset.attrlist) + g:=o + + x:=g.leftedge + y:=g.topedge + w:=g.width + h:=g.height + + inst:=INST_DATA(cl, o) + + retval:=doSuperMethodA(cl, o, msg) + + -> Get pointer to RastPort for gadget. + IF rp:=ObtainGIRPort(msg::opset.ginfo) + SetAPen(rp, msg::opset.ginfo.drinfo.pens[BACKGROUNDPEN]) + SetDrMd(rp, RP_JAM1) -> Erase the old gadget. + RectFill(rp, x, y, x+w, y+h) + inst.midX:=g.leftedge+(g.width/2) -> Recalculate where the + inst.midY:=g.topedge+(g.height/2) -> center of the gadget is. + + -> Rerender the gadget. + -> E-Note: Intuition may alter the message, so don't use a static list + gpmsg.methodid:=GM_RENDER + gpmsg.ginfo:=msg::opset.ginfo + gpmsg.rport:=rp + gpmsg.redraw:=GREDRAW_REDRAW + doMethodA(o, gpmsg) + ReleaseGIRPort(rp) + ENDIF + ELSE + retval:=doSuperMethodA(cl, o, msg) + ENDIF + DEFAULT + -> rkmmodelclass does not recognise the methodID, let the superclass's + -> dispatcher take a look at it. + retval:=doSuperMethodA(cl, o, msg) + ENDSELECT +ENDPROC retval + +-> Build an OM_NOTIFY message for RKMBUT_PULSE and send it to the superclass. +PROC notifyPulse(cl, o:PTR TO gadget, flags, mid, gpi:PTR TO gpinput) + DEF msg:PTR TO opnotify -> E-Note: "opnotify" is really "opupdate" + -> If this is an OM_UPDATE method, make sure the part the OM_UPDATE message + -> adds to the OM_SET message gets added. That lets the dispatcher handle + -> OM_UPDATE and OM_SET in the same case. + msg:=[OM_NOTIFY, [RKMBUT_PULSE, mid-(gpi.mousex+o.leftedge), + GA_ID, o.gadgetid, NIL], + gpi.ginfo, flags]:opnotify + + -> E-Note: A bug (?) in Intuition means that the methodid of an OM_NOTIFY + -> message may be altered, so you can't get away with just using a + -> constant value in the above static list... + msg.methodid:=OM_NOTIFY + + doSuperMethodA(cl, o, msg) +ENDPROC + +-> Erase and rerender the gadget. +PROC renderRKMBut(cl:PTR TO iclass, g:PTR TO gadget, msg:PTR TO gprender) + DEF inst:PTR TO butINST, rp, retval=TRUE, pens:PTR TO INT, + back, shine, shadow, w, h, x, y + inst:=INST_DATA(cl, g) + pens:=msg.ginfo.drinfo.pens + + IF msg.methodid=GM_RENDER + -> If msg is truly a GM_RENDER message (not a gpinput that looks like a + -> gprender), use the rastport within it... + rp:=msg.rport + ELSE -> ...Otherwise, get a rastport using ObtainGIRPort(). + rp:=ObtainGIRPort(msg.ginfo) + ENDIF + + IF rp + IF g.flags AND GFLG_SELECTED + -> If the gadget is selected, reverse the meanings of the pens. + back:=pens[FILLPEN] + shine:=pens[SHADOWPEN] + shadow:=pens[SHINEPEN] + ELSE + back:=pens[BACKGROUNDPEN] + shine:=pens[SHINEPEN] + shadow:=pens[SHADOWPEN] + ENDIF + SetDrMd(rp, RP_JAM1) + + SetAPen(rp, back) -> Erase the old gadget. + RectFill(rp, g.leftedge, g.topedge, + g.leftedge+g.width, g.topedge+g.height) + + SetAPen(rp, shadow) -> Draw shadow edge. + Move(rp, g.leftedge+1, g.topedge+g.height) + Draw(rp, g.leftedge+g.width, g.topedge+g.height) + Draw(rp, g.leftedge+g.width, g.topedge+1) + + w:=g.width/4 -> Draw Arrows - Sorry, no frills imagery + h:=g.height/2 + x:=g.leftedge+(w/2) + y:=g.topedge+(h/2) + + Move(rp, x, inst.midY) + Draw(rp, x+w, y) + Draw(rp, x+w, y+g.height-h) + Draw(rp, x, inst.midY) + + x:=g.leftedge+(w/2)+(g.width/2) + + Move(rp, x+w, inst.midY) + Draw(rp, x, y) + Draw(rp, x, y+g.height-h) + Draw(rp, x+w, inst.midY) + + SetAPen(rp, shine) -> Draw shine edge. + Move(rp, g.leftedge, g.topedge+g.height-1) + Draw(rp, g.leftedge, g.topedge) + Draw(rp, g.leftedge+g.width-1, g.topedge) + + IF msg.methodid<>GM_RENDER -> If we allocated a rastport, give it back. + ReleaseGIRPort(rp) + ENDIF + ELSE + retval:=FALSE + ENDIF +ENDPROC retval + +vers: CHAR 0, '$VER: TestBut 37.1', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.e new file mode 100644 index 0000000..14535c0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.e @@ -0,0 +1,143 @@ +-> RKMModel.e - A simple custom modelclass subclass. + +OPT MODULE +OPT PREPROCESS + +OPT OSVERSION=37 + +MODULE 'utility', + 'amigalib/boopsi', + 'tools/installhook', + 'intuition/classes', + 'intuition/classusr', + 'utility/hooks', + 'utility/tagitem' + +-> The attributes defined by this class +EXPORT ENUM RKMMOD_DUMMY=TAG_USER, + RKMMOD_CURRVAL, -> This attribute is the current value of the model. + RKMMOD_UP, -> These two are fake attributes that rkmmodelclass + RKMMOD_DOWN, -> uses as pulse values to increment/decrement the + -> rkmmodel's RKMMOD_CURRVAL attribute. + RKMMOD_LIMIT -> This attribute contains the upper bound of the + -> rkmmodel's RKMMOD_CURRVAL. The rkmmodel has a + -> static lower bound of zero. + +-> If the programmer doesn't set RKMMOD_LIMIT, it defaults to this. +CONST DEFAULTVALLIMIT=100 + +OBJECT rkmModData + currval, vallimit -> The instance data for this class +ENDOBJECT + +-> Initialise the class +EXPORT PROC initRKMModClass() -> Make the class and set up the dispatcher's hook + DEF cl:PTR TO iclass + IF cl:=MakeClass(NIL, 'modelclass', NIL, SIZEOF rkmModData, 0) + -> E-Note: use installhook to set up the hook + installhook(cl.dispatcher, {dispatchRKMModel}) -> Initialise the Hook + ENDIF +ENDPROC cl + +-> Free the class +EXPORT PROC freeRKMModClass(cl) IS FreeClass(cl) + +-> The class Dispatcher +PROC dispatchRKMModel(cl:PTR TO iclass, o, msg:PTR TO msg) + DEF mmd:PTR TO rkmModData, id, ti:PTR TO tagitem, tstate, tag, + retval=NIL -> A generic return value used by this class's methods. The + -> meaning of this field depends on the method. For example, + -> OM_GET uses this as a boolean return value, while OM_NEW + -> uses it as a pointer to the new object. + -> E-Note: installhook makes sure A4 is set-up properly + id:=msg.methodid + IF id=OM_SET THEN id:=OM_UPDATE -> E-Note: handled the same in this class + SELECT id + CASE OM_NEW -> Pass message onto superclass first so it can set aside memory + -> for the object and take care of superclass instance data. + IF retval:=doSuperMethodA(cl, o, msg) + -> For the OM_NEW method, the object pointer passed to the dispatcher + -> does not point to an object (how could it? The object doesn't exist + -> yet.). doSuperMethodA() returns a pointer to a newly created object. + -> INST_DATA() is a macro defined in 'intuition/classes' that returns a + -> pointer to the object's instance data that is local to this class. For + -> example, the instance data local to this class is the rkmModData + -> structure defined above. + mmd:=INST_DATA(cl, retval) + -> Initialise object's attributes + -> E-Note: "opnew" is really "opset" + mmd.currval:=GetTagData(RKMMOD_CURRVAL, 0, msg::opnew.attrlist) + mmd.vallimit:=GetTagData(RKMMOD_LIMIT,DEFAULTVALLIMIT,msg::opnew.attrlist) + ENDIF + CASE OM_UPDATE -> E-Note: includes OM_SET (see "IF id=.." above) + mmd:=INST_DATA(cl, o) + doSuperMethodA(cl,o,msg) -> Let the superclasses set their attributes first + tstate:=msg::opset.attrlist + -> Step through all of the attribute/value pairs in the list. Use the + -> utility.library tag functions to do this so they can properly process + -> special tag IDs like TAG_SKIP, TAG_IGNORE, etc. + WHILE ti:=NextTagItem({tstate}) + tag:=ti.tag + SELECT tag + CASE RKMMOD_CURRVAL + IF ti.data>mmd.vallimit THEN ti.data:=mmd.vallimit + mmd.currval:=ti.data + notifyCurrVal(cl, o, msg, mmd) + retval:=1 -> Changing RKMMOD_CURRVAL can cause a visual change to the + -> gadgets in the rkmmodel's broadcast list. The rkmmodel has + -> to tell the application by returning a value besides zero. + CASE RKMMOD_UP + mmd.currval:=mmd.currval+1 + -> Make sure the current value is not greater than value limit. + IF mmd.currval>mmd.vallimit THEN mmd.currval:=mmd.vallimit + notifyCurrVal(cl, o, msg, mmd) + retval:=1 -> Changing RKMMOD_UP can cause a visual change to the gadgets + -> in the rkmmodel's broadcast list. The rkmmodel has to tell + -> the application by returning a value besides zero. + CASE RKMMOD_DOWN + mmd.currval:=mmd.currval-1 + -> Make sure the currval didn't go negative + IF mmd.currval<0 THEN mmd.currval:=0 + notifyCurrVal(cl, o, msg, mmd) + retval:=1 -> Changing RKMMOD_DOWN can cause a visual change to gadgets + -> in the rkmmodel's broadcast list. The rkmmodel has to tell + -> the application by returning a value besides zero. + CASE RKMMOD_LIMIT + mmd.vallimit:=ti.data -> Set the limit. Note that this does not do + -> bounds checking on the current + -> rkmModData.currval value. + ENDSELECT + ENDWHILE + CASE OM_GET -> The only attribute that is "gettable" in this class + mmd:=INST_DATA(cl, o) -> or its superclasses is RKMMOD_CURRVAL. + IF msg::opget.attrid=RKMMOD_CURRVAL + msg::opget.storage[]:=mmd.currval + retval:=TRUE + ELSE + retval:=doSuperMethodA(cl, o, msg) + ENDIF + DEFAULT -> rkmmodelclass does not recognise the methodID, so let the + -> superclass's dispatcher take a look at it. + retval:=doSuperMethodA(cl, o, msg) + ENDSELECT +ENDPROC retval + +PROC notifyCurrVal(cl, o, msg:PTR TO opupdate, mmd:PTR TO rkmModData) + DEF notifymsg:PTR TO opnotify -> E-Note: "opnotify" is really "opupdate" + -> If this is an OM_UPDATE method, make sure the part the OM_UPDATE message + -> adds to the OM_SET message gets added. That lets the dispatcher handle + -> OM_UPDATE and OM_SET in the same case. + notifymsg:=[OM_NOTIFY, [RKMMOD_CURRVAL, mmd.currval, NIL], msg.ginfo, + IF msg.methodid=OM_UPDATE THEN msg.flags ELSE 0]:opnotify + + -> E-Note: A bug (?) in Intuition means that the methodid of an OM_NOTIFY + -> message may be altered, so you can't get away with just using a + -> constant value in the above static list... + notifymsg.methodid:=OM_NOTIFY + + -> If the RKMMOD_CurrVal changes, we want everyone to know about it. + -> Theoretically, the class is supposed to send itself a OM_NOTIFY message. + -> Because this class lets its superclass handle the OM_NOTIFY message, it + -> skips the middleman and sends the OM_NOTIFY directly to its superclass. + doSuperMethodA(cl, o, notifymsg) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.m b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/rkmmodel.m new file mode 100644 index 0000000000000000000000000000000000000000..325877d871a85c0ef71d842033c6f408034c5778 GIT binary patch literal 1514 zcmah}&rcIU6n@*TVI>>0F&;b+9Y{=wfc50Tc%V{=V7oPi`YSQe(gikd*$r(E8V`#n zt|lBj_$MggsEG&vgvPT8R}L6BaA?Tl_`TU}0VTM}?7n$3?|a`jZ{9vA6mxWe__;yh zdu8BtQ5k6>?W$dtQE^Z129y~mBYUXlgaOM`b1Pt*l&z0?vYp@VOWT`AFGj{?G#xGx z4T!povTejr_K{)_#P#+X zc6Fc>h@9kDmtrtXI_n?xj-vdw295G3lyyYdi{Nz%YIy7CMGRtno>I2rZN$8_O~IVc z;dQpIZXPh-1&=8EOYW-bP{NbIvyD|%3oXaBP-nRxYee>aoZ2(xheB2~gzwgxPjp%7 zi@g!EKDkSTCmChNWT!&fJ5<#QG(PQlq8}Iow2kGg!~s{Q^5T^p)$yo+y~_rJ<@ zYh;Fes}R8*(GgIKd%cVi1~NIZfs+h-eWGqJ@}9HGw>s&XNa0$l+xmrpIE&JpnUZI4 z4mTMmLMF7KE0txbzB0h>QnF$qQb%8N*Ty(kNC!+`7l*&VGBFIsBcp117# zuWr?`D@EoB7tfhr31graS*g2A70<0^s=gmI+$7Gb`7^D+SuHrtWxtk1M4JEP`Xr1G O7;ivz1Kw{Kc>VyIE2R4X literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/talk2boopsi.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/talk2boopsi.e new file mode 100644 index 0000000..cdc7c7a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/talk2boopsi.e @@ -0,0 +1,107 @@ +-> This example creates a Boopsi prop gadget and integer string gadget, +-> connecting them so they update each other when the user changes their value. +-> The example program only initialises the gadgets and puts them on the window; +-> it doesn't have to interact with them to make them talk to each other. + +OPT OSVERSION=37 + +MODULE 'intuition/gadgetclass', + 'intuition/icclass', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_OBJ, ERR_WIN + +RAISE ERR_OBJ IF NewObjectA()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST PROPGADGET_ID=1, INTGADGET_ID=2, + PROPGADGETWIDTH=10, PROPGADGETHEIGHT=80, INTGADGETHEIGHT=18, + VISIBLE=10, TOTAL=100, INITIALVAL=25, MINWINDOWWIDTH=80 +CONST MINWINDOWHEIGHT=PROPGADGETHEIGHT+70, MAXCHARS=3 + +PROC main() HANDLE + DEF w=NIL:PTR TO window, prop=NIL, integer=NIL + + -> Open the window--notice that the window's IDCMP port + -> does not listen for GADGETUP messages. + w:=OpenWindowTagList(NIL, + [WA_FLAGS, WFLG_DEPTHGADGET OR WFLG_DRAGBAR OR + WFLG_CLOSEGADGET OR WFLG_SIZEGADGET, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_MINWIDTH, MINWINDOWWIDTH, + WA_MINHEIGHT, MINWINDOWHEIGHT, + NIL]) + + -> Create a new propgclass object + prop:=NewObjectA(NIL, 'propgclass', + [GA_ID, PROPGADGET_ID, -> These are defined by gadgetclass and + GA_TOP, w.bordertop+5, -> correspond to similarly named fields + GA_LEFT, w.borderleft+5, -> in the Gadget structure. + GA_WIDTH, PROPGADGETWIDTH, + GA_HEIGHT, PROPGADGETHEIGHT, + -> This tells the prop gadget to map its PGA_Top attribute to + -> STRINGA_LONGVAL when it issues an update about the change to + -> its PGA_Top value. + ICA_MAP, [PGA_TOP, STRINGA_LONGVAL, NIL], + -> The rest of this gadget's attributes are defined by propgclass. + PGA_TOTAL, TOTAL, -> The integer range of the prop gadget. + PGA_TOP, INITIALVAL, -> The initial value of the prop gadget. + PGA_VISIBLE, VISIBLE, -> This determines how much of the prop gadget + -> area is covered by the prop gadget's knob, + -> or how much of the gadget's TOTAL range is + -> taken up by the prop gadget's knob. + PGA_NEWLOOK, TRUE, -> Use new-look prop gadget imagery + NIL]) + + -> Create the integer string gadget + integer:=NewObjectA(NIL, 'strgclass', + [GA_ID, INTGADGET_ID, -> Parameters for the Gadget structure + GA_TOP, w.bordertop+5, + GA_LEFT, w.borderleft+PROPGADGETWIDTH+10, + GA_WIDTH, (MINWINDOWWIDTH- + (w.borderleft+w.borderright+PROPGADGETWIDTH+15)), + GA_HEIGHT, INTGADGETHEIGHT, + -> This tells the string gadget to map its STRINGA_LONGVAL + -> attribute to PGA_TOP when it issues an update. + ICA_MAP, [STRINGA_LONGVAL, PGA_TOP, NIL], + ICA_TARGET, prop, + -> The GA_PREVIOUS attribute is defined by gadgetclass and is used + -> to wedge a new gadget into a list of gadget's linked by their + -> gadget.nextgadget field. When NewObject() creates this gadget, + -> it inserts the new gadget into this list behind the GA_PREVIOUS + -> gadget. This attribute is a pointer to the previous gadget. + -> This attribute cannot be used to link new gadgets into the + -> gadget list of an open window or requester, use + -> AddGList() instead. + GA_PREVIOUS, prop, + -> These attributes are defined by strgclass. The first contains + -> the value of the integer string gadget. The second is the + -> maximum number of characters the user is allowed to type into + -> the gadget. + STRINGA_LONGVAL, INITIALVAL, + STRINGA_MAXCHARS, MAXCHARS, + NIL]) + + -> Because the integer string gadget did not exist when this example created + -> the prop gadget, it had to wait to set the ICA_Target of the prop gadget. + SetGadgetAttrsA(prop, w, NIL, [ICA_TARGET, integer, NIL]) + + AddGList(w,prop,-1,-1,NIL) -> Add the gadgets to the window and display them. + RefreshGList(prop, w, NIL, -1) + + REPEAT -> Wait for the user to click the window close gadget. + UNTIL WaitIMessage(w)=IDCMP_CLOSEWINDOW + + RemoveGList(w, prop, -1) + +EXCEPT DO + IF integer THEN DisposeObject(integer) + IF prop THEN DisposeObject(prop) + IF w THEN CloseWindow(w) + SELECT exception + CASE ERR_OBJ; WriteF('Error: Failed to create new Object\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +ENDPROC + +vers: CHAR 0, '$VER: Talk2boopsi 37.1', 0 \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/userkmmodel.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/userkmmodel.e new file mode 100644 index 0000000..50cdac7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Boopsi/userkmmodel.e @@ -0,0 +1,182 @@ +OPT OSVERSION=37 + +MODULE '*rkmmodel', + 'amigalib/boopsi', + 'utility', + 'intuition/classusr', + 'intuition/gadgetclass', + 'intuition/icclass', + 'intuition/imageclass', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_DRAW, ERR_LIB, ERR_OBJ, ERR_WIN + +RAISE ERR_DRAW IF GetScreenDrawInfo()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_OBJ IF NewObjectA()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST PROPID=1, INTEGERID=2, RIGHTID=3, LEFTID=4, PROPWIDTH=80, PROPHEIGHT=10, + INTWIDTH=50, INTHEIGHT=14, VISIBLE=10, TOTAL=100, INITIALVAL=25 +CONST MINWINDOWWIDTH=80, MINWINDOWHEIGHT=PROPHEIGHT+70, MAXCHARS=4 + +DEF w=NIL:PTR TO window, mydrawinfo=NIL, rkmmodcl=NIL, + rkmmodel=NIL, currval2int=NIL, currval2prop=NIL, + prop=NIL:PTR TO gadget, integer=NIL:PTR TO gadget, + leftbut=NIL:PTR TO gadget, rightbut=NIL:PTR TO gadget, + rightimage=NIL, leftimage=NIL + +PROC main() HANDLE + DEF qwe + utilitybase:=OpenLibrary('utility.library', 37) + w:=OpenWindowTagList(NIL, + [WA_FLAGS, WFLG_DEPTHGADGET OR WFLG_DRAGBAR OR + WFLG_CLOSEGADGET OR WFLG_SIZEGADGET, + WA_IDCMP, IDCMP_CLOSEWINDOW, + NIL]) + -> E-Note: we could have made initRKMModClass raise an exception + IF rkmmodcl:=initRKMModClass() + mydrawinfo:=GetScreenDrawInfo(w.wscreen) + makeGadgetsAndRKMModel() + doMethodA(rkmmodel, [OM_ADDMEMBER, currval2prop]) + currval2prop:=NIL -> E-Note: this is now part of the rkmmodel object + doMethodA(rkmmodel, [OM_ADDMEMBER, currval2int]) + currval2int:=NIL -> E-Note: again, now part of the rkmmodel object + WindowLimits(w, + w.borderleft+w.borderright+integer.leftedge+integer.width+10, + w.bordertop+w.borderbottom+prop.height+10, + w.maxwidth, + w.maxheight) + AddGList(w, prop, -1, -1, NIL) + RefreshGadgets(prop, w, NIL) + + GetAttr(RKMMOD_CURRVAL, rkmmodel, {qwe}) + WriteF('RKMMOD_CURRVAL = \d\n', qwe) + Delay(200) + + IF SetAttrsA(rkmmodel, [RKMMOD_CURRVAL, 10, NIL]) + RefreshGadgets(prop, w, NIL) + ENDIF + GetAttr(RKMMOD_CURRVAL, rkmmodel, {qwe}) + WriteF('RKMMOD_CURRVAL = \d\n', qwe) + Delay(200) + + IF SetAttrsA(rkmmodel, [RKMMOD_CURRVAL, 30, NIL]) + RefreshGadgets(prop, w, NIL) + ENDIF + GetAttr(RKMMOD_CURRVAL, rkmmodel, {qwe}) + WriteF('RKMMOD_CURRVAL = \d\n', qwe) + Delay(200) + + IF SetAttrsA(rkmmodel, [RKMMOD_CURRVAL, 50, NIL]) + RefreshGadgets(prop, w, NIL) + ENDIF + GetAttr(RKMMOD_CURRVAL, rkmmodel, {qwe}) + WriteF('RKMMOD_CURRVAL = \d\n', qwe) + Delay(200) + + IF SetAttrsA(rkmmodel, [RKMMOD_UP, 1, NIL]) + RefreshGadgets(prop, w, NIL) + ENDIF + + -> Wait for the user to click window close gadget + REPEAT + UNTIL WaitIMessage(w)=IDCMP_CLOSEWINDOW + RemoveGList(w, prop, -1) + ENDIF + +EXCEPT DO + IF currval2int THEN DisposeObject(currval2int) + IF currval2prop THEN DisposeObject(currval2prop) + IF rightbut THEN DisposeObject(rightbut) + IF leftbut THEN DisposeObject(leftbut) + IF integer THEN DisposeObject(integer) + IF prop THEN DisposeObject(prop) + IF rkmmodel THEN DisposeObject(rkmmodel) + IF leftimage THEN DisposeObject(leftimage) + IF rightimage THEN DisposeObject(rightimage) + + IF mydrawinfo THEN FreeScreenDrawInfo(w.wscreen, mydrawinfo) + IF rkmmodcl THEN freeRKMModClass(rkmmodcl) + IF w THEN CloseWindow(w) + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ERR_DRAW; WriteF('Error: Failed to get screen DrawInfo\n') + CASE ERR_LIB; WriteF('Error: Failed to open utility library\n') + CASE ERR_OBJ; WriteF('Error: Failed to make new Object\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +ENDPROC + +PROC makeGadgetsAndRKMModel() HANDLE + rightimage:=NewObjectA(NIL, 'sysiclass', + [SYSIA_WHICH, RIGHTIMAGE, + SYSIA_DRAWINFO, mydrawinfo, NIL]) + leftimage:=NewObjectA(NIL, 'sysiclass', + [SYSIA_WHICH, LEFTIMAGE, + SYSIA_DRAWINFO, mydrawinfo, NIL]) + rkmmodel:=NewObjectA(rkmmodcl, NIL, + [RKMMOD_CURRVAL, INITIALVAL, + RKMMOD_LIMIT, TOTAL-VISIBLE, NIL]) + prop:=NewObjectA(NIL, 'propgclass', + [GA_ID, PROPID, + GA_TOP, w.bordertop+5, + GA_LEFT, w.borderleft+5, + GA_WIDTH, PROPWIDTH, + GA_HEIGHT, PROPHEIGHT, + ICA_MAP, [PGA_TOP, RKMMOD_CURRVAL, + STRINGA_LONGVAL, RKMMOD_CURRVAL, + NIL], + ICA_TARGET, rkmmodel, + PGA_FREEDOM, FREEHORIZ, + PGA_TOTAL, TOTAL, + PGA_TOP, INITIALVAL, + PGA_VISIBLE, VISIBLE, + PGA_NEWLOOK, TRUE, + NIL]) + integer:=NewObjectA(NIL, 'strgclass', + [GA_ID, INTEGERID, + GA_TOP, w.bordertop+5, + GA_LEFT, prop.leftedge+prop.width+48, + GA_WIDTH, INTWIDTH, + GA_HEIGHT, INTHEIGHT, + ICA_MAP, [PGA_TOP, RKMMOD_CURRVAL, + STRINGA_LONGVAL, RKMMOD_CURRVAL, + NIL], + ICA_TARGET, rkmmodel, + GA_PREVIOUS, prop, + STRINGA_LONGVAL, INITIALVAL, + STRINGA_MAXCHARS, MAXCHARS, + NIL]) + leftbut:=NewObjectA(NIL, 'buttongclass', + [GA_ID, LEFTID, + GA_IMAGE, leftimage, + GA_TOP, w.bordertop+5, + GA_LEFT, prop.leftedge+prop.width, + ICA_MAP, [GA_ID, RKMMOD_DOWN, NIL], + ICA_TARGET, rkmmodel, + GA_PREVIOUS, integer, + NIL]) + rightbut:=NewObjectA(NIL, 'buttongclass', + [GA_ID, RIGHTID, + GA_IMAGE, rightimage, + GA_TOP, w.bordertop+5, + GA_LEFT, prop.leftedge+prop.width+leftbut.width, + ICA_MAP, [GA_ID, RKMMOD_UP, NIL], + ICA_TARGET, rkmmodel, + GA_PREVIOUS, leftbut, + NIL]) + currval2prop:=NewObjectA(NIL, 'icclass', + [ICA_MAP, [RKMMOD_CURRVAL, PGA_TOP, NIL], + ICA_TARGET, prop, + NIL]) + currval2int:=NewObjectA(NIL, 'icclass', + [ICA_MAP, [RKMMOD_CURRVAL, STRINGA_LONGVAL, NIL], + ICA_TARGET, integer, + NIL]) + RETURN TRUE +EXCEPT + ReThrow() -> E-Note: pass on exception if it is an error +ENDPROC + +vers: CHAR 0, '$VER: UseRKMModel 37.1', 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/simplegad.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/simplegad.e new file mode 100644 index 0000000..288546c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/simplegad.e @@ -0,0 +1,70 @@ +-> simplegad.e - show the use of a button gadget. + +MODULE 'graphics/rastport', -> RastPort and other structures + 'intuition/intuition' -> Intuition data structures and tags + +CONST BUTTON_GAD_NUM=3, MYBUTTONGADWIDTH=100, MYBUTTONGADHEIGHT=50 + +-> NOTE that the use of constant size and positioning values are not +-> recommended; it just makes it easy to show what is going on. The position +-> of the gadget should be dynamically adjusted depending on the height of the +-> font in the title bar of the window. + +ENUM ERR_NONE, ERR_WIN, ERR_KICK + +RAISE ERR_WIN IF OpenWindowTagList()=NIL + +-> Routine to show the use of a button (boolean) gadget. +PROC main() HANDLE + DEF win=NIL:PTR TO window, class, gad:PTR TO gadget + -> Make sure to get version 37, for OpenWindowTags() */ + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + + -> E-Note: E automatically opens the Intuition library + -> E-Note: automatically error-checked (automatic exception) + win:=OpenWindowTagList(NIL, + [WA_WIDTH, 400, + WA_HEIGHT, 100, + WA_GADGETS, -> E-Note: use typed lists for gadget + [NIL, 20, 20, MYBUTTONGADWIDTH, MYBUTTONGADHEIGHT, + GFLG_GADGHCOMP, GACT_RELVERIFY OR GACT_IMMEDIATE, + GTYP_BOOLGADGET, + [-1, -1, 1, 0, RP_JAM1, 5, -> E-Note: Border + [0, 0, -> E-Note: 5 co-ords (INTs) + MYBUTTONGADWIDTH+1, 0, + MYBUTTONGADWIDTH+1, MYBUTTONGADHEIGHT+1, + 0, MYBUTTONGADHEIGHT+1, + 0,0]:INT, + NIL]:border, + NIL, NIL, 0, NIL, BUTTON_GAD_NUM, NIL]:gadget, + WA_ACTIVATE, TRUE, + WA_CLOSEGADGET, TRUE, + WA_IDCMP, IDCMP_GADGETDOWN OR IDCMP_GADGETUP OR + IDCMP_CLOSEWINDOW, + NIL]) + REPEAT + class:=WaitIMessage(win) + -> SELECT on the type of the event + SELECT class + CASE IDCMP_GADGETUP + -> Caused by GACT_RELVERIFY + gad:=MsgIaddr() + WriteF('Received an IDCMP_GADGETUP , gadget number \d\n', gad.gadgetid) + CASE IDCMP_GADGETDOWN + -> Caused by GACT_IMMEDIATE + gad:=MsgIaddr() + WriteF('Received an IDCMP_GADGETDOWN , gadget number \d\n', gad.gadgetid) + ENDSELECT + UNTIL class=IDCMP_CLOSEWINDOW + WriteF('Received an IDCMP_CLOSEWINDOW\n') + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF win THEN CloseWindow(win) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/strhooks.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/strhooks.e new file mode 100644 index 0000000..58077a2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/strhooks.e @@ -0,0 +1,188 @@ +-> strhooks.e - string gadget hooks demo +-> E-Note: this uses several of the 'tools' modules, notably 'installhook' + +MODULE 'utility', + 'graphics/rastport', + 'intuition/intuition', + 'intuition/screens', + 'intuition/sghooks', + 'utility/hooks', + 'tools/ctype', + 'tools/installhook' + +ENUM ERR_NONE, ERR_DRAW, ERR_KICK, ERR_LIB, ERR_PUB, ERR_WIN + +RAISE ERR_DRAW IF GetScreenDrawInfo()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PUB IF LockPubScreen()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST SG_STRLEN=44, MYSTRGADWIDTH=200 + +-> We'll dynamically allocate/clear most structures, buffers +OBJECT vars + sgg_Window:PTR TO window + sgg_Gadget:gadget + sgg_StrInfo:stringinfo + sgg_Extend:stringextend + sgg_Hook:hook + sgg_Buff[SG_STRLEN]:ARRAY + sgg_WBuff[SG_STRLEN]:ARRAY + sgg_UBuff[SG_STRLEN]:ARRAY +ENDOBJECT + +-> Open all required libraries, set-up the string gadget. +-> Prepare the hook, open the sgg_Window and go... +PROC main() HANDLE + -> E-Note: subtle name changes needed... + DEF vars=NIL:PTR TO vars, screen=NIL:PTR TO screen, + drawinfo=NIL:PTR TO drawinfo + + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + + utilitybase:=OpenLibrary('utility.library', 37) + + -> Get the correct pens for the screen + screen:=LockPubScreen(NIL) + + drawinfo:=GetScreenDrawInfo(screen) + + NEW vars -> E-Note: raises an exception if it fails + vars.sgg_Extend.pens[0]:=drawinfo.pens[FILLTEXTPEN] + vars.sgg_Extend.pens[1]:=drawinfo.pens[FILLPEN] + vars.sgg_Extend.activepens[0]:=drawinfo.pens[FILLTEXTPEN] + vars.sgg_Extend.activepens[1]:=drawinfo.pens[FILLPEN] + vars.sgg_Extend.edithook:=vars.sgg_Hook + vars.sgg_Extend.workbuffer:=vars.sgg_WBuff + + vars.sgg_StrInfo.buffer:=vars.sgg_Buff + vars.sgg_StrInfo.undobuffer:=vars.sgg_UBuff + vars.sgg_StrInfo.maxchars:=SG_STRLEN + vars.sgg_StrInfo.extension:=vars.sgg_Extend + + -> There should probably be a border around the string gadget. + -> As is, it is hard to locate when disabled. + vars.sgg_Gadget.leftedge:=20 + vars.sgg_Gadget.topedge:=30 + vars.sgg_Gadget.width:=MYSTRGADWIDTH + vars.sgg_Gadget.height:=screen.rastport.txheight + vars.sgg_Gadget.flags:=GFLG_GADGHCOMP OR GFLG_STRINGEXTEND + vars.sgg_Gadget.activation:=GACT_RELVERIFY + vars.sgg_Gadget.gadgettype:=GTYP_STRGADGET + vars.sgg_Gadget.specialinfo:=vars.sgg_StrInfo + -> E-Note: use typed lists for border and its data + -> E-Note: because we're using E we don't need stupid INIT_LATER + vars.sgg_Gadget.gadgetrender:=[-2,-2,1,0,RP_JAM1,5, + [0, 0, + MYSTRGADWIDTH+3, 0, + MYSTRGADWIDTH+3, screen.rastport.txheight+3, + 0, screen.rastport.txheight+3, + 0, 0]:INT, + NIL]:border + + -> E-Note: use Wouter's installhook + installhook(vars.sgg_Hook, {str_hookRoutine}) + + vars.sgg_Window:=OpenWindowTagList(NIL, + [WA_PUBSCREEN, screen, + WA_LEFT, 21, WA_TOP, 20, + WA_WIDTH, 500, WA_HEIGHT, 150, + WA_MINWIDTH, 50, WA_MAXWIDTH, -1, + WA_MINHEIGHT, 30, WA_MAXHEIGHT, -1, + WA_SIMPLEREFRESH, TRUE, + WA_NOCAREREFRESH, TRUE, + WA_RMBTRAP, TRUE, + WA_IDCMP, IDCMP_GADGETUP OR IDCMP_CLOSEWINDOW, + WA_FLAGS, WFLG_CLOSEGADGET OR WFLG_NOCAREREFRESH OR + WFLG_DRAGBAR OR WFLG_DEPTHGADGET OR + WFLG_SIMPLE_REFRESH, + WA_TITLE, 'String Hook Accepts HEX Digits Only', + WA_GADGETS, vars.sgg_Gadget, + NIL]) + handleWindow(vars) + -> E-Note: exit and clean up via handler +EXCEPT DO + IF (vars<>NIL) AND vars.sgg_Window THEN CloseWindow(vars.sgg_Window) + -> E-Note: vars automatically freed + IF drawinfo THEN FreeScreenDrawInfo(screen, drawinfo) + IF screen THEN UnlockPubScreen(NIL, screen) + IF utilitybase THEN CloseLibrary(utilitybase) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_DRAW; WriteF('Error: Failed to get drawinfo from screen\n') + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + CASE ERR_LIB; WriteF('Error: Failed to open utility.library\n') + CASE ERR_PUB; WriteF('Error: Failed to lock public screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC + +-> This is an example string editing hook, which shows the basics of creating +-> a string editing function. This hook restricts entry to hexadecimal digits +-> (0-9, A-F, a-f) and converts them to upper case. To demonstrate processing +-> of mouse-clicks, this hook also detects clicking on a character, and +-> converts it to a zero. +-> +-> NOTE String editing hooks are called on Intuition's task context, so the +-> hook may not use DOS and may not cause Wait() to be called. +PROC str_hookRoutine(hook, sgw:PTR TO sgwork, msg:PTR TO LONG) + DEF work_ptr, return_code + + -> Hook must return non-zero if command is supported. + -> This will be changed to zero if the command is unsupported. + return_code:=-1 + + IF msg[]=SGH_KEY + -> Key hit -- could be any key (Shift, repeat, character, etc.) + + -> Allow only upper case characters to be entered. + -> Act only on modes that add or update characters in the buffer. + IF (sgw.editop=EO_REPLACECHAR) OR (sgw.editop=EO_INSERTCHAR) + -> Code contains the ASCII representation of the character entered, if + -> it maps to a single byte. We could also look into the work buffer to + -> find the new character. + -> + -> sgw.code = sgw.workbuffer[sgw.bufferpos-1] + -> + -> If the character is not a legal hex digit, don't use the work buffer + -> and beep the screen. + -> E-Note: use isxdigit from 'tools/ctype' + IF isxdigit(sgw.code)=FALSE + sgw.actions:=sgw.actions OR SGA_BEEP + sgw.actions:=sgw.actions AND Not(SGA_USE) + ELSE + -> And make it upper-case, for nicety + work_ptr:=sgw.workbuffer + work_ptr[sgw.bufferpos-1]:=toupper(sgw.code) + ENDIF + ENDIF + ELSEIF msg[]=SGH_CLICK + -> Mouse click + -> Zero the digit clicked on + IF sgw.bufferpos < sgw.numchars + work_ptr:=sgw.workbuffer+sgw.bufferpos + work_ptr[]:="0" + ENDIF + ELSE + -> UNKNOWN COMMAND + -> Hook should return zero if the command is not supported + return_code:=0 + ENDIF +ENDPROC return_code + +-> E-Note: we don't need the hookEntry stuff, installhook does it all + +-> Process messages received by the sgg_Window. Quit when the close gadget +-> is selected. +-> E-Note: E version is simpler, since we use WaitIMessage +PROC handleWindow(vars:PTR TO vars) + DEF class + REPEAT + class:=WaitIMessage(vars.sgg_Window) + -> If a code is set in the hook after an SGH_KEY command, where SGA_END is + -> set on return from the hook, the code will be returned in the Code field + -> of the IDCMP_GADGETUP message. + -> E-Note: ...so use MsgCode() to get at it + UNTIL class=IDCMP_CLOSEWINDOW +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/updatestrgad.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/updatestrgad.e new file mode 100644 index 0000000..1aa2fd2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Gadgets/updatestrgad.e @@ -0,0 +1,119 @@ +-> updatestrgad.e - Show the use of a string gadget. Shows both the use of +-> ActivateGadget() and how to properly modify the contents of a string gadget. + +MODULE 'graphics/rastport', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_KICK, ERR_WIN + +RAISE ERR_WIN IF OpenWindowTagList()=NIL + +-> NOTE that the use of constant size and positioning values are not +-> recommended; it just makes it easy to show what is going on. The position +-> of the gadget should be dynamically adjusted depending on the height of the +-> font in the title bar of the window. This example adapts the gadget height +-> to the screen font. Alternatively, you could specify your font under V37 +-> with the StringExtend structure. +CONST BUFSIZE=100, MYSTRGADWIDTH=200, MYSTRGADHEIGHT=8 + +DEF strBuffer[BUFSIZE]:STRING, strUndoBuffer[BUFSIZE]:STRING, + strGad:PTR TO gadget, ansnum=0, answers:PTR TO LONG + +-> Show the use of a string gadget. +PROC main() HANDLE + DEF win=NIL:PTR TO window + -> Make sure to get version 37, for OpenWindowTags() + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + -> Load a value into the string gadget buffer. + -> This will be displayed when the gadget is first created. + StrCopy(strBuffer, 'START') + + -> E-Note: set-up the two globals... + answers:=['Try Again','Sorry','Perhaps','A Winner'] + strGad:=[NIL, 20, 20, MYSTRGADWIDTH, MYSTRGADHEIGHT, + GFLG_GADGHCOMP, GACT_RELVERIFY OR GACT_STRINGCENTER, + GTYP_STRGADGET, + [-2, -2, 1, 0, RP_JAM1, 5, + [0, 0, + MYSTRGADWIDTH + 3, 0, + MYSTRGADWIDTH + 3, MYSTRGADHEIGHT + 3, + 0, MYSTRGADHEIGHT + 3, + 0, 0]:INT, + NIL]:border, + NIL, NIL, 0, + -> E-Note: use NEW so remaining fields are allocated (and set to 0) + NEW [strBuffer, strUndoBuffer, 0, BUFSIZE]:stringinfo, + 0, NIL]:gadget + + win:=OpenWindowTagList(NIL, + [WA_WIDTH, 400, + WA_HEIGHT, 100, + WA_TITLE, 'Activate Window, Enter Text', + WA_GADGETS, strGad, + WA_CLOSEGADGET, TRUE, + WA_IDCMP, IDCMP_ACTIVEWINDOW OR + IDCMP_CLOSEWINDOW OR IDCMP_GADGETUP, + NIL]) + + handleWindow(win, strGad) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF win THEN CloseWindow(win) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC + +-> Process messages received by the window. Quit when the close gadget +-> is selected, activate the gadget when the window becomes active. +-> E-Note: E version is simpler, since we use WaitIMessage +PROC handleWindow(win, gad) + DEF class + REPEAT + class:=WaitIMessage(win) + SELECT class + CASE IDCMP_ACTIVEWINDOW + -> Activate the string gadget. This is how to activate a string gadget + -> in a new window--wait for the window to become active by waiting for + -> the IDCMP_ACTIVEWINDOW event, then activate the gadget. Here we + -> report on the success or failure. + IF ActivateGadget(gad, win, NIL) + updateStrGad(win, gad, 'Activated') + ENDIF + CASE IDCMP_GADGETUP + -> If it's a gadget message, IAddress points to Gadget. If user hit + -> RETURN in our string gadget for demonstration, we will change what he + -> entered. We only have 1 gadget, so we don't have to check which one. + updateStrGad(win, strGad, answers[ansnum]) + INC ansnum -> Point to next answer + -> E-Note: we know the lengths of lists, so no need for ANSCNT + IF ansnum>=ListLen(answers) THEN ansnum:=0 + ENDSELECT + UNTIL class=IDCMP_CLOSEWINDOW +ENDPROC + +-> Routine to update the value in the string gadget's buffer, then activate +-> the gadget. +PROC updateStrGad(win, gad:PTR TO gadget, newstr) + -> First, remove the gadget from the window. This must be done before + -> modifying any part of the gadget!!! + RemoveGList(win, gad, 1) + + -> For fun, change the value in the buffer, as well as the cursor and initial + -> display position. + StrCopy(gad.specialinfo::stringinfo.buffer, newstr) + gad.specialinfo::stringinfo.bufferpos:=0 + gad.specialinfo::stringinfo.disppos:=0 + + -> Add the gadget back, placing it at the end of the list (-1) and refresh + -> its imagery. + AddGList(win, gad, -1, 1, NIL) + RefreshGList(gad, win, NIL, 1) + + -> Activate the string gadget + ActivateGadget(gad, win, NIL) +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/closewindowsafely.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/closewindowsafely.e new file mode 100644 index 0000000..2d68834 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/closewindowsafely.e @@ -0,0 +1,58 @@ +-> closeWindowSafely +-> +-> These functions close an Intuition window that shares a port with other +-> Intuition windows. +-> +-> We are careful to set the UserPort to NIL before closing, and to free any +-> messages that it might have been sent. + +OPT MODULE -> E-Note: create a module for re-use + +MODULE 'exec/lists', + 'exec/nodes', + 'exec/ports', + 'intuition/intuition' + +-> Function to remove and reply all IntuiMessages on a port that have been +-> sent to a particular window (note that we don't rely on the succ pointer +-> of a message after we have replied it) +PROC stripIntuiMessages(mp:PTR TO mp, win) + DEF msg:PTR TO intuimessage, succ + msg:=mp.msglist.head + WHILE succ:=msg.execmessage.ln.succ + IF msg.idcmpwindow=win + -> Intuition is about to free this message. + -> Make sure that we have politely sent it back. + Remove(msg) + ReplyMsg(msg) + ENDIF + msg:=succ + ENDWHILE +ENDPROC + +-> Entry point to closeWindowSafely(). +-> Strip all IntuiMessages from an IDCMP which are waiting for a specific +-> window. When the messages are gone, set the UserPort of the window to NIL +-> and call ModifyIDCMP(win,0). This will free the Intuition parts of the IDCMP +-> and turn off messages to this port without changing the original UserPort +-> (which may be in use by other windows). +-> E-Note: this is the function we want to export from the module +EXPORT PROC closeWindowSafely(win:PTR TO window) + -> We forbid here to keep out of race conditions with Intuition + Forbid() + + -> Send back any messages for this window that have not yet been processed + stripIntuiMessages(win.userport, win) + + -> Clear UserPort so Intuition will not free it + win.userport:=NIL + + -> Tell Intuition to stop sending more messages + ModifyIDCMP(win, 0) + + -> Turn multitasking back on + Permit() + + -> Now it's safe to really close the window + CloseWindow(win) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/closewindowsafely.m b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/IO_Methods/closewindowsafely.m new file mode 100644 index 0000000000000000000000000000000000000000..a3d3155992b90eda7cc1f9b0a837a105bd0e60dd GIT binary patch literal 258 zcmZ?u^><-lWq^VSFa{@>!3-pI{X+l$P{?KAaeTobq9CB{@c)lO?*BiI7aT8uc|W`w z(is>`Kw=6S3_2UuGH|3ZFi0r@`8qlOZ}_eI&w^n8YtzpC|KtCk1cv{63K;xi{Yw2p z85p4IYJj$I0L=)~XVBMW;7DZn-{$|Gfun!{B(CVd5C) eventloop.e - standard technique to handle IntuiMessages from an IDCMP. + +MODULE 'exec/ports', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_WIN + +RAISE ERR_WIN IF OpenWindowTagList()=NIL + +PROC main() HANDLE + DEF signals, done, win=NIL:PTR TO window + win:=OpenWindowTagList(NIL, + [WA_TITLE, 'Press Keys and Mouse in this Window', + WA_WIDTH, 500, + WA_HEIGHT, 50, + WA_ACTIVATE, TRUE, + WA_CLOSEGADGET, TRUE, + WA_RMBTRAP, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_VANILLAKEY OR + IDCMP_RAWKEY OR IDCMP_DISKINSERTED OR + IDCMP_DISKREMOVED OR IDCMP_MOUSEBUTTONS, + NIL]) + + -> Perform this loop until the message handling routine signals that we + -> are done. + -> + -> When the Wait() returns, check which signal hit and process the correct + -> port. There is only one port here, so the test could be eliminated. If + -> multiple ports were being watched, the test would become: + -> + -> signals:=Wait(Shl(1, win1.userport.sigbit) OR + -> Shl(1, win2.userport.sigbit) OR + -> Shl(1, win3.userport.sigbit)) + -> IF signals AND Shl(1, win1.userport.sigbit) + -> done:=handleWin1IDCMP(win1, done) + -> ELSEIF signals AND Shl(1, win2.userport.sigbit) + -> done:=handleWin2IDCMP(win2, done) + -> ELSEIF signals AND Shl(1, win3.userport.sigbit) + -> done:=handleWin3IDCMP(win3, done) + -> ENDIF + -> + -> Note that these could all call the same routine with different window + -> pointers (if the handling was identical). + -> + -> handleIDCMP() should remove all of the messages from the port. + -> E-Note: since this example should be generalisable to more than one + -> window, WaitIMessage is not used (for a change!) + done:=FALSE + REPEAT + signals:=Wait(Shl(1, win.userport.sigbit)) + IF signals AND Shl(1, win.userport.sigbit) + done:=handleIDCMP(win, done) + ENDIF + UNTIL done + +EXCEPT DO + IF win THEN CloseWindow(win) + SELECT exception + CASE ERR_WIN; WriteF('Error: Failed to open window.\n') + ENDSELECT +ENDPROC + +-> handleIDCMP() - Handle all of the messages from an IDCMP. +PROC handleIDCMP(win:PTR TO window, done) + DEF message:PTR TO intuimessage, code, mousex, mousey, class + + -> Remove all of the messages from the port by calling GetMsg() until + -> it returns NULL. + -> + -> The code should be able to handle three cases: + -> + -> 1. No messages waiting at the port, and the first call to GetMsg() + -> returns NULL. In this case the code should do nothing. + -> + -> 2. A single message waiting. The code should remove the message, + -> processes it, and finish. + -> + -> 3. Multiple messages waiting. The code should process each waiting + -> message, and finish. + WHILE message:=GetMsg(win.userport) + -> It is often convenient to copy the data out of the message. In many + -> cases, this lets the application reply to the message quickly. Copying + -> the data is not required, if the code does not reply to the message + -> until the end of the loop, then it may directly reference the message + -> information anywhere before the reply. + class:=message.class + code:=message.code + mousex:=message.mousex + mousey:=message.mousey + + -> The loop should reply as soon as possible. Note that the code may not + -> reference data in the message after replying to the message. Thus, the + -> application should not reply to the message until it is done referencing + -> information in it. + -> + -> Be sure to reply to every message received with GetMsg(). + ReplyMsg(message) + + -> The class contains the IDCMP type of the message. + SELECT class + CASE IDCMP_CLOSEWINDOW + done:=TRUE + CASE IDCMP_VANILLAKEY + WriteF('IDCMP_VANILLAKEY (\c)\n', code) + CASE IDCMP_RAWKEY + WriteF('IDCMP_RAWKEY\n') + CASE IDCMP_DISKINSERTED + WriteF('IDCMP_DISKINSERTED\n') + CASE IDCMP_DISKREMOVED + WriteF('IDCMP_DISKREMOVED\n') + CASE IDCMP_MOUSEBUTTONS + -> The code often contains useful data, such as the ASCII value (for + -> IDCMP_VANILLAKEY), or the type of button event here. + SELECT code + CASE SELECTUP + WriteF('SELECTUP at \d,\d\n', mousex, mousey) + CASE SELECTDOWN + WriteF('SELECTDOWN at \d,\d\n', mousex, mousey) + CASE MENUUP + WriteF('MENUUP\n') + CASE MENUDOWN + WriteF('MENUDOWN\n') + DEFAULT + WriteF('UNKNOWN CODE\n') + ENDSELECT + DEFAULT + WriteF('Unknown IDCMP message\n') + ENDSELECT + ENDWHILE +ENDPROC done diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/compleximage.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/compleximage.e new file mode 100644 index 0000000..2427de5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/compleximage.e @@ -0,0 +1,83 @@ +-> compleximage.e - Program to show the use of a complex Intuition Image. + +OPT OSVERSION=37 -> E-Note: silently require V37 + +MODULE 'exec/memory', + 'intuition/intuition', + 'intuition/screens' + +ENUM ERR_NONE, ERR_SCRN, ERR_WIN + +RAISE ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST MYIMAGE_LEFT=0, MYIMAGE_TOP=0, + MYIMAGE_WIDTH=24, MYIMAGE_HEIGHT=10, + MYIMAGE_DEPTH=2 + +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem + +-> Main routine. Open required window and draw the images. This routine opens +-> a very simple window with no IDCMP. See the chapters on "Windows" and +-> "Input and Output Methods" for more info. Free all resources when done. +PROC main() HANDLE + DEF scr=NIL, win=NIL:PTR TO window, myImage:image + scr:=OpenScreenTagList(NIL, [SA_DEPTH, 4, SA_PENS, [-1]:INT, NIL]) + win:=OpenWindowTagList(NIL, [WA_RMBTRAP, TRUE, WA_CUSTOMSCREEN, scr, NIL]) + + -> This contains the image data. It is a two bit-plane open rectangle which + -> is 24 pixels wide and 10 high. Make sure it's in CHIP memory by allocating + -> a block of chip memory with a call like this: NewM(data_size,MEMF_CHIP), + -> and then copy the data to that block. + myImage:=[MYIMAGE_LEFT, MYIMAGE_TOP, MYIMAGE_WIDTH, + MYIMAGE_HEIGHT, MYIMAGE_DEPTH, + copyListToChip([ -> First bit-plane of data, open rectangle + $FFFFFF00, $C0000300, $C0000300, $C0000300, + $C0000300, $C0000300, $C0000300, $C0000300, + $C0000300, $FFFFFF00, + -> Second bit-plane of data, filled rectangle + $00000000, $00000000, $00000000, $00FF0000, + $00FF0000, $00FF0000, $00FF0000, $00000000, + $00000000, $00000000]), + 3, 0, NIL]:image -> Use first two bit-planes, clear unused planes + + -> Draw the 1 bit-plane image into the first two bit-planes + DrawImage(win.rport, myImage, 10, 10) + + -> Draw the same image at a new location + DrawImage(win.rport, myImage, 100, 10) + + -> Change the image to use the second and fourth bitplanes, PlanePick is 1010 + -> binary or $0A, and draw it again at a different location + myImage.planepick:=$0A + DrawImage(win.rport, myImage, 10, 50) + + -> Now set all the bits in the first bitplane with PlaneOnOff. This will + -> make all the bits set in the second bitplane appear as color 3 (0011 + -> binary), all the bits set in the fourth bitplane appear as color 9 (1001 + -> binary) and all other pixels will be color 1 (0001 binary. If there were + -> any points in the image where both bits were set, they would appear as + -> color 11 (1011 binary). Draw the image at a different location. + myImage.planeonoff:=$01 + DrawImage(win.rport, myImage, 100, 50) + + -> Wait a bit, then quit. + -> In a real application, this would be an event loop, like the one described + -> in the Intuition Input and Output Methods chapter. + Delay(200) + +EXCEPT DO + IF win THEN CloseWindow(win) + IF scr THEN CloseScreen(scr) + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen.\n') + CASE ERR_WIN; WriteF('Error: Failed to open window.\n') + CASE "MEM"; WriteF('Error: Ran out of (chip) memory.\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/intuitext.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/intuitext.e new file mode 100644 index 0000000..22d87cb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/intuitext.e @@ -0,0 +1,64 @@ +-> intuitext.e - Program to show the use of an Intuition IntuiText object. + +OPT OSVERSION=37 -> E-Note: silently require V37 + +MODULE 'exec/ports', + 'exec/nodes', + 'graphics/rastport', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens' + +ENUM ERR_NONE, ERR_DRAW, ERR_PUB, ERR_WIN + +RAISE ERR_DRAW IF GetScreenDrawInfo()=NIL, + ERR_PUB IF LockPubScreen()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST MYTEXT_LEFT=0, MYTEXT_TOP=0 + +-> Main routine. Open required window and draw the images. This routine opens +-> a very simple window with no IDCMP. See the chapters on "Windows" and +-> "Input and Output Methods" for more info. Free all resources when done. +PROC main() HANDLE + DEF screen=NIL, drawinfo=NIL:PTR TO drawinfo, win=NIL:PTR TO window, + myTEXTPEN, myBACKGROUNDPEN + + screen:=LockPubScreen(NIL) + + drawinfo:=GetScreenDrawInfo(screen) + + -> Get a copy of the correct pens for the screen. This is very important in + -> case the user or the application has the pens set in a unusual way. + myTEXTPEN:=drawinfo.pens[TEXTPEN] + myBACKGROUNDPEN:=drawinfo.pens[BACKGROUNDPEN] + + -> Open a simple window on the workbench screen for displaying a text string. + -> An application would probably never use such a window, but it is useful + -> for demonstrating graphics... + win:=OpenWindowTagList(NIL, [WA_PUBSCREEN, screen, WA_RMBTRAP, TRUE, NIL]) + + + -> Draw the text string at 10, 10 + PrintIText(win.rport, + [myTEXTPEN, myBACKGROUNDPEN, RP_JAM2, MYTEXT_LEFT, MYTEXT_TOP, + [drawinfo.font.mn.ln.name, drawinfo.font.ysize, + drawinfo.font.style, drawinfo.font.flags]:textattr, + 'Hello, World. ;-)', NIL]:intuitext, + 10, 10) + + -> Wait a bit, then quit. + -> In a real application, this would be an event loop, like the one described + -> in the Intuition Input and Output Methods chapter. + Delay(200) + +EXCEPT DO + IF win THEN CloseWindow(win) + IF drawinfo THEN FreeScreenDrawInfo(screen, drawinfo) + IF screen THEN UnlockPubScreen(NIL, screen) + SELECT exception + CASE ERR_DRAW; WriteF('Error: Failed to get DrawInfo for screen\n') + CASE ERR_PUB; WriteF('Error: Failed to lock public screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/shadowborder.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/shadowborder.e new file mode 100644 index 0000000..051f559 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/shadowborder.e @@ -0,0 +1,66 @@ +-> shadowborder.e - Program to show the use of an Intuition Border. + +OPT OSVERSION=37 -> E-Note: silently require V37 + +MODULE 'graphics/rastport', + 'intuition/intuition', + 'intuition/screens' + +ENUM ERR_NONE, ERR_DRAW, ERR_PUB, ERR_WIN + +RAISE ERR_DRAW IF GetScreenDrawInfo()=NIL, + ERR_PUB IF LockPubScreen()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST MYBORDER_LEFT=0, MYBORDER_TOP=0 + +-> Main routine. Open required window and draw the images. This routine opens +-> a very simple window with no IDCMP. See the chapters on "Windows" and +-> "Input and Output Methods" for more info. Free all resources when done. +PROC main() HANDLE + DEF screen=NIL, win=NIL:PTR TO window, drawinfo=NIL:PTR TO drawinfo, + shineBorder, shadowBorder, mySHADOWPEN=1, mySHINEPEN=2 + + -> E-Note: C version doesn't think these should cause fatal errors... + screen:=LockPubScreen(NIL) + drawinfo:=GetScreenDrawInfo(screen) + + -> Get a copy of the correct pens for the screen. This is very important in + -> case the user or the application has the pens set in a unusual way. + mySHADOWPEN:=drawinfo.pens[SHADOWPEN] + mySHINEPEN:=drawinfo.pens[SHINEPEN] + + -> Open a simple window on the workbench screen for displaying a border. An + -> application would probably never use such a window, but it is useful for + -> demonstrating graphics... + -> E-Note: C version uses "screen" after unlocking it! + win:=OpenWindowTagList(NIL, [WA_PUBSCREEN, screen, WA_RMBTRAP, TRUE, NIL]) + + shineBorder:=[MYBORDER_LEFT, MYBORDER_TOP, mySHINEPEN, 0, + RP_JAM1, 5, [0,0, 50,0, 50,30, 0,30, 0,0]:INT, + NIL]:border + shadowBorder:=[MYBORDER_LEFT+1, MYBORDER_TOP+1, mySHADOWPEN, 0, + RP_JAM1, 5, [0,0, 50,0, 50,30, 0,30, 0,0]:INT, + shineBorder]:border + + -> Draw the border at 10, 10 + DrawBorder(win.rport, shadowBorder, 10, 10) + + -> Draw the border again at 100, 10 + DrawBorder(win.rport, shadowBorder, 100, 10) + + -> Wait a bit, then quit. + -> In a real application, this would be an event loop, like the one described + -> in the Intuition Input and Output Methods chapter. + Delay(200) + +EXCEPT DO + IF win THEN CloseWindow(win) + IF drawinfo THEN FreeScreenDrawInfo(screen, drawinfo) + IF screen THEN UnlockPubScreen(NIL, screen) + SELECT exception + CASE ERR_DRAW; WriteF('Error: Failed to get DrawInfo for screen\n') + CASE ERR_PUB; WriteF('Error: Failed to lock public screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/simpleimage.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/simpleimage.e new file mode 100644 index 0000000..2703d1b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Images_Text/simpleimage.e @@ -0,0 +1,62 @@ +-> simpleimage.e - Program to show the use of a simple Intuition Image. + +OPT OSVERSION=37 -> E-Note: silently require V37 + +MODULE 'exec/memory', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_WIN + +RAISE ERR_WIN IF OpenWindowTagList()=NIL + +CONST MYIMAGE_LEFT=0, MYIMAGE_TOP=0, + MYIMAGE_WIDTH=24, MYIMAGE_HEIGHT=10, + MYIMAGE_DEPTH=1 + +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem + +-> Main routine. Open required window and draw the images. This routine opens +-> a very simple window with no IDCMP. See the chapters on "Windows" and +-> "Input and Output Methods" for more info. Free all resources when done. +PROC main() HANDLE + DEF win=NIL:PTR TO window, myImage:image + win:=OpenWindowTagList(NIL, [WA_WIDTH, 200, + WA_HEIGHT, 100, + WA_RMBTRAP, TRUE, + NIL]) + + -> This contains the image data. It is a one bit-plane open rectangle which + -> is 24 pixels wide and 10 high. Make sure it's in CHIP memory by allocating + -> a block of chip memory with a call like this: NewM(data_size,MEMF_CHIP), + -> and then copy the data to that block. + myImage:=[MYIMAGE_LEFT, MYIMAGE_TOP, MYIMAGE_WIDTH, + MYIMAGE_HEIGHT, MYIMAGE_DEPTH, + copyListToChip([$FFFFFF00, $C0000300, $C0000300, $C0000300, + $C0000300, $C0000300, $C0000300, $C0000300, + $C0000300, $FFFFFF00]), + 1, 0, NIL]:image -> Use first bit-plane, clear unused planes + + -> Draw the 1 bit-plane image into the first bit-plane (colour 1) + DrawImage(win.rport, myImage, 10, 10) + + -> Draw the same image at a new location + DrawImage(win.rport, myImage, 100, 10) + + -> Wait a bit, then quit. + -> In a real application, this would be an event loop, like the one described + -> in the Intuition Input and Output Methods chapter. + Delay(200) + +EXCEPT DO + IF win THEN CloseWindow(win) + SELECT exception + CASE ERR_WIN; WriteF('Error: Failed to open window.\n') + CASE "MEM"; WriteF('Error: Ran out of (chip) memory.\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition.e new file mode 100644 index 0000000..09a813f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition.e @@ -0,0 +1,110 @@ +-> easyintuition.e Simple backward-compatible V37 Intuition example +-> +-> This example uses extended structures with the pre-V37 OpenScreen() and +-> OpenWindow() functions to compatibly open an Intuition display. Enhanced +-> V37 options specified via tags are ignored on 1.3 systems. + +-> E-Note: you need to be more specific about modules than C does about includes +MODULE 'intuition/intuition', -> Intuition and window data structures and tags + 'intuition/screens', -> Screen data structures and tags + 'graphics/view', -> Screen resolutions + 'dos/dos' -> Official return codes defined here + +-> Position and sizes for our window +CONST WIN_LEFTEDGE=20, WIN_TOPEDGE=20, + WIN_WIDTH=400, WIN_MINWIDTH=80, + WIN_HEIGHT=150, WIN_MINHEIGHT=20 + +-> Exception values +-> E-Note: exceptions are a much better way of handling errors +ENUM ERR_NONE, ERR_SCRN, ERR_WIN + +-> Automatically raise exceptions +-> E-Note: these take care of a lot of error cases +RAISE ERR_SCRN IF OpenS()=NIL, + ERR_WIN IF OpenW()=NIL + +PROC main() HANDLE + -> Declare variables here + -> E-Note: the signals stuff is handled directly by WaitIMessage + DEF screen1=NIL:PTR TO screen, window1=NIL:PTR TO window + + -> E-Note: E automatically opens the Intuition library + + -> Open the screen + -> E-Note: automatically error-checked (automatic exception) + -> E-Note: simplified using OpenS + screen1:=OpenS(640, -> Width (high-resolution) + STDSCREENHEIGHT, -> Height (non-interlace) + 2, -> Depth (4 colours will be available) + V_HIRES, -> The high-resolution display mode + 'Our Screen', -> The screen title + -> We can specify that we want the V37-compatible 3D look when running under + -> V37 by adding an SA_PENS tag. + [SA_PENS, [-1]:INT, -> Tags for additional V37 features + -> E-Note: these tags replace the missing OpenS parameters + SA_DETAILPEN, 0, + SA_BLOCKPEN, 1, + NIL]) + + -> E-Note: we attach the window to the open screen directly, below + + -> ... and open the window + -> E-Note: automatically error-checked (automatic exception) + window1:=OpenW(WIN_LEFTEDGE, + WIN_TOPEDGE, + WIN_WIDTH, + WIN_HEIGHT, + + -> This field specifies the events we want to get + IDCMP_CLOSEWINDOW, + + -> These flags specify system gadgets and other attributes + WFLG_CLOSEGADGET OR WFLG_SMART_REFRESH OR WFLG_ACTIVATE OR + WFLG_DRAGBAR OR WFLG_DEPTHGADGET OR WFLG_SIZEGADGET OR + WFLG_NOCAREREFRESH, + + 'EasyWindow', -> Window title + screen1, -> Attach to screen1... + CUSTOMSCREEN, -> ... a custom screen + NIL, -> Pointer to first gadget + -> Under V37, we'll get a special screen title when our window is active + -> Tags for additional V37 features + [WA_SCREENTITLE, 'Our Screen - EasyWindow is Active', + -> E-Note: these tags replace the missing OpenW parameters + WA_MINWIDTH, WIN_MINWIDTH, + WA_MINHEIGHT, WIN_MINHEIGHT, + WA_MAXWIDTH, -1, + WA_MAXHEIGHT, -1, + NIL]) + + -> Here's the main input event loop + -> E-Note: the signals and stuff is handled by WaitIMessage + REPEAT + UNTIL handleIDCMP(window1) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF window1 THEN CloseW(window1) + IF screen1 THEN CloseS(screen1) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +-> E-Note: select return code according to exception +ENDPROC IF exception THEN RETURN_WARN ELSE RETURN_OK + +PROC handleIDCMP(win:PTR TO window) + DEF class, done=FALSE + -> E-Note: WaitIMessage replaces a lot of C code concerned with signals + class:=WaitIMessage(win) + -> E-Note: other parts of the message are available via MsgXXX() functions + + -> See what events occurred + SELECT class + CASE IDCMP_CLOSEWINDOW + done:=TRUE + ENDSELECT +ENDPROC done + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition37.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition37.e new file mode 100644 index 0000000..cb3a665 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Intuition_GUI/easyintuition37.e @@ -0,0 +1,103 @@ +-> easyintuition37.e -- Simple Intuition program for V37 (Release 2) and later +-> versions of the operating system + +-> Use lowest non-obsolete version that supplies the functions needed +OPT OSVERSION=37 + +-> E-Note: you need to be more specific about modules than C does about includes +MODULE 'intuition/intuition', -> Intuition and window data structures and tags + 'intuition/screens', -> Screen data structures and tags + 'graphics/modeid', -> Release 2 Amiga display mode ID's + 'dos/dos' -> Official return codes defined here + +-> Position and sizes for our window +CONST WIN_LEFTEDGE=20, WIN_TOPEDGE=20, + WIN_WIDTH=400, WIN_MINWIDTH=80, + WIN_HEIGHT=150, WIN_MINHEIGHT=20 + +-> Exception values +-> E-Note: exceptions are a much better way of handling errors +ENUM ERR_NONE, ERR_SCRN, ERR_WIN + +-> Automatically raise exceptions +-> E-Note: these take care of a lot of error cases +RAISE ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +PROC main() HANDLE + -> Declare variables here + -> E-Note: the signals stuff is handled directly by WaitIMessage + DEF screen1=NIL:PTR TO screen, window1=NIL:PTR TO window + + -> E-Note: E automatically opens the Intuition library + + -> Open the screen + -> E-Note: automatically error-checked (automatic exception) + -> E-Note: pens is just a INT-typed list + screen1:=OpenScreenTagList(NIL, + [SA_PENS, [-1]:INT, + SA_DISPLAYID, HIRES_KEY, + SA_DEPTH, 2, + SA_TITLE, 'Our Screen', + NIL]) + + -> ... and open the window + -> E-Note: automatically error-checked (automatic exception) + window1:=OpenWindowTagList(NIL, + -> Specify window dimensions and limits + [WA_LEFT, WIN_LEFTEDGE, + WA_TOP, WIN_TOPEDGE, + WA_WIDTH, WIN_WIDTH, + WA_HEIGHT, WIN_HEIGHT, + WA_MINWIDTH, WIN_MINWIDTH, + WA_MINHEIGHT, WIN_MINHEIGHT, + WA_MAXWIDTH, -1, + WA_MAXHEIGHT, -1, + -> Specify the system gadgets we want + WA_CLOSEGADGET, TRUE, + WA_SIZEGADGET, TRUE, + WA_DEPTHGADGET, TRUE, + WA_DRAGBAR, TRUE, + -> Specify other attributes + WA_ACTIVATE, TRUE, + WA_NOCAREREFRESH, TRUE, + + -> Specify the events we want to know about + WA_IDCMP, IDCMP_CLOSEWINDOW, + + -> Attach the window to the open screen ... + WA_CUSTOMSCREEN, screen1, + WA_TITLE, 'EasyWindow', + WA_SCREENTITLE,'Our Screen - EasyWindow is Active', + NIL]) + + -> Here's the main input event loop + -> E-Note: the signals and stuff is handled by WaitIMessage + REPEAT + UNTIL handleIDCMP(window1) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF window1 THEN CloseWindow(window1) + IF screen1 THEN CloseScreen(screen1) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +-> E-Note: select return code according to exception +ENDPROC IF exception THEN RETURN_WARN ELSE RETURN_OK + +PROC handleIDCMP(win:PTR TO window) + DEF class, done=FALSE + -> E-Note: WaitIMessage replaces a lot of C code concerned with signals + class:=WaitIMessage(win) + -> E-Note: other parts of the message are available via MsgXXX() functions + + -> See what events occurred + SELECT class + CASE IDCMP_CLOSEWINDOW + done:=TRUE + ENDSELECT +ENDPROC done + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/menulayout.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/menulayout.e new file mode 100644 index 0000000..169a8ce --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/menulayout.e @@ -0,0 +1,460 @@ +-> menulayout.e - Example showing how to do menu layout in general. This +-> example also illustrates handling menu events, including IDCMP_MENUHELP +-> events. +-> +-> Note that handling arbitrary fonts is fairly complex. Applications that +-> require V37 should use the simpler menu layout routines found in the +-> GadTools library. + +OPT PREPROCESS + +MODULE 'dos/dos', + 'graphics/rastport', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens' + +ENUM ERR_NONE, ERR_DRAW, ERR_FONT, ERR_KICK, ERR_MENU, ERR_PUB, ERR_WIN + +RAISE ERR_DRAW IF GetScreenDrawInfo()=NIL, + ERR_FONT IF OpenFont()=NIL, + ERR_MENU IF SetMenuStrip()=FALSE, + ERR_PUB IF LockPubScreen()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +DEF firstMenu + +-> Open all of the required libraries. Note that we require V37, as the +-> routine uses OpenWindowTags(). +PROC main() HANDLE + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + + doWindow() + +EXCEPT DO + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_DRAW; WriteF('Error: Failed to get screen DrawInfo\n') + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + CASE ERR_MENU; WriteF('Error: Failed to attach menu\n') + CASE ERR_PUB; WriteF('Error: Failed to lock public screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT + RETURN IF exception=ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK +ENDPROC + +-> Open a window with some properly positioned text. Layout and set the menus, +-> then process any events received. Cleanup when done. +PROC doWindow() HANDLE + -> E-Note: some of these are global arrays in the C version + DEF settItem, editItem, prtItem, projItem, menus, + winText0:PTR TO intuitext, winText1:PTR TO intuitext, + window=NIL:PTR TO window, screen=NIL:PTR TO screen, + drawinfo=NIL:PTR TO drawinfo, + win_width, alt_width, win_height + + screen:=LockPubScreen(NIL) + drawinfo:=GetScreenDrawInfo(screen) + + -> Window Text for Explanation of Program + -> Get the colors for the window text + -> Use the screen's font for the text + -> E-Note: link directly without an array + winText0:=[drawinfo.pens[TEXTPEN], drawinfo.pens[BACKGROUNDPEN], RP_JAM2, + 0, 0, screen.font, 'How to do a Menu', NIL]:intuitext + winText1:=[drawinfo.pens[TEXTPEN], drawinfo.pens[BACKGROUNDPEN], RP_JAM2, + 0, 0, screen.font, '(with Style)', winText0]:intuitext + + -> Calculate window size + win_width:=100+IntuiTextLength(winText0) + alt_width:=100+IntuiTextLength(winText1) + IF win_width Calculate the correct positions for the text in the window + winText0.leftedge:=Shr(win_width-IntuiTextLength(winText0), 1) + winText0.topedge:=1+screen.wbortop+(2*screen.font.ysize) + winText1.leftedge:=Shr(win_width-IntuiTextLength(winText1), 1) + winText1.topedge:=winText0.topedge+screen.font.ysize + + -> Open the window + window:=OpenWindowTagList(NIL, + [WA_PUBSCREEN, screen, + WA_IDCMP, IDCMP_MENUPICK OR IDCMP_CLOSEWINDOW OR IDCMP_MENUHELP, + WA_FLAGS, WFLG_DRAGBAR OR WFLG_DEPTHGADGET OR WFLG_CLOSEGADGET OR + WFLG_ACTIVATE OR WFLG_NOCAREREFRESH, + WA_LEFT, 10, WA_TOP, screen.barheight+1, + WA_WIDTH, win_width, WA_HEIGHT, win_height, + WA_TITLE, 'Menu Example', WA_MENUHELP, TRUE, + NIL]) + + -> Give a brief explanation of the program + PrintIText(window.rport, winText1, 0, 0) + + -> E-Note: define the menus using (local) typed lists rather than arrays + -> E-Note: link menu items in reverse order to layout + + -> Settings Items + -> 'Eat It Too' (excludes 'Have Your Cake') + settItem:=[NIL, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP OR CHECKIT, 4, + [0, 1, RP_JAM2, CHECKWIDTH, 1, NIL, + ' Eat It Too', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + -> 'Have Your Cake' (initially selected, excludes 'Eat It Too') + settItem:=[settItem, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP OR CHECKIT OR CHECKED, 8, + [0, 1, RP_JAM2, CHECKWIDTH, 1, NIL, + ' Have Your Cake', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + -> 'Auto Save' (toggle-select, initially selected) + settItem:=[settItem, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP OR CHECKIT OR + MENUTOGGLE OR CHECKED, 0, + [0, 1, RP_JAM2, CHECKWIDTH, 1, NIL, + ' Auto Save', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + -> 'Sound...' + settItem:=[settItem, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, + 'Sound...', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + + -> Edit Menu Items + -> 'Undo' (key-equivalent: "Z") + editItem:=[NIL, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Undo', NIL]:intuitext, + NIL, "Z", NIL, MENUNULL]:menuitem + -> 'Erase' (disabled) + editItem:=[editItem, 0, 0, 0, 0, + ITEMTEXT OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Erase', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + -> 'Paste' (key-equivalent: "V") + editItem:=[editItem, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Paste', NIL]:intuitext, + NIL, "V", NIL, MENUNULL]:menuitem + -> 'Copy' (key-equivalent: "C") + editItem:=[editItem, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Copy', NIL]:intuitext, + NIL, "C", NIL, MENUNULL]:menuitem + -> 'Cut' (key-equivalent: "X") + editItem:=[editItem, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Cut', NIL]:intuitext, + NIL, "X", NIL, MENUNULL]:menuitem + + -> Print Sub-Items + -> 'Draft' + prtItem:=[NIL, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Draft', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + -> 'NLQ' + prtItem:=[prtItem, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'NLQ', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + + -> Uses the >> character to indicate a sub-menu item. + -> This is \273 Octal, 0xBB Hex or Alt-0 from the Keyboard. + -> + -> NOTE that standard menus place this character at the right margin of the + -> menu box. This may be done by using a second IntuiText structure for the + -> single character, linking this IntuiText to the first one, and positioning + -> the IntuiText so that the character appears at the right margin. + -> GadTools library will provide the correct behavior. + + -> Project Menu Items + -> 'Quit' (key-equivalent: "Q") + projItem:=[NIL, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Quit', NIL]:intuitext, + NIL, "Q", NIL, MENUNULL]:menuitem + -> 'About...' + projItem:=[projItem, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'About...', NIL]:intuitext, + NIL, NIL, NIL, MENUNULL]:menuitem + -> 'Print' (has sub-menu) + projItem:=[projItem, 0, 0, 0, 0, + ITEMTEXT OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Print »', NIL]:intuitext, + NIL, NIL, prtItem, MENUNULL]:menuitem + -> 'Save As...' (key-equivalent: "A") + projItem:=[projItem, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Save As...', NIL]:intuitext, + NIL, "A", NIL, MENUNULL]:menuitem + -> 'Save' (key-equivalent: "S") + projItem:=[projItem, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Save', NIL]:intuitext, + NIL, "S", NIL, MENUNULL]:menuitem + -> 'Open...' (key-equivalent: "O") + projItem:=[projItem, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'Open...', NIL]:intuitext, + NIL, "O", NIL, MENUNULL]:menuitem + -> 'New' (key-equivalent: "N") + projItem:=[projItem, 0, 0, 0, 0, + ITEMTEXT OR COMMSEQ OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 2, 1, NIL, 'New', NIL]:intuitext, + NIL, "N", NIL, MENUNULL]:menuitem + + -> Menu Titles + -> E-Note: link in reverse order to layout + -> E-Note: use NEW to zero trailing fields + menus:=NEW [NIL, 120, 0, 88, 0, MENUENABLED, 'Settings', settItem]:menu + menus:=NEW [menus, 70, 0, 39, 0, MENUENABLED, 'Edit', editItem]:menu + menus:=NEW [menus, 0, 0, 63, 0, MENUENABLED, 'Project', projItem]:menu + + -> A pointer to the first menu for easy reference + firstMenu:=menus + + -> Adjust the menu to conform to the font (TextAttr) + adjustMenus(menus, window.wscreen.font) + + -> Attach the menu to the window + SetMenuStrip(window, menus) + + REPEAT + UNTIL handleIDCMP(window) + + -> Clean up everything used here + ClearMenuStrip(window) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF window THEN CloseWindow(window) + IF drawinfo THEN FreeScreenDrawInfo(screen, drawinfo) + IF screen THEN UnlockPubScreen(NIL, screen) + -> E-Note: pass on error, or else RETURN_OK if no error + ReThrow() +ENDPROC RETURN_OK + +-> Print out what menu was selected. Properly handle the IDCMP_MENUHELP +-> events. Set done to TRUE if quit is selected. +PROC processMenus(selection, done) + DEF menuNum, itemNum, subNum, item:PTR TO menuitem + + menuNum:=MENUNUM(selection) + itemNum:=ITEMNUM(selection) + subNum:=SUBNUM(selection) + + -> When processing IDCMP_MENUHELP, you are not guaranteed to get a menu item. + IF itemNum<>NOITEM + item:=ItemAddress(firstMenu, selection) + IF item.flags AND CHECKED THEN WriteF('(Checked) ') + ENDIF + + SELECT menuNum + CASE 0 -> Project Menu + SELECT itemNum + CASE NOITEM; WriteF('Project Menu\n') + CASE 0; WriteF('New\n') + CASE 1; WriteF('Open\n') + CASE 2; WriteF('Save\n') + CASE 3; WriteF('Save As\n') + CASE 4; WriteF('Print ') + SELECT subNum + CASE NOSUB; WriteF('Item\n') + CASE 0; WriteF('NLQ\n') + CASE 1; WriteF('Draft\n') + ENDSELECT + CASE 5; WriteF('About\n') + CASE 6; WriteF('Quit\n'); done:=TRUE + ENDSELECT + CASE 1 -> Edit Menu + SELECT itemNum + CASE NOITEM; WriteF('Edit Menu\n') + CASE 0; WriteF('Cut\n') + CASE 1; WriteF('Copy\n') + CASE 2; WriteF('Paste\n') + CASE 3; WriteF('Erase\n') + CASE 4; WriteF('Undo\n') + ENDSELECT + CASE 2 -> Settings Menu + SELECT itemNum + CASE NOITEM; WriteF('Settings Menu\n') + CASE 0; WriteF('Sound\n') + CASE 1; WriteF('Auto Save\n') + CASE 2; WriteF('Have Your Cake\n') + CASE 3; WriteF('Eat It Too\n') + ENDSELECT + CASE NOMENU -> No menu selected, can happen with IDCMP_MENUHELP + WriteF('no menu\n') + ENDSELECT +ENDPROC done + +-> E-Note: used to convert an INT to unsigned +#define UNSIGNED(x) ((x) AND $FFFF) + +-> Handle the IDCMP messages. Set done to TRUE if quit or closewindow is +-> selected. +PROC handleIDCMP(win) + DEF done=FALSE, selection, class, item:PTR TO menuitem + class:=WaitIMessage(win) + SELECT class + CASE IDCMP_CLOSEWINDOW + done:=TRUE + CASE IDCMP_MENUHELP + -> The routine that handles the menus for IDCMP_MENUHELP must be very + -> careful it can receive menu information that is impossible under + -> IDCMP_MENUPICK. For instance, the code value on a IDCMP_MENUHELP may + -> have a valid number for the menu, then NOITEM and NOSUB. IDCMP_MENUPICK + -> would get MENUNULL in this case. IDCMP_MENUHELP never come as + -> multi-select items, and the event terminates the menu processing session. + -> + -> Note that the return value from the processMenus() routine is ignored: + -> the application should not quit if the user selects "help" over the quit + -> menu item. + WriteF('IDCMP_MENUHELP: Help on ') + processMenus(MsgCode(), done) + CASE IDCMP_MENUPICK + -> E-Note: convert message code to an unsigned INT + selection:=UNSIGNED(MsgCode()) + WHILE selection<>MENUNULL + WriteF('IDCMP_MENUPICK: Selected ') + done:=processMenus(selection, done) + item:=ItemAddress(firstMenu, selection) + -> E-Note: convert item.nextselect to an unsigned INT + selection:=UNSIGNED(item.nextselect) + ENDWHILE + ENDSELECT +ENDPROC done + +-> Steps through each item to determine the maximum width of the strip +PROC maxLength(textRPort, first_item, char_size) + DEF maxLength, total_textlen, cur_item:PTR TO menuitem, + itext:PTR TO intuitext, extra_width, maxCommCharWidth, commCharWidth + + extra_width:=char_size -> Used as padding for each item + + -> Find the maximum length of a command character, if any. + -> If found, it will be added to the extra_width field. + maxCommCharWidth:=0 + cur_item:=first_item + WHILE cur_item + IF cur_item.flags AND COMMSEQ + -> E-Note: requires address of the command character + commCharWidth:=TextLength(textRPort, [cur_item.command]:CHAR, 1) + IF commCharWidth>maxCommCharWidth THEN maxCommCharWidth:=commCharWidth + ENDIF + cur_item:=cur_item.nextitem + ENDWHILE + + -> If we found a command sequence, add it to the extra required space. Add + -> space for the Amiga key glyph plus space for the command character. Note + -> this only works for HIRES screens, for LORES, use LOWCOMMWIDTH. + IF maxCommCharWidth>0 THEN extra_width:=extra_width+maxCommCharWidth+COMMWIDTH + + -> Find the maximum length of the menu items, given the extra width + -> calculated above. + maxLength:=0 + cur_item:=first_item + WHILE cur_item + itext:=cur_item.itemfill + total_textlen:=extra_width+itext.leftedge+ + TextLength(textRPort, itext.itext, StrLen(itext.itext)) + + -> Returns the greater of the two + IF total_textlen>maxLength THEN maxLength:=total_textlen + + cur_item:=cur_item.nextitem + ENDWHILE +ENDPROC maxLength + +-> Set all IntuiText in a chain (they are linked through the nexttext field) +-> to the same font. +PROC setITextAttr(first_IText, textAttr) + DEF cur_IText:PTR TO intuitext + cur_IText:=first_IText + WHILE cur_IText + cur_IText.itextfont:=textAttr + cur_IText:=cur_IText.nexttext + ENDWHILE +ENDPROC + +-> Adjust the MenuItems and SubItems +PROC adjustItems(textRPort, first_item, textAttr, char_size, + height, level, left_edge) + DEF item_num, cur_item:PTR TO menuitem, strip_width, subitem_edge + IF first_item=NIL THEN RETURN + + -> The width of this strip is the maximum length of its members. + strip_width:=maxLength(textRPort, first_item, char_size) + + -> Position the items. + cur_item:=first_item + item_num:=0 + WHILE cur_item + cur_item.topedge:=(item_num*height)-level + cur_item.leftedge:=left_edge + cur_item.width:=strip_width + cur_item.height:=height + + -> Place the sub_item 3/4 of the way over on the item + subitem_edge:=strip_width-(strip_width/4) + + setITextAttr(cur_item.itemfill, textAttr) + adjustItems(textRPort, cur_item.subitem, textAttr, char_size, + height, 1, subitem_edge) + + cur_item:=cur_item.nextitem + INC item_num + ENDWHILE +ENDPROC + + +-> The following routines adjust an entire menu system to conform to the +-> specified font's width and height. Allows for Proportional Fonts. This is +-> necessary for a clean look regardless of what the users preference in Fonts +-> may be. Using these routines, you don't need to specify TopEdge, LeftEdge, +-> Width or Height in the MenuItem structures. +-> +-> NOTE that this routine does not work for menus with images, but assumes that +-> all menu items are rendered with IntuiText. +-> +-> This set of routines does NOT check/correct if the menu runs off the screen +-> due to large fonts, too many items, lo-res screen. +PROC adjustMenus(first_menu, textAttr) HANDLE + DEF textrp:PTR TO rastport, cur_menu:PTR TO menu, font=NIL:PTR TO textfont, + start, char_size, height + + -> E-Note: dynamically allocate a zeroed rastport (might raise exception) + NEW textrp + + -> Open the font + font:=OpenFont(textAttr) + SetFont(textrp, font) -> Put font in to temporary RastPort + + char_size:=TextLength(textrp, 'n', 1) -> Get the width of the font + + -> To prevent crowding of the Amiga key when using COMMSEQ, don't allow the + -> items to be less than 8 pixels high. Also, add an extra pixel for + -> inter-line spacing. + height:=1+(IF font.ysize>8 THEN font.ysize ELSE 8) + + start:=2 -> Set Starting Pixel + + -> Step thru the menu structure and adjust it + cur_menu:=first_menu + WHILE cur_menu + cur_menu.leftedge:=start + cur_menu.width:=char_size+ + TextLength(textrp, cur_menu.menuname, + StrLen(cur_menu.menuname)) + adjustItems(textrp, cur_menu.firstitem, textAttr, char_size, height, 0, 0) + start:=start+cur_menu.width+(char_size*2) + cur_menu:=cur_menu.nextmenu + ENDWHILE +EXCEPT DO + IF font THEN CloseFont(font) -> Close the Font + -> E-Note: as C version ignores font error we'll ignore any NEW error... + RETURN exception=ERR_NONE +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/simplemenu.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/simplemenu.e new file mode 100644 index 0000000..71456d1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Menus/simplemenu.e @@ -0,0 +1,139 @@ +-> simplemenu.e: How to use the menu system with a window under all OS versions. + +OPT PREPROCESS + +MODULE 'graphics/rastport', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens' + +-> These values are based on the ROM font Topaz8. Adjust these values to +-> correctly handle the screen's current font. +CONST MENWIDTH=56+8, -> Longest menu item name * font width + 8 pixels for trim + MENHEIGHT=10 -> Font height + 2 pixels + +-> We only use a single menu, but the code is generalisable to more than +-> one menu. +CONST NUM_MENUS=1 + +ENUM ERR_NONE, ERR_WIN, ERR_MENU + +RAISE ERR_WIN IF OpenWindow()=NIL, + ERR_MENU IF SetMenuStrip()=FALSE -> E-Note: not really necessary... + +PROC main() HANDLE + -> E-Note: some of these are global arrays in the C version + DEF topaz80, submenu1, menu1, menutitle, menustrip:PTR TO menu, + win=NIL:PTR TO window, left=2 + + win:=OpenWindow([40, 40, 300, 100, 0, 1, IDCMP_CLOSEWINDOW OR IDCMP_MENUPICK, + WFLG_DRAGBAR OR WFLG_ACTIVATE OR WFLG_CLOSEGADGET, NIL, NIL, + 'Menu Test Window', NIL, NIL, 0, 0, 0, 0, WBENCHSCREEN]:nw) + + -> To keep this example simple, we'll hard-code the font used for menu items. + -> Algorithmic layout can be used to handle arbitrary fonts. Under Release 2, + -> GadTools provides font-sensitive menu layout. Note that we still must + -> handle fonts for the menu headers. + topaz80:=['topaz.font', 8, 0, 0]:textattr + + -> E-Note: linking needs to be done in reverse order to layout + -> Sub-item 1, NLQ + submenu1:=[NIL, MENWIDTH-2, MENHEIGHT-2, MENWIDTH, MENHEIGHT, + ITEMTEXT OR MENUTOGGLE OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 0, 1, topaz80, 'NLQ', NIL]:intuitext, + NIL, NIL, NIL, NIL]:menuitem + -> Sub-item 0, Draft + submenu1:=[submenu1, MENWIDTH-2, -2, MENWIDTH, MENHEIGHT, + ITEMTEXT OR MENUTOGGLE OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 0, 1, topaz80, 'Draft', NIL]:intuitext, + NIL, NIL, NIL, NIL]:menuitem + + -> E-Note: linking needs to be done in reverse order to layout + -> Item 3, Quit + menu1:=[NIL, 0, 3*MENHEIGHT, MENWIDTH, MENHEIGHT, + ITEMTEXT OR MENUTOGGLE OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 0, 1, topaz80, 'Quit', NIL]:intuitext, + NIL, NIL, NIL, NIL]:menuitem + -> Item 2, Print + menu1:=[menu1, 0, 2*MENHEIGHT, MENWIDTH, MENHEIGHT, + ITEMTEXT OR MENUTOGGLE OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 0, 1, topaz80, 'Print »', NIL]:intuitext, + NIL, NIL, submenu1, NIL]:menuitem + -> Item 1, Save + menu1:=[menu1, 0, MENHEIGHT, MENWIDTH, MENHEIGHT, + ITEMTEXT OR MENUTOGGLE OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 0, 1, topaz80, 'Save', NIL]:intuitext, + NIL, NIL, NIL, NIL]:menuitem + -> Item 0, Open... + menu1:=[menu1, 0, 0, MENWIDTH, MENHEIGHT, + ITEMTEXT OR MENUTOGGLE OR ITEMENABLED OR HIGHCOMP, 0, + [0, 1, RP_JAM2, 0, 1, topaz80, 'Open...', NIL]:intuitext, + NIL, NIL, NIL, NIL]:menuitem + + menutitle:='Project' + + -> E-Note: use NEW, or remember to initialise last elements to 0 + menustrip:=[NIL, left, 0, + TextLength(win.wscreen.rastport, menutitle, StrLen(menutitle))+8, + MENHEIGHT, MENUENABLED, menutitle, menu1, 0, 0, 0, 0]:menu + + left:=left+menustrip.width + + SetMenuStrip(win, menustrip) + + handleWindow(win, menustrip) + + ClearMenuStrip(win) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF win THEN CloseWindow(win) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE ERR_MENU; WriteF('Error: Failed to attach menu\n') + ENDSELECT +ENDPROC + +-> E-Note: used to convert an INT to unsigned +#define UNSIGNED(x) ((x) AND $FFFF) + +-> Wait for the user to select the close gadget. +-> E-Note: E version is simpler, since we use WaitIMessage +PROC handleWindow(win, menuStrip) + DEF done=FALSE, class, menuNumber, menuNum, itemNum, subNum, + item:PTR TO menuitem + REPEAT + class:=WaitIMessage(win) + SELECT class + CASE IDCMP_CLOSEWINDOW + done:=TRUE + CASE IDCMP_MENUPICK + -> E-Note: menuNumber is an unsigned INT + menuNumber:=UNSIGNED(MsgCode()) + WHILE (menuNumber<>MENUNULL) AND (done=FALSE) + item:=ItemAddress(menuStrip, menuNumber) + + -> Process this item + -> If there were no sub-items attached to that item, + -> SubNumber will equal NOSUB. + menuNum:=MENUNUM(menuNumber) + itemNum:=ITEMNUM(menuNumber) + subNum:=SUBNUM(menuNumber) + + -> Note that we are printing all values, even things like NOMENU, + -> NOITEM and NOSUB. An application should check for these cases. + WriteF('IDCMP_MENUPICK: menu \d, item \d, sub \d\n', + menuNum, itemNum, subNum) + + -> This one is the quit menu selection... + -> stop if we get it, and don't process any more. + -> E-Note: the C version is wrong! QUIT is itemNum = 3 + IF (menuNum=0) AND (itemNum=3) THEN done:=TRUE + + -> E-Note: menuNumber is an unsigned INT + menuNumber:=UNSIGNED(item.nextselect) + ENDWHILE + ENDSELECT + UNTIL done +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/custompointer.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/custompointer.e new file mode 100644 index 0000000..27b99e6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/custompointer.e @@ -0,0 +1,66 @@ +-> custompointer.c - Show the use of a custom busy pointer, as well as using a +-> requester to block input to a window. + +OPT OSVERSION=37 -> E-Note: silently require V37 + +MODULE 'exec/memory', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_WIN + +RAISE ERR_WIN IF OpenWindowTagList()=NIL + +PROC main() HANDLE + DEF win=NIL, null_request:requester, waitPointer + + -> The window is opened as active (WA_ACTIVATE) so that the busy pointer will + -> be visible. If the window was not active, the user would have to activate + -> it to see the change in the pointer. + win:=OpenWindowTagList(NIL, [WA_ACTIVATE, TRUE, NIL]) + + -> E-Note: the data is really a lot of LONGs (and in Chip memory!) + waitPointer:=copyListToChip([$00000000, -> Reserved, must be NIL + $040007C0, $000007C0, $01000380, $000007E0, + $07C01FF8, $1FF03FEC, $3FF87FDE, $3FF87FBE, + $7FFCFF7F, $7EFCFFFF, $7FFCFFFF, $3FF87FFE, + $3FF87FFE, $1FF03FFC, $07C01FF8, $000007E0, + $00000000 -> Reserved, must be NIL + ]) + + -> A NULL requester can be used to block input in a window without any + -> imagery provided. + InitRequester(null_request) + + Delay(50) -> Simulate activity in the program + + -> Put up the requester to block user input in the window, and set the + -> pointer to the busy pointer. + IF Request(null_request, win) + SetPointer(win, waitPointer, 16, 16, -6, 0) + + Delay(100) -> Simulate activity in the program + + -> Clear the pointer (which resets the window to the default pointer) and + -> remove the requester. + ClearPointer(win) + EndRequest(null_request, win) + ENDIF + + Delay(100) -> Simulate activity in the program + +EXCEPT DO + IF win THEN CloseWindow(win) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE "MEM"; WriteF('Error: Ran out of (chip) memory\n') + ENDSELECT +ENDPROC + +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/mousetest.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/mousetest.e new file mode 100644 index 0000000..5ccd543 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/mousetest.e @@ -0,0 +1,174 @@ +-> mousetest.e - Read position and button events from the mouse. + +OPT OSVERSION=37 + +MODULE 'devices/inputevent', + 'exec/ports', + 'graphics/gfxbase', + 'graphics/rastport', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens' + +ENUM ERR_NONE, ERR_DRAW, ERR_PUB, ERR_WIN + +RAISE ERR_DRAW IF GetScreenDrawInfo()=NIL, + ERR_PUB IF LockPubScreen()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +-> E-Note: C version should use this for a string... +CONST BUFSIZE=15 + +-> Something to use to track the time between messages to test for +-> double-clicks. +OBJECT myTimeVal + leftSeconds, leftMicros + rightSeconds, rightMicros +ENDOBJECT + +PROC main() HANDLE + DEF win=NIL:PTR TO window, scr=NIL:PTR TO screen, + dr_info=NIL:PTR TO drawinfo, width, gfx:PTR TO gfxbase + + -> Lock the default public screen in order to read its DrawInfo data + scr:=LockPubScreen(NIL) + + dr_info:=GetScreenDrawInfo(scr) + + -> Use wider of space needed for output (18 chars and spaces) or titlebar + -> text plus room for titlebar gads (approx 18 each) + -> E-Note: get the right type for gfxbase + gfx:=gfxbase + width:=Max(gfx.defaultfont.xsize * 18, + (18*2)+TextLength(scr.rastport, 'MouseTest', STRLEN)) + + win:=OpenWindowTagList(NIL, + [WA_TOP, 20, + WA_LEFT, 100, + WA_INNERWIDTH, width, + WA_HEIGHT, (2*gfx.defaultfont.ysize)+ + scr.wbortop+scr.font.ysize+1+scr.wborbottom, + WA_FLAGS, WFLG_DEPTHGADGET OR WFLG_CLOSEGADGET OR + WFLG_ACTIVATE OR WFLG_REPORTMOUSE OR + WFLG_RMBTRAP OR WFLG_DRAGBAR, + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_RAWKEY OR + IDCMP_MOUSEMOVE OR IDCMP_MOUSEBUTTONS, + WA_TITLE, 'MouseTest', + WA_PUBSCREEN, scr, + NIL]) + + WriteF('Monitors the Mouse:\n') + WriteF(' Move Mouse, Click and DoubleClick in Windows\n') + + SetAPen(win.rport, dr_info.pens[TEXTPEN]) + SetBPen(win.rport, dr_info.pens[BACKGROUNDPEN]) + SetDrMd(win.rport, RP_JAM2) + + process_window(win) + +EXCEPT DO + IF win THEN CloseWindow(win) + IF dr_info THEN FreeScreenDrawInfo(scr, dr_info) + IF scr THEN UnlockPubScreen(NIL, scr) + SELECT exception + CASE ERR_DRAW; WriteF('Error: Failed to get DrawInfo for screen\n') + CASE ERR_PUB; WriteF('Error: Failed to lock public screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +ENDPROC + +-> process_window() - Simple message loop for processing IntuiMessages +PROC process_window(win:PTR TO window) + -> E-Note: C version failed to use BUFSIZE! + DEF going, msg:PTR TO intuimessage, class, tv, prt_buff[BUFSIZE]:STRING, + xText, yText -> Places to position text in window + + -> E-Note: going rather than done saves a lot of Not()-ing + going:=TRUE + tv:=[0, 0, 0, 0]:myTimeVal + xText:=win.borderleft+(win.ifont.xsize*2) + yText:=win.bordertop+3+win.ifont.baseline + + -> E-Note: we can't use WaitIMessage() because we want mousex, mousey + WHILE going + Wait(Shl(1, win.userport.sigbit)) + WHILE going AND (msg:=GetMsg(win.userport)) + class:=msg.class + SELECT class + CASE IDCMP_CLOSEWINDOW + going:=FALSE + + -> NOTE NOTE NOTE: If the mouse queue backs up a lot, Intuition will + -> start dropping MOUSEMOVE messages off the end until the queue is + -> serviced. This may cause the program to lose some of the MOUSEMOVE + -> events at the end of the stream. + -> + -> Look in the window structure if you need the true position of the + -> mouse pointer at any given time. Look in the MOUSEBUTTONS message if + -> you need position when it clicked. An alternate to this processing + -> would be to set a flag that a mousemove event arrived, then print the + -> position of the mouse outside of a "WHILE GetMsg()" loop. This allows + -> a single processing call for many mouse events, which speeds up + -> processing A LOT! Something like: + -> + -> WHILE GetMsg() + -> IF class=IDCMP_MOUSEMOVE THEN mouse_flag:= TRUE + -> ReplyMsg() -> NOTE: copy out all needed fields first ! + -> ENDWHILE + -> IF mouse_flag + -> process_mouse_event() + -> mouse_flag:=FALSE + -> ENDIF + -> + -> You can also use IDCMP_INTUITICKS for slower paced messages (all + -> messages have mouse coordinates.) + CASE IDCMP_MOUSEMOVE + -> Show the current position of the mouse relative to the upper left + -> hand corner of our window + Move(win.rport, xText, yText) + StringF(prt_buff, 'X=\d[5] Y=\d[5]', msg.mousex, msg.mousey) + Text(win.rport, prt_buff, BUFSIZE) + CASE IDCMP_MOUSEBUTTONS + doButtons(msg, tv) + ENDSELECT + ReplyMsg(msg) + ENDWHILE + ENDWHILE +ENDPROC + +-> Show what mouse buttons where pushed +PROC doButtons(msg:PTR TO intuimessage, tv:PTR TO myTimeVal) + DEF code + IF msg.qualifier AND (IEQUALIFIER_LSHIFT OR IEQUALIFIER_RSHIFT) + WriteF('Shift ') + ENDIF + + code:=msg.code + SELECT code + CASE SELECTDOWN + WriteF('Left Button Down at X=\d Y=\d', msg.mousex, msg.mousey) + IF DoubleClick(tv.leftSeconds, tv.leftMicros, msg.seconds, msg.micros) + WriteF(' DoubleClick!') + ELSE + tv.leftSeconds:=msg.seconds + tv.leftMicros:=msg.micros + tv.rightSeconds:=0 + tv.rightMicros:=0 + ENDIF + CASE SELECTUP + WriteF('Left Button Up at X=\d Y=\d', msg.mousex, msg.mousey) + CASE MENUDOWN + WriteF('Right Button Down at X=\d Y=\d', msg.mousex, msg.mousey) + IF DoubleClick(tv.rightSeconds, tv.rightMicros, msg.seconds, msg.micros) + WriteF(' DoubleClick!') + ELSE + tv.leftSeconds:=0 + tv.leftMicros:=0 + tv.rightSeconds:=msg.seconds + tv.rightMicros:=msg.micros + ENDIF + CASE MENUUP + WriteF('Right Button Up at X=\d Y=\d', msg.mousex, msg.mousey) + ENDSELECT + WriteF('\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/rawkey.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/rawkey.e new file mode 100644 index 0000000..0633e51 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Mouse_Keyboard/rawkey.e @@ -0,0 +1,149 @@ +-> rawkey.e - How to correctly convert from RAWKEY to keymapped ASCII + +MODULE 'console', + 'devices/inputevent', + 'devices/timer', + 'exec/io', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_DEV, ERR_WIN + +RAISE ERR_DEV IF OpenDevice()<>0, + ERR_WIN IF OpenWindowTagList()=NIL + +-> A buffer is created for RawKeyConvert() to put its output. BUFSIZE is the +-> size of the buffer in bytes. NOTE that this program starts out with a +-> buffer size of 2. This is only to show how the buffer is automatically +-> increased in size by this example! In an application, start with a much +-> larger buffer and you will probably never have to increase its size. 128 +-> bytes or so should do the trick, but always be able to change the size if +-> required. +CONST BUFSIZE=2 + +PROC main() HANDLE + DEF win=NIL, ioreq:iostd, ievent=NIL:PTR TO inputevent, + buffer=NIL, bufsize=BUFSIZE + -> Open the console device just to do keymapping. (unit -1 means any unit) + OpenDevice('console.device', -1, ioreq, 0) + consoledevice:=ioreq.device + -> Allocate the initial character buffer used by deadKeyConvert() and + -> RawKeyConvert() for returning translated characters. If the characters + -> generated by these routines cannot fit into the buffer, the application + -> must pass a larger buffer. This is done in this code by freeing the old + -> buffer and allocating a new one. + buffer:=NewR(bufsize) + NEW ievent + win:=OpenWindowTagList(NIL, + [WA_WIDTH, 300, + WA_HEIGHT, 50, + WA_FLAGS, WFLG_DEPTHGADGET OR WFLG_CLOSEGADGET OR WFLG_ACTIVATE, + WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_RAWKEY, + WA_TITLE, 'Raw Key Example', + NIL]) + WriteF('Press keyboard keys to see ASCII conversion from rawkey\n') + WriteF('Unprintable characters will be shown as \c\n\n', $7F) + process_window(win, ievent, {buffer}, {bufsize}) + +EXCEPT DO + IF win THEN CloseWindow(win) + -> E-Note: don't need to free any memory -- automatically done + IF consoledevice THEN CloseDevice(ioreq) + SELECT exception + CASE ERR_DEV; WriteF('Error: Failed to open console device.\n') + CASE ERR_WIN; WriteF('Error: Failed to open window.\n') + CASE "MEM"; WriteF('Error: Ran out of memory.\n') + ENDSELECT +ENDPROC + +-> Convert RAWKEYs into VANILLAKEYs, also shows special keys like HELP, Cursor +-> Keys, FKeys, etc. It returns: +-> -1 if not enough room in the buffer, try again with a bigger buffer. +-> otherwise, returns the number of characters placed in the buffer. +PROC deadKeyConvert(kbuffer, kbsize, kmap, ievent:PTR TO inputevent) + ievent.class:=IECLASS_RAWKEY + ievent.code:=MsgCode() + ievent.qualifier:=MsgQualifier() + ievent.eventaddress:=MsgIaddr() + RETURN RawKeyConvert(ievent, kbuffer, kbsize, kmap) +ENDPROC + +-> print_qualifiers() - Print out the values found in the qualifier bits of +-> the message. This will print out all of the qualifier bits set. +PROC print_qualifiers(qual) + WriteF('Qual: ') + IF qual AND IEQUALIFIER_LSHIFT THEN WriteF('LShft, ') + IF qual AND IEQUALIFIER_RSHIFT THEN WriteF('RShft, ') + IF qual AND IEQUALIFIER_CAPSLOCK THEN WriteF('CapLok, ') + IF qual AND IEQUALIFIER_CONTROL THEN WriteF('Ctrl, ') + IF qual AND IEQUALIFIER_LALT THEN WriteF('LAlt, ') + IF qual AND IEQUALIFIER_RALT THEN WriteF('RAlt, ') + IF qual AND IEQUALIFIER_LCOMMAND THEN WriteF('LCmd, ') + IF qual AND IEQUALIFIER_RCOMMAND THEN WriteF('RCmd, ') + IF qual AND IEQUALIFIER_NUMERICPAD THEN WriteF('NumPad, ') + IF qual AND IEQUALIFIER_REPEAT THEN WriteF('Rpt, ') + IF qual AND IEQUALIFIER_INTERRUPT THEN WriteF('Intrpt, ') + IF qual AND IEQUALIFIER_MULTIBROADCAST THEN WriteF('Multi Broadcast, ') + IF qual AND IEQUALIFIER_MIDBUTTON THEN WriteF('MidBtn, ') + IF qual AND IEQUALIFIER_RBUTTON THEN WriteF('RBtn, ') + IF qual AND IEQUALIFIER_LEFTBUTTON THEN WriteF('LBtn, ') + IF qual AND IEQUALIFIER_RELATIVEMOUSE THEN WriteF('RelMouse, ') +ENDPROC + +-> doKeys() - Show what keys were pressed. +PROC doKeys(ievent, buffer:PTR TO LONG, bufsize:PTR TO LONG) HANDLE + DEF char_pos, numchars, realc, c + + -> deadKeyConvert() returns -1 if there was not enough space in the buffer to + -> convert the string. Here, the routine increases the size of the buffer on + -> the fly... Set the return code to FALSE on failure. + numchars:=deadKeyConvert(buffer[], bufsize[]-1, NIL, ievent) + WHILE (numchars=-1) AND buffer[] + -> Conversion failed, buffer too small. Try to double the size of the buffer. + Dispose(buffer[]) + bufsize[]:=bufsize[]*2 + WriteF('Increasing buffer size to \d\n', bufsize[]) + + buffer[]:=NewR(bufsize[]) + numchars:=deadKeyConvert(buffer[], bufsize[]-1, NIL, ievent) + ENDWHILE + + -> numchars contains the number of characters placed within the buffer. Key + -> up events and key sequences that do not generate any data for the program + -> (like deadkeys) will return zero. Special keys (like HELP, the cursor + -> keys, FKeys, etc.) return multiple characters that have to then be parsed + -> by the application. + + -> If high bit set, then this is a key up otherwise this is a key down + IF MsgCode() AND $80 + WriteF('Key Up: ') + ELSE + WriteF('Key Down: ') + ENDIF + + print_qualifiers(MsgQualifier()) + WriteF(' rawkey #\d maps to \d ASCII character\s\n', + $7F AND MsgCode(), numchars, IF numchars<>1 THEN 's' ELSE '') + FOR char_pos:=0 TO numchars-1 + realc:=(c:=buffer[][char_pos]) + IF (c<=$1F) OR ((c>=$80) AND (c<$A0)) THEN c:=$7F + WriteF(' \d[3] ($\z\h[2]) = \c\n', realc, realc, c) + ENDFOR +EXCEPT DO + RETURN exception=ERR_NONE +ENDPROC + +-> process_window() - Simple event loop. Note that the message is not replied +-> to until the end of the loop so that it may be used in the doKeys() call. +-> E-Note: we use WaitIMessage() so a lot of this and above is simplified +PROC process_window(win, ievent, buffer, bufsize) + DEF going=TRUE, class + WHILE going + class:=WaitIMessage(win) + SELECT class + CASE IDCMP_CLOSEWINDOW + going:=FALSE + CASE IDCMP_RAWKEY + going:=doKeys(ievent, buffer, bufsize) + ENDSELECT + ENDWHILE +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/blockinput.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/blockinput.e new file mode 100644 index 0000000..ed1d416 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/blockinput.e @@ -0,0 +1,111 @@ +-> blockinput.e -- Program to demonstrate how to block the input from a window +-> using a minimal requester, and how to put up a busy pointer. + +OPT OSVERSION=37 -> E-Note: silently require V37 + +MODULE 'exec/memory', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_WIN + +RAISE ERR_WIN IF OpenWindowTagList()=NIL + +-> Open a window and display a busy-pointer for a short time then wait for the +-> user to hit the close gadget (in processIDCMP()). Normally, the application +-> would bracket sections of code where it wishes to block window input with +-> the beginWait() and endWait() functions. +PROC main() HANDLE + DEF win=NIL + + win:=OpenWindowTagList(NIL, + [WA_IDCMP, IDCMP_CLOSEWINDOW OR IDCMP_INTUITICKS, + WA_ACTIVATE, TRUE, + WA_WIDTH, 320, + WA_HEIGHT, 100, + WA_CLOSEGADGET, TRUE, + WA_DRAGBAR, TRUE, + WA_DEPTHGADGET, TRUE, + WA_SIZEGADGET, TRUE, + WA_MAXWIDTH, -1, + WA_MAXHEIGHT, -1, + NIL]) + processIDCMP(win) + +EXCEPT DO + IF win THEN CloseWindow(win) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE "MEM"; WriteF('Error: Ran out of (chip) memory\n') + ENDSELECT +ENDPROC + +-> E-Note: get some Chip memory and copy list (quick, since LONG aligned) +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem + +-> Clear the requester with InitRequester. This makes a requester of +-> width = 0, height = 0, left = 0, top = 0; in fact, everything is zero. This +-> requester will simply block input to the window until EndRequest is called. +-> +-> The pointer is set to a reasonable 4-color busy pointer, with proper offsets. +PROC beginWait(win, waitRequest) + DEF waitPointer + + -> Data for a busy pointer. + -> This data must be in chip memory!!! + -> E-Note: the data is really a lot of LONGs + waitPointer:=copyListToChip([$00000000, -> Reserved, must be NIL + $040007C0, $000007C0, $01000380, $000007E0, + $07C01FF8, $1FF03FEC, $3FF87FDE, $3FF87FBE, + $7FFCFF7F, $7EFCFFFF, $7FFCFFFF, $3FF87FFE, + $3FF87FFE, $1FF03FFC, $07C01FF8, $000007E0, + $00000000 -> Reserved, must be NIL + ]) + + InitRequester(waitRequest) + IF Request(waitRequest, win) + SetPointer(win, waitPointer, 16, 16, -6, 0) + SetWindowTitles(win, 'Busy - Input Blocked', -1) + RETURN TRUE + ELSE + RETURN FALSE + ENDIF +ENDPROC + +-> Routine to reset the pointer to the system default, and remove the requester +-> installed with beginWait(). +PROC endWait(win, waitRequest) + ClearPointer(win) + EndRequest(waitRequest, win) + SetWindowTitles(win, 'Not Busy', -1) +ENDPROC + +-> Wait for the user to close the window. +PROC processIDCMP(win) + DEF class, myreq:requester, tick_count + + -> Put up a requester with no imagery (size zero). + IF beginWait(win, myreq) + -> Insert code here for a window to act as the requester. + + -> We'll count down INTUITICKS, which come about ten times a second. We'll + -> keep the busy state for about three seconds. + tick_count:=30 + ENDIF + + REPEAT + class:=WaitIMessage(win) + SELECT class + CASE IDCMP_INTUITICKS + IF tick_count>0 + DEC tick_count + IF tick_count=0 THEN endWait(win, myreq) + ENDIF + ENDSELECT + UNTIL class=IDCMP_CLOSEWINDOW +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/displayalert.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/displayalert.e new file mode 100644 index 0000000..31b1272 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/displayalert.e @@ -0,0 +1,26 @@ +-> displayalert.e - This program implements a recoverable alert + +MODULE 'intuition/intuition' + +PROC main() + IF DisplayAlert(RECOVERY_ALERT, {alertMsg}, 52) + WriteF('Alert returned TRUE\n') + ELSE + WriteF('Alert returned FALSE\n') + ENDIF +ENDPROC + +-> Each string requires its own positioning information, as explained in the +-> manual. Hex notation has been used to specify the positions of the text. +-> Hex numbers start with a "$" and the characters that make up the number. +-> +-> Each line needs 2 bytes of x position, and 1 byte of y position. +-> in our 1st line: x = 0 $f0 (2 bytes) and y = $14 (1 byte) +-> In our 2nd line: x = 0 $80 (2 bytes) and y = $24 (1 byte) +-> Each line is NIL terminated plus a continuation character (0=done). The +-> entire alert must end in TWO NILs, one for the end of the string, and one +-> for the 0 continuation character. +-> E-Note: using static data is just one way of doing this neatly +alertMsg: + CHAR 0, $f0, $14, 'OH NO, NOT AGAIN!', NIL, 1, + 0, $80, $24, 'PRESS MOUSEBUTTON: LEFT=TRUE RIGHT=FALSE', NIL, 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/easyrequest.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/easyrequest.e new file mode 100644 index 0000000..59f463f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Requesters_Alerts/easyrequest.e @@ -0,0 +1,41 @@ +-> easyrequest.e - Show the use of an easy requester. + +OPT OSVERSION=37 -> Note: silently require V37 + +MODULE 'intuition/intuition' + +-> Main routine to show the use of EasyRequestArgs() +PROC main() + DEF answer, number, text + + number:=3125794 -> For use in the middle button + + -> The easy request strucutre uses many features of EasyRequestArgs(), + -> including: + -> multiple lines of body text separated by '\n'. + -> variable substitution of a string (%s) in the body text. + -> multiple button gadgets separated by '|'. + -> variable substitution in a gadget (long decimal '%ld'). + + -> NOTE in the variable substitution: + -> the string goes in the first open variable (in body text). + -> the number goes in the second open (gadget text). + text:='Text for the request\n'+ + 'Second line of %s text\n'+ + 'Third line of text for the request' + answer:=EasyRequestArgs(NIL, + [SIZEOF easystruct, 0, 'Request Window Name', + text, + 'Yes|%ld|No']:easystruct, + NIL, ['(Variable)', number]) + -> Process the answer. Note that the buttons are numbered in a strange + -> order. This is because the rightmost button is always a negative reply. + -> The code can use this if it chooses, with a construct like: + -> + -> IF EasyRequestArgs() THEN positive_response() + SELECT answer + CASE 1; WriteF('Selected "Yes"\n') + CASE 2; WriteF('Selected "\d"\n', number) + CASE 0; WriteF('Selected "No"\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/clonescreen.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/clonescreen.e new file mode 100644 index 0000000..ec52070 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/clonescreen.e @@ -0,0 +1,120 @@ +-> clonescreen.e - clone an existing public screen + +MODULE 'intuition/screens', -> Screen data structures and tags + 'graphics/text', -> Text font structure + 'graphics/modeid', -> Release 2 Amiga display mode ID's + 'exec/nodes', -> Nodes -- get font name + 'exec/ports' -> Ports -- get font name + +ENUM ERR_NONE, ERR_SCRN, ERR_LOCKPUB, ERR_GETDRAW, ERR_MODEID, ERR_FONT + +RAISE ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_LOCKPUB IF LockPubScreen()=NIL, + ERR_GETDRAW IF GetScreenDrawInfo()=NIL, + ERR_MODEID IF GetVPModeID()=INVALID_ID, + ERR_FONT IF OpenFont()=NIL, + "MEM" IF String()=NIL + +PROC main() + DEF pub_screen_name + pub_screen_name:='Workbench' + + IF KickVersion(37) + -> Require version 37 + -> E-Note: E automatically opens the Intuition and Graphics libraries + cloneScreen(pub_screen_name) + ENDIF +ENDPROC + +-> Clone a public screen whose name is passed to the routine. Width, Height, +-> Depth, Pens, Font and DisplayID attributes are all copied from the screen. +-> Overscan is assumed to be OSCAN_TEXT, as there is no easy way to find the +-> overscan type of an existing screen. AutoScroll is turned on, as it does +-> not hurt. Screens that are smaller than the display clip will not scroll. + +PROC cloneScreen(pub_screen_name) HANDLE + DEF my_screen=NIL:PTR TO screen, screen_modeID, pub_scr_font_name, + font_name, pub_screen_font:PTR TO textattr, opened_font, + pub_screen=NIL:PTR TO screen, screen_drawinfo=NIL:PTR TO drawinfo + + -> pub_screen_name is a pointer to the name of the public screen to clone + -> E-Note: automatically error-checked (automatic exception) + pub_screen:=LockPubScreen(pub_screen_name) + + -> Get the DrawInfo structure from the locked screen + -> E-Note: automatically error-checked (automatic exception) + screen_drawinfo:=GetScreenDrawInfo(pub_screen) + + -> E-Note: pub_screen.viewport is a structure in C and (as usual) a pointer + -> to the structure in E + -> E-Note: automatically error-checked (automatic exception) + screen_modeID:=GetVPModeID(pub_screen.viewport) + + -> Get a copy of the font + -> The name of the font must be copied as the public screen may go away at + -> any time after we unlock it. Allocate enough memory to copy the font + -> name, create a TextAttr that matches the font, and open the font. + -> E-Note: pointer typing needed to multiply select from system objects + pub_scr_font_name:=screen_drawinfo.font.mn.ln.name + + -> E-Note: allocate and copy all in one go + -> E-Note: automatically error-checked (automatic exception) + font_name:=StrCopy(String(StrLen(pub_scr_font_name)), pub_scr_font_name) + + -> E-Note: use a typed list for initialised object + pub_screen_font:=[font_name, + screen_drawinfo.font.ysize, + screen_drawinfo.font.style, + screen_drawinfo.font.flags]:textattr + + -> E-Note: pub_screen_font is a structure in C and (as usual) a pointer to + -> the structure in E + -> E-Note: automatically error-checked (automatic exception) + opened_font:=OpenFont(pub_screen_font) + + -> screen_modeID may now be used in a call to OpenScreenTagList() with the + -> tag SA_DISPLAYID + -> E-Note: automatically error-checked (automatic exception) + my_screen:=OpenScreenTagList(NIL, + [SA_WIDTH, pub_screen.width, + SA_HEIGHT, pub_screen.height, + SA_DEPTH, screen_drawinfo.depth, + SA_OVERSCAN, OSCAN_TEXT, + SA_AUTOSCROLL, TRUE, + SA_PENS, screen_drawinfo.pens, + SA_FONT, pub_screen_font, + SA_DISPLAYID, screen_modeID, + SA_TITLE, 'Cloned Screen', + NIL]) + + -> Free the drawinfo and public screen as we don't need them any more. + -> We now have our own screen. + FreeScreenDrawInfo(pub_screen, screen_drawinfo) + screen_drawinfo:=NIL + UnlockPubScreen(pub_screen_name, pub_screen) + pub_screen:=NIL + + Delay(300) -> Should be the rest of the program + + -> E-Note: exit and clean up via handler +EXCEPT DO + -> The first two are freed in the main code if OpenScreenTagList() does not + -> fail. If something goes wrong, free them here. + IF screen_drawinfo THEN FreeScreenDrawInfo(pub_screen, screen_drawinfo) + IF pub_screen THEN UnlockPubScreen(pub_screen_name, pub_screen) + IF my_screen THEN CloseScreen(my_screen) + IF opened_font THEN CloseFont(opened_font) + -> E-Note: it is not strictly necessary, but tidy, to free the font_name + IF font_name THEN DisposeLink(font_name) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_FONT + -> E-Note: it's helpful to say which font went wrong + WriteF('Error: Failed to open font "\s"\n', font_name) + CASE ERR_GETDRAW; WriteF('Error: Failed to get DrawInfo of screen\n') + CASE ERR_LOCKPUB; WriteF('Error: Failed to locked public screen\n') + CASE ERR_MODEID; WriteF('Error: Public screen has invalid mode ID\n') + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/doublebuffer.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/doublebuffer.e new file mode 100644 index 0000000..2fa630d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/doublebuffer.e @@ -0,0 +1,144 @@ +-> doublebuffer.e - Show the use of a double-buffered screen + +MODULE 'intuition/screens', -> Screen data structures + 'graphics/rastport', -> RastPort and other structures + 'graphics/view', -> ViewPort and other structures + 'graphics/gfx' -> BitMap and other structures + +-> Characteristics of the screen +CONST SCR_WIDTH=320, SCR_HEIGHT=200, SCR_DEPTH=2 + +-> Exception values +-> E-Note: exceptions are a much better way of handling errors +ENUM ERR_NONE, ERR_SCRN, ERR_RAST + +-> Automatically raise exceptions +-> E-Note: these take care of a lot of error cases +RAISE ERR_SCRN IF OpenScreen()=NIL, + ERR_RAST IF AllocRaster()=NIL + +-> Main routine. Setup for using the double buffered screen. Clean up all +-> resources when done or on any error. +PROC main() HANDLE + DEF myBitMaps=NIL:PTR TO LONG, screen=NIL:PTR TO screen + -> E-Note: E automatically opens the Intuition and Graphics libraries + myBitMaps:=setupBitMaps(SCR_DEPTH, SCR_WIDTH, SCR_HEIGHT) + + -> Open a simple quiet screen that is using the first of the two bitmaps. + -> E-Note: use a typed list to get an initialised object + -> E-Note: automatically error-checked (automatic exception) + screen:=OpenScreen([0, -> LeftEdge + 0, -> TopEdge + SCR_WIDTH, -> Width + SCR_HEIGHT, -> Height + SCR_DEPTH, -> Depth + 0, -> DetailPen + 1, -> BlockPen + V_HIRES, -> ViewModes + CUSTOMSCREEN OR CUSTOMBITMAP OR SCREENQUIET, -> Type + NIL, -> Font + NIL, -> DefaultTitle + NIL, -> Gadgets + myBitMaps[0] -> CustomBitMap + ]:ns) + -> Indicate that the rastport is double buffered. + screen.rastport.flags:=RPF_DBUFFER + runDBuff(screen, myBitMaps) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF screen THEN CloseScreen(screen) + IF myBitMaps THEN freeBitMaps(myBitMaps, SCR_DEPTH, SCR_WIDTH, SCR_HEIGHT) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + CASE ERR_RAST; WriteF('Error: Ran out of memory in AllocRaster()\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC + +-> setupBitMaps(): allocate the bit maps for a double buffered screen. +PROC setupBitMaps(depth, width, height) HANDLE + DEF myBitMaps:PTR TO LONG + -> E-Note: an immediate list in E takes the place of the static in C + -> E-Note: initialise the two bitmaps to NIL pointers + myBitMaps:=[NIL,NIL] + -> E-Note: NewR raises an exception if it fails + myBitMaps[0]:=NewR(SIZEOF bitmap) + myBitMaps[1]:=NewR(SIZEOF bitmap) + InitBitMap(myBitMaps[0], depth, width, height) + InitBitMap(myBitMaps[1], depth, width, height) + setupPlanes(myBitMaps[0], depth, width, height) + setupPlanes(myBitMaps[1], depth, width, height) +EXCEPT + freeBitMaps(myBitMaps, depth, width, height) + -> E-Note: exception must be passed on to caller + ReThrow() +ENDPROC myBitMaps + +-> runDBuff(): loop through a number of iterations of drawing into alternate +-> frames of the double-buffered screen. Note that the object is drawn in +-> colour 1. +PROC runDBuff(screen:PTR TO screen, myBitMaps:PTR TO LONG) + DEF ktr, xpos, ypos, toggleFrame=0 + SetAPen(screen.rastport, 1) + FOR ktr:=1 TO 199 + -> Calculate a position to place the object, these calculations ensure the + -> object will stay on the screen given the range of ktr and the size of + -> the object. + xpos:=ktr + ypos:=IF Mod(ktr,100)>=50 THEN 50-Mod(ktr,50) ELSE Mod(ktr,50) + + -> Switch the bitmap so that we are drawing into the correct place + screen.rastport.bitmap:=myBitMaps[toggleFrame] + screen.viewport.rasinfo.bitmap:=myBitMaps[toggleFrame] + + -> Draw the object + -> Here we clear the old frame and draw a simple filled rectangle + SetRast(screen.rastport, 0) + RectFill(screen.rastport, xpos, ypos, xpos+100, ypos+100) + + -> Update the physical display to match the newly drawn bitmap + MakeScreen(screen) -> Tell Intuition to do its stuff + RethinkDisplay() -> Intuition compatible MrgCop() & LoadView() + -> It also does a WaitTOF() + + -> Switch the frame number for the next time through + -> E-Note: this is exactly what the C version does... + toggleFrame:=Eor(toggleFrame, 1) + ENDFOR +ENDPROC + +-> freeBitMaps(): free up the memory allocated by setupBitMaps() +PROC freeBitMaps(myBitMaps:PTR TO LONG, depth, width, height) + -> E-Note: freeBitMaps() can be safely if written carefully + IF myBitMaps[0] + freePlanes(myBitMaps[0], depth, width, height) + Dispose(myBitMaps[0]) + ENDIF + IF myBitMaps[1] + freePlanes(myBitMaps[1], depth, width, height) + Dispose(myBitMaps[1]) + ENDIF +ENDPROC + +-> setupPlanes(): allocate the bit planes for a screen bit map +PROC setupPlanes(bitMap:PTR TO bitmap, depth, width, height) + DEF plane_num, planes:PTR TO LONG + planes:=bitMap.planes + FOR plane_num:=0 TO depth-1 + -> E-Note: automatically error-checked (automatic exception) + planes[plane_num]:=AllocRaster(width, height) + BltClear(planes[plane_num], (width/8)*height, 1) + ENDFOR + -> E-Note: exceptions handled in caller, which frees memory +ENDPROC + +-> freePlanes(): free up the memory allocated by setupPlanes() +PROC freePlanes(bitMap:PTR TO bitmap, depth, width, height) + DEF plane_num, planes:PTR TO LONG + planes:=bitMap.planes + FOR plane_num:=0 TO depth-1 + IF planes[plane_num] THEN FreeRaster(planes[plane_num], width, height) + ENDFOR +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/dualplayfield.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/dualplayfield.e new file mode 100644 index 0000000..47d2f42 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/dualplayfield.e @@ -0,0 +1,157 @@ +-> dualplayfield.e - Shows how to turn on dual-playfield mode in a screen. + +MODULE 'intuition/intuition', -> Intuition data structures and tags + 'intuition/screens', -> Screen data structures and tags + 'graphics/modeid', -> Release 2 Amiga display mode ID's + 'exec/memory', -> Memory flags + 'graphics/gfx', -> Bitmap and other structures + 'graphics/rastport', -> RastPort and other structures + 'graphics/view' -> ViewPort and other structures + +ENUM ERR_NONE, ERR_SCRN, ERR_WIN, ERR_RAST, ERR_MODEID + +RAISE ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL, + ERR_RAST IF AllocRaster()=NIL, + ERR_MODEID IF GetVPModeID()=INVALID_ID + +PROC main() HANDLE + DEF win=NIL, scr=NIL + -> E-Note: E automatically opens the Intuition and Graphics libraries + scr:=OpenScreenTagList(NIL, + [SA_DEPTH, 2, + SA_DISPLAYID, HIRES_KEY, + SA_TITLE, 'Dual Playfield Test Screen', + NIL]) + win:=OpenWindowTagList(NIL, + [WA_TITLE, 'Dual Playfield Mode', + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_WIDTH, 200, + WA_HEIGHT, 100, + WA_DRAGBAR, TRUE, + WA_CLOSEGADGET, TRUE, + WA_CUSTOMSCREEN, scr, + NIL]) + doDualPF(win) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF win THEN CloseWindow(win) + IF scr THEN CloseScreen(scr) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE ERR_RAST; WriteF('Error: Ran out of memory in AllocRaster\n') + CASE ERR_MODEID; WriteF('Error: Bad/invalid mode ID for viewport\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC + +-> Allocate all of the stuff required to add dual playfield to a screen. +PROC doDualPF(win:PTR TO window) HANDLE + DEF myscreen:PTR TO screen, rinfo2=NIL:PTR TO rasinfo, + bmap2=NIL:PTR TO bitmap, rport2=NIL:PTR TO rastport + + myscreen:=win.wscreen -> Find the window's screen + + -> Allocate the second playfield's rasinfo, bitmap, and bitplane + -> E-Note: NewM raises an exception if it fails + rinfo2:=NewM(SIZEOF rasinfo, MEMF_PUBLIC OR MEMF_CLEAR) + -> Get a rastport, and set it up for rendering into bmap2 + rport2:=NewM(SIZEOF rastport, MEMF_PUBLIC) + bmap2:=NewM(SIZEOF bitmap, MEMF_PUBLIC OR MEMF_CLEAR) + InitBitMap(bmap2, 1, myscreen.width, myscreen.height) + + -> Extra playfield will only use one bitplane here. + -> E-Note: automatically error checked (automatic exception) + bmap2.planes[0]:=AllocRaster(myscreen.width, myscreen.height) + InitRastPort(rport2) + rinfo2.bitmap:=bmap2 + rport2.bitmap:=bmap2 + + SetRast(rport2, 0) + + -> E-Note: an exception will be raised if installDualPF fails + installDualPF(myscreen, rinfo2) + SetRGB4(myscreen.viewport, 9, 0, $F, 0) + + drawSomething(rport2) + + handleIDCMP(win) + + removeDualPF(myscreen) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF bmap2 + IF bmap2.planes[0] -> E-Note: NewM makes this zero when bmap2 allocated + FreeRaster(bmap2.planes[0], myscreen.width, myscreen.height) + ENDIF + Dispose(bmap2) + ENDIF + IF rport2 THEN Dispose(rport2) + IF rinfo2 THEN Dispose(rinfo2) + -> E-Note: pass exception on if it was an error + ReThrow() +ENDPROC + +-> Manhandle the viewport: install second playfield and change modes +PROC installDualPF(scrn:PTR TO screen, rinfo2) + -> You can only play with the bits in the Modes field if the upper half of + -> the screen mode ID is zero!!! + -> E-Note: automatic and explicit exceptions raised here + IF GetVPModeID(scrn.viewport) AND $FFFF0000 THEN Raise(ERR_MODEID) + + Forbid() + + -> Install rinfo2 for viewport's second playfield + scrn.viewport.rasinfo.next:=rinfo2 + scrn.viewport.modes:=scrn.viewport.modes OR V_DUALPF + + Permit() + + -> Put viewport change into effect + MakeScreen(scrn) + RethinkDisplay() +ENDPROC + +-> Draw some lines in a rast port... This is used to get some data into the +-> second playfield. The windows on the screen will move underneath these +-> graphics without disturbing them. +PROC drawSomething(rp:PTR TO rastport) + DEF width, height, r, c + + width:=rp.bitmap.bytesperrow * 8 + height:=rp.bitmap.rows + + SetAPen(rp, 1) + + FOR r:=0 TO height-1 STEP 40 + FOR c:=0 TO width-1 STEP 40 + -> E-Note: we could use E's graphics functions + Move(rp, 0, r) + Draw(rp, c, 0) + ENDFOR + ENDFOR +ENDPROC + +-> Simple event loop to wait for the user to hit the close gadget on the window. +PROC handleIDCMP(win) + WHILE WaitIMessage(win)<>IDCMP_CLOSEWINDOW + ENDWHILE +ENDPROC + +-> Remove the effects of installDualPF(). +-> Only call if installDualPF() succeeded. +PROC removeDualPF(scrn:PTR TO screen) + Forbid() + + scrn.viewport.rasinfo.next:=NIL + scrn.viewport.modes:=scrn.viewport.modes AND Not(V_DUALPF) + + Permit() + + MakeScreen(scrn) + RethinkDisplay() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/newlookscreen.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/newlookscreen.e new file mode 100644 index 0000000..f6b6444 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/newlookscreen.e @@ -0,0 +1,47 @@ +-> newlookscreen.e - open a screen with the "new look" + +-> E-Note: you need to be more specific about modules than C does about includes +MODULE 'intuition/screens' -> Screen data structures and tags + +-> Exception values +-> E-Note: exceptions are a much better way of handling errors +ENUM ERR_NONE, ERR_SCRN, ERR_KICK + +-> Automatically raise exceptions +-> E-Note: these take care of a lot of error cases +RAISE ERR_SCRN IF OpenScreenTagList()=NIL + +-> Simple routine to demonstrate opening a screen with the new look. Simply +-> supply the tag SA_PENS along with a minimal pen specification, Intuition +-> will fill in all unspecified values with defaults. Since we are not +-> supplying values, all are Intuition defaults. +PROC main() HANDLE + DEF my_screen=NIL:PTR TO screen + + -> E-Note: E automatically opens the Intuition library + + -> E-Note: use KickVersion rather than checking library version + -> E-Note: Raise() exception rather than nesting conditionals + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + + -> The screen is opened two bitplanes deep so that the new look will show + -> up better. + -> E-Note: automatically error-checked (automatic exception) + -> E-Note: pens is just a INT-typed list + my_screen:=OpenScreenTagList(NIL, + [SA_PENS, [-1]:INT, + SA_DEPTH, 2, + NIL]) + + -> Screen successfully opened + Delay(30) -> Normally the program would be here + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF my_screen THEN CloseScreen(my_screen) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/publicscreen.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/publicscreen.e new file mode 100644 index 0000000..9fd895e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/publicscreen.e @@ -0,0 +1,70 @@ +-> publicscreen.e - open a screen with the pens from a public screen + +MODULE 'intuition/screens' + +ENUM ERR_NONE, ERR_SCRN, ERR_LOCKPUB, ERR_GETDRAW + +RAISE ERR_SCRN IF OpenScreenTagList()=NIL, + ERR_LOCKPUB IF LockPubScreen()=NIL, + ERR_GETDRAW IF GetScreenDrawInfo()=NIL + +PROC main() + IF KickVersion(37) + -> Check the version. Release 2 is required for public screen functions + -> E-Note: E automatically opens the Intuition library + usePubScreenPens() + ENDIF +ENDPROC + +-> Open a screen that uses the pens of an existing public screen (the Workbench +-> screen in this case). +PROC usePubScreenPens() HANDLE + DEF my_screen=NIL:PTR TO screen, pubScreenName, + pub_screen=NIL:PTR TO screen, screen_drawinfo=NIL:PTR TO drawinfo + pubScreenName:='Workbench' + + -> Get a lock on the Workbench screen + -> E-Note: automatically error-checked (automatic exception) + pub_screen:=LockPubScreen(pubScreenName) + + -> Get the DrawInfo structure from the locked screen + -> E-Note: automatically error-checked (automatic exception) + screen_drawinfo:=GetScreenDrawInfo(pub_screen) + + -> The pens are copied in the OpenScreenTagList() call, so we can simply use + -> a pointer to the pens in the tag list. + -> + -> This works better if the depth and colors of the new screen matches that + -> of the public screen. Here we are forcing the Workbench screen pens on a + -> monochrome screen (which may not be a good idea). You could add the tag: + -> (SA_DEPTH, screen_drawinfo.depth) + -> E-Note: automatically error-checked (automatic exception) + my_screen:=OpenScreenTagList(NIL, + [SA_PENS, screen_drawinfo.pens, + -> E-Note: try uncommenting next line (see above) + -> SA_DEPTH, screen_drawinfo.depth, + NIL]) + + -> We no longer need to hold the lock on the public screen or a copy of its + -> DrawInfo structure as we now have our own screen. Release the screen. + FreeScreenDrawInfo(pub_screen, screen_drawinfo) + screen_drawinfo:=NIL + UnlockPubScreen(pubScreenName, pub_screen) + pub_screen:=NIL + + Delay(90) -> Should be the rest of the program + + -> E-Note: exit and clean up via handler +EXCEPT DO + -> The first two are freed in the main code if OpenScreenTagList() does not + -> fail. If something goes wrong, free them here. + IF screen_drawinfo THEN FreeScreenDrawInfo(pub_screen, screen_drawinfo) + IF pub_screen THEN UnlockPubScreen(pubScreenName, pub_screen) + IF my_screen THEN CloseScreen(my_screen) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + CASE ERR_LOCKPUB; WriteF('Error: Failed to locked public screen\n') + CASE ERR_GETDRAW; WriteF('Error: Failed to get DrawInfo of screen\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/pubscreenbeep.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/pubscreenbeep.e new file mode 100644 index 0000000..c10710d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/pubscreenbeep.e @@ -0,0 +1,28 @@ +-> pubscreenbeep.e +-> +-> Simple example of how to find a public screen to work with in Release 2. + +-> E-Note: no need for modules, since we don't use anything that isn't built-in, +-> but module 'intuition/screens' would be needed if we actually needed to know +-> that "my_wbscreen_ptr" was a "PTR TO screen" rather than just a pointer... +PROC main() + DEF my_wbscreen_ptr -> Pointer to the Workbench screen + + IF KickVersion(36) + -> OK, we have the right version of the OS so we can use the new public + -> screen functions of Release 2 (V36) + IF my_wbscreen_ptr:=LockPubScreen('Workbench') + -> OK found the Workbench screen. Normally the program would be here. + -> A window could be opened or the attributes of the screen copied + DisplayBeep(my_wbscreen_ptr) + + UnlockPubScreen(NIL, my_wbscreen_ptr) + ENDIF + ELSE + -> Prior to Release 2 (V36), there were no public screens, just Workbench. + -> In those older systems, windows can be opened on Workbench without + -> locking or a pointer by setting the Type=WBENCHSCREEN in object "nw". + -> Attributes can be obtained by setting the Type argument to WBENCHSCREEN + -> in the call to GetScreenData(). + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/screen34to37.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/screen34to37.e new file mode 100644 index 0000000..554a22e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Screens/screen34to37.e @@ -0,0 +1,57 @@ +-> screen34to37.e +-> +-> Simple example to show how to open a custom screen that gives the new look +-> under V37, yet still works with older version of the operating system. +-> Attach the tag SA_PENS and a minimal pen specification to ExtNewScreen, and +-> call the old OpenScreen() function. The tags will be ignored by V34 and +-> earlier versions of the OS. In V36 and later the tags are accepted by +-> Intuition. + +-> E-Note: you need to be more specific about modules than C does about includes +MODULE 'intuition/screens', -> Screen data structures and tags + 'graphics/view' -> Screen resolutions + +-> Exception values +-> E-Note: exceptions are a much better way of handling errors +ENUM ERR_NONE, ERR_SCRN + +-> Automatically raise exceptions +-> E-Note: these take care of a lot of error cases +RAISE ERR_SCRN IF OpenS()=NIL + +PROC main() HANDLE + -> Pointer to our new, custom screen + DEF my_screen=NIL:PTR TO screen + + -> E-Note: E automatically opens the Intuition library + + -> The screen is opened two bitplanes deep so that the new look will show + -> up better. + -> E-Note: automatically error-checked (automatic exception) + -> E-Note: simplified using OpenS + my_screen:=OpenS(640, -> Smaller values here reduce the + STDSCREENHEIGHT, -> drawing area and save memory. + 2, -> Two planes means 4 colours. + V_HIRES, + 'My Screen', + -> Attach the pen specification tags + -> E-Note: the tag list can be supplied directly + -> E-Note: pens is just an INT-typed list + [SA_PENS, [-1]:INT, + -> E-Note: these tags replace the missing OpenS parameters + SA_DETAILPEN, 0, + SA_BLOCKPEN, 1, + NIL]) + + -> Screen successfully opened + + Delay(200) -> Normally the program would be here + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF my_screen THEN CloseS(my_screen) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_SCRN; WriteF('Error: Failed to open custom screen\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Special/remembertest.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Special/remembertest.e new file mode 100644 index 0000000..c6a38cb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Special/remembertest.e @@ -0,0 +1,85 @@ +-> RememberTest - Illustrates the use of AllocRemember() and FreeRemember(). +-> E-Note: E's New() family of memory allocators are usually adequate... + +MODULE 'dos/dos', + 'exec/memory' + +RAISE "MEM" IF AllocRemember()=NIL + +-> Random sizes to demonstrate the Remember functions. */ +CONST SIZE_A=100, SIZE_B=200 + +PROC main() + methodOne() + methodTwo() +ENDPROC RETURN_OK + +-> MethodOne +-> Illustrates using AllocRemember() to allocate all memory and FreeRemember() +-> to free it all. +PROC methodOne() HANDLE + DEF memBlockA=NIL, memBlockB=NIL, rememberKey=NIL + + memBlockA:=AllocRemember({rememberKey}, SIZE_A, MEMF_CLEAR OR MEMF_PUBLIC) + memBlockB:=AllocRemember({rememberKey}, SIZE_B, MEMF_CLEAR OR MEMF_PUBLIC) + + -> Both memory allocations succeeded. + -> The program may now use this memory. + +EXCEPT DO + -> It is not necessary to keep track of the status of each allocation. + -> Intuition has kept track of all successful allocations by updating its + -> linked list of Remember nodes. The following call to FreeRemember() will + -> deallocate any and all of the memory that was successfully allocated. + -> The memory blocks as well as the link nodes will be deallocated because + -> the "ReallyForget" parameter is TRUE. + -> + -> It is possible to have reached the call to FreeRemember() in one of three + -> states. Here they are, along with their results. + -> + -> 1. Both memory allocations failed. + -> RememberKey is still NIL. FreeRemember() will do nothing. + -> 2. The memBlockA allocation succeeded but the memBlockB allocation failed. + -> FreeRemember() will free the memory block pointed to by memBlockA. + -> 3. Both memory allocations were successful. + -> FreeRemember() will free the memory blocks pointed to by + -> memBlockA and memBlockB. + FreeRemember({rememberKey}, TRUE) + ReThrow() -> E-Note: pass on exception if an error +ENDPROC + +-> MethodTwo +-> Illustrates using AllocRemember() to allocate all memory, FreeRemember() to +-> free the link nodes, and FreeMem() to free the actual memory blocks. +PROC methodTwo() HANDLE + DEF memBlockA=NIL, memBlockB=NIL, rememberKey=NIL + + memBlockA:=AllocRemember({rememberKey}, SIZE_A, MEMF_CLEAR OR MEMF_PUBLIC) + memBlockB:=AllocRemember({rememberKey}, SIZE_B, MEMF_CLEAR OR MEMF_PUBLIC) + + -> Both memory allocations succeeded. + -> For the purpose of illustration, FreeRemember() is called at this point, + -> but only to free the link nodes. The memory pointed to by memBlockA and + -> memBlockB is retained. + FreeRemember({rememberKey}, FALSE) + + -> Individually free the two memory blocks. The Exec FreeMem() call must be + -> used, as the link nodes are no longer available. + FreeMem(memBlockA, SIZE_A) + FreeMem(memBlockB, SIZE_B) + +EXCEPT DO + -> It is possible to have reached the call to FreeRemember() in one of three + -> states. Here they are, along with their results. + -> + -> 1. Both memory allocations failed. + -> RememberKey is still NIL. FreeRemember() will do nothing. + -> 2. The memBlockA allocation succeeded but the memBlockB allocation failed. + -> FreeRemember() will free the memory block pointed to by memBlockA. + -> 3. Both memory allocations were successful. + -> If this is the case, the program has already freed the link nodes with + -> FreeRemember() and the memory blocks with FreeMem(). When + -> FreeRemember() freed the link nodes, it reset RememberKey to NIL. + -> This (second) call to FreeRemember() will do nothing. + FreeRemember({rememberKey}, TRUE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/lines.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/lines.e new file mode 100644 index 0000000..0bfb861 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/lines.e @@ -0,0 +1,294 @@ +-> lines.e -- implements a superbitmap with scroll gadgets +-> This program requires V37, as it uses calls to OpenWindowTags(), +-> LockPubScreen(). + +OPT PREPROCESS -> E-Note: enable use of macros + +MODULE 'layers', -> We are going to use the Layers library + 'intuition/intuition', -> Intuition data structures and tags + 'intuition/screens', -> Screen data structures and tags + 'graphics/rastport', -> RastPort and other structures + 'graphics/clip', -> Layer and other structures + 'graphics/gfx', -> BitMap and other structures + 'graphics/text', -> TextFont and other structures + 'exec/memory' -> Memory flags + +ENUM ERR_NONE, ERR_LIB, ERR_KICK, ERR_PUB, ERR_RAST, ERR_WIN + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_PUB IF LockPubScreen()=NIL, + ERR_RAST IF AllocRaster()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +CONST WIDTH_SUPER=800, HEIGHT_SUPER=600, + UP_DOWN_GADGET=0, LEFT_RIGHT_GADGET=1, NO_GADGET=2 +-> E-Note: MAXPOT and MAXBODY should be used instead of MAXPROPVAL + +#define LAYERXOFFSET(x) (x.rport.layer.scroll_x) +#define LAYERYOFFSET(x) (x.rport.layer.scroll_y) + +-> E-Note: need objects like botGad to be zeroed, so use pointers here +DEF win=NIL:PTR TO window, botGadInfo=NIL:PTR TO propinfo, + botGadImage=NIL:PTR TO image, botGad=NIL:PTR TO gadget, + sideGadInfo=NIL:PTR TO propinfo, sideGadImage=NIL:PTR TO image, + sideGad=NIL:PTR TO gadget + +PROC main() HANDLE + DEF myscreen=NIL + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + + -> E-Note: E automatically opens the Intuition and Graphics libraries + -> Open the Layers library for the program. + -> E-Note: automatically error-checked (automatic exception) + layersbase:=OpenLibrary('layers.library', 33) + + -> LockPubScreen()/UnlockPubScreen is only available under V36 and later. Use + -> GetScreenData() under V34 systems to get a copy of the screen structure... + -> E-Note: automatically error-checked (automatic exception) + myscreen:=LockPubScreen(NIL) + + superWindow(myscreen) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF myscreen THEN UnlockPubScreen(NIL, myscreen) + IF layersbase THEN CloseLibrary(layersbase) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + CASE ERR_LIB; WriteF('Error: Could not open layers.library\n') + CASE ERR_PUB; WriteF('Error: Could not lock public screen\n') + CASE ERR_RAST; WriteF('Error: Ran out of memory in AllocRaster\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE "MEM"; WriteF('Error: Ran out of memory\n') + ENDSELECT +ENDPROC + +-> A string with this format will be found by the version command supplied by +-> Commodore. This will allow users to give version numbers with error reports. +-> E-Note: labels can only be used after the first PROC line... +vers: CHAR '$VER: lines 37.2',0 + +-> Create, initialise and process the super bitmap window. Cleanup if any error. +PROC superWindow(myscreen:PTR TO screen) HANDLE + DEF bigBitMap=NIL:PTR TO bitmap, planeNum, mydepth + + -> Set-up the border prop gadgets for the OpenWindow() call. + initBorderProps(myscreen) + + -> The code relies on the allocation of the BitMap structure with the + -> MEMF_CLEAR flag. This allows the assumption that all of the bitmap + -> pointers are NIL, except those successfully allocated by the program. + -> E-Note: NewM raises an exception if it fails + bigBitMap:=NewM(SIZEOF bitmap, MEMF_PUBLIC OR MEMF_CLEAR) + + mydepth:=myscreen.bitmap.depth + InitBitMap(bigBitMap, mydepth, WIDTH_SUPER, HEIGHT_SUPER) + + -> E-Note: we handle errors with exceptions + FOR planeNum:=0 TO mydepth-1 + bigBitMap.planes[planeNum]:=AllocRaster(WIDTH_SUPER, HEIGHT_SUPER) + ENDFOR + + -> Only open the window if the bitplanes were successfully allocated. Fail + -> via exception if they were not. + + -> OpenWindowTags() and OpenWindowTagList() are only available when the + -> library version is at least V36. Under earlier versions of Intuition, use + -> OpenWindow() with a NewWindow structure. + win:=OpenWindowTagList(NIL, + [WA_WIDTH, 150, + WA_HEIGHT, (4*(myscreen.wbortop+myscreen.font.ysize+1)), + WA_MAXWIDTH, WIDTH_SUPER, + WA_MAXHEIGHT, HEIGHT_SUPER, + WA_IDCMP, IDCMP_GADGETUP OR IDCMP_GADGETDOWN OR + IDCMP_NEWSIZE OR IDCMP_INTUITICKS OR IDCMP_CLOSEWINDOW, + WA_FLAGS, WFLG_SIZEGADGET OR WFLG_SIZEBRIGHT OR WFLG_SIZEBBOTTOM OR + WFLG_DRAGBAR OR WFLG_DEPTHGADGET OR WFLG_CLOSEGADGET OR + WFLG_SUPER_BITMAP OR WFLG_GIMMEZEROZERO OR WFLG_NOCAREREFRESH, + WA_GADGETS, sideGad, + WA_TITLE, {vers}+6, -> Take title from version string + WA_PUBSCREEN, myscreen, + WA_SUPERBITMAP, bigBitMap, + NIL]) + + -> Set-up the window display + SetRast(win.rport, 0) -> Clear the bitplanes + SetDrMd(win.rport, RP_JAM1) + + doNewSize() -> Adjust props to represent portion visible + doDrawStuff() + + -> Process the window, return on IDCMP_CLOSEWINDOW + doMsgLoop() + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF win THEN CloseWindow(win) + IF bigBitMap + FOR planeNum:=0 TO mydepth-1 + -> Free only the bitplanes actually allocated... + IF bigBitMap.planes[planeNum] + FreeRaster(bigBitMap.planes[planeNum], WIDTH_SUPER, HEIGHT_SUPER) + ENDIF + ENDFOR + Dispose(bigBitMap) + ENDIF + ReThrow() -> E-Note: pass exception on if it was an error +ENDPROC + +-> Set-up the prop gadgets -- initialise them to values that fit into the +-> window border. The height of the prop gadget on the side of the window +-> takes the height of the title bar into account in its set-up. Note the +-> initialisation assumes a fixed size "sizing" gadget. +-> +-> Note also, that the size of the sizing gadget is dependent on the screen +-> resolution. The numbers given here are only valid if the screen is NOT +-> lo-res. These values must be re-worked slightly for lo-res screens. +-> +-> The PROPNEWLOOK flag is ignored by 1.3. +PROC initBorderProps(myscreen:PTR TO screen) + DEF top -> E-Note: temp variable for top calc + -> Initialises the two prop gadgets. + -> + -> Note where the PROPNEWLOOK flag goes. Adding this flag requires no extra + -> storage, but tells the system that our program is expecting the new-look + -> prop gadgets under 2.0. + -> E-Note: we initialise using typed lists and NEW, so that we do not need + -> to fill in every field (NEW will zero the trailing ones). + -> Without NEW only a partial structure would be allocated... + -> E-Note: allocate zeroed images + NEW botGadImage, sideGadImage + + botGadInfo:=NEW [AUTOKNOB OR FREEHORIZ OR PROPNEWLOOK, + 0, 0, -1, -1]:propinfo + + botGad:=NEW [NIL, 3, -7, -23, 6, + GFLG_RELBOTTOM OR GFLG_RELWIDTH, + GACT_RELVERIFY OR GACT_IMMEDIATE OR GACT_BOTTOMBORDER, + GTYP_PROPGADGET OR GTYP_GZZGADGET, + botGadImage, NIL, NIL, NIL, + botGadInfo, LEFT_RIGHT_GADGET]:gadget + + sideGadInfo:=NEW [AUTOKNOB OR FREEVERT OR PROPNEWLOOK, + 0, 0, -1, -1]:propinfo + + -> NOTE the TopEdge adjustment for the border and the font for V36. + top:=myscreen.wbortop+myscreen.font.ysize+2 + sideGad:=NEW [botGad, -14, top, 12, -top-11, + GFLG_RELRIGHT OR GFLG_RELHEIGHT, + GACT_RELVERIFY OR GACT_IMMEDIATE OR GACT_RIGHTBORDER, + GTYP_PROPGADGET OR GTYP_GZZGADGET, + sideGadImage, NIL, NIL, NIL, + sideGadInfo, UP_DOWN_GADGET]:gadget +ENDPROC + +-> This function does all the work of drawing the lines +PROC doDrawStuff() + DEF x1, y1, x2, y2, pen, ncolors, deltx, delty + + ncolors:=Shl(1, win.wscreen.bitmap.depth) + -> E-Note: Rnd could be seeded using VbeamPos... + deltx:=Rnd(6)+2 + delty:=Rnd(6)+2 + + pen:=Rnd(ncolors-1)+1 + SetAPen(win.rport, pen) + x1:=0; y1:=0; x2:=WIDTH_SUPER-1; y2:=HEIGHT_SUPER-1 + WHILE x1 < WIDTH_SUPER + Move(win.rport, x1, y1) + Draw(win.rport, x2, y2) + x1:=x1+deltx + x2:=x2-deltx + ENDWHILE + + pen:=Rnd(ncolors-1)+1 + SetAPen(win.rport, pen) + x1:=0; y1:=0; x2:=WIDTH_SUPER-1; y2:=HEIGHT_SUPER-1 + WHILE y1 < HEIGHT_SUPER + Move(win.rport, x1, y1) + Draw(win.rport, x2, y2) + y1:=y1+delty + y2:=y2-delty + ENDWHILE +ENDPROC + +-> This function provides a simple interface to ScrollLayer +PROC slideBitMap(dx, dy) + ScrollLayer(0, win.rport.layer, dx, dy) +ENDPROC + +-> E-Note: define macros to compute fraction of Pot and Body +-> E-Note: use Mul() and Div() since definitely over 16-bits +#define FRACTIONPOT(n,d) (Div(Mul(n, MAXPOT), d)) +#define FRACTIONBODY(n,d) (Div(Mul(n, MAXBODY), d)) + +-> Update the prop gadgets and bitmap positioning when the size changes. +PROC doNewSize() + DEF tmp + tmp:=LAYERXOFFSET(win) + win.gzzwidth + IF tmp>=WIDTH_SUPER THEN slideBitMap(WIDTH_SUPER-tmp, 0) + + NewModifyProp(botGad, win, NIL, AUTOKNOB OR FREEHORIZ, + FRACTIONPOT(LAYERXOFFSET(win), WIDTH_SUPER - win.gzzwidth), + NIL, + FRACTIONBODY(win.gzzwidth, WIDTH_SUPER), + MAXBODY, + 1) + + tmp:=LAYERYOFFSET(win) + win.gzzheight + IF tmp>=HEIGHT_SUPER THEN slideBitMap(0, HEIGHT_SUPER-tmp) + + NewModifyProp(sideGad, win, NIL, AUTOKNOB OR FREEVERT, + NIL, + FRACTIONPOT(LAYERYOFFSET(win), HEIGHT_SUPER - win.gzzheight), + MAXBODY, + FRACTIONBODY(win.gzzheight, HEIGHT_SUPER), + 1) +ENDPROC + +-> E-Note: convert signed INT from a Pot to unsigned for calculations +#define UNSIGNED(x) (x AND $FFFF) +-> E-Note: define macro to compute layer offset from Pot value +-> E-Note: use Mul() and Div() since definitely over 16-bits +#define CALCOFFSET(size, pot) (Div(Mul(size, UNSIGNED(pot)), MAXPOT)) + +-> Process the currently selected gadget. This is called from IDCMP_INTUITICKS +-> and when the gadget is released IDCMP_GADGETUP. +PROC checkGadget(gadgetID) + DEF tmp, dx=0, dy=0 + + SELECT gadgetID + CASE UP_DOWN_GADGET + tmp:=CALCOFFSET(HEIGHT_SUPER-win.gzzheight, sideGadInfo.vertpot) + dy:=tmp - LAYERYOFFSET(win) + CASE LEFT_RIGHT_GADGET + tmp:=CALCOFFSET(WIDTH_SUPER-win.gzzwidth, botGadInfo.horizpot) + dx:=tmp - LAYERXOFFSET(win) + ENDSELECT + + IF dx OR dy THEN slideBitMap(dx, dy) +ENDPROC + +-> Main message loop for the window. +-> E-Note: E version is simpler, since we use WaitIMessage +PROC doMsgLoop() + DEF class, currentGadget=NO_GADGET, g:PTR TO gadget + -> E-Note: g is used to cast the type of MsgIaddr() + REPEAT + class:=WaitIMessage(win) + SELECT class + CASE IDCMP_NEWSIZE + doNewSize() + doDrawStuff() + CASE IDCMP_GADGETDOWN + g:=MsgIaddr() + currentGadget:=g.gadgetid + CASE IDCMP_GADGETUP + checkGadget(currentGadget) + currentGadget:=NO_GADGET + CASE IDCMP_INTUITICKS + checkGadget(currentGadget) + ENDSELECT + UNTIL class=IDCMP_CLOSEWINDOW +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/openwindowtags.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/openwindowtags.e new file mode 100644 index 0000000..d7f9b97 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/openwindowtags.e @@ -0,0 +1,44 @@ +-> openwindowtags.e - open a window using tags + +MODULE 'intuition/intuition' -> Intuition data structures and tags + +CONST MY_WIN_LEFT=20, MY_WIN_TOP=10, + MY_WIN_WIDTH=300, MY_WIN_HEIGHT=110 + +ENUM ERR_NONE, ERR_WIN, ERR_KICK + +RAISE ERR_WIN IF OpenWindowTagList()=NIL + +-> Open a simple window using OpenWindowTagList() +PROC main() HANDLE + DEF win=NIL + -> These calls are only valid if we have Intuition version 37 or greater + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + win:=OpenWindowTagList(NIL, + [WA_LEFT, MY_WIN_LEFT, + WA_TOP, MY_WIN_TOP, + WA_WIDTH, MY_WIN_WIDTH, + WA_HEIGHT, MY_WIN_HEIGHT, + WA_CLOSEGADGET, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW, + NIL]) + -> Window successfully opened here + handle_window_events(win) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF win THEN CloseWindow(win) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + ENDSELECT +ENDPROC + +-> Normally this routine would contain an event loop like the one given in the +-> chapter "Intuition Input and Output Methods". Here we just wait for any +-> messages we requested to appear at the Window's port. +PROC handle_window_events(win) + -> E-Note: we can use E's special message poller + WaitIMessage(win) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/visiblewindow.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/visiblewindow.e new file mode 100644 index 0000000..9494f98 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/visiblewindow.e @@ -0,0 +1,114 @@ +-> visiblewindow.e +-> Open a window on the visible part of a screen, with the window as large as +-> the visible part of the screen. It is assumed that the visible part of the +-> screen is OSCAN_TEXT, which how the user has set their preferences. + +MODULE 'intuition/intuition', -> Intuition data structures and tags + 'intuition/screens', -> Screen data structures and tags + 'graphics/gfx', -> Graphics structures + 'graphics/modeid' -> Release 2 Amiga display mode ID's + +ENUM ERR_NONE, ERR_WIN, ERR_PUB + +RAISE ERR_WIN IF OpenWindowTagList()=NIL, + ERR_PUB IF LockPubScreen()=NIL + +-> Minimum window width and height: These values should really be calculated +-> dynamically given the size of the font and the window borders. Here, to +-> keep the example simple they are hard-coded values. +CONST MIN_WINDOW_WIDTH=100, MIN_WINDOW_HEIGHT=50 + +-> E-Note: minimum and maximum are built-in + +PROC main() + -> These calls are only valid if we have version 37 or greater + -> E-Note: E automatically opens the Intuition and Graphics libraries + IF KickVersion(37) + fullScreen() + ELSE -> E-Note: we can print a minimal error + WriteF('Error: Needs Kickstart V37+\n') + ENDIF +ENDPROC + +-> Open a window on the default public screen, then leave it open until the +-> user selects the close gadget. The window is full-sized, positioned in the +-> currently visible OSCAN_TEXT area. +PROC fullScreen() HANDLE + DEF test_window=NIL:PTR TO window, pub_screen=NIL:PTR TO screen, + rect:rectangle, screen_modeID, + -> Set some reasonable defaults for left, top, width and height + -> We'll pick up the real values with the call to QueryOverscan() + left=0, top=0, width=640, height=200 + + -> Get a lock on the default public screen + -> E-Note: automatically error-checked (automatic exception) + pub_screen:=LockPubScreen(NIL) + + -> This technique returns the text overscan rectangle of the screen that we + -> are opening on. If you really need the actual value set into the display + -> clip of the screen, use the VideoControl() command of the graphics library + -> to return a copy of the ViewPortExtra structure. See the Graphics library + -> chapter and Autodocs for more details. + -> + -> GetVPModeID() is a graphics call... + IF (screen_modeID:=GetVPModeID(pub_screen.viewport))<>INVALID_ID + IF QueryOverscan(screen_modeID, rect, OSCAN_TEXT) + -> Make sure window coordinates are positive or zero + left := Max(0, -pub_screen.leftedge) + top := Max(0, -pub_screen.topedge) + + -> Get width and height from size of display clip + width:=rect.maxx-rect.minx+1 + height:=rect.maxy-rect.miny+1 + + -> Adjust height for pulled-down screen (only show visible part) + IF pub_screen.topedge > 0 + height:=height-pub_screen.topedge + ENDIF + + -> Ensure that window fits on screen + height:=Min(height,pub_screen.height) + width:=Min(width,pub_screen.width) + + -> Make sure window is at least minimum size + width:=Max(width, MIN_WINDOW_WIDTH) + height:=Max(height, MIN_WINDOW_HEIGHT) + ENDIF + ENDIF + + -> Open the window on the public screen + -> E-Note: automatically error-checked (automatic exception) + test_window:=OpenWindowTagList(NIL, + [WA_LEFT, left, WA_WIDTH, width, + WA_TOP, top, WA_HEIGHT, height, + WA_CLOSEGADGET, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_PUBSCREEN, pub_screen, + NIL]) + -> Unlock the screen. The window now acts as a lock on the screen, and we do + -> not need the screen after the window has been closed. + UnlockPubScreen(NIL, pub_screen) + -> E-Note: set it to NIL to help deal with errors + pub_screen:=NIL + + -> If we have a valid window open, run the rest of the program, then clean + -> up when done. + handle_window_events(test_window) + + -> E-Note: exit and clean up via handler +EXCEPT DO + IF test_window THEN CloseWindow(test_window) + IF pub_screen THEN UnlockPubScreen(NIL, pub_screen) + -> E-Note: we can print a minimal error message + SELECT exception + CASE ERR_PUB; WriteF('Error: Could not lock public screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +ENDPROC + +-> Wait for the user to select the close gadget. +PROC handle_window_events(win) + -> E-Note: we can use E's special message poller + REPEAT + UNTIL WaitIMessage(win)=IDCMP_CLOSEWINDOW +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/winpubscreen.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/winpubscreen.e new file mode 100644 index 0000000..b606f24 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Intuition/Windows/winpubscreen.e @@ -0,0 +1,57 @@ +-> winpubscreen.e +-> Open a window on the default public screen (usually the Workbench screen) + +MODULE 'intuition/intuition' -> Intuition data structures and tags + +ENUM ERR_NONE, ERR_WIN, ERR_KICK, ERR_PUB + +RAISE ERR_WIN IF OpenWindowTagList()=NIL, + ERR_PUB IF LockPubScreen()=NIL + +-> Open a simple window on the default public screen, then leave it open until +-> the user selects the close gadget. +PROC main() HANDLE + DEF test_window=NIL, test_screen=NIL + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + -> Get a lock on the default public screen + test_screen:=LockPubScreen(NIL) + -> Open the window on the public screen + test_window:=OpenWindowTagList(NIL, + [WA_LEFT, 10, WA_TOP, 20, + WA_WIDTH, 300, WA_HEIGHT, 100, + WA_DRAGBAR, TRUE, + WA_CLOSEGADGET, TRUE, + WA_SMARTREFRESH, TRUE, + WA_NOCAREREFRESH, TRUE, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_TITLE, 'Window Title', + WA_PUBSCREEN, test_screen, + NIL]) + -> Unlock the screen. The window now acts as a lock on the screen, and we do + -> not need the screen after the window has been closed. + UnlockPubScreen(NIL, test_screen) + -> Note: set it to NIL to help deal with errors + test_screen:=NIL + + -> If we have a valid window open, run the rest of the program, then clean up + -> when done. + handle_window_events(test_window) + + -> Note: exit and clean up via handler +EXCEPT DO + IF test_window THEN CloseWindow(test_window) + IF test_screen THEN UnlockPubScreen(NIL, test_screen) + -> Note: we can print a minimal error message + SELECT exception + CASE ERR_KICK; WriteF('Error: Needs Kickstart V37+\n') + CASE ERR_PUB; WriteF('Error: Could not lock public screen\n') + CASE ERR_WIN; WriteF('Error: Failed to open window\n') + ENDSELECT +ENDPROC + +-> Wait for the user to select the close gadget. +PROC handle_window_events(win) + -> Note: we can use E's special message poller + REPEAT + UNTIL WaitIMessage(win)=IDCMP_CLOSEWINDOW +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.e new file mode 100644 index 0000000..92f8076 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.e @@ -0,0 +1,155 @@ +-> appkeymap.e - Subroutines to copy the default keymap, modify the copy +-> +-> Usage: (PTR TO keymap) appkeymap:=createAppKeyMap() +-> PROC deleteAppKeyMap(appkeymap:PTR TO keymap) +-> +-> This example modifies the copied keymap by unmapping all of the numeric +-> keypad keys. This creates a good keymap for use with either keymap.library +-> MapANSI() or commodities InvertString(). If you used a default keymap with +-> the above functions, numeric keypad raw key values would be returned for +-> keys which are available with fewer keypresses on numeric pad than on the +-> normal keyboard. It is generally preferable to have the normal keyboard +-> raw values since many applications attach special meanings to numeric pad +-> keys. The AlterAppKeyMap() routine in this module could easilty be +-> modified to instead set new values for numeric pad or function keys. +-> +-> IMPORTANT: Do Not Use SetKeyMapDefault() unless you are a system +-> preferences editor OR an application that takes over the machine. If you +-> want to use a customized keymap such as this in your application, open your +-> own Intuition window, attach a console device to it, and then use the +-> console device SETKEYMAP command to set your console device unit to your +-> custom keymap. + +->>> Header (globals) +OPT MODULE + +MODULE 'keymap', + 'devices/keymap' + +ENUM ERR_NONE, ERR_ASK, ERR_LIB + +RAISE ERR_ASK IF AskKeyMapDefault()=NIL, + ERR_LIB IF OpenLibrary()=NIL + +-> Raw keys we might want to remap which are the same on all keyboards +EXPORT ENUM UP_KEY=$4C, DOWN_KEY, RIGHT_KEY, LEFT_KEY, F1_KEY, F2_KEY, F3_KEY, + F4_KEY, F5_KEY, F6_KEY, F7_KEY, F8_KEY, F9_KEY, F10_KEY + +EXPORT CONST N0_KEY=$0F, N1_KEY=$1D, N2_KEY=$1E, N3_KEY=$1F, N4_KEY=$2D, + N5_KEY=$2E, N6_KEY=$2F, N7_KEY=$3D, N8_KEY=$3E, N9_KEY=$3F + +EXPORT CONST NPERIOD_KEY=$3C, NOPAREN_KEY=$5A, NCPAREN_KEY=$5B, NSLASH_KEY=$5C, + NASTER_KEY=$5D, NMINUS_KEY=$4A, NPLUS_KEY=$5E, NENTER_KEY=$43 + +EXPORT CONST RETURN_KEY=$44, HELP_KEY=$5F + +-> Count of elements in keymap arrays +EXPORT CONST MAP_SIZE=64, TYPE_SIZE=64, CAPS_SIZE=8, REPS_SIZE=8 +EXPORT CONST MAP_SIZE_P=MAP_SIZE*2, TYPE_SIZE_P=TYPE_SIZE*2, + CAPS_SIZE_P=CAPS_SIZE*2, REPS_SIZE_P=REPS_SIZE*2 + +-> We allocate our Lo and Hi array pairs each as a single array +EXPORT OBJECT keyMapArrays + lhKeyMap[MAP_SIZE_P]:ARRAY OF LONG + lhKeyMapTypes[TYPE_SIZE_P]:ARRAY + lhCapsable[CAPS_SIZE_P]:ARRAY + lhRepeatable[REPS_SIZE_P]:ARRAY +ENDOBJECT + +DEF karrays:PTR TO keyMapArrays, defkeymap:PTR TO keymap, + appkeymap:PTR TO keymap, mapsize +->>> + +->>> EXPORT PROC createAppKeyMap() +EXPORT PROC createAppKeyMap() HANDLE + keymapbase:=OpenLibrary('keymap.library', 37) + defkeymap:=NIL -> E-Note: help with error trapping + -> Get a pointer to the keymap which is set as the system default + defkeymap:=AskKeyMapDefault() + -> Allocate our KeyMap structures and arrays + mapsize:=SIZEOF keymap+SIZEOF keyMapArrays + appkeymap:=NIL + appkeymap:=NewR(mapsize) + -> Init our appkeymap fields to point to our allocated arrays. + -> Each LH array contains a Lo and a Hi array. + -> E-Note: the +1 in the C version means +SIZEOF keymap + karrays:=appkeymap+SIZEOF keymap + appkeymap.lokeymap:=karrays.lhKeyMap + appkeymap.hikeymap:=karrays.lhKeyMap+(MAP_SIZE*(SIZEOF LONG)) + appkeymap.lokeymaptypes:=karrays.lhKeyMapTypes + appkeymap.hikeymaptypes:=karrays.lhKeyMapTypes+TYPE_SIZE + appkeymap.locapsable:=karrays.lhCapsable + appkeymap.hicapsable:=karrays.lhCapsable+CAPS_SIZE + appkeymap.lorepeatable:=karrays.lhRepeatable + appkeymap.hirepeatable:=karrays.lhRepeatable+REPS_SIZE + + -> Copy the user's default system keymap arrays to our appkeymap arrays to + -> get the proper keymappings for the user's keyboard. + copyKeyMap(defkeymap, appkeymap) + + -> Now make our changes to our appkeymap + alterAppKeyMap(appkeymap) +EXCEPT DO + IF keymapbase THEN CloseLibrary(keymapbase) +ENDPROC appkeymap +->>> + +->>> EXPORT PROC deleteAppKeyMap(appkeymap:PTR TO keymap) +EXPORT PROC deleteAppKeyMap(appkeymap:PTR TO keymap) + IF appkeymap THEN Dispose(appkeymap) +ENDPROC +->>> + +->>> PROC alterAppKeyMap(appkeymap:PTR TO keymap) +PROC alterAppKeyMap(appkeymap:PTR TO keymap) + DEF nullkeys, keymappings:PTR TO LONG, keymaptypes, rawkeynum, i + -> NIL terminated ARRAY of keys our application wants to remap or disable + nullkeys:=[N0_KEY, N1_KEY, N2_KEY, N3_KEY, N4_KEY, + N5_KEY, N6_KEY, N7_KEY, N8_KEY, N9_KEY, + NPERIOD_KEY, NOPAREN_KEY, NCPAREN_KEY, NSLASH_KEY, + NASTER_KEY, NMINUS_KEY, NPLUS_KEY, NENTER_KEY, + NIL]:CHAR + -> Our application wants numeric pad keys remapped to nothing so that we can + -> use this keymap with MapANSI and NOT get back raw codes for numeric + -> keypad. Alternatively (for example) you could set the types to + -> KCF_STRING and set the mappings to point to NIL terminated strings. + keymappings:=appkeymap.lokeymap + keymaptypes:=appkeymap.lokeymaptypes + + i:=0 + WHILE rawkeynum:=nullkeys[i] + -> Because we allocated each of our Lo and Hi ARRAY pairs as sequential + -> memory, we can use the RAWKEY values directly to index into our + -> sequential Lo/Hi ARRAY + keymaptypes[rawkeynum]:=KCF_NOP + INC i + ENDWHILE +ENDPROC +->>> + +->>> PROC copyKeyMap(s:PTR TO keymap, d:PTR TO keymap) +PROC copyKeyMap(s:PTR TO keymap, d:PTR TO keymap) + DEF bb, ll:PTR TO LONG, i + -> Copy keymap s (source) to keymap d (dest) + ll:=s.lokeymap + FOR i:=0 TO MAP_SIZE-1 DO d.lokeymap[i]:=ll[]++ + ll:=s.hikeymap + FOR i:=0 TO MAP_SIZE-1 DO d.hikeymap[i]:=ll[]++ + + bb:=s.lokeymaptypes + FOR i:=0 TO TYPE_SIZE-1 DO d.lokeymaptypes[i]:=bb[]++ + bb:=s.hikeymaptypes + FOR i:=0 TO TYPE_SIZE-1 DO d.hikeymaptypes[i]:=bb[]++ + + bb:=s.locapsable + FOR i:=0 TO CAPS_SIZE-1 DO d.locapsable[i]:=bb[]++ + bb:=s.hicapsable + FOR i:=0 TO CAPS_SIZE-1 DO d.hicapsable[i]:=bb[]++ + + bb:=s.lorepeatable + FOR i:=0 TO REPS_SIZE-1 DO d.lorepeatable[i]:=bb[]++ + bb:=s.hirepeatable + FOR i:=0 TO REPS_SIZE-1 DO d.hirepeatable[i]:=bb[]++ +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.m b/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/appkeymap.m new file mode 100644 index 0000000000000000000000000000000000000000..b8657e3f850ce8eeaa8505bf85a65c0a858fcc5a GIT binary patch literal 2128 zcmaJ>O-vhC5S}%zSs{zKDXLIKU=z6&RK`yFn@R+{wRdBP{k&b<4G_SX)~Ty(s+CEl zTFPN7wN&E7A%~u-963Z0hg^DVq#kp~p{jB~Z7xxAKq^vwKnQ0$Z+5*rBFb9t^PAc4 zoB7_4Rx1><@EZ8fMt9OjlODu>Sp^{Xd<0SncMHb@9GhcBcT3%ujIo^iV65P7X7+pT z*l#B+_X)e-c{1Z%kESM28)Cmg4=jwOI|nu(?k23x0lV*R2Mj4-?2g?=!Ec=%VzyI> z&JMj>D*gju)V7sGryX&ys)Es;Vs-Y^$BK;q?XzhJcjFY;X&m8mpo~0x$no*_K4*Y9 zFGAp{6z4Fex@n&m^Ycznop;$&UxYAYa24-3=;t;9R`f6vu!e9QyExi4fIo00vOk}t zRaJ2(tGI(zck9!8?mb-L!B+tN=Wv(2y?nXCSDpVG_Sho(mY;+&4)TnHtXK+Xv_l16 z%Z4t4pOv}~eTuvcFbHp)Ix{>no=jbuoSK-wwy-#}lmU1Ll$#(cqYzGdv)H>}!zjeV zO2&rR`B6v!b$L_a=jg;EiuSrQ3g!>X;BMO>I?6ro>W6*4Hb| zTC;`c2+)fo?11!(18^J1GLA_IL+s1CRlikNZTm{SRjAnjAgzOhKmPR9Y}+e__wI{k zy>^tz$;3l&U636f>~N40SR16b2qPS!O}I_?h;WneXTm##TnduI=aNB~CA>%&Cp^s& zUJ~vQ{z>>d;a$RY!ZpHMgkEL*Uf|?9;f$Y;dJ9~st=2h7BEDqNTSiD8r~trsl=;Tf z;+jL4x1b+qfOT*K)n>ESTE#4VNv%e(tzqcL?;Lb9<(6GXngmhII#wf7vsY^?7WW_# zbHi$wbsM)l$U^8Yy@k*QS3%6wj8e5UJ+D;_@G=?om5fuKGqfWdr=S`^f?QT}THdH$ z(dMuwubVZsa>ZmqCc`vV)=WRcSGL5Ae5K?ixMqeGrdc;ZRTi0AI@EB^0xRX!QckFQ zjb#kg)cjVQGtY{zWG0xQnbXCrCzFvg#Xj+C@Mw}<6rxM)VpWl(VTw454o3FU37L;7oB~si_R*#=&Y=Z&PuxI%+y6^pXs7A zL+?7{XHv{-dfE5JV`ffY&iM%*7qZ2x-Baam^Of$Y^S5$vo4mU#2Y1Pf)4@&h mapansi.e - Converts a string to input events using MapANSI() function. +-> +-> This example will also take the created input events and add them to the +-> input stream using the simple commodities.library function AddIEvents(). +-> Alternately, you could open the input.device and use the input device +-> command IND_WRITEEVENT to add events to the input stream. + +->>> Header (globals) +MODULE 'commodities', + 'keymap', + 'devices/inputevent' + +ENUM ERR_NONE, ERR_INT, ERR_LIB, ERR_OVER + +RAISE ERR_LIB IF OpenLibrary()=NIL + +DEF inputEvent=NIL:PTR TO inputevent +->>> + +->>> PROC main() +PROC main() HANDLE + DEF string, tmp1, tmp2, i, + iebuffer[6]:ARRAY -> Space for two dead keys + 1 key + qualifiers + openall() + string:=';String converted to input events and sent to input device\n' + inputEvent.class:=IECLASS_RAWKEY + -> Turn each character into an inputevent + tmp1:=string + WHILE tmp1[] + -> Convert one character, use default key map + i:=MapANSI(tmp1, 1, iebuffer, 3, NIL) + -> Make sure we start without deadkeys + inputEvent.prev1downcode:=0 + inputEvent.prev1downqual:=0 + inputEvent.prev2downcode:=0 + inputEvent.prev2downqual:=0 + + tmp2:=iebuffer + SELECT i + CASE -2 + WriteF('Internal error\n') + Raise(ERR_INT) + CASE -1 + WriteF('Overflow\n') + Raise(ERR_OVER) + CASE 0 + WriteF('Can''t generate code\n') + CASE 3 + inputEvent.prev2downcode:=tmp2[]++ + inputEvent.prev2downqual:=tmp2[]++ + inputEvent.prev1downcode:=tmp2[]++ + inputEvent.prev1downqual:=tmp2[]++ + inputEvent.code:=tmp2[]++ + inputEvent.qualifier:=tmp2[] + CASE 2 + inputEvent.prev1downcode:=tmp2[]++ + inputEvent.prev1downqual:=tmp2[]++ + inputEvent.code:=tmp2[]++ + inputEvent.qualifier:=tmp2[] + CASE 1 + inputEvent.code:=tmp2[]++ + inputEvent.qualifier:=tmp2[] + ENDSELECT + + -> Send the key down event + AddIEvents(inputEvent) + -> Create a key up event + inputEvent.code:=inputEvent.code OR IECODE_UP_PREFIX + -> Send the key up event + AddIEvents(inputEvent) + tmp1++ + ENDWHILE +EXCEPT DO + closeall() + SELECT exception + CASE ERR_INT; WriteF('Error: MapANSI() internal error\n') + CASE ERR_LIB; WriteF('Error: could not open required library\n') + CASE ERR_OVER; WriteF('Error: MapANSI() overflow error\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC +->>> + +->>> PROC openall() +PROC openall() + keymapbase:=OpenLibrary('keymap.library', 37) + cxbase:=OpenLibrary('commodities.library', 37) + NEW inputEvent +ENDPROC +->>> + +->>> PROC closeall() +PROC closeall() + IF inputEvent THEN END inputEvent + IF cxbase THEN CloseLibrary(cxbase) + IF keymapbase THEN CloseLibrary(keymapbase) +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/maprawkey.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/maprawkey.e new file mode 100644 index 0000000..c7003ae --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Keymap/maprawkey.e @@ -0,0 +1,97 @@ +-> maprawkey.e - Map Intuition RAWKEY events to ANSI with MapRawKey() + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'keymap', + 'devices/inputevent', + 'exec/ports', + 'intuition/intuition' + +ENUM ERR_NONE, ERR_LIB, ERR_WIN + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +-> E-Note: used to convert an INT to unsigned +#define UNSIGNED(x) ((x) AND $FFFF) + +DEF window=NIL:PTR TO window +->>> + +->>> PROC main() +PROC main() HANDLE + DEF imsg:PTR TO intuimessage, eventptr:PTR TO LONG, windowsignal, + inputevent:PTR TO inputevent, buffer[8]:ARRAY, i, going=TRUE, class + openall() + window:=OpenWindowTagList(NIL, + [WA_WIDTH, 500, + WA_HEIGHT, 60, + WA_TITLE, 'MapRawKey - Press Keys', + WA_FLAGS, WFLG_CLOSEGADGET OR WFLG_ACTIVATE, + WA_IDCMP, IDCMP_RAWKEY OR IDCMP_CLOSEWINDOW, + NIL]) + windowsignal:=Shl(1, window.userport.sigbit) + + -> Initialise inputevent object + -> E-Note: first allocate it cleared using NEW + NEW inputevent + inputevent.class:=IECLASS_RAWKEY + + WHILE going + Wait(windowsignal) + + WHILE imsg:=GetMsg(window.userport) + class:=imsg.class + SELECT class + CASE IDCMP_CLOSEWINDOW + going:=FALSE + CASE IDCMP_RAWKEY + inputevent.code:=imsg.code + inputevent.qualifier:=UNSIGNED(imsg.qualifier) + + WriteF('RAWKEY: Code=$\z\h[4] Qualifier=$\z\h[4]\n', + imsg.code, UNSIGNED(imsg.qualifier)) + + -> Make sure deadkeys and qualifiers are taken into account. + eventptr:=imsg.iaddress + inputevent.eventaddress:=eventptr[] + + -> Map RAWKEY to ANSI + i:=MapRawKey(inputevent, buffer, 8, NIL) + + IF i=-1 + WriteF('*Overflow*') + ELSEIF i + -> This key or key combination mapped to something + WriteF('MAPS TO: ') + Write(stdout, buffer, i) + WriteF('\n') + ENDIF + ENDSELECT + ReplyMsg(imsg) + ENDWHILE + ENDWHILE +EXCEPT DO + IF window THEN CloseWindow(window) + closeall() + SELECT exception + CASE ERR_LIB; WriteF('Error: could not open keymap library\n') + CASE ERR_WIN; WriteF('Error: could not open window\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC +->>> + +->>> PROC openall() +PROC openall() + keymapbase:=OpenLibrary('keymap.library', 37) +ENDPROC +->>> + +->>> PROC closeall() +PROC closeall() + IF keymapbase THEN CloseLibrary(keymapbase) +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dpieee.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dpieee.e new file mode 100644 index 0000000..0b7d984 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dpieee.e @@ -0,0 +1,29 @@ +-> dpieee.e - Math DP IEEE example of dTst(). + +->>> Header (globals) +MODULE 'tools/longreal' + +CONST STRSIZE=20 +CONST FRACTSIZE=STRSIZE-8 +->>> + +->>> PROC main() +PROC main() HANDLE + -> E-Note: use the longreals from 'tools/longreal' for double precision IEEE + DEF num1:longreal, result, six:longreal, s[STRSIZE]:STRING + dInit(FALSE) -> E-Note: only use mathieeedoubbas library + dDiv(dPi(num1), dFloat(-6,six), num1) -> -30 degrees in radians + -> E-Note: or alternatively use dInit(TRUE) and dRad(dFloat(-30,num1), num1) + + result:=dTst(num1) + WriteF('Num1 = \s and result = \d\n', dFormat(s, num1, FRACTSIZE), result) + +EXCEPT DO + dCleanup() + SELECT exception + CASE "DLIB"; WriteF('Error: could not open mathieeedoubbas library\n') + ENDSELECT +ENDPROC +->>> + + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dptrans.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dptrans.e new file mode 100644 index 0000000..542bf1d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/dptrans.e @@ -0,0 +1,31 @@ +-> dptrans.e - Math Double-Precision Transcendental example of dSin(). + +->>> Header (globals) +MODULE 'tools/longreal' + +CONST STRSIZE=20 +CONST FRACTSIZE=STRSIZE-8 +->>> + +->>> PROC main() +PROC main() HANDLE + -> E-Note: use the longreals from 'tools/longreal' for double precision IEEE + DEF num1:longreal, result:longreal, four:longreal, s[STRSIZE]:STRING + dInit() + dDiv(dPi(num1), dFloat(4, four), num1) + -> E-Note: or alternatively use dRad(dFloat(45, num1), num1) + + dSin(num1, result) + WriteF('The double precision sine of 45 degrees is \s\n', + dFormat(s, result, FRACTSIZE)) + +EXCEPT DO + dCleanup() + SELECT exception + CASE "DLIB"; WriteF('Error: could not open mathieeedoubbas library\n') + ENDSELECT +ENDPROC +->>> + + + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/spieee.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/spieee.e new file mode 100644 index 0000000..008c966 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/spieee.e @@ -0,0 +1,32 @@ +-> spieee.e - Math SP IEEE example of SPMul(). + +->>> Header (globals) +MODULE 'mathieeesingbas' + +ENUM ERR_NONE, ERR_LIB + +RAISE ERR_LIB IF OpenLibrary()=NIL + +CONST STRSIZE=10, ACC=5 +->>> + +->>> PROC main() +PROC main() HANDLE + -> E-Note: IEEE single is the format used for reals in E + DEF mul1=-3.6, mul2=18.7 -> 3.6 multiplied by 18.7 + DEF result, s[STRSIZE]:STRING + mathieeesingbasbase:=OpenLibrary('mathieeesingbas.library', 34) + result:=IeeeSPMul(mul1, mul2) + -> E-Note: alternatively, no need to open library, use: result:=!mul1*mul2 + WriteF(RealF(s, mul1, ACC)) + WriteF(' multiplied by ') + WriteF(RealF(s, mul2, ACC)) + WriteF(' = \s\n', RealF(s, result, ACC)) +EXCEPT DO + IF mathieeesingbasbase THEN CloseLibrary(mathieeesingbasbase) + SELECT exception + CASE ERR_LIB; WriteF('Error: could not open mathieeesingbas library\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/sptrans.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/sptrans.e new file mode 100644 index 0000000..7ac3cf5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Math/sptrans.e @@ -0,0 +1,30 @@ +-> sptrans.e - Math SP IEEE Transcendental example of SPCos(). + +->>> Header (globals) +MODULE 'mathieeesingtrans' + +ENUM ERR_NONE, ERR_LIB + +RAISE ERR_LIB IF OpenLibrary()=NIL + +CONST STRSIZE=10, ACC=5 +->>> + +->>> PROC main() +PROC main() HANDLE + -> E-Note: IEEE single is the format used for reals in E + -> E-Note: C version gets it wrong: 30 degrees in radians is PI/6=0.52359878 + DEF num1=0.52359878, result, s[STRSIZE]:STRING + mathieeesingtransbase:=OpenLibrary('mathieeesingtrans.library', 34) + result:=IeeeSPCos(num1) + -> E-Note: alternatively, no need to open library, use: result:=Fcos(num1) + WriteF('The single precision cosine of 30 degrees is \s\n', + RealF(s, result, ACC)) +EXCEPT DO + IF mathieeesingtransbase THEN CloseLibrary(mathieeesingtransbase) + SELECT exception + CASE ERR_LIB; WriteF('Error: could not open mathieeesingtrans library\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/prefnotify.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/prefnotify.e new file mode 100644 index 0000000..cb289ca --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/prefnotify.e @@ -0,0 +1,57 @@ +-> prefnotify.e - Notified if serial prefs change +OPT PREPROCESS + +MODULE 'dos/dos', + 'dos/notify' + +ENUM ERR_NONE, ERR_KICK, ERR_NOTIFY, ERR_SIGNAL + +RAISE ERR_NOTIFY IF StartNotify()<>DOSTRUE, + ERR_SIGNAL IF AllocSignal()=255 + +#define PREFSFILENAME 'ENV:sys/serial.prefs' + +PROC main() HANDLE + DEF done=FALSE, notifyrequest=NIL:PTR TO notifyrequest, + signum=255, signals + -> We need at least V37 for notification + IF KickVersion(37)=FALSE THEN Raise(ERR_KICK) + -> Allocate a NotifyRequest structure + NEW notifyrequest + -> And allocate signalsbit + signum:=AllocSignal(-1) + -> Initialise notification request + notifyrequest.name:=PREFSFILENAME + notifyrequest.flags:=NRF_SEND_SIGNAL + -> Signal this task... + notifyrequest.task:=FindTask(NIL) + + -> ... with this signals bit + notifyrequest.signalnum:=signum + + StartNotify(notifyrequest) + WriteF('Select Serial Prefs SAVE or USE to notify this program\n') + WriteF('CTRL-C to exit\n\n') + -> Loop until Ctrl-C to exit + REPEAT + signals:=Wait(Shl(1, signum) OR SIGBREAKF_CTRL_C) + IF signals AND Shl(1, signum) + WriteF('Notification signal received.\n') + ENDIF + IF signals AND SIGBREAKF_CTRL_C + EndNotify(notifyrequest) + done:=TRUE + ENDIF + UNTIL done +EXCEPT DO + IF signum<>255 THEN FreeSignal(signum) + IF notifyrequest THEN END notifyrequest -> E-Note: not really necessary... + SELECT exception + CASE ERR_KICK; WriteF('Requires at least V37\n') + CASE ERR_NOTIFY; WriteF('Can''t start notification\n') + CASE ERR_SIGNAL; WriteF('No signals available\n') + CASE "MEM"; WriteF('Not enough memory for NotifyRequest.\n') + ENDSELECT +ENDPROC + +verstag: CHAR 0, '$VER: prefnot 37.1 (09.07.91)', 0 \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/showprefs.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/showprefs.e new file mode 100644 index 0000000..7418d0d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Preferences/showprefs.e @@ -0,0 +1,137 @@ +-> showprefs.e - Parse and show some info from an IFF Preferences file +-> E-Note: ignore the rubbish (in the C version) about startup code + +MODULE 'iffparse', + 'devices/timer', + 'dos/dos', + 'graphics/text', + 'libraries/iffparse', + 'prefs/font', + 'prefs/icontrol', + 'prefs/input', + 'prefs/overscan', + 'prefs/printergfx', + 'prefs/printertxt', + 'prefs/prefhdr', + 'prefs/screenmode', + 'prefs/serial' + +ENUM ERR_NONE, ERR_IFF, ERR_LIB, ERR_OPEN, ERR_RDARGS, TOTAL_ERRS + +-> E-Note: the use of exceptions is carefully balanced +RAISE ERR_IFF IF AllocIFF()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_OPEN IF Open()=NIL, + ERR_RDARGS IF ReadArgs()=NIL + +PROC main() HANDLE + DEF readargs=NIL, rargs[2]:ARRAY OF LONG, iffhandle=NIL:PTR TO iffhandle, + filename=NIL, error, rc=RETURN_OK, iffErrTxt:PTR TO LONG + + iffparsebase:=OpenLibrary('iffparse.library', 37) + + readargs:=ReadArgs('FILE/A', rargs, NIL) + IF filename:=rargs[0] + -> Allocate an IFF handle + iffhandle:=AllocIFF() + -> Open the file for reading + iffhandle.stream:=Open(filename, OLDFILE) + -> Initialise the iff handle + InitIFFasDOS(iffhandle) + IF (error:=OpenIFF(iffhandle, IFFF_READ))=0 + PropChunk(iffhandle, ID_PREF, ID_PRHD) + + PropChunk(iffhandle, ID_PREF, ID_FONT) + PropChunk(iffhandle, ID_PREF, ID_ICTL) + PropChunk(iffhandle, ID_PREF, ID_INPT) + PropChunk(iffhandle, ID_PREF, ID_OSCN) + PropChunk(iffhandle, ID_PREF, ID_PGFX) + PropChunk(iffhandle, ID_PREF, ID_PTXT) + PropChunk(iffhandle, ID_PREF, ID_SCRM) + PropChunk(iffhandle, ID_PREF, ID_SERL) + + -> E-Note: handle the funny loop more cleanly using a separate procedure + REPEAT + UNTIL error:=parse(iffhandle) + ENDIF + CloseIFF(iffhandle) + IF error<>IFFERR_EOF + iffErrTxt:=['EOF', 'EOC', 'no lexical scope', 'insufficient memory', + 'stream read error','stream write error','stream seek error', + 'file corrupt', 'IFF syntax error', 'not an IFF file', + 'required call-back hook missing', NIL] + WriteF('\s: \s\n', rargs[], iffErrTxt[-error-1]) + rc:=RETURN_FAIL + ENDIF + ENDIF +EXCEPT DO + SELECT TOTAL_ERRS OF exception + CASE ERR_OPEN, ERR_RDARGS + error:=IoErr() + SetIoErr(error) + IF error + rc:=RETURN_FAIL + PrintFault(error, IF filename THEN filename ELSE '') + ENDIF + CASE ERR_IFF; WriteF('Can''t allocate IFF handle\n') + CASE ERR_LIB; WriteF('Can''t open iffparse.library\n') + ENDSELECT + IF iffhandle THEN FreeIFF(iffhandle) + IF readargs THEN FreeArgs(readargs) + IF iffparsebase THEN CloseLibrary(iffparsebase) +ENDPROC rc + +-> E-Note: handle the funny loop more cleanly using a separate procedure +PROC parse(iffhandle) + DEF ifferror, sp:PTR TO storedproperty, hdrsp, cnode:PTR TO contextnode + IF ifferror:=ParseIFF(iffhandle, IFFPARSE_STEP) + RETURN IF ifferror=IFFERR_EOC THEN 0 ELSE ifferror + ENDIF + + -> Do nothing if this is a PrefHeader chunk; we'll pop it later when there + -> is a pref chunk. + IF cnode:=CurrentChunk(iffhandle) + IF (cnode.id=ID_PRHD) OR (cnode.id=ID_FORM) THEN RETURN 0 + ENDIF + + -> Get the preferences header, stored previously + hdrsp:=FindProp(iffhandle, ID_PREF, ID_PRHD) + + IF sp:=FindProp(iffhandle, ID_PREF, ID_FONT) + WriteF('FrontPen: \d\n', sp.data::fontprefs.frontpen) + WriteF('BackPen: \d\n', sp.data::fontprefs.backpen) + WriteF('Font: \s\n', sp.data::fontprefs.name) + WriteF('YSize: \d\n', sp.data::fontprefs.textattr.ysize) + WriteF('Style: \d\n', sp.data::fontprefs.textattr.style) + WriteF('Flags: \d\n', sp.data::fontprefs.textattr.flags) + ELSEIF sp:=FindProp(iffhandle, ID_PREF, ID_ICTL) + WriteF('TimeOut: \d\n', sp.data::icontrolprefs.timeout) + WriteF('MetaDrag: \d\n', sp.data::icontrolprefs.metadrag) + WriteF('WBtoFront: \d\n', sp.data::icontrolprefs.wbtofront) + WriteF('FrontToBack: \d\n', sp.data::icontrolprefs.fronttoback) + WriteF('ReqTrue: \d\n', sp.data::icontrolprefs.reqtrue) + WriteF('ReqFalse: \d\n', sp.data::icontrolprefs.reqfalse) + -> Etc. + ELSEIF sp:=FindProp(iffhandle, ID_PREF, ID_INPT) + WriteF('PointerTicks: \d\n', sp.data::inputprefs.pointerticks) + WriteF('DoubleClick/Secs: \d\n', sp.data::inputprefs.doubleclick.secs) + WriteF('DoubleClick/Micro: \d\n', sp.data::inputprefs.doubleclick.micro) + -> Etc. + ELSEIF sp:=FindProp(iffhandle, ID_PREF, ID_OSCN) + WriteF('DisplayID: $\h\n', sp.data::overscanprefs.displayid) + -> Etc. + ELSEIF sp:=FindProp(iffhandle, ID_PREF, ID_PGFX) + WriteF('Aspect: \d\n', sp.data::printergfxprefs.aspect) + -> Etc. + ELSEIF sp:=FindProp(iffhandle, ID_PREF, ID_PTXT) + WriteF('Driver: \s\n', sp.data::printertxtprefs.driver) + -> Etc. + ELSEIF sp:=FindProp(iffhandle, ID_PREF, ID_SCRM) + WriteF('DisplayID: $\h\n', sp.data::screenmodeprefs.displayid) + -> Etc. + ELSEIF sp:=FindProp(iffhandle, ID_PREF, ID_SERL) + WriteF('BaudRate: \d\n', sp.data::serialprefs.baudrate) + -> Etc. + ENDIF + RETURN 0 +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/README b/amigae33a/E_v3.3a/Src/Src/Rkrm/README new file mode 100644 index 0000000..186a128 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/README @@ -0,0 +1,41 @@ +Short: E versions of RKRM examples (Part One and Two) +Author: m88jrh@ecs.ox.ac.uk (Jason R. Hulance) + +JRH's RKRM Examples (Part One and Two) +====================================== + +This archive contains translations of all the examples from the following +chapters of the RKRM (Libraries): ASL, Commodities, Exec, GadTools, +Intuition, Preferences, Workbench, Expansion, Graphics (all the corresponding +chapters), IFFParse, Keymap, Math (minus the FFP examples) and Utility. Also +included are translations of all the Resource, Clipboard and Console examples +from the RKRM (Devices). + +The examples retain most of the original comments, with comments specific to +these E versions beginning "-> E-Note:". A lot of effort has been put into +showing how to effectively use E features such as exceptions and lists. +A number of bugs in the original examples have also been eliminated. + +If you are new to E you should pay special attention to the effect of using +exceptions: error handling is and clean-up is neatly separated from the main +code, and the code is generally much less indented. You should also notice +the special care taken to initialise variables appropriately so that +clean-up is made much more simple in the handlers. + +If you wish to recompile the sources (I expect you might...), you will need +my Typed Modules (V40), my AmigaLib modules and my Useful modules. These +archives should all be available where you found this archive (Aminet? In +'dev/e'?). [note: these are all included in the 'Modules' directory of +this distribution -wouter] + +These executables, E sources and E modules are all Copyright (C) 1995, +Jason R. Hulance. +The original RKRM examples are Copyright (C) 1992, Commodore-Amiga Inc. + +You are free to use the files in this archive to help create your own +programs (whether they are freeware or commercial), but if you wish to +distribute any part of this archive you must include it all, unmodified, +and with this file. + +(Hopefully, there will be a Part Three which will contain the remainder of the +RKRM examples.) diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Allocate_Misc.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Allocate_Misc.e new file mode 100644 index 0000000..189b57c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Allocate_Misc.e @@ -0,0 +1,47 @@ +-> Allocate_Misc.e +-> +-> Example of allocating a miscellaneous resource. We will allocate the serial +-> resource and wait until CTRL-C is pressed. While we are waiting, the +-> Query_Serial program should be run. It will try to open the serial device +-> and if unsuccessful, will return the name of the owner. It will be us! + +-> E-Note: E does not (as of v3.1a) support Resources in the conventional way +MODULE 'other/misc', + 'dos/dos', + 'resources/misc' + +ENUM ERR_NONE, ERR_BITS, ERR_PORT + +PROC main() HANDLE + -> E-Note: to help with cleaning up "owner" has been split into "portowner" + -> and "bitsowner" which are initialised to non-NIL values + DEF portowner=-1, bitsowner=-1 -> Owner of misc resource + + miscbase:=OpenResource('misc.resource') + + -> Allocate both pieces of the serial hardware + IF portowner:=allocMiscResource(MR_SERIALPORT, 'Serial Port Hog') + Raise(ERR_PORT) + ENDIF + IF bitsowner:=allocMiscResource(MR_SERIALBITS, 'Serial Port Hog') + Raise(ERR_BITS) + ENDIF + + -> Wait for CTRL-C to be pressed + WriteF('\nWaiting for CTRL-C...\n') + Wait(SIGBREAKF_CTRL_C) + + -> We're back + +EXCEPT DO + -> Deallocate the serial port register + IF bitsowner=NIL THEN freeMiscResource(MR_SERIALBITS) + -> Deallocate the serial port + IF portowner=NIL THEN freeMiscResource(MR_SERIALPORT) + SELECT exception + CASE ERR_BITS + WriteF('Unable to allocate MR_SERIALBITS because \s owns it\n', bitsowner) + CASE ERR_PORT + WriteF('Unable to allocate MR_SERIALPORT because \s owns it\n', portowner) + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/CIA_interval.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/CIA_interval.e new file mode 100644 index 0000000..4d086d9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/CIA_interval.e @@ -0,0 +1,271 @@ +-> Cia_Interval.e - Demonstrate allocation and use of a cia interval timer + +OPT PREPROCESS + +-> E-Note: we need eCodeIntServer() in order to use an E PROC as a CIA interrupt +MODULE 'other/cia', + 'other/ecode', + 'exec/interrupts', + 'exec/libraries', + 'exec/nodes', + 'exec/tasks', + 'hardware/cia', + 'resources/cia' + +ENUM ERR_NONE, ERR_ECODE, ERR_SIG, ERR_TIMER + +CONST COUNTDOWN=20, HICOUNT=$FF, LOCOUNT=$FF + +CONST STOPA_AND=CIACRAF_TODIN OR CIACRAF_PBON OR + CIACRAF_OUTMODE OR CIACRAF_SPMODE + -> + -> AND mask for use with control register A + -> (interval timer A on either CIA) + -> + -> STOP - + -> START bit 0 == 0 (STOP IMMEDIATELY) + -> PBON bit 1 == same + -> OUT bit 2 == same + -> RUN bit 3 == 0 (SET CONTINUOUS MODE) + -> LOAD bit 4 == 0 (NO FORCE LOAD) + -> IN bit 5 == 0 (COUNTS 02 PULSES) + -> SP bit 6 == same + -> TODIN bit 7 == same (unused on ciacra) + +CONST STOPB_AND=CIACRBF_ALARM OR CIACRBF_PBON OR CIACRBF_OUTMODE + -> + -> AND mask for use with control register B + -> (interval timer B on either CIA) + -> + -> STOP - + -> START bit 0 == 0 (STOP IMMEDIATELY) + -> PBON bit 1 == same + -> OUT bit 2 == same + -> RUN bit 3 == 0 (SET CONTINUOUS MODE) + -> LOAD bit 4 == 0 (NO FORCE LOAD) + -> IN0 bit 5 == 0 (COUNTS 02 PULSES) + -> IN1 bit 6 == 0 (COUNTS 02 PULSES) + -> ALARM bit 7 == same (TOD alarm control bit) + +CONST STARTA_OR=CIACRAF_START + -> + -> OR mask for use with control register A + -> (interval timer A on either CIA) + -> + -> START - + -> + -> START bit 0 == 1 (START TIMER) + -> + -> All other bits unaffected. + +CONST STARTB_OR=CIACRBF_START + -> + -> OR mask for use with control register B + -> (interval timer A on either CIA) + -> + -> START - + -> + -> START bit 0 == 1 (START TIMER) + -> + -> All other bits unaffected. + +-> Structure which will be used to hold all relevant information about cia +-> timer we manage to allocate. +OBJECT freetimer + ciabase -> CIA Library Base + timerbit -> Timer bit allocated + cia -> Pointer to hardware + ciacr:PTR TO CHAR -> Pointer to control register + cialo:PTR TO CHAR -> Pointer to low byte of timer + ciahi:PTR TO CHAR -> Pointer to high byte of timer + timerint:is -> Interrupt structure + stopmask:CHAR -> Stop/set-up timer + startmask:CHAR -> Start timer +ENDOBJECT + +-> Structure which will be used by the interrupt routine called when our +-> cia interval timer generates an interrupt. +OBJECT exampledata + task -> Task to signal + signal -> Signal bit to use + counter +ENDOBJECT + +DEF ciaa=CIAA_ADDR:PTR TO cia, ciab=CIAB_ADDR:PTR TO cia + +-> This is the interrupt routine which will be called when our CIA interval +-> timer counts down. +-> +-> This example decrements a counter each time the interrupt routine is called +-> until the counter reaches 0, at which time it signals our main task. +-> +-> Note that interrupt handling code should be efficient, and will generally be +-> written in assembly code. Signaling another task such as this example does +-> is also a useful way of handling interrupts in an expedient manner. +-> E-Note: thanks to eCodeIntServer() we get ft.timerint.data as an argument +PROC exampleInterrupt(ed:PTR TO exampledata) + IF ed.counter + ed.counter:=ed.counter-1 -> Decrement counter + ELSE + ed.counter:=COUNTDOWN -> Reset counter + Signal(ed.task, Shl(1, ed.signal)) + ENDIF +ENDPROC + +PROC main() HANDLE + DEF ft:freetimer, ed:exampledata + + -> Set up data which will be passed to interrupt + ed.task:=FindTask(NIL) + + -> E-Note: C version doesn't check the return value properly + ed.signal:=AllocSignal(-1) + IF ed.signal=-1 THEN Raise(ERR_SIG) + + -> Prepare freetimer object: set-up interrupt + ft.timerint.ln.type:=NT_INTERRUPT + ft.timerint.ln.pri:=0 + ft.timerint.ln.name:='cia_example' + + ft.timerint.data:=ed + -> E-Note: eCodeIntServer() wraps an E PROC for use as a CIA interrupt + ft.timerint.code:=eCodeIntServer({exampleInterrupt}) + IF ft.timerint.code=NIL THEN Raise(ERR_ECODE) + + -> Call function to find a free CIA interval timer with flag indicating + -> that we prefer a CIA-A timer. + WriteF('Attempting to allocate a free timer\n') + + findFreeTimer(ft, TRUE) + + WriteF('CIA-\c timer ', IF ft.cia=ciaa THEN "A" ELSE "B") + + WriteF('\c allocated\n', IF ft.timerbit=CIAICRB_TA THEN "A" ELSE "B") + + -> We found a free interval timer. Let's start it running. + startTimer(ft, ed) + + -> Wait for a signal + WriteF('Waiting for signal bit \d\n', ed.signal) + + Wait(Shl(1, ed.signal)) + + WriteF('We woke up!\n') + + -> Release the interval timer + remICRVector(ft.ciabase, ft.timerbit, ft.timerint) + +EXCEPT DO + IF ed.signal<>-1 THEN FreeSignal(ed.signal) + SELECT exception + CASE ERR_ECODE; WriteF('Ran out of memory in eCodeIntServer()\n') + CASE ERR_SIG; WriteF('Could not allocate signal\n') + CASE ERR_TIMER; WriteF('No CIA interval timer available\n') + ENDSELECT +ENDPROC + +-> This routine sets up the interval timer we allocated with addICRVector(). +-> Note that we may have already received one, or more interrupts from our +-> timer. Make no assumptions about the initial state of any of the hardware +-> registers we will be using. +PROC startTimer(ft:PTR TO freetimer, ed:PTR TO exampledata) + DEF cia:PTR TO cia + cia:=ft.cia + + -> Note that there are differences between control register A, and B on + -> each CIA (e.g., the TOD alarm bit, and INMODE bits). + IF ft.timerbit=CIAICRB_TA + -> E-Note: use offsets to get addresses of the CIA bytes + ft.ciacr:=cia+CIACRA -> Control register A + ft.cialo:=cia+CIATALO -> Low byte counter + ft.ciahi:=cia+CIATAHI -> High byte counter + + ft.stopmask:=STOPA_AND -> Set-up mask values + ft.startmask:=STARTA_OR + ELSE + ft.ciacr:=cia+CIACRB -> Control register B + ft.cialo:=cia+CIATBLO -> Low byte counter + ft.ciahi:=cia+CIATBHI -> High byte counter + + ft.stopmask:=STOPB_AND -> Set-up mask values + ft.startmask:=STARTB_OR + ENDIF + + -> Modify control register within Disable(). This is done to avoid race + -> conditions since code like this will be generated: + -> + -> value = Read hardware byte + -> AND value with MASK + -> Write value to hardware byte + -> + -> If we take a task switch in the middle of this sequence, two tasks trying + -> to modify the same register could trash each others' bits. + -> + -> Normally this code would be written in Assembly language using atomic + -> instructions so that the Disable() would not be needed. + + Disable() + -> STOP timer, set 02 pulse count-down mode, set continuous mode + ft.ciacr[]:=ft.ciacr[] AND ft.stopmask + Enable() + + -> Clear signal bit - interrupt will signal us later + SetSignal(NIL, Shl(1, ed.signal)) + + -> Count-down X number of times + ed.counter:=COUNTDOWN + + -> Start the interval timer - we will start the counter after writing the + -> low, and high byte counter values. + ft.cialo[]:=LOCOUNT + ft.ciahi[]:=HICOUNT + + -> Turn on start bit - same bit for both A, and B control regs + Disable() + ft.ciacr[]:=ft.ciacr[] OR ft.startmask + Enable() +ENDPROC + +-> A routine to find a free interval timer. +-> +-> This routine makes no assumptions about which interval timers (if any) are +-> available for use. Currently there are two interval timers per CIA chip. +-> +-> Because CIA usage may change in the future, your code should use a routine +-> like this to find a free interval timer. +-> +-> Note that the routine takes a preference flag (which is used to indicate +-> that you would prefer an interval timer on CIA-A). If the flag is FALSE, +-> it means that you would prefer an interval timer on CIA-B. +PROC findFreeTimer(ft:PTR TO freetimer, preferA) + DEF ciaabase, ciabbase + + -> Get pointers to both Resource bases + ciaabase:=OpenResource(CIAANAME) + ciabbase:=OpenResource(CIABNAME) + + -> Try for a CIA-A timer first? + ft.ciabase:=IF preferA THEN ciaabase ELSE ciabbase -> Library address + ft.cia:=IF preferA THEN ciaa ELSE ciab -> Hardware address + + IF tryTimer(ft) THEN RETURN + + -> Try for an interval timer on the other cia + ft.ciabase:=IF preferA THEN ciabbase ELSE ciaabase -> Library address + ft.cia:=IF preferA THEN ciab ELSE ciaa -> Hardware address + + IF tryTimer(ft)=FALSE THEN Raise(ERR_TIMER) +ENDPROC + +-> Try to obtain a free interval timer on a CIA. +PROC tryTimer(ft:PTR TO freetimer) + IF NIL=addICRVector(ft.ciabase, CIAICRB_TA, ft.timerint) + ft.timerbit:=CIAICRB_TA + RETURN TRUE + ENDIF + + IF NIL=addICRVector(ft.ciabase, CIAICRB_TB, ft.timerint) + ft.timerbit:=CIAICRB_TB + RETURN TRUE + ENDIF +ENDPROC FALSE diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Disk_Unit_ID.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Disk_Unit_ID.e new file mode 100644 index 0000000..f3b20df --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Disk_Unit_ID.e @@ -0,0 +1,26 @@ +-> Get_Disk_Unit_ID.e - Example of getting the UnitID of a disk + +OPT PREPROCESS + +-> E-Note: E does not (as of v3.1a) support Resources in the conventional way +MODULE 'other/disk', + 'resources/disk' + +PROC main() + DEF ids, type + IF NIL=(diskbase:=OpenResource(DISKNAME)) + WriteF('Cannot open \s\n', DISKNAME) -> E-Note: big typo in C version + ELSE + WriteF('Defined drive types are:\n') + WriteF(' AMIGA $00000000\n') + WriteF(' 5.25" $55555555\n') + WriteF(' AMIGA $00000000 (high density)\n') -> Commodore-only product + WriteF(' None $FFFFFFFF\n\n') + + -> What are the UnitIDs? + FOR ids:=0 TO 3 + type:=getUnitID(ids) + WriteF('The UnitID for unit \d is $\z\h[8]\n', ids, type) + ENDFOR + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Filesys.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Filesys.e new file mode 100644 index 0000000..030f127 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Get_Filesys.e @@ -0,0 +1,38 @@ +-> Get_Filesys.e - Example of examining the FileSysRes list + +OPT PREPROCESS + +MODULE 'exec/lists', + 'exec/nodes', + 'resources/filesysres' + +DEF filesysresbase:PTR TO filesysresource + +PROC main() + DEF fse:PTR TO filesysentry, x + -> NOTE - you should actually be in a Forbid while accessing any system list + -> for which no other method of arbitration is available. However, for this + -> example we will be printing the information (which would break a Forbid + -> anyway) so we won't Forbid. In real life, you should Forbid, copy the + -> information you need, Permit, then print the info. + IF NIL=(filesysresbase:=OpenResource(FSRNAME)) + WriteF('Cannot open \s\n', FSRNAME) + ELSE + fse:=filesysresbase.filesysentries.head + WHILE fse.ln.succ + -> An A3000 running V34 does not have the name field filled in. + -> An A2000 running V34 with an A590/2091 controller also does not have + -> the name field filled in. + IF fse.ln.name THEN WriteF('Found filesystem creator: \s\n', fse.ln.name) + + WriteF(' DosType: ') + FOR x:=24 TO 8 STEP -8 DO Out(stdout, Shr(fse.dostype,x) AND $FF) + + Out(stdout, (fse.dostype AND $FF)+$30) + + WriteF('\n Version: \d', Shr(fse.version, 16)) + WriteF('.\d\n\n', fse.version AND $FFFF) + fse:=fse.ln.succ + ENDWHILE + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Query_Serial.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Query_Serial.e new file mode 100644 index 0000000..c909a2e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Query_Serial.e @@ -0,0 +1,60 @@ +-> Query_Serial.e - Try to open the serial device and if unsuccessful, +-> return the name of the owner. + +OPT PREPROCESS -> E-Note: we are using the NAME macros + +-> E-Note: E does not (as of v3.1a) support Resources in the conventional way +MODULE 'amigalib/io', + 'amigalib/ports', + 'other/misc', + 'devices/serial', + 'dos/dos', + 'exec/io', + 'resources/misc' + +ENUM ERR_NONE, ERR_CRIO, ERR_PORT + +CONST UNIT_NUMBER=0 + +DEF serialMP=NIL, serialIO=NIL:PTR TO ioextser + +PROC main() HANDLE + DEF status, -> Return value of SDCMD_QUERY + user -> Name of serial port owner if not us + + IF NIL=(serialMP:=createPort(NIL, NIL)) THEN Raise(ERR_PORT) + IF NIL=(serialIO:=createExtIO(serialMP, SIZEOF ioextser)) THEN Raise(ERR_CRIO) + IF OpenDevice(SERIALNAME, UNIT_NUMBER, serialIO, 0) + WriteF('\n\s did not open', SERIALNAME) + + miscbase:=OpenResource(MISCNAME) + + -> Find out who has the serial device + IF NIL=(user:=allocMiscResource(MR_SERIALPORT, 'Us')) + WriteF('\n') + freeMiscResource(MR_SERIALPORT) + ELSE + WriteF(' because \s owns it\n\n', user) + ENDIF + ELSE + serialIO.iostd.command:=SDCMD_QUERY + SendIO(serialIO) -> Execute query + + status:=serialIO.status -> Store returned status + + WriteF('\t The serial port status is \h\n', status) + + AbortIO(serialIO) + WaitIO(serialIO) + + CloseDevice(serialIO) + ENDIF + +EXCEPT DO + IF serialIO THEN deleteExtIO(serialIO) + IF serialMP THEN deletePort(serialMP) + SELECT exception + CASE ERR_CRIO; WriteF('Can''t create IO request\n') + CASE ERR_PORT; WriteF('Can''t create message port\n') + ENDSELECT +ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_BattClock.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_BattClock.e new file mode 100644 index 0000000..c62a70d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_BattClock.e @@ -0,0 +1,63 @@ +-> Read_BattClock.e +-> +-> Example of reading the BattClock and converting its output to a useful +-> measure of time by calling the Amiga2Date() utility function. + +OPT PREPROCESS + +-> E-Note: E does not (as of v3.1a) support Resources in the conventional way +MODULE 'other/battclock', -> E-Note: swapping these two trips a bug in EC v3.1a + 'utility', + 'resources/battclock', + 'utility/date' + +ENUM ERR_NONE, ERR_LIB, ERR_RES + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_RES IF OpenResource()=NIL + +PROC main() HANDLE + DEF days:PTR TO LONG, months:PTR TO LONG, ampm, + amigaTime, myClock:clockdata + days:=['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', + 'Friday', 'Saturday'] + months:=['January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December'] + + utilitybase:=OpenLibrary('utility.library', 33) + battclockbase:=OpenResource(BATTCLOCKNAME) + + -> Get number of seconds till now + amigaTime:=readBattClock() + + -> Convert to a ClockData structure + Amiga2Date(amigaTime, myClock) + + WriteF('\nRobin, tell everyone the BatDate and BatTime') + + -> Print the Date + WriteF('\n\nOkay Batman, the BatDate is ') + WriteF('\s, \s \d, \d', days[myClock.wday], months[myClock.month-1], + myClock.mday, myClock.year) + + -> Convert military time to normal time and set AM/PM + IF myClock.hour<12 + ampm:='AM' -> hour less than 12, must be morning + ELSE + ampm:='PM' -> hour greater than 12,must be night + myClock.hour:=myClock.hour-12 -> Subtract the extra 12 of military + ENDIF + + IF myClock.hour=0 THEN myClock.hour:=12 -> Don't forget the 12s + + -> Print the time + WriteF('\n the BatTime is ') + WriteF('\d:\z\d[2]:\z\d[2] \s\n\n', + myClock.hour, myClock.min, myClock.sec, ampm) +EXCEPT DO + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ERR_LIB; WriteF('Error: Could not open utility.library\n') + CASE ERR_RES; WriteF('Error: Unable to open the \s\n', BATTCLOCKNAME) + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_Potinp.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_Potinp.e new file mode 100644 index 0000000..3962b6d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Resources/Read_Potinp.e @@ -0,0 +1,65 @@ +-> Read_Potinp.e +-> +-> An example of using the potgo.resource to read pins 9 and 5 of port 1 +-> (the non-mouse port). This bypasses the gameport.device. When the right +-> or middle button on a mouse plugged into port 1 is pressed, the read value +-> will change. +-> +-> Use of port 0 (mouse) is unaffected. + +-> E-Note: E does not (as of v3.1a) support Resources in the conventional way +MODULE 'other/potgo', + 'dos/dos', + 'hardware/custom' + +ENUM ERR_NONE, ERR_POT, ERR_RES + +RAISE ERR_RES IF OpenResource()=NIL + +CONST OUTRY=$8000, DATRY=$4000, OUTRX=$2000, DATRX=$1000 + +DEF potbits, value + +PROC main() HANDLE + -> E-Note: set-up "custom" + DEF custom=CUSTOMADDR:PTR TO custom + + potgobase:=OpenResource('potgo.resource') + + -> Get the bits for the right and middle mouse buttons on the alternate + -> mouse port. + potbits:=allocPotBits(OUTRY OR DATRY OR OUTRX OR DATRX) + + IF potbits<>(OUTRY OR DATRY OR OUTRX OR DATRX) + freePotBits(potbits) + Raise(ERR_POT) + ENDIF + + -> Set all ones in the register (masked by potbits) + writePotgo($FFFFFFFF, potbits) + + WriteF('\n'+ + 'Plug a mouse into the second port. This program will indicate when\n'+ + 'the right or middle button (if the mouse is so equipped) is pressed.\n'+ + 'Stop the program with Control-C. Press return now to begin.\n') + -> E-Note: stdout is valid (we've used WriteF()), so try that if no stdin + Inp(IF stdin THEN stdin ELSE stdout) + + REPEAT + -> Read word at $DFF016 + value:=custom.potinp + + -> Show what was read (restricted to our allocated bits) + -> E-Note: use "\b" to prevent a linefeed, giving single line, fast update + WriteF('POTINP = $\h\b', value AND potbits) + UNTIL SIGBREAKF_CTRL_C AND SetSignal(0, 0) -> Until CTRL-C is pressed + WriteF('\n') + + freePotBits(potbits) + +EXCEPT DO + SELECT exception + CASE ERR_POT; WriteF('Pot bits are already allocated! \h\n', potbits) + CASE ERR_RES; WriteF('Could not open potgo.resource\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/a2d.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/a2d.e new file mode 100644 index 0000000..521b546 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/a2d.e @@ -0,0 +1,55 @@ +-> a2d.e + +->>> Header (globals) +MODULE 'timer', + 'utility', + 'devices/timer', + 'exec/io', + 'utility/date' + +ENUM ERR_NONE, ERR_DEV, ERR_LIB + +RAISE ERR_DEV IF OpenDevice()<>0, + ERR_LIB IF OpenLibrary()=NIL +->>> + +->>> PROC main() +PROC main() HANDLE + DEF clockdata:PTR TO clockdata, tr:PTR TO timerequest, tv:PTR TO timeval, + seconds, open_dev=FALSE + utilitybase:=OpenLibrary('utility.library', 37) + NEW tr, tv, clockdata + OpenDevice('timer.device', UNIT_VBLANK, tr, 0) + open_dev:=TRUE + timerbase:=tr.io.device + + GetSysTime(tv) + + WriteF('GetSysTime():\t\d \d\n', tv.secs, tv.micro) + + Amiga2Date(tv.secs, clockdata) + + WriteF('Amiga2Date(): sec \d min \d hour \d\n', + clockdata.sec, clockdata.min, clockdata.hour) + + WriteF(' mday \d month \d year \d wday \d\n', + clockdata.mday, clockdata.month, clockdata.year, clockdata.wday) + + seconds:=CheckDate(clockdata) + + WriteF('CheckDate():\t\d\n', seconds) + + seconds:=Date2Amiga(clockdata) + + WriteF('Date2Amiga():\t\d\n', seconds) +EXCEPT DO + IF open_dev THEN CloseDevice(tr) + END clockdata, tv, tr + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ERR_DEV; WriteF('Error: could not open timer device\n') + CASE ERR_LIB; WriteF('Error: could not open utility library\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/hooks1.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/hooks1.e new file mode 100644 index 0000000..27d39bb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/hooks1.e @@ -0,0 +1,39 @@ +-> hooks1.e + +->>> Header (globals) +MODULE 'utility', + 'utility/hooks', + 'tools/installhook' + +ENUM ERR_NONE, ERR_LIB + +RAISE ERR_LIB IF OpenLibrary()=NIL +->>> + +->>> PROC myFunction(h:PTR TO hook, o, msg) +-> This function only prints out a message indicating that we are inside the +-> callback function. +PROC myFunction(h:PTR TO hook, o, msg) + -> E-Note: installhook has set-up access to data segment + WriteF('Inside myFunction()\n') +ENDPROC 1 +->>> + +->>> PROC main() +PROC main() HANDLE + DEF h:hook + -> Open the utility library + utilitybase:=OpenLibrary('utility.library', 36) + -> Initialise the callback hook + -> E-Note: use installhook to do the main stuff (so h.data cannot be used) + installhook(h, {myFunction}) + -> Use the utility library function to invoke the hook + CallHookPkt(h, NIL, NIL) +EXCEPT DO + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ERR_LIB; WriteF('Error: could not open utility library\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/istr.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/istr.e new file mode 100644 index 0000000..316710a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/istr.e @@ -0,0 +1,39 @@ +-> istr.e + +->>> Header (globals) +MODULE 'utility' + +ENUM ERR_NONE, ERR_LIB + +RAISE ERR_LIB IF OpenLibrary()=NIL +->>> + +->>> PROC main() +PROC main() HANDLE + DEF butter, bread, ch1, ch2, result + butter:='Bøtervløøt' + bread:='Knåckerbrøt' + + utilitybase:=OpenLibrary('utility.library', 37) + + result:=Stricmp(butter, bread) + + WriteF('Comparing \s with \s yields \d\n', butter, bread, result) + + result:=Strnicmp(bread, butter, StrLen(bread)) + + WriteF('Comparing (with length) \s with \s yields \d\n', bread, butter, result) + + ch1:=ToUpper($E6) -> æ ASCII character 230 ae ligature + ch2:=ToLower($D0) -> Ð ASCII character 208 Icelandic Eth + + WriteF('Chars \c \c\n', ch1, ch2) +EXCEPT DO + -> E-Note: C version forgets to close the library! + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ERR_LIB; WriteF('Error: could not open utility library\n') + ENDSELECT +ENDPROC +->>> + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/tag1.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/tag1.e new file mode 100644 index 0000000..2aa2c4e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/tag1.e @@ -0,0 +1,74 @@ +-> tag1.e + +->>> Header (globals) +MODULE 'utility', + 'intuition/intuition', + 'utility/tagitem' + +ENUM ERR_NONE, ERR_LIB, ERR_TAG, ERR_WIN + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_TAG IF AllocateTagItems()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL +->>> + +->>> PROC main() +PROC main() HANDLE + DEF tags=NIL:PTR TO tagitem, win=NIL + KickVersion(37) + -> We need the utility library for this example + utilitybase:=OpenLibrary('utility.library', 37) + + -> ********************************************************************* + -> This section allocates a tag array, fills it in with values, and then + -> uses it. + -> ********************************************************************* + + -> Allocate a tag array + tags:=AllocateTagItems(7) + -> Fill in our tag array + tags[0].tag:=WA_WIDTH + tags[0].data:=320 + tags[1].tag:=WA_HEIGHT + tags[1].data:=50 + tags[2].tag:=WA_TITLE + tags[2].data:='RKM Tag Example 1' + tags[3].tag:=WA_IDCMP + tags[3].data:=IDCMP_CLOSEWINDOW + tags[4].tag:=WA_CLOSEGADGET + tags[4].data:=TRUE + tags[5].tag:=WA_DRAGBAR + tags[5].data:=TRUE + tags[6].tag:=TAG_DONE + + -> Open the window, using the tag attributes as the only description. + win:=OpenWindowTagList(NIL, tags) + -> Wait for an event to occur + WaitIMessage(win) + + -> Close the window now that we're done with it + CloseWindow(win) + win:=NIL -> E-Note: help with error trapping + + -> ********************************************************************* + -> This section builds a static tag list, and passes it to the function. + -> ********************************************************************* + + win:=OpenWindowTagList(NIL, + [WA_WIDTH, 320, + WA_HEIGHT, 50, + WA_TITLE, 'RKM Tag Example 1', + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_CLOSEGADGET, TRUE, + WA_DRAGBAR, TRUE, + TAG_DONE]) + -> Wait for an event to occur + WaitIMessage(win) +EXCEPT DO + IF win THEN CloseWindow(win) + IF tags THEN FreeTagItems(tags) + IF utilitybase THEN CloseLibrary(utilitybase) +ENDPROC +->>> + + diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/uptime.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/uptime.e new file mode 100644 index 0000000..8ccdcf4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Utility/uptime.e @@ -0,0 +1,54 @@ +-> uptime.e + +->>> Header (globals) +OPT PREPROCESS + +MODULE 'utility', + 'dos/dos', + 'dos/dosextens', + 'utility/date' + +ENUM ERR_NONE, ERR_INFO, ERR_LIB, ERR_LOCK + +RAISE ERR_INFO IF Info()<>DOSTRUE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_LOCK IF Lock()=NIL +->>> + +->>> PROC main() +PROC main() HANDLE + DEF infodata=NIL:PTR TO infodata, ramdevice:PTR TO devlist, + now=NIL:PTR TO datestamp, currenttime, boottime, lock=NIL, d, h, m + utilitybase:=OpenLibrary('utility.library', 37) + NEW infodata, now + lock:=Lock('RAM:', SHARED_LOCK) + Info(lock, infodata) + -> E-Note: convert BCPL pointer + ramdevice:=BADDR(infodata.volumenode) + boottime:=Smult32(ramdevice.volumedate.days, 86400) + + Smult32(ramdevice.volumedate.minute, 60) + + SdivMod32(ramdevice.volumedate.tick, TICKS_PER_SECOND) + DateStamp(now) + currenttime:=Smult32(now.days, 86400) + + Smult32(now.minute, 60) + + SdivMod32(now.tick, TICKS_PER_SECOND) + currenttime:=currenttime-boottime + IF currenttime > 0 + -> E-Note: a multiple assignment gets the two UdivMod32() results + d,h:=UdivMod32(currenttime, 86400) + h,m:=UdivMod32(h, 3600) + m:=UdivMod32(m, 60) + WriteF('Up for \d days, \d hours, \d minutes\n', d, h, m) + ENDIF +EXCEPT DO + IF lock THEN UnLock(lock) + END now, infodata + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ERR_INFO; WriteF('Error: could not get info on lock\n') + CASE ERR_LIB; WriteF('Error: could not open utility library\n') + CASE ERR_LOCK; WriteF('Error: could not lock RAM:\n') + CASE "MEM"; WriteF('Error: ran out of memory\n') + ENDSELECT +ENDPROC +->>> diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appicon.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appicon.e new file mode 100644 index 0000000..5e1c96d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appicon.e @@ -0,0 +1,80 @@ +-> appicon.e -- Show use of an AppIcon + +OPT OSVERSION=37 + +MODULE 'icon', + 'wb', + 'workbench/startup', + 'workbench/workbench' + +ENUM ERR_NONE, ERR_APPICON, ERR_DOBJ, ERR_LIB, ERR_PORT + +RAISE ERR_APPICON IF AddAppIconA()=NIL, + ERR_DOBJ IF GetDefDiskObject()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL + +PROC main() HANDLE + DEF dobj=NIL:PTR TO diskobject, myport=NIL, appicon=NIL, + appmsg:PTR TO appmessage, dropcount=0, x + -> Get the the right version of the Icon Library, initialise iconbase + iconbase:=OpenLibrary('icon.library', 37) + -> Get the the right version of the Workbench Library + workbenchbase:=OpenLibrary('workbench.library', 37) + -> This is the easy way to get some icon imagery + -> Real applications should use custom imagery + dobj:=GetDefDiskObject(WBDISK) + -> The type must be set to NIL for a WBAPPICON + dobj.type:=NIL + + -> The CreateMsgPort() function is in Exec version 37 and later only + myport:=CreateMsgPort() + -> Put the AppIcon up on the Workbench window + appicon:=AddAppIconA(0, 0, 'TestAppIcon', myport, NIL, dobj, NIL) + -> For the sake of this example, we allow the AppIcon to be activated + -> only five times. + WriteF('Drop files on the Workbench AppIcon\n') + WriteF('Example exits after 5 drops\n') + + WHILE dropcount<5 + -> Here's the main event loop where we wait for messages to show up + -> from the AppIcon + WaitPort(myport) + + -> Might be more than one message at the port... + WHILE appmsg:=GetMsg(myport) + IF appmsg.numargs=0 + -> If numargs is 0 the AppIcon was activated directly + WriteF('User activated the AppIcon.\n') + WriteF('A Help window for the user would be good here\n') + ELSEIF appmsg.numargs>0 + -> If numargs is >0 the AppIcon was activated by having one or more + -> icons dropped on top of it + WriteF('User dropped \d icons on the AppIcon\n', appmsg.numargs) + FOR x:=0 TO appmsg.numargs-1 + WriteF('#\d name="\s"\n', x+1, appmsg.arglist[x].name) + ENDFOR + ENDIF + -> Let Workbench know we're done with the message + ReplyMsg(appmsg) + ENDWHILE + INC dropcount + ENDWHILE + +EXCEPT DO + IF appicon THEN RemoveAppIcon(appicon) + IF myport + -> Clear away any messages that arrived at the last moment + WHILE appmsg:=GetMsg(myport) DO ReplyMsg(appmsg) + DeleteMsgPort(myport) + ENDIF + IF dobj THEN FreeDiskObject(dobj) + IF workbenchbase THEN CloseLibrary(workbenchbase) + IF iconbase THEN CloseLibrary(iconbase) + SELECT exception + CASE ERR_APPICON; WriteF('Error: Could not attach AppIcon to Workbench\n') + CASE ERR_DOBJ; WriteF('Error: Could not get default icon\n') + CASE ERR_LIB; WriteF('Error: Could not open required library\n') + CASE ERR_PORT; WriteF('Error: Could not create port\n') + ENDSELECT +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appmenuitem.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appmenuitem.e new file mode 100644 index 0000000..968f37a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appmenuitem.e @@ -0,0 +1,69 @@ +-> appmenuitem.e -- Show use of an AppMenuItem + +OPT OSVERSION=37 + +MODULE 'wb', + 'dos/dostags', + 'workbench/startup', + 'workbench/workbench' + +ENUM ERR_NONE, ERR_APPMENU, ERR_LIB, ERR_PORT + +RAISE ERR_APPMENU IF AddAppMenuItemA()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL + +PROC main() HANDLE + DEF myport=NIL, appitem=NIL, + appmsg=NIL:PTR TO appmessage, result, x, count=0, file + workbenchbase:=OpenLibrary('workbench.library', 37) + -> The CreateMsgPort() function is in Exec version 37 and later only + myport:=CreateMsgPort() + -> Add our own AppMenuItem to the Workbench Tools Menu + appitem:=AddAppMenuItemA(0, -> Our ID# for item + 'SYS:Utilities/More', -> Our UserData + 'Browse Files', -> MenuItem Text + myport, NIL) -> MsgPort, no tags + + WriteF('Select Workbench Tools demo menuitem "Browse Files"\n') + + -> For this example, we allow the AppMenuItem to be selected only once, + -> then we remove it and exit + WaitPort(myport) + WHILE (appmsg:=GetMsg(myport)) AND (count<1) + -> Handle messages from the AppMenuItem - we have only one item so we don't + -> have to check its appmsg.id number. We'll System() the command string + -> that we passed as userdata when we added the menu item. We find our + -> userdata pointer in appmsg.userdata + + WriteF('User picked AppMenuItem with \d icons selected\n', appmsg.numargs) + FOR x:=0 TO appmsg.numargs-1 + WriteF(' #\d name="\s"\n', x+1, appmsg.arglist[x].name) + ENDFOR + + INC count + IF file:=Open('CON:0/40/640/150/AppMenu Example/auto/close/wait', OLDFILE) + result:=SystemTagList(appmsg.userdata, [SYS_INPUT, file, + SYS_OUTPUT, NIL, + SYS_ASYNCH, TRUE, NIL]) + -> If Asynch System() itself fails, we must close file + IF result=-1 THEN Close(file) + ENDIF + ReplyMsg(appmsg) + ENDWHILE + +EXCEPT DO + IF appitem THEN RemoveAppMenuItem(appitem) + IF myport + -> Clear away any messages that arrived at the last moment + -> and let Workbench know we're done with the messages + WHILE appmsg:=GetMsg(myport) DO ReplyMsg(appmsg) + DeleteMsgPort(myport) + ENDIF + IF workbenchbase THEN CloseLibrary(workbenchbase) + SELECT exception + CASE ERR_APPMENU; WriteF('Error: Could not attach AppMenuItem to Workbench\n') + CASE ERR_LIB; WriteF('Error: Could not open workbench.library\n') + CASE ERR_PORT; WriteF('Error: Could not create port\n') + ENDSELECT +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appwindow.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appwindow.e new file mode 100644 index 0000000..4dd3873 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/appwindow.e @@ -0,0 +1,76 @@ +-> appwindow.e -- Show use of an AppWindow + +OPT OSVERSION=37 + +MODULE 'wb', + 'exec/ports', + 'intuition/intuition', + 'workbench/startup', + 'workbench/workbench' + +ENUM ERR_NONE, ERR_APPWIN, ERR_LIB, ERR_PORT, ERR_WIN + +RAISE ERR_APPWIN IF AddAppWindowA()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL, + ERR_WIN IF OpenWindowTagList()=NIL + +PROC main() HANDLE + DEF awport=NIL:PTR TO mp, win=NIL:PTR TO window, appwin=NIL, + imsg:PTR TO intuimessage, amsg:PTR TO appmessage, argptr:PTR TO wbarg, + winsig, appwinsig, signals, id=1, userdata=0, done=FALSE, i + workbenchbase:=OpenLibrary('workbench.library', 37) + -> The CreateMsgPort() function is in Exec version 37 and later only + awport:=CreateMsgPort() + win:=OpenWindowTagList(NIL, [WA_WIDTH, 200, WA_HEIGHT, 50, + -> E-Note: C version uses obsolete flags + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_FLAGS, WFLG_CLOSEGADGET OR WFLG_DRAGBAR, + WA_TITLE, 'AppWindow', + NIL]) + appwin:=AddAppWindowA(id, userdata, win, awport, NIL) + WriteF('AppWindow added... Drag files into AppWindow\n') + winsig:=Shl(1, win.userport.sigbit) + appwinsig:=Shl(1, awport.sigbit) + REPEAT + -> Wait for IDCMP messages and AppMessages + signals:=Wait(winsig OR appwinsig) + + IF signals AND winsig -> Got an IDCMP message + WHILE imsg:=GetMsg(win.userport) + -> E-Note: C version uses obsolete flags + IF imsg.class=IDCMP_CLOSEWINDOW THEN done:=TRUE + ReplyMsg(imsg) + ENDWHILE + ENDIF + IF signals AND appwinsig -> Got an AppMessage + WHILE amsg:=GetMsg(awport) + WriteF('AppMsg: Type=\d, ID=\d, NumArgs=\d\n', + amsg.type, amsg.id, amsg.numargs) + argptr:=amsg.arglist + FOR i:=0 TO amsg.numargs-1 + WriteF(' arg(\d): Name="\s", Lock=\h\n', + i, argptr.name, argptr.lock) + argptr++ + ENDFOR + ReplyMsg(amsg) + ENDWHILE + ENDIF + UNTIL done + +EXCEPT DO + IF appwin THEN RemoveAppWindow(appwin) + IF win THEN CloseWindow(win) + IF awport + -> Make sure there are no more outstanding messages + WHILE amsg:=GetMsg(awport) DO ReplyMsg(amsg) + DeleteMsgPort(awport) + ENDIF + IF workbenchbase THEN CloseLibrary(workbenchbase) + SELECT exception + CASE ERR_APPWIN; WriteF('Error: Could not create AppWindow\n') + CASE ERR_LIB; WriteF('Error: Could not open required library\n') + CASE ERR_PORT; WriteF('Error: Could not create port\n') + CASE ERR_WIN; WriteF('Error: Could not open window\n') + ENDSELECT +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/iconexample.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/iconexample.e new file mode 100644 index 0000000..a6e33a5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/iconexample.e @@ -0,0 +1,185 @@ +-> iconexample.e - Workbench icon startup, creation, and parsing example + +MODULE 'icon', + 'dos/dos', + 'intuition/intuition', + 'workbench/startup', + 'workbench/workbench' + +ENUM ERR_NONE, ERR_LIB, ERR_OPEN, ERR_WRITE, ERR_MAKE + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_OPEN IF Open()=NIL, + ERR_WRITE IF Write()=-1 + +DEF projIcon:diskobject + +PROC main() HANDLE + DEF wbenchMsg:PTR TO wbstartup, wbarg:PTR TO wbarg, file=NIL, i, olddir, + projname, deftoolname, iconImageData, iconGadget, toolTypes + projname:='RAM:Example_Project' + deftoolname:='iconexample' + toolTypes:=['FILETYPE=text', 'FLAGS=BOLD|ITALICS', NIL] + -> Plane 0 + iconImageData:=[$0000,$0000,$0000,$1000,$0000,$0000,$0000,$3000, + $0FFF,$FFFC,$0000,$3000,$0800,$0004,$0000,$3000, + $0800,$07FF,$FFC0,$3000,$08A8,$A400,$00A0,$3000, + $0800,$0400,$0090,$3000,$08AA,$A400,$0088,$3000, + $0800,$042A,$A0FC,$3000,$082A,$A400,$0002,$3000, + $0800,$0400,$0002,$3000,$0800,$A42A,$A0A2,$3000, + $0800,$0400,$0002,$3000,$0950,$A42A,$8AA2,$3000, + $0800,$0400,$0002,$3000,$082A,$A400,$0002,$3000, + $0800,$042A,$2AA2,$3000,$0FFF,$FC00,$0002,$3000, + $0000,$0400,$0002,$3000,$0000,$07FF,$FFFE,$3000, + $0000,$0000,$0000,$3000,$7FFF,$FFFF,$FFFF,$F000, + -> Plane 1 + $FFFF,$FFFF,$FFFF,$E000,$D555,$5555,$5555,$4000, + $D000,$0001,$5555,$4000,$D7FF,$FFF9,$5555,$4000, + $D7FF,$F800,$0015,$4000,$D757,$5BFF,$FF55,$4000, + $D7FF,$FBFF,$FF65,$4000,$D755,$5BFF,$FF75,$4000, + $D7FF,$FBD5,$5F01,$4000,$D7D5,$5BFF,$FFFD,$4000, + $D7FF,$FBFF,$FFFD,$4000,$D7FF,$5BD5,$5F5D,$4000, + $D7FF,$FBFF,$FFFD,$4000,$D6AF,$5BD5,$755D,$4000, + $D7FF,$FBFF,$FFFD,$4000,$D7D5,$5BFF,$FFFD,$4000, + $D7FF,$FBD5,$D55D,$4000,$D000,$03FF,$FFFD,$4000, + $D555,$53FF,$FFFD,$4000,$D555,$5000,$0001,$4000, + $D555,$5555,$5555,$4000,$8000,$0000,$0000,$0000]:INT + -> E-Note: C version uses obsolete gadget flags + iconGadget:=[NIL, -> Next Gadget Pointer + 97, 12, 52, 23, -> Left, Top, Width, Height + GFLG_GADGIMAGE OR GFLG_GADGHBOX, -> Flags + GACT_IMMEDIATE OR GACT_RELVERIFY, -> Activation Flags + GTYP_BOOLGADGET, -> Gadget Type + [0, 0, -> Top Corner + 52, 22, 2, -> Width, Height, Depth + iconImageData, -> Image Data + 3, 0, -> PlanePick, PlaneOnOff + NIL]:image, -> Next Image + NIL, -> Select Image + NIL, -> Gadget Text + NIL, -> Mutual Exclude + NIL, -> Special Info + 0, -> Gadget ID + NIL]:gadget -> User Data + -> E-Note: a list can't be used for a diskobject because of the nested gadget + projIcon.magic:=WB_DISKMAGIC + projIcon.version:=WB_DISKVERSION + CopyMem(iconGadget, projIcon.gadget, SIZEOF gadget) + projIcon.type:=WBPROJECT + projIcon.defaulttool:=deftoolname + projIcon.tooltypes:=toolTypes + projIcon.currentx:=NO_ICON_POSITION + projIcon.currenty:=NO_ICON_POSITION + projIcon.drawerdata:=NIL + projIcon.toolwindow:=NIL + projIcon.stacksize:=4000 + + -> Open icon.library + iconbase:=OpenLibrary('icon.library',33) + + -> If started from CLI, this example will create a small text file + -> RAM:Example_Project, and create an icon for the file which points + -> to this program as its default tool. + IF wbmessage=NIL + -> Make a sample project (data) file + file:=Open(projname, NEWFILE) + Write(file, 'Have a nice day\n', STRLEN) + + -> Now save/update icon for this data file + makeIcon(projname, toolTypes, deftoolname) + WriteF('\s data file and icon saved.\n', projname) + WriteF('Use Workbench menu Icon Information to examine the icon.\n') + WriteF('Then copy this example (iconexample) to RAM:\n') + WriteF('and double-click the \s project icon\n', projname) + ELSE -> Else we are from WB - ie. we were either started by a tool icon, + -> or as in this case, by being the default tool of a project icon. + -> E-Note: WriteF opens its own window if necessary + wbenchMsg:=wbmessage + + -> First arg is our executable (tool). Any additional args are projects + -> or icons passed to us via either extend select or default tool method. + wbarg:=wbenchMsg.arglist + FOR i:=0 TO wbenchMsg.numargs-1 + -> If there's a directory lock for this wbarg, CD there + olddir:=-1 + IF wbarg.lock AND (wbarg.name[]<>0) THEN olddir:=CurrentDir(wbarg.lock) + + showToolTypes(wbarg) + + IF (i>0) AND (wbarg.name[]<>0) + WriteF('In Main. We could open the \s file here\n', wbarg.name) + ENDIF + IF olddir<>-1 THEN CurrentDir(olddir) -> CD back where we were + wbarg++ + ENDFOR + Delay(500) + WriteF('\nPress RETURN to close window\n') + ENDIF +EXCEPT DO + IF file THEN Close(file) + SELECT exception + CASE ERR_LIB; WriteF('Can''t open icon.library\n') + CASE ERR_OPEN; WriteF('Can''t open file "\s"\n', projname) + CASE ERR_WRITE; WriteF('Error writing data file\n') + CASE ERR_MAKE; WriteF('Error writing icon\n') + ENDSELECT + RETURN IF exception=ERR_NONE THEN RETURN_OK ELSE RETURN_FAIL +ENDPROC + +PROC makeIcon(name, newtooltypes, newdeftool) + DEF dobj:PTR TO diskobject, oldtooltypes, olddeftool, success=FALSE + IF dobj:=GetDiskObject(name) + -> If file already has an icon, we will save off any fields we need to + -> update, update those fields, put the object, restore the old field + -> pointers and then free the object. This will preserve any custom + -> imagery the user has, and the user's current placement of the icon. + -> If your application does not know where the user currently keeps your + -> application, you should not update his dobj.defaulttool. + oldtooltypes:=dobj.tooltypes + olddeftool:=dobj.defaulttool + + dobj.tooltypes:=newtooltypes + dobj.defaulttool:=newdeftool + + success:=PutDiskObject(name, dobj) + + -> We must restore the original pointers before freeing + dobj.tooltypes:=oldtooltypes + dobj.defaulttool:=olddeftool + FreeDiskObject(dobj) + ENDIF + -> Else, put our default icon + IF success=FALSE THEN success:=PutDiskObject(name, projIcon) + IF success=FALSE THEN Raise(ERR_MAKE) +ENDPROC + +PROC showToolTypes(wbarg:PTR TO wbarg) + DEF dobj:PTR TO diskobject, toolarray, s, success=FALSE + WriteF('\nWBArg Lock=$\h, Name=\s ($\h)\n', + wbarg.lock, wbarg.name, wbarg.name[]) + + IF (wbarg.name[]<>0) AND (dobj:=GetDiskObject(wbarg.name)) + WriteF(' We have read the DiskObject (icon) for this arg\n') + toolarray:=dobj.tooltypes + + IF s:=FindToolType(toolarray, 'FILETYPE') + WriteF(' Found tooltype FILETYPE with value \s\n', s) + ENDIF + IF s:=FindToolType(toolarray, 'FLAGS') + WriteF(' Found tooltype FLAGS with value \s\n', s) + IF MatchToolValue(s, 'BOLD') + WriteF(' BOLD flag requested\n') + ENDIF + IF MatchToolValue(s, 'ITALICS') + WriteF(' ITALICS flag requested\n') + ENDIF + ENDIF + -> Free the diskobject we got + FreeDiskObject(dobj) + success:=TRUE + ELSEIF wbarg.name[]=0 + WriteF(' Must be a disk or drawer icon\n') + ELSE + WriteF(' Can''t find any DiskObject (icon) for this WBArg\n') + ENDIF +ENDPROC success diff --git a/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/prargs.e b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/prargs.e new file mode 100644 index 0000000..c7aecee --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Rkrm/Workbench/prargs.e @@ -0,0 +1,55 @@ +-> PrArgs.e - This program prints all Workbench or Shell (CLI) arguments. +-> E-Note: ignore all the rubbish (in the C version) about start-ups + +MODULE 'other/split', + 'workbench/startup' + +PROC main() + DEF argmsg:PTR TO wbstartup, wb_arg:PTR TO wbarg, ktr, olddir, + argv:PTR TO LONG + -> wbmessage is non-NIL when run from the Workbench, NIL when run from the CLI + IF wbmessage + -> E-Note: WriteF opens its own output window, if necessary + -> wbmessage contains a pointer to the WBStartup message + argmsg:=wbmessage + wb_arg:=argmsg.arglist -> Head of the arg list + + WriteF('Run from the Workbench, \d args.\n', argmsg.numargs) + + FOR ktr:=0 TO argmsg.numargs-1 + IF wb_arg.lock<>NIL + -> Locks supported, change to the proper directory + olddir:=CurrentDir(wb_arg.lock) + + -> Process the file. + -> If you have done the CurrentDir() above, then you can access the file + -> by its name. Otherwise, you have to examine the lock to get a + -> complete path to the file. + WriteF('\tArg \d[2] (w/ lock): "\s".\n', ktr, wb_arg.name) + + -> Change back to the original directory when done. Be sure to change + -> back before you exit. + CurrentDir(olddir) + ELSE + -> Something that does not support locks + WriteF('\tArg \d[2] (no lock): "\s".\n', ktr, wb_arg.name) + ENDIF + wb_arg++ + ENDFOR + -> E-Note: no need to wait: output window closes after a RETURN press + ELSE + -> E-Note: WriteF opens its own output window, if necessary + -> E-Note: argSplit() splits arg into a NIL-terminated E-list, which can be + -> used like C's argv (except that the first element of the list is + -> the first argument, not the program name...) + IF argv:=argSplit() + WriteF('Run from the CLI, \d args.\n', ListLen(argv)) + FOR ktr:=0 TO ListLen(argv)-1 + -> Print an arg, and its number + WriteF('\tArg \d[2]: "\s".\n', ktr+1, argv[ktr]) + ENDFOR + ELSE -> E-Note: argSplit() ran out of memory... + WriteF('Run from the CLI, arg is "\s".\n', arg) + ENDIF + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/AmigaLib.doc b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/AmigaLib.doc new file mode 100644 index 0000000..0e663fc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/AmigaLib.doc @@ -0,0 +1,115 @@ +Short: amiga.lib as E modules +Type: dev/e +Author: m88jrh@ecs.ox.ac.uk (Jason R. Hulance) +Uploader: m88jrh@ecs.ox.ac.uk (Jason R. Hulance) + + +AmigaLib +======== + +Amiga E modules of many of the amiga.lib functions. +These translations are Copyright (C) 1995, Jason R. Hulance. +The original amiga.lib is Copyright (C) 1985-1992, Commodore-Amiga Inc. + +You are free to use these modules in your programs, whether they are freeware +or commercial. However, if you want to distribute any of this archive you +must include it all, unmodified, together with this file. + + +Contents +-------- + + argarray.m: + PROC argArrayInit(str=0) + PROC argArrayDone() + PROC argInt(tt,entry,defaultval) + PROC argString(tt,entry,defaultstring) + + boopsi.m: + PROC callHookA(h,obj,msg) + PROC coerceMethodA(cl,obj,msg) + PROC doMethodA(obj,msg) + PROC doSuperMethodA(cl,obj,msg) + PROC setSuperAttrsA(cl,obj,msg) + + cx.m: + PROC freeIEvents(events) + PROC hotKey(description,port,id) + PROC invertString(str,km) + PROC invertStringRev(str,km) + PROC userFilter(tt,action_name,default_descr) + + interrupts.m: + PROC addTOF(i,p,a) + PROC remTOF(i) + PROC waitbeam(pos) + + io.m: + PROC beginIO(ioreq) + PROC createExtIO(port,ioSize) + PROC deleteExtIO(ioReq) + PROC createStdIO(port) + PROC deleteStdIO(ioReq) + + lists.m: + PROC newList(mlh) + + ports.m: + PROC createPort(name,pri) + PROC deletePort(port) + + random.m: + PROC fastRand(num) + PROC rangeRand(num) + + tasks.m: + PROC createTask(name,pri,initPC,stackSize) + PROC deleteTask(tc) + + time.m: + PROC timeDelay(unit,seconds,micros) + +There are also a number of test programs, which show how to use many of +the functions. + + +Documentation +------------- + +The documentation on amiga.lib serves as adequate documentation of these +functions, with the following observations: + + argarray.m: + o argArrayInit() takes only an optional string. This can be a string + of arguments like the E global "arg" (which is the default). This + string is only used if "wbmessage" is NIL, and is *altered* if used + (i.e., the result is a manipulation of the string, and so by default + "arg" will be affected). If you don't like this, pass this function + a copy of your arguments string (and be careful not to free it until + you've finished with the result of this function). + + boopsi.m: + o callHookA() is like CallHookPkt() from utility.library except it does + not require the utility.library to be open! + o setSuperAttrsA() replaces the stack-based (varargs) function + SetSuperAttrs(). setSuperAttrsA() takes a pointer to a Boopsi message + as its third argument (so you would usually use a typed list). + + cx.m: + o invertStringRev() is like InvertString() except it does not require + you to reverse the string to be inverted. See testcx.e. + o userFilter(tt, action_name, default_descr) creates a CxFilter object + with a description string taken from the tooltype defined by + "action_name" in the tooltypes array "tt" (which is usually the result + of a call to argArrayInit()). If the tooltype is not found then the + "default_descr" is used instead. + + interrupts.m: + o waitbeam(pos) waits until the VBeam position is at least "pos". + + tasks.m: + o createTask() can has slightly enhanced error checking if you are + running V37+. + +The main reason for the creation of these modules was my translations of the +RKRM examples. These should provide even more useful documentation. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/argarray.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/argarray.e new file mode 100644 index 0000000..105eb11 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/argarray.e @@ -0,0 +1,46 @@ +OPT MODULE + +MODULE 'icon', + 'other/split', + 'workbench/startup', + 'workbench/workbench' + +DEF cxlib_arg, cxlib_dobj:PTR TO diskobject + +EXPORT PROC argArrayInit(str=NIL) + DEF argmsg:PTR TO wbstartup, lock=NIL + IF iconbase=NIL + RETURN NIL + ELSEIF argmsg:=wbmessage + IF argmsg.arglist.lock THEN lock:=CurrentDir(argmsg.arglist.lock) + cxlib_dobj:=GetDiskObject(argmsg.arglist.name) + IF lock THEN CurrentDir(lock) + RETURN IF cxlib_dobj THEN cxlib_dobj.tooltypes ELSE NIL + ELSE + RETURN cxlib_arg:=argSplit(str) + ENDIF +ENDPROC + +EXPORT PROC argArrayDone() + IF iconbase + IF wbmessage + FreeDiskObject(cxlib_dobj) + ELSE + DisposeLink(cxlib_arg) + ENDIF + ENDIF +ENDPROC + +EXPORT PROC argString(tt:PTR TO LONG, entry, defaultstring) + DEF res=NIL + IF tt AND (iconbase<>NIL) + res:=FindToolType(tt, entry) + ENDIF +ENDPROC IF res THEN res ELSE defaultstring + +EXPORT PROC argInt(tt:PTR TO LONG, entry, defaultval) + DEF res=NIL + IF tt AND (iconbase<>NIL) + IF res:=FindToolType(tt, entry) THEN StrToLong(res, {defaultval}) + ENDIF +ENDPROC defaultval diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/boopsi.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/boopsi.e new file mode 100644 index 0000000..ab5f122 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/boopsi.e @@ -0,0 +1,41 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'intuition/classes', + 'intuition/classusr', + 'utility/hooks' + +EXPORT PROC callHookA(h:PTR TO hook, obj, msg) +-> CallHookPkt would require that caller has the utility library open + DEF entry + entry:=h.entry + MOVE.L h, A0 + MOVE.L msg, A1 + MOVE.L obj, A2 + MOVE.L entry, A3 + JSR (A3) + MOVE.L D0, entry +ENDPROC entry + +EXPORT PROC setSuperAttrsA(cl:PTR TO iclass, obj, msg) +ENDPROC doSuperMethodA(cl, obj, [OM_SET, msg, NIL]) + +EXPORT PROC coerceMethodA(cl:PTR TO iclass, obj, msg) + IF obj AND (cl<>NIL) + RETURN callHookA(cl.dispatcher, obj, msg) + ENDIF +ENDPROC NIL + +EXPORT PROC doSuperMethodA(cl:PTR TO iclass, obj, msg) + IF obj AND (cl<>NIL) + RETURN callHookA(cl.super.dispatcher, obj, msg) + ENDIF +ENDPROC NIL + +EXPORT PROC doMethodA(obj, msg) + DEF o:PTR TO object_ + IF obj + o:=OBJECT_(obj) -> Get real object + RETURN callHookA(o.class.dispatcher, obj, msg) + ENDIF +ENDPROC NIL diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/cx.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/cx.e new file mode 100644 index 0000000..6eb7122 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/cx.e @@ -0,0 +1,116 @@ +OPT MODULE + +OPT PREPROCESS + +MODULE 'commodities', + 'icon', + 'devices/inputevent', + 'libraries/commodities' + +EXPORT PROC userFilter(tt, action_name, default_descr) + DEF desc=NIL + IF (iconbase=NIL) OR (cxbase=NIL) THEN RETURN NIL + IF tt THEN desc:=FindToolType(tt, action_name) +ENDPROC CxFilter(IF desc THEN desc ELSE default_descr) + +EXPORT PROC hotKey(description, port, id) + DEF filter + IF cxbase=NIL THEN RETURN NIL + IF filter:=CxFilter(description) + AttachCxObj(filter, CxSender(port, id)) + AttachCxObj(filter, CxTranslate(NIL)) + IF CxObjError(filter) + DeleteCxObjAll(filter) + filter:=NIL + ENDIF + ENDIF +ENDPROC filter + +EXPORT PROC freeIEvents(events:PTR TO inputevent) + DEF next + WHILE events + next:=events.nextevent + END events + events:=next + ENDWHILE +ENDPROC + +ENUM ERR_NONE, ERR_ESC, ERR_ANGLE + +EXPORT PROC invertStringRev(str, km) HANDLE + DEF events=NIL, c, curr:PTR TO inputevent, ie:PTR TO inputevent + IF cxbase=NIL THEN RETURN NIL + IF str + IF str[] + curr:=(events:=NEW ie) + c:=str[]++ + REPEAT + IF c="<" + str:=doangle(str, curr) + ELSE + IF c="\\" THEN c:=doesc(str[]++) + InvertKeyMap(c, curr, km) + ENDIF + IF c:=str[]++ + curr.nextevent:=NEW ie + curr:=ie + ENDIF + UNTIL c=NIL + ENDIF + ENDIF + RETURN events +EXCEPT + freeIEvents(events) + RETURN NIL +ENDPROC + +EXPORT PROC invertString(str, km) HANDLE + DEF events=NIL:PTR TO inputevent, c, prev:PTR TO inputevent + IF cxbase=NIL THEN RETURN NIL + IF str + IF str[] + WHILE c:=str[]++ + prev:=events + NEW events + events.nextevent:=prev + IF c="<" + str:=doangle(str, events) + ELSE + IF c="\\" THEN c:=doesc(str[]++) + InvertKeyMap(c, events, km) + ENDIF + ENDWHILE + ENDIF + ENDIF + RETURN events +EXCEPT + freeIEvents(events) + RETURN NIL +ENDPROC + +PROC doesc(c) + SELECT "u" OF c + CASE "\q", "'", "<", "\\" + RETURN c + CASE "0" + RETURN 0 + CASE "n", "r" + RETURN "\b" + CASE "t" + RETURN "\t" + DEFAULT + Raise(ERR_ESC) + ENDSELECT +ENDPROC + +PROC doangle(str, events:PTR TO inputevent) + DEF s, c, ix:inputxpression + s:=str + WHILE s[] AND (s[]<>">") DO s++ + IF c:=s[] THEN s[]:=NIL + IF ParseIX(str, ix)<>0 THEN Raise(ERR_ANGLE) + events.class:=ix.class + events.code:=ix.code + events.qualifier:=ix.qualifier + s[]++:=c +ENDPROC s diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/interrupts.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/interrupts.e new file mode 100644 index 0000000..391e89c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/interrupts.e @@ -0,0 +1,28 @@ +OPT MODULE + +MODULE 'graphics/graphint', + 'hardware/intbits' + +EXPORT PROC addTOF(i:PTR TO isrvstr, p, a) + i.code:={ttskasm} + i.iptr:=i + i.ccode:=p + i.carg:=a + AddIntServer(INTB_VERTB, i) +ENDPROC + +EXPORT PROC remTOF(i:PTR TO isrvstr) + RemIntServer(INTB_VERTB, i) +ENDPROC + +EXPORT PROC waitbeam(pos) + WHILE pos>VbeamPos() DO NOP +ENDPROC + +ttskasm: + MOVE.L $1A(A1), -(A7) + MOVEA.L $16(A1), A0 + JSR (A0) + ADDQ.L #4, A7 + MOVEQ.L #0, D0 + RTS diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/io.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/io.e new file mode 100644 index 0000000..402b892 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/io.e @@ -0,0 +1,42 @@ +OPT MODULE + +MODULE 'exec/io', + 'exec/memory', + 'exec/nodes', + 'exec/ports' + +ENUM ERR_NONE, ERR_SIG + +RAISE ERR_SIG IF AllocSignal()=-1 + +EXPORT PROC beginIO(ioreq:PTR TO io) + DEF base + base:=ioreq.device + MOVEA.L base, A6 + MOVEA.L ioreq, A1 + JSR -30(A6) +ENDPROC + +EXPORT PROC createStdIO(port) IS createExtIO(port, SIZEOF iostd) + +EXPORT PROC deleteStdIO(ioReq) IS deleteExtIO(ioReq) + +EXPORT PROC createExtIO(port, ioSize) HANDLE + DEF ioReq=NIL:PTR TO io + IF port + ioReq:=NewM(ioSize, MEMF_CLEAR OR MEMF_PUBLIC) + ioReq.mn.ln.type:=NT_REPLYMSG + ioReq.mn.length:=ioSize + ioReq.mn.replyport:=port + ENDIF +EXCEPT DO +ENDPROC ioReq + +EXPORT PROC deleteExtIO(ioReq:PTR TO io) + IF ioReq + ioReq.mn.ln.succ:=-1 + ioReq.mn.replyport:=-1 + ioReq.device:=-1 + Dispose(ioReq) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/lists.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/lists.e new file mode 100644 index 0000000..ad216c3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/lists.e @@ -0,0 +1,9 @@ +OPT MODULE + +MODULE 'exec/lists' + +EXPORT PROC newList(mlh:PTR TO mlh) + mlh.head:=mlh+4 -> Point to tail + mlh.tail:=NIL + mlh.tailpred:=mlh -> Point to head +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/ports.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/ports.e new file mode 100644 index 0000000..224edc9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/ports.e @@ -0,0 +1,37 @@ +OPT MODULE + +MODULE 'amigalib/lists', + 'exec/lists', + 'exec/memory', + 'exec/nodes', + 'exec/ports' + +EXPORT PROC createPort(name, pri) HANDLE + DEF sigBit=-1, port=NIL:PTR TO mp + sigBit:=AllocSignal(-1) + port:=NewM(SIZEOF mp, MEMF_CLEAR OR MEMF_PUBLIC) + port.ln.name:=name + port.ln.pri:=pri + port.ln.type:=NT_MSGPORT + port.flags:=PA_SIGNAL + port.sigbit:=sigBit + port.sigtask:=FindTask(NIL) + IF name + AddPort(port) + ELSE + newList(port.msglist) + ENDIF + RETURN port +EXCEPT + IF port THEN Dispose(port) + IF sigBit<>-1 THEN FreeSignal(sigBit) + RETURN NIL +ENDPROC + +EXPORT PROC deletePort(port:PTR TO mp) + IF port.ln.name THEN RemPort(port) + port.sigtask:=-1 + port.msglist.head:=-1 + FreeSignal(port.sigbit) + Dispose(port) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/random.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/random.e new file mode 100644 index 0000000..5daaa7d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/random.e @@ -0,0 +1,23 @@ +OPT MODULE + +OPT PREPROCESS + +DEF rangeSeed + +EXPORT PROC fastRand(num) IS IF num>0 THEN num*2 ELSE Eor(num*2, $1d872b41) + +#define UNSIGNED(x) (x AND $FFFF) + +EXPORT PROC rangeRand(num) + DEF max + max:=UNSIGNED(num-1) + REPEAT + max:=Shr(max,1) + rangeSeed:=fastRand(rangeSeed) + UNTIL (max<=0) + IF num + RETURN UNSIGNED(Shr(Mul(UNSIGNED(num), UNSIGNED(rangeSeed)), 16)) + ELSE + RETURN UNSIGNED(rangeSeed) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/tasks.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/tasks.e new file mode 100644 index 0000000..ca796a8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/tasks.e @@ -0,0 +1,46 @@ +OPT MODULE + +MODULE 'amigalib/lists', + 'exec/memory', + 'exec/nodes', + 'exec/tasks' + +OBJECT fakememlist + ln_succ:LONG + ln_pred:LONG + ln_type:CHAR + ln_pri:CHAR + ln_name:LONG + numentries:INT + tsk_reqs:LONG + tsk_length:LONG + stk_reqs:LONG + stk_length:LONG +ENDOBJECT + +EXPORT PROC createTask(name, pri, initPC, stackSize, data=NIL) + DEF ml:fakememlist, newTask=NIL:PTR TO tc + stackSize:=(stackSize+3) AND -4 -> Not(3) is -4 (honest!) + CopyMem([0, 0, 0, 0, 0, 2, + MEMF_PUBLIC OR MEMF_CLEAR, SIZEOF tc, + MEMF_CLEAR, stackSize]:fakememlist, + ml, SIZEOF fakememlist) + IF ml:=AllocEntry(ml) + newTask:=ml.tsk_reqs + newTask.splower:=ml.stk_reqs + newTask.spupper:=newTask.splower+stackSize + newTask.spreg:=newTask.spupper + newTask.userdata:=data + newTask.ln.type:=NT_TASK + newTask.ln.pri:=pri + newTask.ln.name:=name + newList(newTask.mementry) + AddHead(newTask.mementry, ml) + IF (AddTask(newTask, initPC, 0)=NIL) AND KickVersion(37) + FreeEntry(ml) + RETURN NIL + ENDIF + ENDIF +ENDPROC newTask + +EXPORT PROC deleteTask(tc) IS RemTask(tc) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testargarray.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testargarray.e new file mode 100644 index 0000000..fa912e4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testargarray.e @@ -0,0 +1,23 @@ +MODULE 'icon', + 'amigalib/argarray' + +ENUM ERR_NONE, ERR_LIB + +RAISE ERR_LIB IF OpenLibrary()=NIL + +PROC main() HANDLE + DEF p:PTR TO LONG, i=0 + iconbase:=OpenLibrary('icon.library', 33) + IF p:=argArrayInit() -> Result is a NIL-terminated list of strings + WriteF('Integer value of "ARG_ONE" is \d (default is 2)\n', + argInt(p, 'ARG_ONE', 2)) + WriteF('String value of "OTHER" is "\s" (default is "fred")\n', + argString(p, 'OTHER', 'fred')) + WriteF('\nActual arguments are:\n') + WHILE p[] DO WriteF('\d[2]: "\s"\n', i++, p[]++) + WriteF('Total: \d arguments\n', i) + argArrayDone() + ENDIF +EXCEPT DO + IF iconbase THEN CloseLibrary(iconbase) +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testcx.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testcx.e new file mode 100644 index 0000000..9509970 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testcx.e @@ -0,0 +1,94 @@ +OPT PREPROCESS + +MODULE 'commodities', + 'amigalib/cx', + 'devices/timer', + 'devices/inputevent', + 'dos/dos', + 'exec/ports', + 'libraries/commodities' + +ENUM ERR_NONE, ERR_BRKR, ERR_CRCX, ERR_CXERR, ERR_HOT, ERR_LIB, ERR_PORT + +RAISE ERR_BRKR IF CxBroker()=NIL, + ERR_CRCX IF CreateCxObj()=NIL, + ERR_LIB IF OpenLibrary()=NIL, + ERR_PORT IF CreateMsgPort()=NIL + +CONST EVT_HOTKEY=1 + +DEF broker_mp=NIL:PTR TO mp, broker=NIL, cxsigflag, ie:PTR TO inputevent + +PROC main() HANDLE + DEF hotkey, msg, newshell + newshell:='newshell\b' + cxbase:=OpenLibrary('commodities.library', 37) + broker_mp:=CreateMsgPort() + cxsigflag:=Shl(1, broker_mp.sigbit) + + broker:=CxBroker([NB_VERSION, 0, + 'HotKey', 'Little Hotkey', 'A little hot key commodity', + NBU_UNIQUE OR NBU_NOTIFY, + 0, 0, 0, broker_mp, 0]:newbroker, NIL) + + IF hotkey:=hotKey('rawkey control f1', broker_mp, EVT_HOTKEY) + AttachCxObj(broker, hotkey) + IF CxObjError(hotkey)<>FALSE + Raise(ERR_CXERR) + ELSE + IF ie:=invertStringRev(newshell, NIL) + ActivateCxObj(broker, TRUE) + processMsg() + freeIEvents(ie) + ENDIF + ENDIF + ELSE + Raise(ERR_HOT) + ENDIF +EXCEPT DO + IF broker THEN DeleteCxObjAll(broker) + IF broker_mp + WHILE msg:=GetMsg(broker_mp) DO ReplyMsg(msg) + DeleteMsgPort(broker_mp) + ENDIF + IF cxbase THEN CloseLibrary(cxbase) + SELECT exception + CASE ERR_BRKR; WriteF('Error: Could not create broker\n') + CASE ERR_CRCX; WriteF('Error: Could not create CX object\n') + CASE ERR_CXERR; WriteF('Error: Could not activate broker\n') + CASE ERR_HOT; WriteF('Error: Could not create hot key\n') + CASE ERR_LIB; WriteF('Error: Could not open required library\n') + CASE ERR_PORT; WriteF('Error: Could not create message port\n') + ENDSELECT +ENDPROC + +PROC processMsg() + DEF msg, sigrcvd, msgid, msgtype, going=TRUE + WHILE going + sigrcvd:=Wait(SIGBREAKF_CTRL_C OR cxsigflag) + WHILE msg:=GetMsg(broker_mp) + msgid:=CxMsgID(msg) + msgtype:=CxMsgType(msg) + ReplyMsg(msg) + SELECT msgtype + CASE CXM_IEVENT + IF msgid=EVT_HOTKEY + WriteF('You hit the HotKey -- adding input events\n') + AddIEvents(ie) + ENDIF + CASE CXM_COMMAND + SELECT msgid + CASE CXCMD_DISABLE + ActivateCxObj(broker, FALSE) + CASE CXCMD_ENABLE + ActivateCxObj(broker, TRUE) + CASE CXCMD_KILL + going:=FALSE + CASE CXCMD_UNIQUE + going:=FALSE + ENDSELECT + ENDSELECT + ENDWHILE + IF sigrcvd AND SIGBREAKF_CTRL_C THEN going:=FALSE + ENDWHILE +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts.e new file mode 100644 index 0000000..64516ee --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts.e @@ -0,0 +1,20 @@ +MODULE 'amigalib/interrupts', + 'dos/dos', + 'graphics/graphint' + +DEF var + +PROC main() + DEF i:isrvstr + var:=0 + WriteF('var = \d\n', var) + addTOF(i, {test_int}, {var}) + WriteF('var = \d\n', var) + Wait(SIGBREAKF_CTRL_C) + WriteF('var = \d\n', var) + remTOF(i) +ENDPROC + +PROC test_int(addr:PTR TO LONG) + addr[]:=addr[]+1 +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts2.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts2.e new file mode 100644 index 0000000..7012a98 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testinterrupts2.e @@ -0,0 +1,33 @@ +MODULE 'amigalib/interrupts', + 'dos/dos', + 'graphics/graphint' + +DEF var + +-> This example using an interrupt to toggle which string to print. +-> Try running it in a Shell, then try redirecting output to a file. +-> Look at the difference in the number of times it prints the same +-> string (i.e., how many times it gets to complete a WriteF before +-> the interrupt occurs), +PROC main() + DEF i:isrvstr, strs:PTR TO LONG, x, y, z + strs:=['hello\n', 'goodbye\n'] + var:=0 + x:=0; y:=0 + WriteF('var = \d\n', var) + addTOF(i, {test_int}, {var}) + WriteF('var = \d\n', var) + REPEAT + z:=var + IF z<>y + x:=0; y:=z + ENDIF + WriteF('\d \s', x++, strs[z]) + UNTIL CtrlC() + WriteF('var = \d\n', var) + remTOF(i) +ENDPROC + +PROC test_int(addr:PTR TO LONG) + addr[]:=1-addr[] +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testtime.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testtime.e new file mode 100644 index 0000000..d06003a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/testtime.e @@ -0,0 +1,8 @@ +MODULE 'amigalib/time' + +PROC main() + DEF error + WriteF('Just going to delay for 20 secs...\n') + error:=timeDelay(0, 20, 0) + WriteF(IF error THEN 'Ack! Something went wrong.\n' ELSE 'Done!\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/time.e b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/time.e new file mode 100644 index 0000000..54b81d0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/AmigaLib/time.e @@ -0,0 +1,24 @@ +OPT MODULE + +MODULE 'amigalib/io', + 'amigalib/ports', + 'devices/timer', + 'exec/io' + +EXPORT PROC timeDelay(unit, seconds, micros) + DEF port, tr:PTR TO timerequest, error=TRUE + IF port:=createPort(NIL, 0) + IF tr:=createExtIO(port, SIZEOF timerequest) + IF OpenDevice('timer.device', unit, tr, 0)=0 + tr.time.secs:=seconds + tr.time.micro:=micros + tr.io.command:=TR_ADDREQUEST + DoIO(tr) + CloseDevice(tr) + error:=FALSE + ENDIF + deleteExtIO(tr) + ENDIF + deletePort(port) + ENDIF +ENDPROC error diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.doc b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.doc new file mode 100644 index 0000000..be9b788 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.doc @@ -0,0 +1,63 @@ +arexx.m: simple routines for adding an arexx-port to your program. + + port:=rx_OpenPort(portname) + +Creates an arexx-port. macro programs may now reach you by saying +'ADDRESS portname'. May raise: "MEM", "SIG", "DOUB". the last two are +'could not allocate signal' and 'port with same name already exists'. + + rx_ClosePort(port) + +Frees up the port and all associated resources. May safely be called +with NIL. + + mes,string:=rx_GetMsg(port) + +Just about the same as exec's GetMsg, only now rexx-specific. +extracts the string send from the macro program. If mes=NIL then there +was no message. + + rx_ReplyMsg(mes,rc=0,resultstring=NIL) + +reply the message you got from rx_GetMsg(). pass rc=0 for no error, +and a string if you think the command send requires a result. rc>0 +signals an error (no result is returned). + + rx_HandleAll(interpret_proc,portname) + +The first four functions supply you with all the machinery needed +for adding an arexxport to your programs. However, if all your +program does is wait for and process messages from arexx anyway, +you can use this function which encapsulates the other four. All +it needs is a PROC to process the messages and again a portname. + +Alternatively, the source of this function is a usefull example +of how to call the other four functions, just incase you want +to call them yourself: + + +PROC rx_HandleAll(interpret_proc,portname) HANDLE + DEF port=NIL,sig,quit=FALSE,mes,s,rc,rs + port,sig:=rx_OpenPort(portname) + REPEAT + Wait(sig) + REPEAT + mes,s:=rx_GetMsg(port) + IF mes + quit,rc,rs:=interpret_proc(s) + rx_ReplyMsg(mes,rc,rs) + ENDIF + UNTIL (mes=NIL) OR (quit=TRUE) + UNTIL quit + Raise() +EXCEPT + rx_ClosePort(port) + ReThrow() +ENDPROC + + +From the code we can see that the proc given as an argument to rx_HandleAll() +gets as argument a string he may want to process, and returns a flag +wether to quit or not, and the rc and result as mentioned in the rx_Reply() +function. see arexxsimple.e how to make an arexxhost with this function +with just a few lines of code. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.e b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.e new file mode 100644 index 0000000..5629443 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexx.e @@ -0,0 +1,73 @@ +OPT MODULE + +MODULE 'exec/ports', 'exec/nodes', 'rexx/storage', 'rexxsyslib' + +RAISE "MEM" IF CreateArgstring()=NIL + +DEF rexxsysbase + +EXPORT PROC rx_OpenPort(portname) + DEF port:PTR TO mp,sig,exc=0 + NEW port + Forbid() + IF FindPort(portname) + exc:="DOUB" + ELSE + port.sigtask:=FindTask(0) + port.flags:=PA_SIGNAL + port::ln.name:=portname + port::ln.type:=NT_MSGPORT + IF (sig:=AllocSignal(-1))=NIL + exc:="SIG" + ELSE + port.sigbit:=sig + AddPort(port) + ENDIF + ENDIF + Permit() + IF exc THEN Raise(exc) +ENDPROC port,Shl(1,sig) + +EXPORT PROC rx_ClosePort(port:PTR TO mp) + IF port + FreeSignal(port.sigbit) + RemPort(port) + Dispose(port) + ENDIF +ENDPROC + +EXPORT PROC rx_GetMsg(port) + DEF mes:PTR TO rexxmsg + IF mes:=GetMsg(port) + rexxsysbase:=mes.libbase + RETURN mes,Long(mes.args) + ENDIF +ENDPROC NIL,NIL + +EXPORT PROC rx_ReplyMsg(mes:PTR TO rexxmsg,rc=0,resultstring=NIL) + mes.result1:=rc + mes.result2:=NIL + IF mes.action AND RXFF_RESULT AND (rc=0) AND (resultstring<>NIL) + mes.result2:=CreateArgstring(resultstring,StrLen(resultstring)) + ENDIF + ReplyMsg(mes) +ENDPROC + +EXPORT PROC rx_HandleAll(interpret_proc,portname) HANDLE + DEF port=NIL,sig,quit=FALSE,mes,s,rc,rs + port,sig:=rx_OpenPort(portname) + REPEAT + Wait(sig) + REPEAT + mes,s:=rx_GetMsg(port) + IF mes + quit,rc,rs:=interpret_proc(s) + rx_ReplyMsg(mes,rc,rs) + ENDIF + UNTIL (mes=NIL) OR (quit=TRUE) + UNTIL quit + Raise() +EXCEPT + rx_ClosePort(port) + IF exception THEN ReThrow() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.e b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.e new file mode 100644 index 0000000..46d4a97 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.e @@ -0,0 +1,11 @@ +-> test arexx module, the easy way out + +MODULE 'tools/arexx' + +PROC main() + rx_HandleAll({process},'AREXXTESTPORT') +ENDPROC + +PROC process(s) + WriteF('Received message "\s" from Arexx!\n',s) +ENDPROC StrCmp(s,'quit'),0,'result!' diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.rexx b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.rexx new file mode 100644 index 0000000..b993952 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Arexx/arexxtest.rexx @@ -0,0 +1,14 @@ +/* rx module test */ + +address AREXXTESTPORT + +OPTIONS RESULTS + +say 'testing....' + +'bla' +say 'result='result +'quit' +say 'result='result + +say 'done.' diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Async/async.guide b/amigae33a/E_v3.3a/Src/Src/Tools/Async/async.guide new file mode 100644 index 0000000..c436bb7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Async/async.guide @@ -0,0 +1,346 @@ +@database Async.guide + + +@$VER: Async.Guide 1.0 (06.11.93). +@toc async.m/main +@author Michael Zucchi +@(c) 1993 Michael Zucchi, All right reserved + + +@node Main "Async.guide" +@next "Commands" + +Aynschronous file reading module for AmigaE2.5+ + +© 1993 @{"Michael Zucchi" Link "Author"} +All Rights Reserved + +This document describes the usage of a suite of asynchronous file reading +routines designed for the AmigaE language. The interface is designed to +follow the V36 dos.library calls as closely as possible. + +The following sections are available: + + @{" OverView " Link "OverView"} some of the ideas behind the module + + @{u}General functions@{uu} + + @{"as_Open() " Link "as_Open"} to open a file + @{"as_Close() " Link "as_Close"} to close a file + @{"as_Read() " Link "as_Read"} reading from the file + + @{u}High level functions@{uu} + + @{"as_FGetS() " Link "as_FGetS"} reading text lines + @{"as_FGetC() " Link "as_FGetC"} reading character by character + + @{u}Low level functions@{uu} + + @{"as_NextBuffer()" Link "as_NextBuffer"} accessing input buffers direct + + + @{" Examples " Link Examples} + + @{b}NOTE: This module @{i}requires @{ui}Workbench 2.0 (V36) or higher! Please + make sure that this version of the system libraries is present before + using these functions.@{ub} + +@endnode + +@node OverView "Module overview" + +Just what is meant by 'asynchronous i/o'? + +When most programs use dos.library to read/write files, they simply call +Read() or Write(). What happens then is that these functions examine the +filehandle passed to them for information about the handler that handles +the file, and creates a dos 'packet' out of this information (see +dos/dosextens.m to see what a packet looks like). This packet is then sent +via the standard message passing system to the handler handling the file. +The dos function calls then wait for a reply to the request via the process's +message port pr_MessagePort - i.e. they @{u}wait@{uu} until the filesystem and handler +have retrieved the information before returning (incidentally, the fact that +the replies come in through pr_MessagePort is the reason dos cannot be called +from a standard 'task'). With a slow i.o device (e.g. floppy disk) all +of this waiting can mean the cpu is sitting idle a lot of the time waiting +for data to come in. + +How do you fix this less than ideal situation? Its quite simple. You +can create your @{u}own@{uu} packets and send these packets direct to dos. +This way, a custom reply port can be set up for the packets, and requests +for reads (or writes) can be sent out immediately, and the data read when +the packets are returned. If something needs to be done while the filesystem +is fetching this data, then your program can get it done - without having +to wait. + +This is basically what async.m does. Currently only reading is supported, +but writing will be added in the future, along with utilitiy functions like +Seek() etc. I got the idea from some code i got off the local BBS, something +from one of the cool guys at Commodore i think. + +@endnode + +@node "Author" "The guy who wrote it" + +I wrote this code some time ago, mainly for a multi-threaded directory +utility i've been working on from time to time. I found it so handy for +adding just that extra bit of performance to just about everything i wrote +that i thought other people might find it useful too. + +Presently, i study `from time to time' (:-) in order to obtain a Computer +Systems Engineering degree from the Univerity Of South Australia. +I'm `Zed' of FRONTIER in my anti-os hours. + +I can be contacted in the following ways: + +Internet email: + +9107047w@lux.levels.unisa.edu.au + till the end of '94 at least - reliable + +`Real Mode' (tm) mail: + +Michael Zucchi +PO BOX 824 +Waikerie +South Australia 5330 + slow, but very reliable - till mum sells the house :) + +Michael Zucchi +110 Dunrobin Rd +Warradale +South Australia 5046 + to my door - till i move (?) + +@endnode + + +@node as_Open +async.m/as_Open async.m/as_Open + +SYNTAX + + file := as_Open( name:PTR TO CHAR, + mode:LONG, + count:LONG, + size:LONG ); + +PURPOSE + Opens an asynchronous file, and returns a pointer to a (private) file + handle. When called, packets will be sent to the appropriate handler + to fill all buffers, and the return will call immediately. + +INPUTS + name A string, describing the name of the file to open + mode Same as mode in dos.library/Open. @{u}Must@{uu} be MODE_OLDFILE + for now. + count Number of buffers to allocate. 3 works very well. + size The size of each buffer to allocate. Above 5000 works + well, must be a multiple of 4. + +OUTPUTS + file A pointer to a filehandle that may be passed to the other + async functions. + +NOTES + No sanity checking is done on any of the input values. Use + reasonable values for everything. + The filehandle returned by as_Open() is NOT compatible with normal + dos filehandles, and system calls! + +SEE ALSO + @{"as_Close()" Link "as_Close"}, @{"as_NextBuffer()" Link "as_NextBuffer"}, @{"as_Read()" Link "as_Read"}, @{"as_FGetS()" Link "as_FGetS"}, @{"as_FGetC()" Link "as_FGetC"} +@endnode + +@node as_Close +async.m/as_Close async.m/as_Close + +SYNTAX + + as_Close( file:LONG ); + +PURPOSE + Closes the file, free's all memory buffers and cleans up all + outstanding packets. This call may be made as any time on a valid + async filehandle. + +INPUTS + file valid filehandle from as_Open(), or NIL in which case nothing + happens. + +OUTPUTS + +NOTES + +SEE ALSO + @{"as_Open()" Link "as_Open"} + +@endnode + +@node as_Read +async.m/as_Read async.m/as_Read + +SYNTAX + + bytes := as_Read( file:LONG, + buffer:PTR TO CHAR, + number:LONG ); + +PURPOSE + as_Read reads a number of bytes ('number') into the buffer specified + by 'buffer', from the async file 'file'. + + The number of bytes actually read in is indicated by the return value. + A return of zero indicates end of file, and errors are flagged by a + return value of -1. + +INPUTS + file Only a valid filehandle from as_Open() is allowed. + buffer A pointer to at least 'number' bytes of memory to store the + data. May be arbitrarily aligned. + number Specifies the number of bytes to read. number=0 is ignored. + +OUTPUTS + bytes The number of bytes actually stored in 'buffer'. A value of + zero indicates end of file, and -1 that a file error has + occurred, check IoErr() for detail. + +NOTES + +SEE ALSO + @{"as_Open()" Link "as_Open"}, @{"as_Close()" Link "as_Close"}, @{"as_NextBuffer()" Link "as_NextBuffer"}, @{"as_FGetS()" Link "as_FGetS"}, @{"as_FGetC()" Link "as_FGetC"} +@endnode + +@node as_FGetS +async.m/as_FGetS async.m/as_FGetS + +SYNTAX + + buffer := as_FGetS( file:LONG, + buffer:PTR TO CHAR, + number:LONG ); + +PURPOSE + Reads upto 'size' bytes from the file 'file' into the buffer pointed + to by the buffer parameter. Stops reading at end of file or once a + NEWLINE ($0a) character is encountered. Returns a pointer to that + buffer or NIL on end of file or error. + + The string stored in the buffer is NULL terminated. + +INPUTS + file A valid filehandle from @{"as_Open()" Link "as_Open"}. + buffer A pointer to at least 'number' bytes of memory to store the + data. May be arbitrarily aligned. + number Specifies the number of bytes to read, at maximum. This @{b}MUST + be >2@{ub}. + +OUTPUTS + buffer Same as 'buffer' passed as an input, or NIL on end of file + or file error. + +NOTES + If the line is too long to fit, the input stream is not skipped till + the next linefeed. + +SEE ALSO + @{"as_Open()" Link "as_Open"}, @{"as_Close()" Link "as_Close"}, @{"as_Read()" Link "as_Read"}, @{"as_NextBuffer()" Link "as_NextBuffer"}, @{"as_FGetC()" Link "as_FGetC"} +@endnode + +@node as_FGetC +async.m/as_FGetC async.m/as_FGetC + +SYNTAX + + char := as_FGetC( file:LONG ); + +PURPOSE + Reads the next character from the input file. Returns -1 on error + or end of file. The character is an unsigned 32 bit quantity. + +INPUTS + file A valid filehandle from @{"as_Open()" Link "as_Open"}. + +OUTPUTS + char The next available byte from the input stream, or -1 on + error. + +NOTES + This call is about as efficient as possible. + +SEE ALSO + @{"as_Open()" Link "as_Open"}, @{"as_Close()" Link "as_Close"}, @{"as_Read()" Link "as_Read"}, @{"as_NextBuffer()" Link "as_NextBuffer"}, @{"as_FGetS()" Link "as_FGetS"} +@endnode + + +@node as_NextBuffer +async.m/as_NextBuffer async.m/as_NextBuffer + +SYNTAX + + buffer,valid := as_NextBuffer( file:LONG ); + +PURPOSE + Returns the next available data buffer in the file. If end of file + has not yet been reached, and a buffer has now been made free, then + another read request is sent to the filesystem, in an asynchronous + manner. + +INPUTS + file A valid filehandle from @{"as_Open()" Link "as_Open"}. + +OUTPUTS + buffer The address of the internal data buffer, 0 for end of file, + or -1 on a file error. + valid Number of valid bytes in the buffer. This will be the same + as the size of each buffer as specified when the file was + opened, unless it is the last buffer being read. + +NOTES + @{b}The call is NOT compatible with any of the other reading functions.@{ub} + If you call those functions, you must NOT call this function, and + visa-versa. It is a low level function which both of the other read + functions make use of directly, and should only be used (esclusively) + where extra performance/lower memory use is required. + +SEE ALSO + @{"as_Open()" Link "as_Open"}, @{"as_Close()" Link "as_Close"}, @{"as_Read()" Link "as_Read"}, @{"as_FGetS()" Link "as_FGetS"}, @{"as_FGetC()" Link "as_FGetC"} +@endnode + + +@node Examples "Information about the examples" + +Included with this package are a few examples of using this module. + +@{u}typef@{uu} + + This is a simple example demonstrating the use of the as_FGetS() call. + It simply types a specified file to the current shell - quite a bit + faster than c:type does. + + usage: + @{"typef" Link typef.e/main} [Name] + +@{u}PlaySamp@{uu} + + This is a non-trivial example of the as_Read() function. It is a + complete 'raw sample' player that can be used to play ANY sized sample + from disk. + + usage: + @{"PlaySamp" Link playsamp.e/main} [Name] [ ... ] RATE + +@{u}histogram@{uu} + + A simple example of using the as_NextBuffer() command. It counts + the occurrannces of each byte in a file, and produces a report when + done. + + usage: + @{"histogram" Link histogram.e/main} [Name] + + Coding a more useful example for as_NextBuffer() requires a bit more + work than i have time for :) + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Async/histogram.e b/amigae33a/E_v3.3a/Src/Src/Tools/Async/histogram.e new file mode 100644 index 0000000..917af89 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Async/histogram.e @@ -0,0 +1,36 @@ +/* + + histogram.e Michael Zucchi 1993 + + Gives a population count for each byte in a file. + + */ + +MODULE 'tools/async', 'dos/dos' + +DEF counts[300]:ARRAY OF LONG; + +PROC main() + +DEF in,args:PTR TO LONG,rdargs,start:PTR TO CHAR,size,i; + +args:=[0]; +IF rdargs:=ReadArgs('Name/A', args, 0) + IF (in:=as_Open(args[0],MODE_OLDFILE,3,5120)) + REPEAT + start,size := as_NextBuffer(in); + IF start>0 + FOR i:=0 TO size-1 + counts[start[i]]:=counts[start[i]]+1; + ENDFOR + ENDIF + UNTIL start<=0 + as_Close(in) + FOR i:=0 TO 255 + WriteF('$\h[02]: \d\n', i, counts[i]); + ENDFOR + ENDIF + FreeArgs(rdargs) +ENDIF + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Async/playsamp.e b/amigae33a/E_v3.3a/Src/Src/Tools/Async/playsamp.e new file mode 100644 index 0000000..05ae273 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Async/playsamp.e @@ -0,0 +1,152 @@ +/* + + PlaySamp.e Michael Zucchi 1993 + + A disk based raw sample player, written in AmigaE. + + */ + +MODULE 'tools/async', + 'dos/dos', + 'exec/io', 'exec/memory', 'exec/ports', + 'devices/audio' + +CONST BUFFSIZE = 5120, + BUFFCOUNT = 3 + +PROC main() + +DEF args:PTR TO LONG,rdargs,rate,names:PTR TO LONG + +args:=[0,0] +IF rdargs:=ReadArgs('Name/A/M,Rate/N',args,0) + + -> is there an easier way to do this crap? + MOVE.L args,A0 + MOVE.L 4(A0),D0 + BEQ.S rate_def + MOVE.L D0,A0 + MOVE.L (A0),D0 + CMP.L #999,D0 + BLT.S rate_def + CMP.L #60001,D0 + BLT.S rate_ok +rate_def: + MOVE.L #10000,D0 +rate_ok: + MOVE.L D0,rate + + names:=args[0]; + WHILE (names[0]) + play(names[]++,rate) + ENDWHILE + FreeArgs(rdargs) +ENDIF + +ENDPROC + +PROC play(filename,rate) + +DEF arequest1:PTR TO ioaudio, + arequest2:ioaudio, + reply1,reply2, + ior:PTR TO io, + ioa:PTR TO ioaudio, + mnode:PTR TO mn, + buffer1,buffer2, + file, + len, + go + +WriteF('playing "\s"\n',filename) + +IF file:=as_Open(filename,MODE_OLDFILE,BUFFCOUNT,BUFFSIZE) + IF buffer1:=AllocVec(BUFFSIZE,MEMF_CHIP) + IF buffer2:=AllocVec(BUFFSIZE,MEMF_CHIP) + IF reply1:=CreateMsgPort() + IF reply2:=CreateMsgPort() + IF arequest1:=CreateIORequest(reply1, SIZEOF ioaudio) + + /* want to allocate and use any channel with OpenDev() */ + arequest1.data:=[1,2,4,8]:CHAR + arequest1.length:=4; + ior:=arequest1 + ior.command:=ADCMD_ALLOCATE + IF (0=OpenDevice('audio.device', 0, arequest1, 0)) + + /* copy iorequest for double buffered operation */ + ior.flags:=ADIOF_PERVOL + arequest1.volume:=64 /* volume = MAX */ + arequest1.period:=Div(3546895,rate)/* set frequency */ + arequest1.cycles:=1 /* 1 cycle only */ + ior.command:=CMD_WRITE + CopyMem(arequest1,arequest2,SIZEOF ioaudio) + mnode:=arequest2 + mnode.replyport:=reply2 + + /* send first two buffer's full to device */ + len:=as_Read(file,buffer1,BUFFSIZE) + arequest1.data:=buffer1 + arequest1.length:=len + beginio(arequest1) + len:=as_Read(file,buffer2,BUFFSIZE) + arequest2.data:=buffer2 + arequest2.length:=len + beginio(arequest2) + + /* wait on request1 first time around */ + mnode:=arequest1 + go:=1 + + /* until done, keep feeding data to device */ + WHILE (go) + WaitPort(mnode.replyport) + VOID GetMsg(mnode.replyport) + ioa:=mnode + IF ioa=arequest1 + mnode:=arequest2 + ELSE + mnode:=arequest1 + ENDIF + IF ((len:=as_Read(file, ioa.data, BUFFSIZE))>0) AND (CheckSignal(SIGBREAKF_CTRL_C)=0) + ioa.length:=len + beginio(ioa) + ELSE + go:=0 + ENDIF + ENDWHILE + + /* clean up */ + WaitPort(mnode.replyport) + GetMsg(mnode.replyport) + + CloseDevice(arequest1) + ENDIF + DeleteIORequest(arequest1) + ENDIF + DeleteMsgPort(reply2) + ENDIF + DeleteMsgPort(reply1) + ENDIF + FreeVec(buffer2) + ENDIF + FreeVec(buffer1) + ENDIF + as_Close(file) +ENDIF + +ENDPROC + + +/* from amiga.lib */ +PROC beginio(arequest) + MOVE.L arequest,A1 + MOVE.L A6,-(A7) + MOVE.L $14(A1),A6 + JSR -$1E(A6) + MOVE.L (A7)+,A6 +ENDPROC + + + + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Async/typef.e b/amigae33a/E_v3.3a/Src/Src/Tools/Async/typef.e new file mode 100644 index 0000000..f13adca --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Async/typef.e @@ -0,0 +1,26 @@ +/* + + typef.e Michael Zucchi 1993 + + A simple, quick 'type' command, using async.m + + */ + +MODULE 'tools/async', 'dos/dos' + +PROC main() + +DEF in,args:PTR TO LONG,rdargs,line[1024]:ARRAY OF CHAR + +args:=[0]; +IF rdargs:=ReadArgs('Name/A', args, 0) + IF (in:=as_Open(args[0],MODE_OLDFILE,3,5120)) + WHILE (as_FGetS(in, line, 1024)) AND (CheckSignal(SIGBREAKF_CTRL_C)=0) + PutStr(line) + ENDWHILE + as_Close(in) + ENDIF + FreeArgs(rdargs) +ENDIF + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Boopsi/Boopsi.e b/amigae33a/E_v3.3a/Src/Src/Tools/Boopsi/Boopsi.e new file mode 100644 index 0000000..72459a0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Boopsi/Boopsi.e @@ -0,0 +1,21 @@ +OPT MODULE + +MODULE 'intuition/classes', 'utility/hooks', 'intuition/classusr' + +/* example call: domethod(myobj,[METHODID,...]) */ + +EXPORT PROC domethod(obj:PTR TO object,msg:PTR TO msg) + DEF h:PTR TO hook,o:PTR TO object,dispatcher + IF obj + o:=obj-SIZEOF object /* instance data is to negative offset */ + h:=o.class + dispatcher:=h.entry /* get dispatcher from hook in iclass */ + MOVE.L h,A0 + MOVE.L msg,A1 + MOVE.L obj,A2 /* probably should use CallHookPkt, but the */ + MOVE.L dispatcher,A3 /* original code (DoMethodA()) doesn't. */ + JSR (A3) /* call classDispatcher() */ + MOVE.L D0,o + RETURN o + ENDIF +ENDPROC NIL diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/clonescreen.e b/amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/clonescreen.e new file mode 100644 index 0000000..c14ff2f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/clonescreen.e @@ -0,0 +1,76 @@ +-> clonescreen.c, from RKRM libs. + +OPT MODULE, OSVERSION=37 + +MODULE 'intuition/intuition', 'intuition/screens', + 'graphics/text', 'graphics/modeid' + +EXPORT PROC openclonescreen(pub_screen_name,clone_title,depth=0,clone_pub_name=NIL) + DEF my_screen=NIL:PTR TO screen, screen_modeID, pub_scr_font_name, + font_name, font_name_size, pub_screen_font:PTR TO textattr, + opened_font=NIL:PTR TO textfont, pub_screen:PTR TO screen, + screen_drawinfo=NIL:PTR TO drawinfo, di_font:PTR TO textfont + + IF pub_screen:=LockPubScreen(pub_screen_name) + IF screen_drawinfo:=GetScreenDrawInfo(pub_screen) + di_font:=screen_drawinfo.font + IF (screen_modeID:=GetVPModeID(pub_screen.viewport))<>INVALID_ID + pub_scr_font_name:=Long(di_font+10) -> node.name + font_name_size:=1+StrLen(pub_scr_font_name) + IF font_name:=String(font_name_size) + StrCopy(font_name,pub_scr_font_name) + pub_screen_font:=[font_name,di_font.ysize,di_font.style,di_font.flags]:textattr + IF opened_font:=OpenFont(pub_screen_font) + IF my_screen:=OpenScreenTagList(NIL, + [SA_WIDTH, pub_screen.width, + SA_HEIGHT, pub_screen.height, + SA_DEPTH, IF depth THEN depth ELSE screen_drawinfo.depth, + SA_TYPE, IF clone_pub_name THEN PUBLICSCREEN ELSE CUSTOMSCREEN, + SA_OVERSCAN, OSCAN_TEXT, + SA_AUTOSCROLL, TRUE, + SA_FONT, pub_screen_font, + SA_PENS, screen_drawinfo.pens, + SA_DISPLAYID, screen_modeID, + SA_TITLE, clone_title, + SA_PUBNAME, clone_pub_name, + NIL]) + ENDIF + ENDIF + ENDIF + ENDIF + FreeScreenDrawInfo(pub_screen,screen_drawinfo) + ENDIF + UnlockPubScreen(pub_screen_name,pub_screen) + ENDIF + IF my_screen=NIL THEN Raise("SCR") +ENDPROC my_screen,opened_font + +EXPORT PROC closeclonescreen(screen,font,window=NIL) + DEF r + IF window THEN CloseWindow(window) + IF screen THEN r:=CloseScreen(screen) + IF r THEN IF font THEN CloseFont(font) +ENDPROC r + +EXPORT PROC getcloneinfo(screen:PTR TO screen) + DEF di:PTR TO drawinfo, depth=0 + IF di:=GetScreenDrawInfo(screen) + depth:=di.depth + FreeScreenDrawInfo(screen,di) + ENDIF +ENDPROC depth,screen.width,screen.height + +EXPORT PROC backdropwindow(screen:PTR TO screen,idcmp=0,flags=0) + DEF wnd=NIL:PTR TO window + IF (wnd:=OpenWindowTagList(NIL, + [WA_LEFT,0, + WA_TOP,0, + WA_WIDTH,screen.width, + WA_HEIGHT,screen.height, + WA_IDCMP,idcmp, + WA_FLAGS,flags OR $1900, + WA_TITLE,'', + WA_CUSTOMSCREEN,screen, + NIL]))=NIL THEN Raise("WIN") + stdrast:=wnd.rport +ENDPROC wnd diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/testclone.e b/amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/testclone.e new file mode 100644 index 0000000..c7ca29c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/CloneScreen/testclone.e @@ -0,0 +1,21 @@ +-> test screen cloning + +OPT OSVERSION=37 + +MODULE 'tools/clonescreen' + +PROC main() HANDLE + DEF screen=NIL,font=NIL,win=NIL,xsize,ysize,depth + screen,font:=openclonescreen('Workbench','My Cloned Workbench') + win:=backdropwindow(screen) + depth,xsize,ysize:=getcloneinfo(screen) + EasyRequestArgs(win,[20,0,'On My Own Screen + Backdrop Window!', + 'Screen Dimensions Are \dx\dx\d', + 'Continue'],0,[xsize,ysize,depth]) +EXCEPT DO + closeclonescreen(screen,font,win) + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "WIN"; WriteF('no window!\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.doc b/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.doc new file mode 100644 index 0000000..0ed142a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.doc @@ -0,0 +1,18 @@ +constructors.m + +This module conatins various constructor functions for common +data structures. + + lh:=newlist(lh=NIL:PTR TO lh,type=0) + +initialises a an exec list header for you. if lh=NIL, it will allocate +a the header for you, otherwise it will use the pointer. +raises: "MEM" (only if lh=NIL) +example: mylist:=newlist() + + ln:=newnode(ln=NIL:PTR TO ln,name=NIL,type=0,pri=0) + +like newlist, newnode will allocate a node for you if ln=NIL. +raises: "MEM" (only if ln=NIL) +example: newnode(n,'bla') + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.e b/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.e new file mode 100644 index 0000000..47ffd96 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructors.e @@ -0,0 +1,22 @@ +-> various constructors module + +OPT MODULE +OPT EXPORT + +MODULE 'exec/lists', 'exec/nodes' + +PROC newlist(lh=NIL:PTR TO lh,type=0) + IF lh=NIL THEN lh:=NEW lh + lh.head:=lh+4 + lh.tailpred:=lh + lh.tail:=0 + lh.type:=0 + lh.pad:=0 +ENDPROC lh + +PROC newnode(ln=NIL:PTR TO ln,name=NIL,type=0,pri=0) + IF ln=NIL THEN ln:=NEW ln + ln.name:=name + ln.pri:=pri + ln.type:=type +ENDPROC ln diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructorstest.e b/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructorstest.e new file mode 100644 index 0000000..c64f3ae --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Constructors/constructorstest.e @@ -0,0 +1,11 @@ +-> constructortest.e + +MODULE 'tools/constructors' + +PROC main() HANDLE + DEF list,a + list:=newlist() + FOR a:=1 TO 10 DO Enqueue(list,newnode(NIL,'silly_nodes_test'+a,0,Rnd(100))) +EXCEPT + WriteF('no mem!\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.doc b/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.doc new file mode 100644 index 0000000..6ee0d8f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.doc @@ -0,0 +1,36 @@ +cookRawkey.m - Module of functions designed to process a raw input event, +translating it into its corresponding Vanilla keycode as defined by the +current keymap. Uses the console.device. + + warmupRawkeyCooker() + +Initializes the module to enable processing of raw input events. Should be +called once prior to invoking any of the other functions in the module. +May raise any of the following exceptions: "MEM", ER_CREATEPORT, +ER_CREATEIO, ER_OPENDEVICE, ER_ASKKEYMAP. + + ascii_keycode:=cookRawkey(message.code, message.qualifier, message.iaddress) + +ascii_keycode gets the Vanilla ASCII value if one exists, else 0. message is +here a PTR TO intuimessage, which contains the address of an IDCMP_RAWKEY +message. Vanilla ASCII codes may be manufactured by passing in a valid raw +code and a valid raw qualifier, and a valid PTR TO LONG which points to +deadkey prefixes (or zeroized memory if deadkeys aren't desired, i.e., +[0]:LONG) for the iaddress. + + shutdownRawkeyCooker() + +Cleans up the module. Should be called once when the module's functions are +no longer needed. Raises no exceptions. Performs complete sanity checks, +and may therefore be safely called multiple times. + + +NOTES: + +It is entirely possible that this module will successfully translate any +kind of raw input event properly, although this has not been tested. :-) + +You may repeatedly warmup and shutdown the rawkey cooker module, but you must +be careful to call shutdownRawkeyCooker() before calling warmupRawkeyCooker() +a subsequent time. Otherwise, the allocated resources will be irreclaimable +and your system will degrade. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.e b/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.e new file mode 100644 index 0000000..75f25a2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkey.e @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------------* + cookRawkey.e - Use console.device to convert rawkeys to asciikeys. + + Modifications: + Rev 1, 4 Oct 94, Barry Wills + cookRawkey() modified to correctly process deadkeys; + 1) changed parameter 'iAddress' to 'iAddress:PTR TO LONG'; + 2) changed statement 'PutLong(ie+10, iAddress)' to + 'PutLong(ie+10, iAddress[])' + *---------------------------------------------------------------------------*/ +OPT MODULE + +MODULE 'console', + 'devices/console', + 'devices/conunit', + 'devices/inputevent', + 'devices/keymap', + 'exec/io', + 'exec/ports' + +EXPORT CONST ER_NONE = 0, + ER_CREATEPORT = "PORT", + ER_CREATEIO = "IO", + ER_OPENDEVICE = "DEV", + ER_ASKKEYMAP = "KMAP" + +DEF consoleMessagePort:PTR TO mp, + consoleIO:PTR TO iostd + +EXPORT PROC warmupRawkeyCooker() + IF (consoleMessagePort:=CreateMsgPort())=NIL THEN RETURN ER_CREATEPORT + IF (consoleIO:=CreateIORequest(consoleMessagePort, SIZEOF iostd))= + NIL THEN RETURN ER_CREATEIO + IF OpenDevice('console.device', CONU_LIBRARY, + consoleIO, CONFLAG_DEFAULT) THEN RETURN ER_OPENDEVICE + consoleIO.command:=CD_ASKKEYMAP + consoleIO.length:=SIZEOF keymap + consoleIO.data:=NewR(SIZEOF keymap) + IF DoIO(consoleIO) THEN RETURN ER_ASKKEYMAP + IF (consoleIO.flags AND IOF_QUICK)=0 THEN WaitIO(consoleIO) + consoledevice:=consoleIO.device +ENDPROC ER_NONE + /* warmupRawkeyCooker */ + +EXPORT PROC shutdownRawkeyCooker() + IF consoleIO + IF consoleIO.data THEN Dispose(consoleIO.data) + IF consoleIO.device + AbortIO(consoleIO) + CloseDevice(consoleIO) + ENDIF + DeleteIORequest(consoleIO) + ENDIF + IF consoleMessagePort THEN DeleteMsgPort(consoleMessagePort) +ENDPROC + /* shutdownRawkeyCooker */ + +EXPORT PROC cookRawkey(idcmpCode, idcmpQualifier, iAddress:PTR TO LONG) + DEF asciiChar=0, ie:inputevent, buffer[1]:STRING, actual + ie.nextevent:=NIL + ie.class:=IECLASS_RAWKEY + ie.subclass:=0 + ie.code:=idcmpCode + ie.qualifier:=idcmpQualifier + PutLong(ie+10, iAddress[]) + actual:=RawKeyConvert(ie, buffer, 1, consoleIO.data) + IF actual=1 THEN asciiChar:=buffer[0] +ENDPROC asciiChar + /* cookRawkey */ diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkeyTest.e b/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkeyTest.e new file mode 100644 index 0000000..e7cc209 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/CookRawKey/cookRawkeyTest.e @@ -0,0 +1,124 @@ +/*------------------------------------------------------------------------* + cookRawkeyTest.e - test and demonstrate usage of module cookRawkey.m + + See function winDim() for a neato (although somewhat messy) example of + font- and os-sensitivity. + + Note: if your using custom fonts, you must have all characters defined + in order to see them. If any show up blank (except for, like, Space), + chances are that character isn't defined in your font. + *------------------------------------------------------------------------*/ + +MODULE 'devices/inputevent', + 'graphics/gfxbase', + 'graphics/rastport', + 'graphics/text', + 'intuition/intuition', + 'intuition/screens', + 'tools/cookRawkey', + 'tools/ctype' + +CONST ESCAPE_KEY=27 + +CONST TEXT_MAXLENGTH=23, + TITLE_MAXLENGTH=20 + +DEF wborleft, wborbottom, fontBelowBase + +PROC max(a, b) IS IF a>b THEN a ELSE b + +PROC winDim(gfxBase:PTR TO gfxbase, windowTitle) +/* determine the dimensions necessary to display our text. */ + DEF scr:PTR TO screen, xsize=0, ysize=0 + IF KickVersion(36) + IF scr:=LockPubScreen('Workbench') + xsize:=max(gfxBase.defaultfont::textfont.xsize*TEXT_MAXLENGTH, + IntuiTextLength([0,1,RP_JAM1,0,0, scr.font, + windowTitle,NIL]:intuitext)+1)+ + (wborleft:=scr.wborleft)+scr.wborright + ysize:=gfxBase.defaultfont::textfont.ysize+ + scr.rastport::rastport.font::textfont.ysize+ + scr.wbortop+1+ + (wborbottom:=scr.wborbottom) + UnlockPubScreen(NIL, scr) + ENDIF + ELSE + wborleft:=4 + wborbottom:=4 + xsize:=8*TEXT_MAXLENGTH+(wborleft*2) + ysize:=8*2+(wborbottom*2+1) + ENDIF +ENDPROC xsize,ysize + +PROC format(s, format, n) +/*---------------------------------------------------------* + format string 's' with number 'n', according to format + string 'format'. pads leading spaces in 's' with zeroes. + *---------------------------------------------------------*/ + DEF i, strLast + StringF(s, format, n) + strLast:=StrLen(s)-1 + FOR i:=0 TO strLast DO IF s[i]=" " THEN s[i]:="0" +ENDPROC s + +PROC main() HANDLE + DEF win=NIL:PTR TO window, winTitle, winHeight, winWidth, + idcmpMessage:PTR TO intuimessage, idcmpCode, idcmpQualifier, iAddress, + error, errorMessage, asciiChar, hexStr[3]:STRING, decStr[3]:STRING + /*------------------------------* + Init rawkey conversion module. + *------------------------------*/ + IF error:=warmupRawkeyCooker() THEN Raise(error) + winWidth,winHeight:=winDim(gfxbase, winTitle:='Press Escape to Quit') + /*-- Convert rawkeys until ESC key is pressed. --*/ + IF win:=OpenW(20, 20, winWidth, winHeight, + IDCMP_RAWKEY, WFLG_ACTIVATE, + winTitle, NIL, WBENCHSCREEN, NIL) + IF FALSE=KickVersion(36) THEN SetTopaz(win) + fontBelowBase:=win.rport::rastport.txheight- + win.rport::rastport.font::textfont.baseline + REPEAT + /*-- Wait on rawkey. --*/ + WHILE (idcmpMessage:=GetMsg(win.userport))=NIL DO WaitPort(win.userport) + /*-- Copy intuimessage info, then reply. --*/ + idcmpCode:=idcmpMessage.code + idcmpQualifier:=idcmpMessage.qualifier + iAddress:=idcmpMessage.iaddress + ReplyMsg(idcmpMessage) + /*------------------------* + Convert rawkey to ascii. + *------------------------*/ + IF asciiChar:=cookRawkey(idcmpCode, idcmpQualifier, iAddress) + TextF(wborleft, win.height-wborbottom-fontBelowBase, + 'Char=\c Hex=$\s Dec=\s', + IF isprint(asciiChar) THEN asciiChar ELSE $7f, + format(hexStr, '\h[3]', asciiChar), + format(decStr, '\d[3]', asciiChar)) + ENDIF + UNTIL asciiChar=ESCAPE_KEY + CloseW(win) + ELSE + WriteF('Can''t open window\n') + ENDIF + /*---------------------------------* + Cleanup rawkey conversion module. + *---------------------------------*/ + shutdownRawkeyCooker() +EXCEPT + errorMessage:='figger it out' + /*--------------------------------------* + Handle exceptions raised by conversion + *--------------------------------------*/ + SELECT exception + CASE "MEM"; errorMessage:='get memory' + CASE ER_CREATEPORT; errorMessage:='create message port' + CASE ER_CREATEIO; errorMessage:='create IO request' + CASE ER_OPENDEVICE; errorMessage:='open console.device' + CASE ER_ASKKEYMAP; errorMessage:='ask keymap' + ENDSELECT + WriteF('Could not \s!\n', errorMessage) + /*---------------------------------* + Cleanup rawkey conversion module. + *---------------------------------*/ + shutdownRawkeyCooker() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctest.e b/amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctest.e new file mode 100644 index 0000000..b6815a4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctest.e @@ -0,0 +1,5 @@ +MODULE 'tools/ctype' + +PROC main() + WriteF('\d \d \d\n',islower(tolower("A")),islower(toupper("a")),isalnum("+")) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctype.doc b/amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctype.doc new file mode 100644 index 0000000..58ee219 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Ctype/ctype.doc @@ -0,0 +1,16 @@ +ctype.m: functions usually found in ctype.h + +tolower(c) converts any char to lowercase +toupper(c) converts any char to uppercase + +isspace(a) " " +isupper(a) "A" .. "Z" +islower(a) "a" .. "z" +isalpha(a) "a" .. "z", "A" .. "Z" +isalnum(a) "a" .. "z", "A" .. "Z", "0" .. "9" +isxdigit(a) "0" .. "9", "a" .. "f", "A" .. "Z" +isdigit(a) "0" .. "9" +iscntrl(a) 0 .. 31, 128 .. 159 +isprint(a) 32 .. 127, 160 .. 255 +isgraph(a) isprint - isspace +ispunct(a) isgraph - isalnum diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.License b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.License new file mode 100644 index 0000000..4dee842 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.License @@ -0,0 +1,56 @@ + Gadget & Image Collection #1 + +COPYRIGHT and TRADEMARKS + +Gadget & Image Collection #1 +(c) Copyright 1992-94 Commodore-Amiga, Inc. All Rights Reserved + +FILES + + classes (dir) + gadgets (dir) + button.gadget calendar.gadget + tabs.gadget + images (dir) + led.image + + +DISCLAIMER + +These FILES are provided "AS-IS" and subject to change without notice; +no warranties are made. All use is at your own risk. No liability or +responsibility is assumed. + + +DISTRIBUTION + +The FILES may be reproduced and distributed subject to agreement with +the following terms and conditions: + +1. The FILES may be reproduced but may not be modified in any way + with the exception of unarchiving for unarchived distribution. + +2. The FILES may only be distributed as an integral part of a software + product solely for Commodore Amiga computers. + +3. Commodore shall be held harmless from any and all claims, damages + and liabilities resulting from or arising out of the use or + distribution of the FILES. + +4. The copyright, trademarks, and disclaimer shown above must be + distributed with all copies of the FILES. + +5. The FILES may not be installed on a user's system or Workbench + unless the installation procedure has determined that the user's + system or Workbench does not contain a more recent version of the + FILES. + +7. Such technical information as is contained in the FILES (and any + product thereof) or in the related documentation, utilities, and + examples may not be exported in contravention of the laws and + regulations of the United States. + +8. Commodore may terminate permission to distribute the FILES at + any time, with or without cause. This permission will + automatically terminate upon any breach of these terms and + conditions. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.Readme b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.Readme new file mode 100644 index 0000000..c8cd852 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/GI1.Readme @@ -0,0 +1,12 @@ +GI1 42.1 - Copyright (c) 1994 Commodore-Amiga, Inc. + All Rights Reserved. + Written by David N. Junod + +This is a collection of BOOPSI gadgets and images. Includes a +sophisticated button gadget, calendar gadget, LED image and a page +selection gadget. These classes work with all Amigas and require a +minimum of 2.04 (V37). + +See GI1.License for distribution information. An Installer installation +script is included to ease installation of the classes, Autodocs, header +files and examples. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/button.gadget b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/button.gadget new file mode 100644 index 0000000000000000000000000000000000000000..7ee40a7e64ca88e9fd041b786492dd51bd660129 GIT binary patch literal 4868 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 g&<{9 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/calendar.gadget b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/calendar.gadget new file mode 100644 index 0000000000000000000000000000000000000000..dde638006dd395a731b5fe5a1e185aa3f2f7d850 GIT binary patch literal 6100 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/tabs.gadget b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Classes/Gadgets/tabs.gadget new file mode 100644 index 0000000000000000000000000000000000000000..03c93274316dfee530e249594213aa5bce8cc9f1 GIT binary patch literal 6008 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 b@vZ$JWOHiY4H?+Awr07>F|*B9_xXPS5~3=h literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/EasyGUI.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/EasyGUI.doc new file mode 100644 index 0000000..d666696 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/EasyGUI.doc @@ -0,0 +1,1322 @@ + Introducing: + + E A S Y G U I v3.3b4 + + An interface builder for E, with the following highlights: + + - It's totally Font-Sensitive + - It's Resizable + - It's Self-Organising, i.e. it arranges gadgets + - It's more StyleGuide compliant than your granny + - It's Fast and Flexible + - It's relatively small, needs no extra external libraries + - The layout-engine is user-extendable with PLUGINs + - And above all: It's extremely easy to use!!! + ++---------------------------------------------------------------+ +| 0. History | ++---------------------------------------------------------------+ + +As of v3.3a, maintained by Jason R. Hulance, who you can contact at +the addresses given in the Beginner's Guide to Amiga E. +(Email: jason@fsel.com) + +[v3.3b4:] +- Fixed changegui() window resizing to move window as well, if + necessary. + +[v3.3b3 is a minor update that fixes a bug with AppWindow messages +that crept in under the guise of a safety feature in v3.3b...] + +Changes from the v3.3b version: +- Fixed bug: STR, INTEGER and CHECK gadgets' action functions were not + getting passed the correct new value parameter. +- Fixed bug: LISTV wasn't always wide enough for label. +- Added EG_HIDE tag to enable the GUI to be created with a hidden (closed) + window. +- Changed blockwin()/unblockwin() so they now nest properly. + +Changes from the v3.3a version: +- MAJOR CHANGE: made the main functions use a taglist for their optional + arguments (it was getting a bit ridiculous...). This gives a bit more + flexibility for the programmer and makes for much more readable code, so + I'm afraid it was inevitable. To ease the change-over a bit there is an + example module which gives the old style versions of the functions (just + for EasyGUI.m; you can do your own for EasyGUI_lite.m). +- MAJOR ADDITION: support for multi-window GUIs. This is via the + multiinit(), addmultiA(), multimessage(), cleanmulti() and checkmulti() + functions. The new scheme shares message ports, and efficiently + dispatches on the message data. This is *massively* more efficient than + using the old scheme (OR-ing the signal masks of each window), and + effectively removes the limit of windows that a GUI can use. +- Changed 'info' default to -1, which now gets translated to the guihandle. + This helps a lot with multi-window GUIs. +- Changed 'data' default to -1, which now gets translated to the gadget + (not the *real* gadget, but the one that can be used with the setXXX() + functions). +- Changed the default screen to be the *default* public screen (rather than + specifically Workbench). +- Changed AppWindow gadget location code to make it more robust, and now + includes the gadget label as "hittable". +- Added a short description of the examples to this doc. +- Added a reference to the guihandle to each PLUGIN so they can more easily + access the GUI window and use the GUI manipulation functions. +- Added closewin()/openwin() to enable the window to be temporarily closed + and opened. These are most useful for iconification (see the iconify and + toolify PLUGINs). Note that this new feature may break old PLUGINs that + assume the GUI window will never change. +- Added extra 'maxw' and 'maxh' parameters to make window open with maximum + width/height (taking into account position, too). +- Added extra 'wintype' parameter to give control over window borders. +- Added some more changeXXX() functions, and changed (sorry!) the other + changeXXX() functions to make them more uniform. +- Added extra checking in message loop to ignore stray IDCMP_MOUSEMOVE + messages. This is needed because GadTools doesn't identify the gadget if + you use GACT_FOLLOWMOUSE, so your PLUGIN finds it hard to trap this + message properly. + [Problem reported by Ralph Wermke ] +- Fixed bug in key handling code for the SLIDER gadget. + [Bug reported first by Fred van der Zee ] +- Fixed an old bug: guihandles weren't deallocated by cleangui(). +- Fixed an old bug: some messages weren't getting replied. +- Fixed an old bug: window wasn't being centred on screen if smaller than + display (and may not have been openable). +- Minor changes to the layout of a couple of gadgets. +- Made gadtoolsbase and workbenchbase public, mainly so that PLUGINs + can use them (if you have a GUI open then they must be valid). +- Made things more friendly for multi-tasking: gh.wnd is NIL when the + GUI is in an unmodifiable state. +- Made awprocs use a copy of the appmessage, mainly so that they can do + things like manipulate the GUI without problems. +- Made a third version of EasyGUI. This is EasyGUI_debug.m, which is the + same as EasyGUI.m except that it will print a short diagnostic message + before raising an exception. This should be used when developing your + program to help track down the actual reason for a fault. + +Changes from the v3.2e version: +- Lots of minor fixes to most gadgets. +- Added conditional resizing. +- Added (optional) data field for all gadgets. +- Added Style Guide compliant keyboard shortcuts. +- Added extra arguments to some PLUGIN methods. +- Added simple mechanism for PLUGINs to use GadTools gadgets (gtrender()). +- Added AppWindow support for main window, *BUTTON, LISTV, STR and PLUGINs. +- Added a lot of GUI manipulation functions. +- Made an EasyGUI_lite version without a lot of features. + +changes from the v3.2a version: +- now supports PLUGINs for unlimited complex gui's!!! (check section 5) +- added settext() and setnum() +- fixed NUM gadget +- added topaz-fallback version +- bug: rendered into the border when used with sysihack +- bug: could cause enforcer hits when some strings were NIL +- bug: dealocation of resources in wrong order caused problems + +changes from the v3.1a version: +- new functions to access/modify gadgets while GUI is active +- easily add gadtools menus +- more complete docs +- works better with multiple simultanuous EasyGUIs +- LISTV, MX and CYCLE have an extra "current" parameter now +- STR now takes an _estring_ as value (change this in old sources!) +- bug: current gadget values would reset upon resize +- bug: would open in middle of screen instead of visible part +- many tiny bugs removed + ++---------------------------------------------------------------+ +| 1. EasyGUI Intro | ++---------------------------------------------------------------+ + +EasyGUI takes the form a module file that needs to be included into your E +source (needless to say, it needs v2.04/v37 of the OS). The most simple +form of constructing a GUI consist of calling the function easyguiA() with +a (possibly nested) E list which describes your GUI. just to show how +Easy, try this source: + + MODULE 'tools/EasyGUI' + PROC main() IS easyguiA('um,...',[BUTTON,0,'Ok!']) + +This'll open a window with just one gadget in it, and wait for the user to +push it. If easyguiA() can't get what it wants, it'll start throwing around +exceptions, so we'll probably need an exception handler to be able to +inform the user properly (see below). + +The first arg of easyguiA() is the window title, the second one is the GUI +description. The form of these desciptions is quite simple: It's a list +with as first element the type of gadget, the second is called an action +value (more later), and the rest is gadget-specific. + +To be able to build GUI's outof more components than just one gadget, one +can group gadgets with a ROW and a COL list: + + [COLS, + [BUTTON,1,'Ok'], + [BUTTON,0,'Cancel'] + ] + +This'll create a new group, consisting of two gadgets next to each other. +COLS and ROWS groups are like a single gadget, i.e. you can easily put them +into other groups, to create GUI's of infinite complexity. + +Other Grouping functions are EQCOLS and EQCOLS, which try to align gadgets +in a group. IF you get strange layouts using these, you should try grouping +subgroups before putting them in a larger group. + +[BEVEL,a] will put a bevel box around a, whatever it is (a gadget, a +group...), and BEVELR is the recessed version. + +Other elements of groups are mostly gadgets, which have a specific #of +arguments. [If the number of arguments is incorrect, EasyGUI will raise the +"Egui" exception.] + +The first element is always the type of gadget to create (see below). The +second element is always something called an "actionvalue", which tells +EasyGUI what needs to be done when the user interacts with the gadget. All +elements after that are gadget specific. + +An action value may be: +- a small positive integer (0-1000). If the user selects this gadget, + EasyGUI will close the window, and return that value as returnvalue from + the easyguiA() call. This is meant for "Ok" / "Cancel" type buttons. +- a pointer to an "action function". If the user selects this gadget, + EasyGUI will call the function with as arguments depending on the type of + gadget (for example a slider will get it's current value). After the + actionfunction returns, EasyGUI continues processing messages from the + GUI. + example: + + ...[BUTTON,{load},'Load'],... + + PROC load(info) IS WriteF('You pushed the "Load" button!\n') + + + the value of `info' is explained below. Or: + + DEF s[100]:STRING + + ...[STR,{str},'input:',s,50,4], + [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1],... + + PROC str(info,news) IS WriteF('the new string is: \s\n',news) + PROC cycle(info,newc) IS WriteF('the new choice is: \d\n',newc) + + In the action function, you can store the new value, however EasyGUI + keeps track of it itself too: In the case of the STR above it will + StrCopy() new values into your estring, so it automatically has the + correct value after closing. In the case of all other gadgets it stores + the new (integer) value in the list (so that `1' in `CYCLE' may become + `0'). This has the added benefit that windows that are opened and then + closed again will automatically start with the current values. + + If you want to close the GUI from an action function then you can call + the quitgui() function, which raises a "QUIT" exception (be careful to + not handle this exception in your code -- just ReThrow() it if your + action function has an exception handler). The single argument to + quitgui() (which defaults to 0) will be returned from the easyguiA() call, + in the same way that action values are. The definition of quitgui() is: + + PROC quitgui(ret=0) IS Throw("QUIT",ret) + + There are two new, optional arguments to action functions: `qual' and + `data'. If you wish to use these arguments your action function must + include them at the beginning (and you must have a `data' argument if you + want to use the `qual' argument). For instance, a button action function + can be defined in any of these three ways: + + PROC action(info) IS WriteF('info=$\h\n', + info) + PROC action(data,info) IS WriteF('info=$\h,data=$\h\n', + info,data) + PROC action(qual,data,info) IS WriteF('info=$\h,data=$\h,qual=$\h\n', + info,data,qual) + + (This scheme gives *full* compatibility with the old EasyGUI action + functions, whilst still allowing the new features to be used.) + + The `data' argument is the optional data field specified in the gadget. + If it is not specified or it's -1 then the actual data value that is used + is the gadget list pointer (for use with the setXXX() functions). You + could use it, instead, to pass a pointer to an object specific to the + gadget. The action function can then just call a method of that object. + This allows the same action function to be used by a number of different + gadgets, with the specific action being carried out via the data element + (since the data can be different for each gadget). + + The `qual' is basically the qualifier part of the intuimessage used to + indicate gadget clicks. Use the IEQUALIFIER_XXX constants from the + module 'devices/inputevent' to see which qualifiers were pressed when + the gadget was clicked. For example: + + PROC buttonaction(qual,data,info) + IF qual AND (IEQUALIFIER_LSHIFT OR IEQUALIFIER_RSHIFT) + PrintF('You were pressing a shift key when you clicked on me!\n') + ENDIF + ENDPROC + +The easyguiA() function: + + easyguiA(windowtitle,gui,tags=NIL) + +`tags' is a taglist which can use the following tags: + +EG_INFO + the data may be ANY value, and is passed as an arg to the action + functions. For example if you write a prefsrequester, this may be the + the prefs OBJECT. Your actionfunctions then have a simple task changing + the value of the element in question. (If this is -1 or not present, + then it the info used will be the 'guihandle' value for this GUI. See + Chapter 4.) + +EG_SCRN + the data is an optional screen ptr to open on. if NIL or not present + EasyGUI opens on the default public screen (usually Workbench). + +EG_FONT + the data is a fontdescription (i.e., a `textattr'). If NIL or not + present, EasyGUI will use the same font as the screen (for Workbench this + is the font the user selected as "screenfont" in fontprefs). + +EG_MENU + the data is a newmenus structure (as in gadtools.library). EasyGUI will + then automatically attach it to the window and arrange any messages. You + can give the same actionvalues as gadgets in the newmenu.userdata, and + the actionfunction can be the same as for a `BUTTON', i.e.: + + [...,NM_ITEM,0,'Load','l',0,0,{load},...]:newmenu + + can use the same load() as in the example further above (the optional + `qual' and `data' arguments [see below] will always be NIL). [The + constants NM_ITEM, etc., are from the module 'libraries/gadtools'.] + +EG_GHVAR + the data is the address of a LONG variable which gets a copy of the + guihandle (see Multiple Windows, below). You just specify something like + {gh} instead of having to use guiinitA(), etc. Note that you can also + get the guihandle by using the new default for the `info' of a GUI + (as described above). + +EG_AWPROC + the data is a function to be called when the user drops icons on the + window (and no gadget handles the drop). By default, this is NIL and + this means that the window will not to be made into an AppWindow. If + it's *not* NIL then the window *will* be an AppWindow, and the *BUTTON, + LISTV and STR gadgets will get their awprocs called if icons are dropped + directly on them (PLUGIN gadgets can also react to AppWindow messages). + If the drop does not land on a gadget with an awproc then this awproc + (for the whole window) will be called. (See the examples.) awprocs are + like action functions and can be defined in one of two ways: + + PROC awproc(info,awmsg:PTR TO appmessage) + PROC awproc(data,info,awmsg:PTR TO appmessage) + + `info' is the GUI info, `awmsg' is a *copy* of the appmessage and `data' + is the optional data field for the gadget (or the `plugin_object' for + PLUGINs, and NIL for the window one). + +EG_TOP, EG_LEFT + the data define the top-left coordinate of the window. If either of them + is -1 (the default), then the window will be centred on that axis (in the + visible part of the screen). + +EG_MAXW, EG_MAXH + the (boolean) data specify whether to try make the window size maximal in + width or height (based on screen size), rather than the default of + minimal (based on the GUI). If you specify a position then the maximal + size of that axis will be the remaining part of the screen. So, on a + screen of width 640, if you specify EG_LEFT of 100 then the maximum width + the window can be is 540. + +EG_WTYPE + the data is a constant to dictate the window decoration (i.e., what + happens with the borders). The choices are: + + WTYPE_SIZE the default, which gives you all the standard + gadgets and a size gadget at the bottom. + WTYPE_NOSIZE omits the size gadget. + WTYPE_BASIC just has a simple border around the window. + WTYPE_NOBORDER has (suprisingly) no border. + + Be careful with these last two options as there is no close gadget for + the user to click -- you must provide them with your own method of + closing the GUI (a menu item?). (Note: the window title is ignored with + the last two types, since there's no title bar.) + +EG_CLOSE + the data is an action value/function used when the user clicks the close + gadget on the GUI window. This is most useful for multi-window GUIs (see + Multiple Windows), but it can be useful to prompt the user to confirm + before quitting the GUI. The action value will be returned from + easyguiA()/guimessage()/multiloop()/multimessage(), as usual. The action + function can be defined in one of two ways: + + PROC closeproc(info) + PROC closeproc(mh:PTR TO multihandle,info) + + `info' is the GUI's info parameter (see above), and `mh' is the + multi-window handle (see Multiple Windows) or NIL if it's a single window + GUI. + +EG_CLEAN + the data is a function to be called when the GUI is destroyed (e.g., by + calling cleangui()). This is most useful for multi-window GUIs (see + Multiple Windows), but it can generally be useful for cleaning up the + GUI's PLUGINs (see Chapter 5). The function will be called *after* the + window and the GUI has been closed and deallocated, so, for example, the + PLUGINs will no longer be on screen. It should be defined like this: + + PROC cleanproc(info) + + `info' is the GUI's info parameter (see above). Note: if guiinitA() or + addmultiA() cause an exception then this function will *not* be called. + This makes it easier to setup a GUI (see the examples). + +EG_HIDE + the (boolean) data specifies whether the GUI window is initially hidden + (closed). The default is FALSE; if you specify TRUE then you can use + openwin() to show the window when you want it to be seen. Note: this tag + is a bit useless for a normal call to easyguiA() as there's little chance + of it receiving any GUI messages if the window is closed (so the Wait() + will never return). + + ++---------------------------------------------------------------+ +| 2. Gadgets | ++---------------------------------------------------------------+ + +general format: [NAME,action,text,...] +in {}: which direction it may resize. ++ = a value that can be affected lateron with the set#? functions +* = optional value (can be omitted) + +Each gadget shows the gadget template, explanation, the form of the +actionfunction, and a typical example. + +The optional arguments to action functions (qual and data) are described in +the above chapter. + + +[BUTTON,action,intext,data*,key*,awproc*,disabled+*] + data = user data value passed to action function + key = keyboard shortcut (presses button) + awproc(data*,info,awmsg) = AppWindow proc (see above) + disabled = whether this gadget is disabled or not + buttonaction(qual*,data*,info) + example: [BUTTON,0,'Cancel'] + +[CHECK,action,righttext,checkedbool+,lefttextbool,data*,key*,disabled+*] + checkedbool = whether gadget should initially be check-marked + key = keyboard shortcut (toggles check) + disabled = whether this gadget is disabled or not + checkaction(qual*,data*,info,checkedbool) + example: [CHECK,{case},'Ignore case',TRUE,FALSE] + +[INTEGER,action,lefttext,num+,relsize,data*,key*,disabled+*] + num = initial value + key = keyboard shortcut (activates gadget) + disabled = whether this gadget is disabled or not + integeraction(qual*,data*,info,newnum) {x} + example: [INTEGER,{v},'int:',5,3] + (Note: see discussion of getinteger() in chapter 4 below.) + +[LISTV,action,textabove,relx,rely,execlist+,readbool,selected,current+, + data*,key*,awproc*,disabled+*] + execlist = ptr to an execlist. (see tools/constructors.m) + readbool = whether listview is read-only (action is ignored if it is!) + selected = 0=none, 1=highlight/show selected + key = keyboard shortcut (unshifted->select next, shifted->prev) + awproc(data*,info,awmsg) = AppWindow proc (see above) + disabled = whether this gadget is disabled or not + listviewaction(qual*,data*,info,num_selected) {x,y} + example: [LISTV,0,NIL,5,5,filenamelist,0,NIL,0] + (Note: disabling doesn't work under V37.) + +[MX,action,righttext,nil_term_elist,lefttextbool,current, + data*,key*,disabled+*] + (Note: under v37 the righttext is spaced correctly but not rendered.) + key = keyboard shortcut (unshifted->next choice, shifted->prev, wraps) + disabled = whether this gadget is disabled or not + mxaction(qual*,data*,info,num_selected) + example: [MX,{v},NIL,['One','Two','Three',NIL],FALSE,1] + (Note: disabling doesn't work under V37.) + +[CYCLE,action,lefttext,nil_term_elist,current,data*,key*,disabled+*] + key = keyboard shortcut (unshifted->next choice, shifted->prev, wraps) + disabled = whether this gadget is disabled or not + cycleaction(qual*,data*,info,num_selected) + example: [CYCLE,{v},'choose:',['Yep','Nope',NIL],1] + +[PALETTE,action,lefttext,depth,relx,rely,current+,data*,key*,disabled+*] + (Note: the current field is new to v3.3a and is _not_ optional, so any + existing v3.2e sources using a PALETTE gadget will need a small edit.) + depth = 1..8, number of bitplanes this color is for + key = keyboard shortcut (unshifted->next pen, shifted->prev, wraps) + disabled = whether this gadget is disabled or not + paletteaction(qual*,data*,info,colour) {x,y} + example: [PALETTE,{v},'color:',3,5,2] + +[SCROLL,action,isvert,total+,top+,visible+,relsize,data*,key*,disabled+*] + total = resolution of scroller + top = current top represented + visible = current + key = keyboard shortcut (unshifted->increment, shifted->decrement) + disabled = whether this gadget is disabled or not + scolleraction(qual*,data*,info,curtop) {x|y} + example: [SCROLL,{v},FALSE,10,0,2,2] + +[SLIDE,action,lefttext,isvert,min,max,cur+,relsize,levelformat, + data*,key*,disabled+*] + min,max = value range of slider + cur = current value + levelformat = string that shows levelformat, example '%2ld'. leave + a large amount of spaces left in lefttext for this. + key = keyboard shortcut (unshifted->increment, shifted->decrement) + disabled = whether this gadget is disabled or not + slideraction(qual*,data*,info,cur) {x|y} + example: [SLIDE,0,'Colors:',FALSE,1,8,3,5,''] + +[STR,action,lefttext,initial+,maxchars,relsize, + over*,data*,key*,awproc*,disabled+*] + initial = initial string contents: NOTE: HAS TO BE AN ESTRING! + maxchars = max #of chars for string + over = overwrite mode boolean (default is FALSE, i.e., insert mode) + key = keyboard shortcut (activates gadget) + awproc(data*,info,awmsg) = AppWindow proc (see above) + disabled = whether this gadget is disabled or not + stringaction(qual*,data*,info,string) {x} + (Note: action function is passed the E-string, not the gadget's buffer.) + example: [STR,0,'Pattern',s,100,5] (DEF s[100]:STRING) + (Note: see discussion of getstr() in chapter 4 below.) + +[TEXT,text,lefttext,borderbool,relsize] {x} + borderbool = whether or not a recessed bevelbox is placed around 'text' + example: [TEXT,'Selected Fonts',NIL,FALSE,3] + +[NUM,int,lefttext,borderbool,relsize] {x} + borderbool: as TEXT + example: [NUM,123,'num:',TRUE,5] + +[SBUTTON,action,intext,data*,key*,awproc*,disabled+*] {x} + same as button, only now resizes horizontally. + +[PLUGIN,action,plugin_object,isgt*,awproc*] + isgt = whether this PLUGIN is made from GadTools gadgets (see chapter 5) + awproc(plugin_object*,info,awmsg) = AppWindow proc (see above) + pluginaction(info,plugin_object) + (see separate chapter 5 on using/implementing these). + +[BAR], [SPACE] {x,y}, [SPACEH] {x}, [SPACEV] {y} + BAR places a nice divider-bar between gadgets/groups. Whether it's + horizontal or vertical depends on which group it is in. + SPACE/SPACEH/SPACEV do nothing, they only eat up space. This can be very + handy in GUI design, they act like a spring between elements (do not use + them on the borders of a GUI, only in the middle). + + +#?text: + (where #? is left/right etc.): a text to place next to the gadget. Often + is allowed to be NIL. + +relsize,relx,rely: + Generally gadgets will automatically get a size depending on a number of + factors, but relsize allows the programmer to give a minimum size for + certain gadgets, thereby sizing a whole group. If other gadgets already + account for the minimum size, this one can safely be set to a low value + such as 2. All these sizes are calculated in terms of the _height_ of + the font. Always try out your GUI with different fonts. For example if + you design a gui that only just fits horizontally with an 8 point font on + 640x200, when run on with a 13 point font on 640x512, the gui will be + quite a bit bigger horizontally, but the screen isn't, so it won't fit. + (see also: the "bigg" exception below). + +nil_term_elist: + a nil-terminated E list, such as ['One','Two','Three',NIL] + +isvert: + TRUE if gadget needs to be vertical, horizontal by default. + +key: + All keyboard shortcuts are optional (so marked with a * in the following + descriptions). If specified then they must be lowercase letters ("a" to + "z"). However, the shifted and unshifted keystrokes are *both* handled, + in the way described by the Style Guide (and this is briefly outlined for + each gadget). Also, if a key is specified then an "_" in the gadget + label text indicates the character in the label which is to be + underscored (and this ought to be the same letter as the key). If a key + is not specified then any "_"s in the label are not special. (If an + action function is invoked as a result of a key press then the `qual' + will always be 0.) + +disabled: + If this optional field is specified then the gadget can be disabled and + enabled using the setdisabled() function (see below, chapter 4), and the + current status of the gadget will be recorded in this field, too. + + +The following constants/enumerations are defined in order to make +referencing/creating the lists for each gadget a bit more readable. + + EXPORT ENUM BEV_GUI=1, + BUT_ACT=1, BUT_TXT, BUT_DATA, BUT_KEY, BUT_APPW, BUT_DIS, + CHK_ACT=1, CHK_TXT, CHK_VAL, CHK_LEFT, CHK_DATA, CHK_KEY, CHK_DIS, + INT_ACT=1, INT_TXT, INT_VAL, INT_REL, INT_DATA, INT_KEY, INT_DIS, + LST_ACT=1, LST_TXT, LST_RELX, LST_RELY, LST_LIST, LST_RO, LST_SHOW, + LST_CURR, LST_DATA, LST_KEY, LST_APPW, LST_DIS, + MX_ACT=1, MX_TXT, MX_LIST, MX_LEFT, MX_CURR, MX_DATA, MX_KEY, + MX_DIS, + CYC_ACT=1, CYC_TXT, CYC_LIST, CYC_CURR, CYC_DATA, CYC_KEY, CYC_DIS, + PAL_ACT=1, PAL_TXT, PAL_DEP, PAL_RELX, PAL_RELY, PAL_CURR, PAL_DATA, + PAL_KEY, PAL_DIS, + SCR_ACT=1, SCR_VERT, SCR_TOTL, SCR_TOP, SCR_VIS, SCR_REL, SCR_DATA, + SCR_KEY, SCR_DIS, + SLI_ACT=1, SLI_TXT, SLI_VERT, SLI_MIN, SLI_MAX, SLI_CURR, SLI_REL, + SLI_FMT, SLI_DATA, SLI_KEY, SLI_DIS, + STR_ACT=1, STR_TXT, STR_STR, STR_MAX, STR_REL, STR_OVR, STR_DATA, + STR_KEY, STR_APPW, STR_DIS, + TXT_VAL=1, TXT_TXT, TXT_BORD, TXT_REL, + NUM_VAL=1, NUM_TXT, NUM_BORD, NUM_REL, + PLG_ACT=1, PLG_OBJ, PLG_GT, PLG_APPW + + ++---------------------------------------------------------------+ +| 3. How Layout Works | ++---------------------------------------------------------------+ + +EasyGUI works by automatically layouting the gadgets on the screen. In a +first pass, it will compute the minimum size for each element: for gadgets +this involves the size of fonts and various other things. For a ROWS list, +for example, it will take the width of the biggest gadget as its width, and +computes its height by adding the heights of all other gadgets. For EQROWS +this is slightly more complicated: EasyGUI also computes a "middle" for +various gadgets, often between the text that denotes what a gadget is about +and the gadget itself. It then tries to align all of these. for EQCOLS it +simply tries to make all columns equal width. + +In a second pass, EasyGUI assigns the final coordinates to all gadgets. +Important to notice is that in a GUI often there is more space available +than is required for a gadget, for example the gadget above it in a ROWS +environment is much wider. Also, the user may have resized the window. To +do something useful with this space, EasyGUI looks at which gadgets can do +something useful with extra space, such as LISTV, or STR, SCROLL etc. This +process of granting extra space propagates through ROWS/COLS, which act as +gadgets themselves. Gadgets like BUTTON don't benefit from more space, so +they give that away to their neighbours. + + ++---------------------------------------------------------------+ +| 4. Advanced features | ++---------------------------------------------------------------+ + +Different versions of EasyGUI +----------------------------- +For those who care more about saving a few KB than the extra functionality, +there are two different versions: + + 1) EasyGUI_lite.m + This does not have multi-window support, keyboard support for + gadgets, AppWindow support or GUI manipulation functions (i.e., + dynamically changing a GUI, window blocking and gadget disabling). + Current code size: 17324 bytes. + 2) EasyGUI.m + The full version, with nothing taken out. + Current code size: 23968 bytes. + +There's also a third version of EasyGUI which is just a variant of +EasyGUI.m: this is a debug version, EasyGUI_debug.m, which gives some more +information about an error before raising an exception (so you shouldn't +really distribute programs compiled with this module -- it's just for +development purposes). + + +Throwing exceptions from actionfunctions +---------------------------------------- +is allowed: EasyGUI will catch it, close the window properly, and then +ReThrow() if it wasn't a "QUIT" exception. If it was "QUIT" then the +exceptioninfo value will be the return value of the easyguiA()/guimessage() +or multiloop()/multimessage() functions, just like the way actionvalues +work (except for the slight difference in a multi-window GUI, as noted +below). + +Exceptions raised by EasyGUI itself: + +"MEM" -- no mem +"GUI" -- for things like CreateGadgetA, OpenWindowTagList etc. +"GT" -- couldn't open gadtools.library + +"bigg" -- for "BIG Gui": interface is calculated to be bigger than the + screen. Generally you should keep gui's small, so that they + still fit on 640x200 topaz screens. If the user runs Times/30 on + a screen this size, he probably knows he has a problem. +"Egui" -- a design error: most probably handed over a list to dogui() that + was either to long or too short + -- Raise()ed by own function + + +Multiple Windows +---------------- +There are two ways of handling multiple windows in EasyGUI. The first +has really been superseded by the second, though. + +1) The simplest use of EasyGUI is just by calling easyguiA(). You can + however open any number of windows, and check messages for all of them. + + guiinitA(windowtitle,gui,tags=NIL) + guimessage(guihandle) + cleangui(guihandle) + + Call guiinitA() for each window (exactly the same arguments as + easyguiA(). Then, keep calling guimessage() for each of them, when + messages arive. you can close them again with cleangui(), for example + when a gui returns a positive integer (the actioncode). Negative integers + signal that it simply finished processing all messages, but no need to + close the window yet. Note: it is *not* safe to call cleangui() from + *any* action function (except as noted below, in the description of + cleanmulti()). (If you want to close the GUI prematurely, you can use + the closewin() function.) + + example of usage of these three function (= definition easyguiA()) + + EXPORT PROC easyguiA(windowtitle,gui,tags=NIL) HANDLE + DEF gh=NIL:PTR TO guihandle,res=-1 + gh:=guiinitA(windowtitle,gui,tags) + WHILE res<0 + Wait(gh.sig) + res:=guimessage(gh) + ENDWHILE + EXCEPT DO + cleangui(gh) + ReThrow() + ENDPROC res + + the object you get has some handy fields in there: the window in question + `wnd' (or NIL if it's currently closed), the sigmask `sig' (i.e., _not_ + the signal bits) if you want to do a proper Wait() (OR them), the GUI's + info and the handle for the multi-window group `mh' (or NIL if this is a + single GUI) [see below for more details on this]. + + OBJECT guihandle + /* Public (read-only) parts: */ + wnd:PTR TO window + sig:LONG + info + mh:PTR TO multihandle -> See below... + ENDOBJECT + + The GUI's info is provided to make retrieving the info from the guihandle + easier (in an EG_CLEAN proc, for instance). If you want to draw into + `wnd': stdrast is automatically set to the last EasyGUI opened. `wnd' + can also be used a flag to indicate when it is safe to manipulate the + GUI (to help with multi-tasking): when it's NIL it's not safe to modify + the GUI directly, unless you've been passed the window pointer (e.g., + render() and clear_render()). The setXXX() functions are always safe. + Note: `wnd' can change due to closewin()/openwin() calls which mean that + the GUI may be in different windows during its life. + +2) But starting in v3.3b, there's a much more efficient (and simpler) way + of handling multiple-window GUIs. This uses the functions multiinit(), + addmultiA(), multiloop() (which uses multimessage()) and cleanmulti(), in + roughly the same way as the single window versions. It's all based + around a `multihandle': + + OBJECT multihandle + /* Public (read-only) parts: */ + sig:LONG + opencount:LONG + ENDOBJECT + + multiinit() + addmultiA(multihandle,windowtitle,gui,tags=NIL) + multiloop(multihandle) + multimessage(multihandle) + cleanmulti(multihandle) + + multiinit() is used to initialise a new group of GUIs and produce a new + `multihandle'. It takes no arguments. You must call this function first + and use the multihandle with the other functions to refer to your group + of GUIs. You can still refer to each individual GUI using a guihandle + (see below). A quick example to show how simple the new multi-window + scheme is: + + PROC multiplewindows() HANDLE + DEF mh=NIL, gh1:PTR TO guihandle, gh2:PTR TO guihandle,res + mh:=multiinit() + gh1:=addmultiA(mh,'GUI One',[BUTTON,{but1},'Press Me']) + gh2:=addmultiA(mh,'GUI Two',[BUTTON,{but2},'Press Me']) + -> Could add more GUIs... + res:=multiloop(mh) + EXCEPT DO + cleanmulti(mh) + ENDPROC + + addmultiA() is very much like guiinitA(). It creates a new window with + your specified GUI and returns the guihandle. You can call this function + even from action functions, when the GUI group is active. + + addmultiA(mh:PTR TO multihandle,windowtitle,gui,tags=NIL) + + The extra parameter is `mh' to indicate the group to which this window + will be added. + + If the tag EG_CLOSE is not specified or the data is an action value + (between 0 and 1000) then the GUI will be destroyed and removed from the + group (the guihandle will now be invalid) and the action value will be + returned (from multimessage()) -- just like a normal action value. If it + is an action function then the window is *not* closed and the action + function is called. As stated above, you define such an action function + in one of two ways: + + PROC closeproc(info) + PROC closeproc(mh:PTR TO multihandle,info) + + `info' is the GUI's info parameter and `mh' is the multihandle for this + group. Use `mh' to find the `opencount' -- the number of GUIs with open + windows. This count will include this GUI so if it's equal to one then + you know this is the last open window in the group. Your action function + may want to prompt the user and then close the window (using closewin()), + destroy the GUI and remove it from the group (using cleangui()), or leave + the window open. + + multiloop() is defined in terms of multimessage() and opencount, and is + similar to the definition of easyguiA(). + + EXPORT PROC multiloop(mh:PTR TO multihandle) + DEF res=-1 + WHILE res<0 + EXIT mh.opencount=0 + Wait(mh.sig) + res:=multimessage(mh) + ENDWHILE + ENDPROC res + + The signal mask for waiting for messages is `sig' in the multihandle. + You can use this for more complex Wait()s, and then call multimessage() + to handle any messages that may have arrived for any of the GUIs. Any + action values generated by a GUI (or via quitgui()) are returned by + multimessage() and hence terminate multiloop(). The above example calls + multiloop() only once, so an action value will eventually destroy the + whole group (by calling cleanmulti()). Note: a real action value will + cause the GUI that produced it to be closed via cleangui(), but a value + returned through use of quitgui() will not -- this is because if you've + called quitgui() then you can just as easily write code to close the + window (or whatever) in the same action function. + + By using the `opencount', the loop will be terminated when there are no + more open GUI windows. Alternatively, if you are using your own Wait() + you might want to check that there are no GUIs left (even ones with + closed windows). To this end there's the function multiempty() which + returns TRUE if and only if there are no GUIs in the group. (Note: if + there are only GUIs left with no window then the simple Wait() will never + return!) + + cleanmulti() destroys all GUIs in the group (whether they have an open or + closed window) and deallocates the multihandle. It is *not* safe to use + the multihandle or any of the guihandles after this. So, in particular, + it is *not* safe to call cleanmulti() from *any* action function. It is, + however, safe to call cleangui() on GUIs in the group, if you are using + cleanmulti() to do the final cleanup (rather than calling cleangui() on + remembered guihandles). + + To help with manipulating a group there are the multiexists() and + multiforall() functions, which work in a very similar way to ForAll() and + Exists(). + + multiforall(varaddr,mh:PTR TO multihandle,expr) + multiexists(varaddr,mh:PTR TO multihandle,expr) + + `varaddr' is the address of a (global) guihandle variable, `mh' + identifies the GUI group and `expr' is a quoted expression to be + evaluated. multiforall() will evaluate the expression for every GUI in + the group (whether its window is open or closed) and return TRUE if the + expression is TRUE (non-zero) for all GUIs, else it will return FALSE. + multiexists() will stop at the first GUI for which the expression is + TRUE, and return the value of the expression. Unlike Exists(), you are + guaranteed that the variable pointed to by `varaddr' will contain the + guihandle of the corresponding GUI (or NIL if none were found). So, you + can use multiexists() to find GUIs. Note: be careful what the expression + does with the guihandle and the GUI group; it is quite safe to cleangui() + on the supplied guihandle, but it is not safe to affect any other GUI in + this way. Any GUIs added to the group by the expression will not be part + of the forall or exists (for those who can't live without knowing: the + list is explored from head to tail, and new GUIs are added to the head; + so the last GUI considered will be the oldest GUI). + + For example, you can print the title of each GUI with an open window: + + multiforall({gh},mh,`IF gh.wnd THEN WriteF('\s\n',gh.wnd.title) ELSE 0) + + A final reminder: `varaddr' must be the *address* of a *global* variable + (and so must all the variables used in the quoted expression). + + Useful note: as long as a guihandle is valid (i.e., as long as cleangui() + has not been called on it), the normal GUI functions checkgui() and + guimessage() will actually work on the whole group that a GUI is in. + (Note: the proper, safe functions to use for multi-window GUIs are + checkmulti() and multimessage(), respectively.) + + +Multiple copies of a GUI +------------------------ +If your app allows to have multiple copies of the _same_ gui open at the +same time (for example if you open windows recursively, or you use the +multiple window technique described above to open more instances of one +GUI), you might need to dynamically allocate the GUI description, because +of the way dynamically computed values are put into static E lists. A GUI +desciption with [] lists is static, i.e. only allocated once. Adding NEW to +all of them is hard to deallocate, and this is where disposegui() comes in. +To safely use this feature, allocate ALL lists belonging to the GUI +desciption dynamically with NEW [...] (this does not include lists such as +the one used for the various labels in CYCLE-gadgets). + + easyguiA('Bla', + gui:=NEW [ROWS, + NEW [STR,{str},'input:',s,50,4], + NEW [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1]]) + disposegui(gui) + +Call disposegui() with the top-level list. On each gadget-list (i.e., +NEW [CYCLE,...]) it will simply call FastDisposeList(), on COLS and ROWS +etc. it will first deallocate each element recursively. + + +Manipulating Gadgets +-------------------- +[This assumes you've got the guihandle by using the ghaddr argument of +easyguiA(), the DIY version of EasyGUI (as described under 'Multiple +Windows'), or you're using the new default for the 'info' of a GUI.] + +You might need to modify gadgets while a GUI is active, for example to set +a slider when a corresponding integer gadget is modified by the user, or to +change the contents of a listview. + +You can denote gadgets to change by simply storing their addresses, i.e.: + + [COLS, + mygad:=[CHECK,....], + ... + ] + +Now you can use `mygad' with some of the functions below. Note that, of +course `mygad' isn't a gadget, but it helps EasyGUI to find the real +gadget. + + setcheck(gh,gad,bool) + setinteger(gh,gad,new) + setlistvlabels(gh,gad,labs) + setlistvselected(gh,gad,active) + setlistvvisible(gh,gad,vis) + setmx(gh,gad,active) + setcycle(gh,gad,active) + setpalette(gh,gad,colour) + setscrolltop(gh,gad,top) + setscrolltotal(gh,gad,total) + setscrollvisible(gh,gad,visible) + setslide(gh,gad,new) + setstr(gh,gad,new) + settext(gh,gad,newtext) + setnum(gh,gad,newnum) + +for all these: `gh' is the gui you're talking about (as returned from +guiinitA()/addmultiA(), or via the `ghaddr' argument of easyguiA() or the +new default for the 'info' of a GUI), `gad' is a value that denotes the +gadget as described above. the third value is whatever you're changing +about the gadget. Note that in doing so, you need to respect usual +restrictions on gadtools gadgets, for example setlistvlabels() requires +that you first set it to -1, then modify the list, and put it back. +setlistvvisible() will try to make the indicated item in the LISTV visible. +setlistvselected() will make a new selection and try to make it visible +(and -1 turns off the selection). + + setdisabled(gh,gad,disabled=TRUE) + +This applies to all gadgets, but works only if you've actually specified a +value (TRUE or FALSE) for the optional `disabled' field for the gadget. + + realgadget:=findgadget(gh,list) + +allows you to find the gadget address, for all those modifications that +aren't possible with the above set#? functions. It returns an intuition +gadget structure. Note that preferably you will want to use the set#? +functions, as these cooperate with EasyGUI very well (in keeping track of +the current value, for example: setstr() also copies the new value to the +estring you attached to the gadget). While there is at least one GUI still +allocated the `gadtoolsbase' and `workbenchbase' are valid, so you can +quite easily manipulate gadgets in action functions using GadTools +functions. (If you do open either of these libraries, be careful not to +overwrite these variables with NIL! That is, use an automatic exception on +OpenLibrary() or otherwise check the return value before assigning it.) + + getstr(gh,gad) + getinteger(gh,gad) + +These return and store the current value of a STR or INTEGER gadget (where +gh and gad are as described above for the setxxx() functions). They are +useful because Intuition only sends a message (and so causes the current +values to be stored) when the user hits the return or tab key in these +gadgets. So, if you really want to know a STR or INTEGER gadget's current +value use getstr() or getinteger(). + + +Topaz Fallback +-------------- +the function `easygui_fallbackA()' is equivalent to `easyguiA()' apart from +the fact that when EasyGUI fails with the "bigg" exception, it will try +again with topaz-8. Note that you should never want to rely on topaz, this +function was only added for emergency situations. If your GUI is too big +on some systems, you should redesign your GUI to fit comfortably instead. +(see other parts of this doc that talk about GUI-size and testing). + + +GUI Manipulation +---------------- + + closewin(gh) + +Temporarily closes the GUI window. Use openwin() to reinstate the GUI. +This function is useful for iconifying a GUI (see the iconify and toolify +PLUGINs). You can test whether a GUI's window is closed (or otherwise +unmodifiable) by checking if the `wnd' element of the guihandle is NIL. +Note that if your GUI is on the default public screen then it will no +longer be a visitor (i.e., you can then use changescreen() to move it to a +new screen). (A blocked window is unblocked before it is closed.) + + openwin(gh) + +Reopens a closed GUI window: it will reopen in the same position and size +as it was when it closed. Note that the window is not guaranteed to open +correctly again (someone may have grabbed your memory, for example). The +window will always open unblocked. Once open again, gh.wnd will be non-NIL +(i.e., the address of the window). + + changegui(gh,gui) + +Changes the GUI in a window (fairly) seamlessly. The old GUI is removed +and the new GUI tries to take its place, resizing if necessary (a NIL `gui' +is just ignored). The window will be resized if the new GUI's minimum size +is bigger than the current size, or if the new GUI does not allow resizing. +A side-effect of this new, dynamic ability to change GUIs is that the +default window type is to have a size gadget, even the GUI can't be +resized. You can change this by specifying a different EG_WTYPE, or use +changewindowtype(). + + changemenus(gh,newmenus=NIL) + +Changes the GUI's menus. If `newmenus' is NIL or not present then the +current menus are removed and the window is left with no menus. + + changeinfo(gh,info=-1) + +Changes the GUI's info. If `info' is -1 or not present then the GUI's +info is changed to be the guihandle for the window. (Remember: the info is +passed to the GUI's action functions.) + + changetitle(gh,windowtitle=NIL) + +Changes the title of the GUI's window. (But remember that the title is +ignored for window type WTYPE_BASIC and WTYPE_NOBORDER.) + + changescreen(gh,scr=NIL) + +If the GUI window is closed (gh.wnd=NIL) then this will alter the GUI's +screen (if it's open then this function does nothing). If `scr' is NIL +then the default public screen will be used. If the font was linked to the +screen then it will be updated, too. + + changefont(gh,tattr=NIL) + +Again, this works only if the GUI window is closed. If `tattr' is NIL then +the font of the screen is used. + + changewintype(gh,wintype=WTYPE_SIZE) + +Another one that works only if the GUI window is closed. This sets the +window border type. You can use one of WTYPE_NOBORDER, WTYPE_BASIC, +WTYPE_NOSIZE and WTYPE_SIZE, as described above. + + movewin(gh,x=-1,y=-1) + +Moves the window of the GUI referenced by gh to the new (top-left) +coordinate. If x or y is -1 (the default) then that coordinate is not +changed. (Note: the change is delayed until the next INTUITICK.) + + sizewin(gh,xs=-1,ys=-1) + +Attempts to resize the window of the GUI referenced by gh. If xs or ys is +-1 (the default) then that dimension is not changed. The resizing is not +guaranteed to be carried out since the size may be smaller than the GUI's +minimum or the GUI may not be sizable. (Note: the change is delayed until +the next INTUITICK.) + +Simple window blocking to prevent the user using a GUI: + + blockwin(gh) + +This puts up an invisible requester over the window of the GUI referenced +by gh, and disables window sizing. If you're running v39+ then the busy +pointer will be set on this window. You would use this to block a GUI +before you put up another one. Note: the window can still be moved and +depth arranged. (This works only if the GUI's window is open.) + + unblockwin(gh) + +Reinstates the GUI, allowing the user to interact with it again. The +blockwin() and unblockwin() calls nest, so you need an equal number of +unblockwin() calls to blockwin() calls before the window is actually +unblocked. Note: a GUI window is implicitly unblocked (forcefully!) when +it is closed. In general: try to design your GUIs such that the user can +use them all simultaneously, this is much friendlier (i.e., make use of the +multi-window support given by addmultiA()...). + + checkgui(gh) + +Checks for any GUI messages and processes them, invoking actionfunctions if +necessary. If this causes the GUI to want to be closed (e.g., the user has +pressed the close gadget), then a "QUIT" exception is thrown and the +exceptioninfo is the value that would have been returned by the easyguiA() +call (so, as with quitgui(), your exception handlers might like to make +"QUIT" a special case and just ReThrow() it). + +This function is useful, for example, when you're in an action function +that's performing a long calculation. By polling the GUI at convenient +points using this function you will make the GUI more responsive. However, +you are responsible for coping with the possibility that the user may +cause, for instance, the same action function to be called again. A simple +solution is use some kind of semaphore (a global boolean variable, for +example) to mark whether you are currently in an action function and busy. +See the led_test.e examples and the old CU Amiga tutorials on Amiga E. + + checkmulti(mh) + +This is checkgui() for multi-window GUIs. As mentioned above (in 'Multiple +Windows') you can use checkgui() to check and act on messages for *all* the +GUIs in the same group as the one identified by the guihandle, but the +guihandle must be valid. This function uses the multihandle so is always +safe as long as the group exists. + + ++---------------------------------------------------------------+ +| 5. PLUGINs | ++---------------------------------------------------------------+ + +PLUGINs allow the programmer to extend EasyGUI with new functionality, +i.e., to add any kind of rendering/gadgets to the GUI, while cooperating +automatically with EasyGUI's layout/resizing. You can use plugins to add +rendering areas in the midst of EasyGUI gadgetry (e.g., for graphics +programs), add BOOPSI gadgets to a GUIs etc. You can supply ready-made +plugins for other programmers to use. + + OBJECT plugin + /* Public (read-only) parts: */ + -> Position and size. + x:INT,y:INT,xs:INT,ys:INT + -> guihandle for the GUI the PLUGIN is on. + gh:PTR TO guihandle + ENDOBJECT + +Any PLUGIN is an object inherited from the 'plugin' object found in +easygui.m. To implement a new plugin all that needs to be done is redefine +a few methods. Then, this PLUGIN can be plugged in to any EasyGUI with for +example: + + [PLUGIN,{plugaction},NEW mp.myplugin()] + +in your GUI-spec. Whether the action-value is used depends on the PLUGIN, +as we'll see below. If it is called it will be passed the PLUGIN object as +well as the GUI info: + + PROC pluginaction(info,plugin_object:PTR TO plugin) + +Have a quick look at the plugin example sources, or keep them handy while +reading the bit below. + +Creating the object +------------------- +create your new object as a 'plugin'-subtype. You may add constructors/ +destructors if you wish. following methods implement the plugins +behaviour, and may be redefined: + + will_resize() + +is called once just before the window is opened. You should return a +flag-set telling in which ways your object can resize, making use of the +constants RESIZEX and RESIZEY, 0 of course meaning your object is fixed in +size (default method returns RESIZEX OR RESIZEY, i.e., resize in both +directions). New to v3.3a is COND_RESIZEX and COND_RESIZEY, which allow +your PLUGIN to resize in the corresponding direction only if something else +in its gadget group is unconditionally resizable. (For example, a BAR is +conditionally resizable, so that it does not force a group of BUTTONs to be +resizable.) + + min_size(ta:PTR TO textattr,fontheight) + +is called once just before the window is opened. ta is the font used +in the GUI. you should return the _minimum_ x and y sizes of your +PLUGIN as _two_ returnvalues, making use of `fontheight' if you wish. +Note that EasyGUI may actually grant you a lot more space than just +the minimum space you ask for, depending on the other gadgets and +user-resizing. If your object can have al sorts of sizes, pick a +relatively small one as minimum. The default method just returns +(fontheight,fontheight) + + render(ta:PTR TO textattr,x,y,xs,ys,win:PTR TO window) + +Here you should render your object to the window. In the case of a gadget +this means creating the gadget and attaching it to the window (AddGList(), +RefreshGList(), make sure you render only your own gadget(s)). ta is the +font used in the GUI. (xs,ys) is always at least the minimum size you +asked for. (x,y,xs,ys) is also copied to your object before this method is +called, for use in other methods). The default method paints a nice black +box :-) You shouldn't take too long in this method as it will make window +redraw look slow. (It is safe to use existing v3.2e PLUGIN modules, but to +recompile under v3.3a you will need to add the `ta' argument to your PLUGIN +render() method.) + + gtrender(gl,vis,ta:PTR TO textattr,x,y,xs,ys,win:PTR TO window) + +New to v3.3a: a replacement for render() which enables simple addition of +GadTools gadgets to the standard EasyGUI gadgets. If you want to use this +method instead of the normal render() then: 1) the PLUGIN must support it, +and 2) you must specify TRUE for the `isgt' field of the PLUGIN gadget. +gtrender() should simply create its gadgets by linking into the current +list (given by `gl') and using the visual info `vis'. It should then +return the new gadget list (i.e., the last GadTools gadget linked in). And +then that's it: your GadTools gadgets will be freed automatically, so if +your PLUGIN is just GadTools gadgets you don't need to override the normal +(empty) definition clear_render(). If you use gtrender() then you need not +override render(): this will help indicate a problem if users forget to +specify `isgt' with your PLUGIN. See the password PLUGIN example. + + clear_render(win:PTR TO window) + +mainly useful for gadgets to remove the gadget from the window and free it +(RemoveGList(), remove only your own gadget(s)!). Normally render() is +called when the window opens, and clear_render() when the window closes, +when the user resizes, however, clear_render() and render() are called one +after another, in that order, to account for the changed window layout. +The default method does nothing. + + message_test(imsg:PTR TO intuimessage,win:PTR TO window) + +is phase-1 of the message handling, splitted in two to not block intuition +too much. In message_test() the only thing you should do is return TRUE +_if_ and _only_if_ the intuimessage is meant for your object, otherwise +FALSE. (The only exceptions to this are IDCMP_MOUSEMOVE messages from a +GACT_FOLLOWMOUSE or WFLG_REPORTMOUSE, which can be ignored safely [i.e., +you may return FALSE] as they cannot easily be attributed to an originating +gadget). For a mouse-click, test if it was in your area (the current +dimensions of your object in the GUI are present in the `plugin' object), +for gadgets, make sure it is really your gadget causing the message (check +.iaddress). If you reply TRUE to messages that are potentially meant for +other objects, you might choke them. Do not engage in other actions in +this method, such as rendering; do these things in the message_action() +method. The default method returns FALSE. + +The GUI window uses the following IDCMP flags: + + IDCMP_ACTIVEWINDOW IDCMP_INACTIVEWINDOW + IDCMP_GADGETDOWN IDCMP_GADGETUP + IDCMP_INTUITICKS + IDCMP_MOUSEBUTTONS IDCMP_MOUSEMOVE + IDCMP_NEWSIZE + IDCMP_RAWKEY IDCMP_VANILLAKEY + +You may get your PLUGIN objects to generate these messages (via gadgets) +and then trap them (via message_test()), or you can just snoop on them in +message_test(). + + message_action(class,qual,code,win:PTR TO window) + +is the second part, and will only be called if you returned TRUE in the +previous method. here you may do any action needed (additional rendering +based on the user action). class, qual and code are copies of the class, +qualifier and code part of the intuimessage, so you don't need to remember +them in message_test(). You should return TRUE if you want the action the +user of the PLUGIN has written in his GUI-spec to be executed upon +termination of this method (do this if your object clearly can be "hit", +such as a gadget. If you just do some rendering you might want to ignore +the actionvalue). The default method returns FALSE. (As noted above, the +action function is passed the PLUGIN object as well as the GUI info.) + +Note: do not confuse message_action() with action values: the former is for +implementing the plugin's behaviour generally, while the latter is for +specific behaviour in a specific GUI, attached by the user of your plugin +(which could be you again :-). + + appmessage(amsg:PTR TO appmessage,win:PTR TO window) + +Like the testing for window IDCMP, but for AppWindow message testing. +Return TRUE _only_if_ the message is meant for this PLUGIN. The PLUGINs +(optional) awproc will then be called (as normal, with the optional data +field being the `plugin_object'). Note: for compatibility, the +appmessage() method is called only for PLUGINs that specify a non-NIL +`awproc' field. Just be careful to *not* specify a non-NIL `awproc' field +with old PLUGIN modules. + +If you supply a plugin as module for others, you'll have to state what +constructor(s) they may use, wether or not they have to supply a sensible +action-value. END will almost always have to be called. + + ++---------------------------------------------------------------+ +| 6. guide to the examples | ++---------------------------------------------------------------+ + +There are numerous examples to show the various features of EasyGUI. +Here's a small guide to help you find the ones that might be interesting: + + alldist.e - The original example. + alldist2.e - The original example, using multi-windows and + blocking. You can have all the example GUIs + open at once! + + testaw.e - AppWindow example. + testchange.e - changegui() example. + testchange2.e - changeXXX() and multi-window example. + testkey.e - Keyboard shortcuts example, with window + blocking and gadget disabling. + testmulti.e - Multi-window example (recursive!). + testmulti2.e - Multi-window and multiforall() example. + testqual.e - Qualifier example. + + animcontrol_test.e - Tests animcontrol PLUGIN. + button_test.e - Tests flavours of button PLUGIN. + calendar_test.e - Tests calender PLUGIN. + colorwheel_test.e - Tests colorwheel PLUGIN. + gradient_test.e - Tests gradient (slider) PLUGIN. + imagebutton_test.e - Tests flavours of imagebutton PLUGIN. + led_test.e - Tests led PLUGIN, with pseudo-async activity. + led_test2.e - Tests led PLUGIN, with multi-windows and + pseudo-async activities. + led_test3.e - Tests led PLUGIN, with multi-windows and + *real* async activities. + led_test4.e - Tests led and ticker PLUGINs, with + multi-windows and pseudo-async activities. + password_test.e - Tests password PLUGIN. + tabs_test.e - Tests tabs PLUGIN. + tabs_test2.e - Tests tabs PLUGIN and changegui() example. + tapedeck_test.e - Tests tapedeck PLUGIN. + ticker_test.e - Tests ticker PLUGIN. + +These can be found in Src/EasyGUI. The sources for the example PLUGINs are +in Src/Plugins. + + ++---------------------------------------------------------------+ +| 7. bugs/future | ++---------------------------------------------------------------+ + +bugs: +- method of displaying slider values not bulletproof +- GadTools sends two messages if your slider value is changed to a + negative value, so your action function can get called twice. + +[the planned render spaces can now be done much better by using PLUGINs] + + +---------------------------------------------------------------- + +General advice: try out and modify the examples. Sometimes something won't +work, but EasyGUI is flexible enough that at least one way of arranging +groups etc. will give you a nice GUI :-). If you need more power than +EasyGUI currently gives, you'll have to use MUI/BGUI/WhatEver instead. + +Wouter (and Jason!) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/animcontrol.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/animcontrol.doc new file mode 100644 index 0000000..4eae096 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/animcontrol.doc @@ -0,0 +1,61 @@ +AnimControl PLUGIN +------------------ +Consists of play, rewind, fast forward, stop and frame number gadgets. +Uses the 'tapedeck.gadget' which needs to be in the normal place of +libs:gadgets/ (usually libs: is also assigned to sys:classes/, and .gadget +files should be stored in the sys:classes/gadgets/ directory). + +Constructors: + + animcontrol(frame=0,frames=8,play=FALSE,disabled=FALSE) + frame -> The first frame (=position of slider) + frames -> The number of frames (=extent of slider) + play -> Whether the play button is pressed initially + disabled -> Whether this gadget is disabled + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only): + + OBJECT animcontrol OF plugin + frame -> Current frame number + mode -> Current mode + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + + The mode is taken from 'gadgets/tapedeck'. It will be: + o BUT_PLAY if playing + o BUT_STOP if stopped + o BUT_FORWARD if fast forward is being held + o BUT_REWIND if rewind is being held + +New methods: + + setframe(n) -> Set the current frame number + setplay(play=TRUE) -> Set play/stop mode + setdisabled(disabled=TRUE) -> Disable/enable the gadget + +Action functions: + + Your action function will be called (or your action value returned + by easygui()) in the following circumstances: + o The rewind or fast forward button has been pressed + (mode will be BUT_FORWARD or BUT_REWIND) + o The rewind or fast forward button has been released + (mode will be BUT_STOP) + o The play button has been pressed (and released) + (mode will be BUT_PLAY) + o The stop button has been pressed (and released) + (mode will be BUT_STOP) + o The frame slider has been moved + (mode will be BUT_STOP, frame may have changed) + +Exceptions: + + "anim" will be raised by the constructor if the .gadget file can't + be opened. + "anim" will be raised by the render() method if the gadget can't + be created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/button.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/button.doc new file mode 100644 index 0000000..657c1c0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/button.doc @@ -0,0 +1,68 @@ +Button PLUGIN +------------- +A flexible button gadget in three flavours: normal (momentary), toggle and +push (sticky). Uses the 'button.gadget' which needs to be in the normal +place of libs:gadgets/ (usually libs: is also assigned to sys:classes/, and +.gadget files should be stored in the sys:classes/gadgets/ directory). + +Constructors: + + button(text,resizex=FALSE,resizey=FALSE,disabled=FALSE) + text -> The button's label + resizex -> Whether this button can resize in width + resizey -> Whether this button can resize in height + disabled -> Whether this gadget is disabled + + togglebutton(text,selected=FALSE,resizex=FALSE,resizey=FALSE, + disabled=FALSE) + text -> The button's label + selected -> Whether this button is selected (on) initially + resizex -> Whether this button can resize in width + resizey -> Whether this button can resize in height + disabled -> Whether this gadget is disabled + + pushbutton(text,selected=FALSE,resizex=FALSE,resizey=FALSE, + disabled=FALSE) + text -> The button's label + selected -> Whether this button is selected (on) initially + resizex -> Whether this button can resize in width + resizey -> Whether this button can resize in height + disabled -> Whether this gadget is disabled + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only): + + OBJECT button OF plugin + selected -> Current state of the button (=0 is off, <>0 is on) + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + + The selected element is useful only for toggle and push buttons. + +New methods: + + setselected(selected=TRUE) -> Set the button on or off + settext(text) -> Change the button label + setdisabled(disabled=TRUE) -> Disable/enable the gadget + + Note: setselected() is ignored for normal buttons. + Note: push buttons cannot be deselected by the user (they're sticky), + so use setselected() to deselect them when necessary. + Note: settext() does not check that the new label is not too wide... + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When the button is pressed to select or deselect it. + +Exceptions: + + "butt" will be raised by the constructor if the .gadget file can't be + opened. + "butt" will be raised by the render() method if the gadget can't be + created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/calendar.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/calendar.doc new file mode 100644 index 0000000..539a443 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/calendar.doc @@ -0,0 +1,51 @@ +Calendar PLUGIN +--------------- +Draws a calendar of a month and allows a day to be selected. Uses the +'calendar.gadget' which needs to be in the normal place of libs:gadgets/ +(usually libs: is also assigned to sys:classes/, and .gadget files should +be stored in the sys:classes/gadgets/ directory). + +Constructors: + + calendar(date:PTR TO clockdata,resizex=FALSE,resizey=FALSE, + disabled=FALSE) + date -> The initial date selected + resizex -> Whether this gadget can resize in width + resizey -> Whether this gadget can resize in height + disabled -> Whether this gadget is disabled + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only, except as mentioned below): + + OBJECT calendar OF plugin + date:PTR TO clockdata -> Current date + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + +New methods: + + setdate(date=NIL:PTR TO clockdata) -> Set the current date + setdisabled(disabled=TRUE) -> Disable/enable the gadget + + Note: if NIL if specified for setdate() then the current date will be + used (in which case it's OK to edit the data in self.date just + before calling setdate()). + Note: it's up to you to make sure the dates you supply are sensible. + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When one of the day buttons is pressed + (the date will reflect the current state) + +Exceptions: + + "cal" will be raised by the constructor if the .gadget file can't be + opened. + "cal" will be raised by the render() method if the gadget can't be + created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/colorwheel.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/colorwheel.doc new file mode 100644 index 0000000..8c6a209 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/colorwheel.doc @@ -0,0 +1,62 @@ +ColorWheel PLUGIN +----------------- +The famous colorwheel from the Palette prefs program. Uses the +'colorwheel.gadget' which needs to be in the normal place of libs:gadgets/ +(usually libs: is also assigned to sys:classes/, and .gadget files should +be stored in the sys:classes/gadgets/ directory). + +Constructors: + + colorwheel(rgb:PTR TO colorwheelrgb,hsb=NIL:PTR TO colorwheelhsb, + box=FALSE,disabled=FALSE) + rgb -> The initial value as RGB + hsb -> The initial value as HSB + box -> Whether to put a bevel box around the wheel + disabled -> Whether this gadget is disabled + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only, except as mentioned below): + + OBJECT colorwheel OF plugin + rgb:PTR TO colorwheelrgb -> Current RGB value + hsb:PTR TO colorwheelhsb -> Current HSB value + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + + Only one of rgb and hsb will be valid at any time (the invalid one will + be NIL), depending on which system you used when you last set the + current value. + +New methods: + + setrgb(rgb=NIL) -> Set the current value using RGB + sethsb(hsb=NIL) -> Set the current value using HSB + getrgb(rgb) -> Get the current RGB value + gethsb(hsb) -> Get the current HSB value + setdisabled(disabled=TRUE) -> Disable/enable the gadget + + Note: using setrgb()/sethsb() changes the system that the colorwheel + uses, so after a setrgb() the hsb element will be invalid (NIL). + Note: if NIL is specified for setrgb() or sethsb() then the current one + will be used (in which case it's OK to edit the data in self.rgb + or self.hsb just before calling setXXX()). + Note: getrgb()/gethsb() fill in the colorwheelrgb/hsb that you supply + with the current colorwheel value, but do not change the system + that's being used. + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When the pointer is moved. + +Exceptions: + + "colw" will be raised by the constructor if the .gadget file can't be + opened. + "colw" will be raised by the render() method if the gadget can't be + created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/gradient.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/gradient.doc new file mode 100644 index 0000000..4751bda --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/gradient.doc @@ -0,0 +1,51 @@ +GradientSlider PLUGIN +--------------------- +The silder that goes with the colorwheel from the Palette prefs program. +Uses the 'gradientslider.gadget' which needs to be in the normal place of +libs:gadgets/ (usually libs: is also assigned to sys:classes/, and .gadget +files should be stored in the sys:classes/gadgets/ directory). + +Constructors: + + gradient(vert=FALSE,curval=0,rel=5,pens=NIL:PTR TO INT,disabled=FALSE) + vert -> Whether this gadget is vertical or horizontal + curval -> The current value of the slider + rel -> The relative size (height if vert, width if not) + pens -> The pen array used in the gradient (ends with -1) + disabled -> Whether this gadget is disabled + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only, except as mentioned below): + + OBJECT button OF plugin + curval -> The current value of the slider (0 to $FFFF) + pens:PTR TO INT -> The current pen array for the gradient + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + +New methods: + + setcurval(x) -> Set the current value of the slider + setpens(pens=NIL:PTR TO INT) -> Change the pen array + setdisabled(disabled=TRUE) -> Disable/enable the gadget + + Note: if NIL is specified for setpens() then the current pen array + will be used (in which case it's OK to edit the data in self.pens + just before calling setpens()). + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When the slider is moved or released. + +Exceptions: + + "grad" will be raised by the constructor if the .gadget file can't be + opened. + "grad" will be raised by the render() method if the gadget can't be + created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/imagebutton.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/imagebutton.doc new file mode 100644 index 0000000..d73ca83 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/imagebutton.doc @@ -0,0 +1,81 @@ +ImageButton PLUGIN +------------------ +A flexible image button gadget in three flavours: normal (momentary), +toggle and push (sticky). Uses the 'button.gadget' which needs to be in +the normal place of libs:gadgets/ (usually libs: is also assigned to +sys:classes/, and .gadget files should be stored in the +sys:classes/gadgets/ directory). + +Constructors: + + imagebutton(image:PTR TO image,width=0,height=0, + resizex=FALSE,resizey=FALSE,disabled=FALSE) + image -> The button's image + width -> The nominal width of the gadget + height -> The nominal height of the gadget + resizex -> Whether this button can resize in width + resizey -> Whether this button can resize in height + disabled -> Whether this gadget is disabled + + toggleimagebutton(image:PTR TO image,width=0,height=0,selected=FALSE, + resizex=FALSE,resizey=FALSE,disabled=FALSE) + image -> The button's image + width -> The nominal width of the gadget + height -> The nominal height of the gadget + selected -> Whether this button is selected (on) initially + resizex -> Whether this button can resize in width + resizey -> Whether this button can resize in height + disabled -> Whether this gadget is disabled + + pushimagebutton(image:PTR TO image,width=0,height=0,selected=FALSE, + resizex=FALSE,resizey=FALSE,disabled=FALSE) + image -> The button's image + width -> The nominal width of the gadget + height -> The nominal height of the gadget + selected -> Whether this button is selected (on) initially + resizex -> Whether this button can resize in width + resizey -> Whether this button can resize in height + disabled -> Whether this gadget is disabled + + Note: the width and height of the gadget will be at least as big as + that needed to fit the image (so it's safe to specify them as 0). + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only): + + OBJECT imagebutton OF plugin + selected -> Current state of the button (=0 is off, <>0 is on) + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + + The selected element is useful only for toggle and push buttons. + +New methods: + + setselected(selected=TRUE) -> Set the button on or off + setimage(image:PTR TO image) -> Change the button's image + setdisabled(disabled=TRUE) -> Disable/enable the gadget + + Note: setselected() is ignored for normal buttons. + Note: push buttons cannot be deselected by the user (they're sticky), + so use setselected() to deselect them when necessary. + Note: setimage() will work only if the image fits in the button's + minimum size (so, you should specify the maximum width and height + of the images you will use in the constructor...) + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When the button is pressed to select or deselect it. + +Exceptions: + + "butt" will be raised by the constructor if the .gadget file can't be + opened. + "butt" will be raised by the render() method if the gadget can't be + created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/led.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/led.doc new file mode 100644 index 0000000..402cd4c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/led.doc @@ -0,0 +1,50 @@ +LED PLUGIN +---------- +Draws pairs of digits to look like LED displays (such as clocks). Uses the +'led.image' which needs to be in the normal place of libs:images/ (usually +libs: is also assigned to sys:classes/, and .image files should be stored +in the sys:classes/images/ directory). + +Constructors: + + led(pairs=2,values=NIL,colon=FALSE,signed=FALSE,negative=FALSE,pen=1) + pairs -> The number of pairs of digits + values -> The values (one value per pair of digits) + colon -> Whether the colon between pairs is displayed + signed -> Whether use will be made of the leading minus sign + negative -> Whether the leading minus sign is on or off + pen -> The pen (colour) of the LED + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only, except as mentioned below): + + OBJECT led OF plugin + pairs + values:PTR TO INT + colon + signed + negative + pen + PRIVATE ... + ENDOBJECT + +New methods: + + redisplay() -> Redraw according to new values + + Note: it is OK to change the public data just before calling + redisplay() (and this is the only real use for redisplay()). + +Action functions: + + Ignored. + +Exceptions: + + "led" will be raised by the constructor if the .image file can't be + opened. + "led" will be raised by the render()/redisplay() methods if the image + can't be created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/password.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/password.doc new file mode 100644 index 0000000..2734905 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/password.doc @@ -0,0 +1,48 @@ +Password PLUGIN +--------------- +Makes a rudimentary password entry gadget. Uses a standard GadTools string +gadget so you need to specify TRUE for the optional `isgt' field of the +PLUGIN gadget to use it (otherwise you get a black rectangle!). + +Constructors: + + password(estr,label=NIL,over=FALSE,relx=0,disabled=FALSE) + estr -> The initial password (must be an E-string) + label -> The label for the gadget + over -> Whether the string gadget is in overwrite mode + relx -> Relative width (default is 5) + disabled -> Whether this gadget is disabled + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only): + + OBJECT password OF plugin + estr -> Current password + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + +New methods: + + setpass(str) -> Set the password to str (copied) + setdisabled(disabled=TRUE) -> Disable/enable the gadget + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When the return or tab is pressed in the gadget + + Note: unlike normal STR gadgets, the estr is *always* up-to-date. + +Exceptions: + + "pass" will be raised by the constructor if the gadtools.library can't + be opened. + "pass" will be raised by the render() method if the gadget can't be + created. + "MEM" will be raised by the constructor or setpass() method if the + temporary string can't be created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tabs.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tabs.doc new file mode 100644 index 0000000..05c23cb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tabs.doc @@ -0,0 +1,47 @@ +Tabs PLUGIN +----------- +Makes a set of tabs for page selection (most useful with changegui()). +Uses the 'tabs.gadget' which needs to be in the normal place of +libs:gadgets/ (usually libs: is also assigned to sys:classes/, and .gadget +files should be stored in the sys:classes/gadgets/ directory). + +Constructors: + + tabs(tabslist:PTR TO tablabel,current=0,max=TRUE,disabled=FALSE) + tabslist -> The list of labels to use + current -> The initial tab selected + max -> Whether each tab has the width of the widest tab + disabled -> Whether this gadget is disabled + + Note: the gadget will *conditionally* resize in width. + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only): + + OBJECT tabs OF plugin + current -> Currently selected tab + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + +New methods: + + setcurrent(x) -> Set the current selected tab + setdisabled(disabled=TRUE) -> Disable/enable the gadget + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When one of the tabs is pressed + (current will indicate the selected tab) + +Exceptions: + + "tabs" will be raised by the constructor if the .gadget file can't be + opened. + "tabs" will be raised by the render() method if the gadget can't be + created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tapedeck.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tapedeck.doc new file mode 100644 index 0000000..d59942d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/tapedeck.doc @@ -0,0 +1,52 @@ +TapeDeck PLUGIN +--------------- +Consists of play, rewind, fast forward, stop and pause gadgets. Uses the +'tapedeck.gadget' which needs to be in the normal place of libs:gadgets/ +(usually libs: is also assigned to sys:classes/, and .gadget files should +be stored in the sys:classes/gadgets/ directory). + +Constructors: + + tapedeck(mode=BUT_STOP,paused=FALSE,disabled=FALSE) + mode -> The current mode (see below) + paused -> Whether the pause button is pressed initially + disabled -> Whether this gadget is disabled + +Destructor: + + END *must* be called for each NEWed object. + +Data (should be considered read-only): + + OBJECT tapedeck OF plugin + mode -> Current mode + paused -> Paused or not + disabled -> Disabled or enabled + PRIVATE ... + ENDOBJECT + + The mode is taken from 'gadgets/tapedeck'. It will be: + o BUT_PLAY if playing + o BUT_STOP if stopped + o BUT_FORWARD if fast forwarding + o BUT_REWIND if rewinding + +New methods: + + setmode(mode=BUT_STOP) -> Set the current mode + setpaused(paused=TRUE) -> Set paused on or off + setdisabled(disabled=TRUE) -> Disable/enable the gadget + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When one of the buttons is pressed + (mode and paused will reflect the current state) + +Exceptions: + + "tape" will be raised by the constructor if the .gadget file can't be + opened. + "tape" will be raised by the render() method if the gadget can't be + created. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/ticker.doc b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/ticker.doc new file mode 100644 index 0000000..8fa5580 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Docs/ticker.doc @@ -0,0 +1,23 @@ +Ticker PLUGIN +------------- +A simple PLUGIN that absorbs all the IDCMP_INTUITICKS and calls its action +function on each tick. + +Constructors: + + None, just create the object. + +Destructor: + + None, you needn't call END, but it doesn't hurt. + +Action functions: + + Your action function will be called (or your action value returned by + easygui()) in the following circumstances: + o When an IDCMP_INTUITICK occurs. Note: IDCMP_INTUITICKS only happen + to the active window! + +Exceptions: + + None. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/all.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/all.e new file mode 100644 index 0000000..b5c3d81 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/all.e @@ -0,0 +1,379 @@ +-> Test GUI's gathered in one program. + +OPT OSVERSION=37 +MODULE 'tools/EasyGUI', 'tools/exceptions', 'libraries/gadtools' + +DEF gh + +DEF havefonts=FALSE, havescreenmode=FALSE, havefile=FALSE, havesearch=FALSE, + havesearch2=FALSE, haveamosaic=FALSE, havedb=FALSE, havedm=FALSE, + havetiny=FALSE, havemessy=FALSE + +DEF s[50]:STRING + +PROC main() HANDLE + DEF mh=NIL:PTR TO multihandle + StrCopy(s,'bla') + mh:=multiinit() + addmultiA(mh,'EasyGUI Tests', + [EQROWS, + [BUTTON,{fonts},'Fonts'], + [BUTTON,{screenmode},'ScreenMode'], + [BUTTON,{file},'File Requester'], + [BUTTON,{search},'Search Requester'], + [BUTTON,{search2},'Search Requester 2'], + [BUTTON,{amosaic},'Amosaic'], + [BUTTON,{db},'DataBase'], + [BUTTON,{dm},'DiskMaster'], + [BUTTON,{tiny},'Tiny Test'], + [BUTTON,{messy},'Messy Test'] + ], + [EG_CLOSE,{quit}, NIL] + ) + REPEAT + WriteF('result=\d\n',multiloop(mh)) + UNTIL mh.opencount=0 +EXCEPT DO + cleanmulti(mh) + report_exception() +ENDPROC + +PROC quit(mh,info) IS multiforall({gh},mh,`cleangui(gh)) + +PROC havenot(var:PTR TO LONG) + var[]:=FALSE +ENDPROC + +PROC fonts(x:PTR TO guihandle) + IF havefonts=FALSE + havefonts:=TRUE + addmultiA(x.mh, 'Font Preferences', + [EQROWS, + [TEXT,'Selected Fonts',NIL,FALSE,3], + [BEVELR, + [EQROWS, + [TEXT,'xentiny 8','Workbench Icon Text:',FALSE,3], + [TEXT,'end 10','System Default Text:',FALSE,3], + [TEXT,'except 12','Screen text:',FALSE,3] + ] + ], + [SBUTTON,0,'Select Workbench Icon Text...'], + [SBUTTON,0,'Select System Default Text...'], + [SBUTTON,0,'Select Screen text...'], + [BAR], + [COLS, + [BUTTON,0,'Save'], + [SPACEH], + [BUTTON,0,'Use'], + [SPACEH], + [BUTTON,0,'Cancel'] + ] + ], + [EG_CLEAN,{havenot}, EG_INFO,{havefonts}, NIL] + ) + ENDIF +ENDPROC + +PROC screenmode(x:PTR TO guihandle) + IF havescreenmode=FALSE + havescreenmode:=TRUE + addmultiA(x.mh,'ScreenMode Preferences', + [EQROWS, + [COLS, + [EQROWS, + [LISTV,0,'Display Mode',10,4,NIL,TRUE,0,0], + [COLS, + [EQROWS,[INTEGER,0,'Width:',640,5],[INTEGER,0,'Height:',512,5]], + [ROWS,[CHECK,0,'Default',TRUE,FALSE],[CHECK,0,'Default',TRUE,FALSE]] + ], + [SLIDE,0,'Colors:',FALSE,1,8,3,5,''], + [CHECK,0,'AutoScroll:',TRUE,TRUE] + ], + ->[BAR], + [BEVELR, + [EQROWS, + [TEXT,'688x539','Visible Size:',FALSE,3], + [TEXT,'640x200','Minimum Size:',FALSE,3], + [TEXT,'16368x16384','Maximum Size:',FALSE,3], + [TEXT,'256','Maximum Colors:',FALSE,3], + [SPACE] + ] + ] + ], + [BAR], + [COLS, + [BUTTON,0,'Save'], + [SPACEH], + [BUTTON,0,'Use'], + [SPACEH], + [BUTTON,0,'Cancel'] + ] + ], + [EG_CLEAN,{havenot}, EG_INFO,{havescreenmode}, NIL] + ) + ENDIF +ENDPROC + +PROC file(x:PTR TO guihandle) + IF havefile=FALSE + havefile:=TRUE + addmultiA(x.mh,'Select a file:', + [EQROWS, + [LISTV,0,NIL,1,5,NIL,0,NIL,0], + [STR,{fr},'Pattern',s,200,5], + [STR,{fr},'Drawer',s,200,5], + [STR,{fr},'File',s,200,5], + [COLS, + [BUTTON,1,'Ok'], + [SPACEH], + [BUTTON,2,'Disks'], + [SPACEH], + [BUTTON,3,'Parent'], + [SPACEH], + [BUTTON,0,'Cancel'] + ] + ], + [EG_CLEAN,{havenot}, EG_INFO,{havefile}, NIL] + ) + ENDIF +ENDPROC + +PROC fr(a,b) IS WriteF('fr: \s\n',b) + +PROC search(x:PTR TO guihandle) + IF havesearch=FALSE + havesearch:=TRUE + addmultiA(x.mh,'Enter Search/Replace text:', + [ROWS, + [ROWS, -> ROWS + [EQROWS, + [STR,{find},'Locate',s,10,10], + [STR,{repl},'Replace',s,10,10] + ], + [COLS, -> COLS + [CHECK,{case},'Ignore case',TRUE,FALSE], + [CHECK,{word},'Whole words only',FALSE,FALSE], + [CHECK,{forw},'Search forward',TRUE,FALSE] + ] + ], + [BAR], + [EQCOLS, + [BUTTON,1,'Search'], + [SPACEH], + [BUTTON,2,'Replace'], + [SPACEH], + [BUTTON,0,'Cancel'] + ] + ], + [EG_CLEAN,{havenot}, EG_INFO,{havesearch}, NIL] + ) + ENDIF +ENDPROC + +PROC find(x,y) IS WriteF('Find="\s"!\n',y) +PROC repl(x,y) IS WriteF('Repl="\s"!\n',y) +PROC case(x,y) IS WriteF('Case=\d!\n',y) +PROC word(x,y) IS WriteF('Word=\d!\n',y) +PROC forw(x,y) IS WriteF('Forw=\d!\n',y) + +PROC search2(x:PTR TO guihandle) + IF havesearch2=FALSE + havesearch2:=TRUE + addmultiA(x.mh,'Enter Search/Replace text:', + [ROWS, + [COLS, -> ROWS + [EQROWS, + [STR,{find},'Locate',s,10,10], + [STR,{repl},'Replace',s,10,10] + ], + [EQROWS, -> COLS + [CHECK,{case},'Ignore case',TRUE,FALSE], + [CHECK,{word},'Whole words only',FALSE,FALSE], + [CHECK,{forw},'Search forward',TRUE,FALSE] + ] + ], + [BAR], + [EQCOLS, + [BUTTON,1,'Search'], + [SPACEH], + [BUTTON,2,'Replace'], + [SPACEH], + [BUTTON,0,'Cancel'] + ] + ], + [EG_CLEAN,{havenot}, EG_INFO,{havesearch2}, NIL] + ) + ENDIF +ENDPROC + +PROC amosaic(x:PTR TO guihandle) + IF haveamosaic=FALSE + haveamosaic:=TRUE + addmultiA(x.mh,'AMosaic', + [EQROWS, + [TEXT,'Wouter''s WWW page','Title:',TRUE,3], + [TEXT,'file://localhost/...','URL:',TRUE,3], + [COLS, + [SBUTTON,0,'Back'], + [SBUTTON,0,'Forward'], + [SBUTTON,0,'Home'], + [SBUTTON,0,'Open'], + [SBUTTON,0,'Reload'], + [SBUTTON,0,'Quit'] + ], + [COLS, + [BEVELR, + [SPACE] + ], + [SCROLL,0,TRUE,10,0,2,10] + ], + [TEXT,'file://localhost/...',NIL,FALSE,3] + ], + [EG_CLEAN,{havenot}, EG_INFO,{haveamosaic}, NIL] + ) + ENDIF +ENDPROC + +PROC db(x:PTR TO guihandle) + IF havedb=FALSE + havedb:=TRUE + addmultiA(x.mh,'EasyBase v0.1', + [ROWS, + [LISTV,0,NIL,5,4,NIL,0,NIL,0], + [COLS, + [BUTTON,0,'New'], + [BUTTON,{fields},'Fields',x.mh], + [BUTTON,0,'Load'], + [BUTTON,0,'Save']]], + [EG_CLEAN,{havenot}, EG_INFO,{havedb}, NIL]) + ENDIF +ENDPROC + +PROC fields(mh,i) HANDLE + multiforall({gh},mh,`blockwin(gh)) + easyguiA('Edit Fields', + [ROWS, + [LISTV,0,NIL,5,3,NIL,0,NIL,0], + [COLS, + [BUTTON,{addfield},'Add'], + [BUTTON,0,'Delete'], + [BUTTON,0,'Change']]]) +EXCEPT DO + multiforall({gh},mh,`unblockwin(gh)) + ReThrow() +ENDPROC + +PROC editfield(gh) HANDLE + blockwin(gh) + easyguiA('Field Characteristics', + [ROWS, + [EQROWS, + [STR,0,'fieldname',s,200,10], + [INTEGER,0,'fieldlength',40,10]], + [BUTTON,0,'Ok']]) +EXCEPT DO + unblockwin(gh) + ReThrow() +ENDPROC + +PROC addfield(i) IS editfield(i) + +PROC dm(x:PTR TO guihandle) + IF havedm=FALSE + havedm:=TRUE + addmultiA(x.mh,'E FileManager v0.1', + [ROWS, + [COLS, + [ROWS, + [LISTV,0,NIL,1,10,NIL,0,NIL,0], + [STR,0,'',s,200,5] + ], + [EQROWS, + [BUTTON,1,'DF0:'], + [BUTTON,1,'DF1:'], + [BUTTON,1,'Ram:'], + [BUTTON,1,'System:'], + [BUTTON,1,'Work:'], + [BUTTON,1,'E:'], + [SPACEV] + ], + [ROWS, + [LISTV,0,NIL,1,5,NIL,0,NIL,0], + [STR,0,'',s,200,5] + ] + ], + [COLS, + [EQROWS,[SBUTTON,1,'Parent'],[SBUTTON,1,'All']], + [EQROWS,[SBUTTON,1,'Copy'],[SBUTTON,1,'Clear']], + [EQROWS,[SBUTTON,1,'Move'],[SBUTTON,1,'Toggle']], + [EQROWS,[SBUTTON,1,'Rename'],[SBUTTON,1,'Size']], + [EQROWS,[SBUTTON,1,'Delete'],[SBUTTON,1,'View']], + [EQROWS,[SBUTTON,1,'MakeDir'],[SBUTTON,0,'Config']] + ] + ], + [EG_CLEAN,{havenot}, EG_INFO,{havedm}, NIL] + ) + ENDIF +ENDPROC + +PROC tiny(x:PTR TO guihandle) + IF havetiny=FALSE + havetiny:=TRUE + addmultiA(x.mh,'um..',[SBUTTON,0,'blerk'], + [EG_CLEAN,{havenot}, EG_INFO,{havetiny}, NIL]) + ENDIF +ENDPROC + +PROC messy(x:PTR TO guihandle) + IF havemessy=FALSE + havemessy:=TRUE + addmultiA(x.mh,'test-gui', + [ROWS, + [COLS, + [BEVEL, + [ROWS, + [BUTTON,{um},'Um,...'], + [MX,{v},NIL,['One','Two','Three',NIL],FALSE,1], + [BUTTON,{pom},'PomPomPom'], + [CHECK,{v},'check this out!',TRUE,FALSE], + [STR,{v},'input',s,50,3], + [LISTV,{v},NIL,2,5,NIL,FALSE,0,0] + ] + ], + [BEVEL, + [EQROWS, + [STR,{v},'input',s,50,4], + [INTEGER,{v},'int:',5,3], + [SLIDE,{v},'tata: ',FALSE,0,999,20,2,'%3ld'], + [TEXT,'bla','text:',FALSE,5], + [NUM,123,'num:',TRUE,5], + [PALETTE,{v},'kleur:',3,5,2,0], + [CYCLE,{v},'choose:',['Yep','Nope',NIL],1], + [SCROLL,{v},FALSE,10,0,2,2] + ] + ] + ], + [BAR], + [EQCOLS, + [BUTTON,1,'Save'], + [BUTTON,2,'Use'], + [BUTTON,0,'Cancel'] + ] + ], + [EG_CLEAN,{havenot}, EG_INFO,{havemessy}, + EG_MENU,[NM_TITLE,0,'Project',0, 0,0,0, + NM_ITEM,0,'Load', 'l',0,0,{um}, + NM_ITEM,0,'Save', 's',0,0,{um}, + NM_ITEM,0,'Bla ->', 0, 0,0,0, + NM_SUB,0,'aaargh', 'a',0,0,1, + NM_SUB,0,'hmmm', 'h',0,0,2, + NM_ITEM,0,'Quit', 'q',0,0,0, + 0,0,0,0,0,0,0]:newmenu, + NIL] + ) + ENDIF +ENDPROC + +PROC um(x) IS WriteF('um!\n') +PROC pom(x) IS WriteF('pom!\n') +PROC v(x,y) IS WriteF('v=\d!\n',y) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/animcontrol_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/animcontrol_test.e new file mode 100644 index 0000000..815ccd6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/animcontrol_test.e @@ -0,0 +1,32 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'plugins/animcontrol' + +PROC main() HANDLE + DEF a=NIL:PTR TO animcontrol + NEW a.animcontrol(10,20) + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + [TEXT,'AnimControl test...',NIL,TRUE,1], + [PLUGIN,{animcontrolaction},a], + [EQCOLS, + [BUTTON,{reset},'Reset',a], + [BUTTON,{toggle_enabled},'Toggle Enabled',a] + ] + ]) +EXCEPT DO + END a + report_exception() +ENDPROC + +PROC animcontrolaction(i,a:PTR TO animcontrol) + PrintF('Action: mode=\d frame=\d\n', a.mode, a.frame) +ENDPROC + +PROC reset(a:PTR TO animcontrol,i) + a.setframe(10) + a.setplay(FALSE) +ENDPROC + +PROC toggle_enabled(a:PTR TO animcontrol,i) + a.setdisabled(a.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/button_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/button_test.e new file mode 100644 index 0000000..40b4bc9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/button_test.e @@ -0,0 +1,42 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'plugins/button' + +DEF b2=NIL:PTR TO button + +PROC main() HANDLE + DEF b1=NIL:PTR TO button, b3=NIL:PTR TO button, + bp=NIL:PTR TO button + NEW bp.togglebutton('Paused') + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + [TEXT,'Button test...',NIL,TRUE,5], + [COLS, + [PLUGIN,{buttonaction1},NEW b1.togglebutton('New')], + [PLUGIN,{buttonaction1},NEW b2.pushbutton('Open')], + [PLUGIN,{buttonaction2},NEW b3.button('Save')], + [PLUGIN,{buttonaction3},bp] + ], + [SBUTTON,{toggle_enabled},'Toggle Enabled',bp] + ]) +EXCEPT DO + END b1,b2,b3,bp + report_exception() +ENDPROC + +PROC buttonaction1(i,b:PTR TO button) + WriteF('button selected=\d\n', b.selected) +ENDPROC + +PROC buttonaction2(i,b:PTR TO button) + WriteF('button selected=\d\n', b.selected) + b2.setselected(FALSE) +ENDPROC + +PROC buttonaction3(i,b:PTR TO button) + WriteF('button selected=\d\n', b.selected) + b.settext(IF b.selected THEN 'Play' ELSE 'Paused') +ENDPROC + +PROC toggle_enabled(b:PTR TO button,i) + b.setdisabled(b.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/calendar_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/calendar_test.e new file mode 100644 index 0000000..9ec220e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/calendar_test.e @@ -0,0 +1,38 @@ +MODULE 'tools/EasyGUI', 'tools/exceptions', + 'utility/date', + 'plugins/calendar' + +DEF title + +PROC main() HANDLE + DEF c=NIL:PTR TO calendar + NEW c.calendar([0,0,0,25,12,1996,0]:clockdata,TRUE) + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + title:=[TEXT,'Calendar: December 1996',NIL,TRUE,5], + [PLUGIN,{calendaraction},c], + [EQCOLS, + [BUTTON,{reset},'Set to October',c], + [BUTTON,{toggle_enabled},'Toggle Enabled',c] + ] + ]) +EXCEPT DO + END c + report_exception() +ENDPROC + +PROC calendaraction(i,c:PTR TO calendar) + WriteF('You picked day \d\n', c.date.mday) +ENDPROC + +PROC reset(c:PTR TO calendar,gh) + IF c.date.month<>10 + c.date.month:=10 + c.setdate() + settext(gh,title,'Calendar: October 1996') + ENDIF +ENDPROC + +PROC toggle_enabled(c:PTR TO calendar,i) + c.setdisabled(c.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/colorwheel_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/colorwheel_test.e new file mode 100644 index 0000000..8a0569c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/colorwheel_test.e @@ -0,0 +1,62 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'gadgets/colorwheel', + 'plugins/colorwheel' + +DEF rgb:colorwheelrgb, hsb:colorwheelhsb, title + +PROC init(rgb:PTR TO colorwheelrgb) + rgb.red:=-1; rgb.blue:=0; rgb.green:=0 +ENDPROC + +PROC main() HANDLE + DEF c=NIL:PTR TO colorwheel + init(rgb) + NEW c.colorwheel(rgb,NIL,TRUE) + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + title:=[TEXT,'Colorwheel test (using RGB)...',NIL,TRUE,1], + [COLS, + [PLUGIN,{colorwheelaction},c], + [EQROWS, + [BUTTON,{reset},'Reset',c], + [BUTTON,{swap},'RGB/HSB',c], + [BUTTON,{toggle_enabled},'Toggle Enabled',c] + ] + ] + ]) +EXCEPT DO + END c + report_exception() +ENDPROC + +PROC colorwheelaction(i,c:PTR TO colorwheel) + IF c.rgb + PrintF('RGB r=$\h, g=$\h, b=$\h\n', + c.rgb.red, c.rgb.green, c.rgb.blue) + ELSE + PrintF('HSB h=$\h, s=$\h, b=$\h\n', + c.hsb.hue, c.hsb.saturation, c.hsb.brightness) + ENDIF +ENDPROC + +PROC reset(c:PTR TO colorwheel,gh) + init(rgb) + c.setrgb(rgb) + settext(gh,title,'Reset Colorwheel to RGB...') +ENDPROC + +PROC swap(c:PTR TO colorwheel,gh) + IF c.rgb + settext(gh,title,'Now Colorwheel is HSB...') + c.gethsb(hsb) + c.sethsb(hsb) + ELSE + settext(gh,title,'Colorwheel using RGB...') + c.getrgb(rgb) + c.setrgb(rgb) + ENDIF +ENDPROC + +PROC toggle_enabled(c:PTR TO colorwheel,i) + c.setdisabled(c.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/gradient_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/gradient_test.e new file mode 100644 index 0000000..3bb4571 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/gradient_test.e @@ -0,0 +1,40 @@ +MODULE 'tools/EasyGUI', 'tools/exceptions', + 'plugins/gradient' + +DEF disabled=FALSE, pens1, pens2 + +PROC main() HANDLE + DEF g=NIL:PTR TO gradient + pens1:=[2,0,1,-1]:INT + pens2:=[1,0,2,-1]:INT + NEW g.gradient(FALSE,$4444,6,pens1) + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + [TEXT,'GradientSlider test...',NIL,TRUE,15], + [PLUGIN,{gradaction},g], + [COLS, + [BUTTON,{reset},'Reset',g], + [BUTTON,{swap_pens},'Swap Pens',g], + [BUTTON,{toggle_enabled},'Toggle Enabled',g] + ] + ]) +EXCEPT DO + report_exception() +ENDPROC + +PROC gradaction(i,g:PTR TO gradient) + WriteF('gradient value = \z$\h[4]\n', g.curval) +ENDPROC + +PROC reset(g:PTR TO gradient,i) + g.setcurval($4444) + g.setpens(pens1) +ENDPROC + +PROC swap_pens(g:PTR TO gradient,i) + g.setpens(IF g.pens=pens1 THEN pens2 ELSE pens1) +ENDPROC + +PROC toggle_enabled(g:PTR TO gradient,i) + g.setdisabled(g.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/iconify_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/iconify_test.e new file mode 100644 index 0000000..6bf2cd9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/iconify_test.e @@ -0,0 +1,33 @@ +MODULE 'tools/exceptions', + 'tools/easygui', + 'other/split', + 'plugins/iconify' + +PROC main() HANDLE + DEF args:PTR TO LONG, p=NIL:PTR TO iconify + IF args:=argSplit() + IF args[] + PrintF('Using the icon for "\s"\n',args[]) + ELSE + PrintF('Using default icon (try "sys:tools/CMD" as an argument)\n') + ENDIF + NEW p.iconify('Iconify',args[],'Hello',TRUE) + easyguiA('GadTools in EasyGUI!', + [ROWS, + [TEXT,'Iconify test...',NIL,TRUE,1], + [SPACE], + [PLUGIN,0,p,TRUE], + [SPACE], + [BUTTON,{toggle_enabled},'Toggle Enabled',p] + ]) + ELSE + PrintF('Bad arguments: specify a filename\n') + ENDIF +EXCEPT DO + END p + report_exception() +ENDPROC + +PROC toggle_enabled(p:PTR TO iconify,i) + p.setdisabled(p.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/imagebutton_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/imagebutton_test.e new file mode 100644 index 0000000..fcbd9eb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/imagebutton_test.e @@ -0,0 +1,128 @@ +MODULE 'tools/easygui', 'tools/exceptions', 'tools/copylist', + 'intuition/intuition', + 'plugins/imagebutton' + +DEF pp1, pp2, b2=NIL:PTR TO imagebutton + +PROC main() HANDLE + DEF b1=NIL:PTR TO imagebutton, b3=NIL:PTR TO imagebutton, + bp=NIL:PTR TO imagebutton, img1, img2, img3, + d1=NIL, d2=NIL, d3=NIL, d4=NIL, d5=NIL + img1:=[0,0,22,22,3, + d1:=copyListToChip([ /* Plane 0 */ + $00000000,$00000000,$00000000,$00000000, + $00FC0000,$00060000,$00058000,$0404C000, + $0407E000,$04006000,$04006000,$04006000, + $04006000,$04006000,$04006000,$04006000, + $04006000,$04006000,$04006000,$07FFE000, + $01FFE000,$00000000, + /* Plane 1 */ + $00000000,$02000000,$0A800000,$07000000, + $38C00000,$07F80000,$0BFA8000,$07FB4000, + $07F82000,$07FFA000,$07FFA000,$07FFA000, + $03FFA000,$03FFA000,$03FFA000,$03FFA000, + $03FFA000,$03FFA000,$03FFA000,$00002000, + $01FFE000,$00000000, + /* Plane 2 */ + $00000000,$00000000,$00000000,$00000000, + $00C00000,$00000000,$00008000,$04004000, + $04002000,$04002000,$04002000,$04002000, + $00002000,$00002000,$00002000,$00002000, + $00002000,$00002000,$00002000,$00002000, + $01FFE000,$00000000]), + $0007,0,NIL]:image + img2:=[0,0,22,22,3, + d2:=copyListToChip([ /* Plane 0 */ + $00000000,$00007000,$0003F000,$000FF000, + $001FF800,$000FF800,$0007F800,$1E0FF000, + $21DFF000,$40FFF000,$407FF000,$40FB2000, + $5FFF8000,$50008000,$7000E000,$6000C000, + $60018000,$60018000,$40010000,$7FFE0000, + $00000000,$00000000, + /* Plane 1 */ + $00000000,$00004000,$00022000,$0001E000, + $0017E800,$000BE800,$0003D800,$0007D000, + $1ECE5000,$3F1DB000,$3FB9F000,$3F752000, + $20000000,$2FFF0000,$3FFF6000,$1FFF4000, + $1FFF8000,$3FFE8000,$3FFE0000,$00000000, + $00000000,$00000000, + /* Plane 2 */ + $00000000,$00004000,$00020000,$00000000, + $00100800,$00080800,$00001800,$00001000, + $1EC01000,$3F01B000,$3F81F000,$3F052000, + $20000000,$25550000,$3AAA6000,$15554000, + $0AAB8000,$35548000,$2AAA0000,$00000000, + $00000000,$00000000]), + $0007,0,NIL]:image + img3:=[0,0,22,22,3, + d3:=copyListToChip([ /* Plane 0 */ + $00000000,$10000000,$3C000000,$7E000000, + $3F000000,$1FB00000,$0FF00000,$07FC0000, + $07FC0000,$0BFC0000,$17FF8000,$17F8C000, + $11F8C000,$17FFE000,$14002000,$1C003800, + $18003000,$18006000,$18006000,$10004000, + $1FFF8000,$00000000, + /* Plane 1 */ + $00000000,$00000000,$14000000,$3A000000, + $1D000000,$0E900000,$07200000,$03EC0000, + $01EC0000,$05F40000,$0BF00000,$08F74000, + $0F374000,$08000000,$0BFFC000,$0FFFD800, + $07FFD000,$07FFE000,$0FFFA000,$0FFF8000, + $00000000,$00000000, + /* Plane 2 */ + $00000000,$00000000,$04000000,$02000000, + $01000000,$00900000,$00000000,$000C0000, + $000C0000,$04040000,$08000000,$08074000, + $0F274000,$08000000,$09554000,$0EAA9800, + $05555000,$02AAE000,$0D552000,$0AAA8000, + $00000000,$00000000]), + $0007,0,NIL]:image + pp1:=[0,0,22,7,2, + d4:=copyListToChip([$00030000, $0003C000, $0003F000, $0003FC00, + $0003F000, $0003C000, $00030000, + $E3800000, $E3800000, $E3800000, $E3800000, + $E3800000, $E3800000, $E3800000]), + $0003, 0, NIL]:image + pp2:=[0,0,22,7,2, + d5:=copyListToChip([$E3800000, $E3800000, $E3800000, $E3800000, + $E3800000, $E3800000, $E3800000, + $00030000, $0003C000, $0003F000, $0003FC00, + $0003F000, $0003C000, $00030000]), + $0003, 0, NIL]:image + + NEW bp.toggleimagebutton(pp1,30,22) + + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + [TEXT,'ImageButton test...',NIL,TRUE,5], + [COLS, + [PLUGIN,{buttonaction1},NEW b1.toggleimagebutton(img1)], + [PLUGIN,{buttonaction1},NEW b2.pushimagebutton(img2)], + [PLUGIN,{buttonaction2},NEW b3.imagebutton(img3)], + [PLUGIN,{buttonaction3},bp] + ], + [SBUTTON,{toggle_enabled},'Toggle Enabled',bp] + ]) +EXCEPT DO + END b1,b2,b3,bp + Dispose(d1); Dispose(d2); Dispose(d3); Dispose(d4); Dispose(d5) + report_exception() +ENDPROC + +PROC buttonaction1(i,b:PTR TO imagebutton) + WriteF('button selected=\d\n', b.selected) +ENDPROC + +PROC buttonaction2(i,b:PTR TO imagebutton) + WriteF('button selected=\d\n', b.selected) + b2.setselected(FALSE) +ENDPROC + +PROC buttonaction3(i,b:PTR TO imagebutton) + WriteF('button selected=\d\n', b.selected) + b.setimage(IF b.selected THEN pp2 ELSE pp1) +ENDPROC + +PROC toggle_enabled(b:PTR TO imagebutton,i) + b.setdisabled(b.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test.e new file mode 100644 index 0000000..097a284 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test.e @@ -0,0 +1,55 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'graphics/text', + 'plugins/led' + +DEF going=FALSE, title + +PROC main() HANDLE + DEF l=NIL:PTR TO led + NEW l.led(2,[0,0]:INT,TRUE) + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + title:=[TEXT,'LED Boopsi image tester...',NIL,TRUE,1], + [COLS, + [EQROWS, + [BUTTON,{runaction},'Run',l], + [BUTTON,{stopaction},'Stop'] + ], + [PLUGIN,0,l] + ] + ]) +EXCEPT DO + END l + report_exception() +ENDPROC + +PROC runaction(l:PTR TO led,gh) HANDLE + DEF h,m + IF going + settext(gh,title,'I''m busy counting!') + ELSE + going:=TRUE + settext(gh,title,'Started counting...') + Delay(10) + FOR h:=0 TO 12 + FOR m:=0 TO 59 + l.values:=[h,m]:INT + l.redisplay() + l.colon:=(l.colon=FALSE) + checkgui(gh) + Delay(10) + settext(gh,title,'Counting...') + ENDFOR + ENDFOR + settext(gh,title,'Finished!') + going:=FALSE + ENDIF +EXCEPT + going:=FALSE + settext(gh,title,'You stopped me!') + IF exception<>"STOP" THEN ReThrow() +ENDPROC + +PROC stopaction(i) + IF going THEN Raise("STOP") +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test2.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test2.e new file mode 100644 index 0000000..9c7fa05 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test2.e @@ -0,0 +1,149 @@ +-> This one shows the use of multi-window GUIs with PLUGINs, and multiple, +-> pseudo-asynchronous activities. +MODULE 'tools/easygui', 'tools/exceptions', + 'graphics/text', 'intuition/intuition', + 'plugins/led' + +-> Global for multiforall(). +DEF gh:PTR TO guihandle + +-> Number of GUIs counting. +DEF counting=0 + +CONST NUM_VALUES=2 + +-> Store all the GUI data in one place. +OBJECT mygui + -> In particular, keep PLUGIN references here. + ledplug:PTR TO led + gh:PTR TO guihandle + gui + title + going + values[NUM_VALUES]:ARRAY OF INT +ENDOBJECT + +-> The main loop: create one window to start with. +PROC main() HANDLE + DEF mh=NIL + mh:=multiinit() + create(mh) + multiloop(mh) +EXCEPT DO + cleanmulti(mh) + report_exception() +ENDPROC + +-> Create a new GUI. +PROC create(mh) HANDLE + DEF t, g, gui=NIL:PTR TO mygui + NEW gui + -> Allocate all PLUGINs for the GUI like this. + NEW gui.ledplug.led(NUM_VALUES,gui.values,TRUE) + -> Now we can try opening a GUI. + gui.gh:=addmultiA(mh,'BOOPSI in EasyGUI!', + g:=NEW [ROWS, + t:=NEW [TEXT,'LED Boopsi image tester...',NIL,TRUE,16], + NEW [COLS, + NEW [EQROWS, + NEW [BUTTON,{runaction},'Run/Stop'], + NEW [BUTTON,{spawn},'Spawn'], + NEW [BUTTON,0,'Quit'] + ], + NEW [PLUGIN,0,gui.ledplug] + ] + ], + [EG_INFO,gui, EG_LEFT,Rnd(400), EG_TOP,Rnd(400), + -> The cleanup routine will deallocate the PLUGINs used. + EG_CLEAN,{cleanmygui}, EG_CLOSE,{close}, NIL]) + gui.gui:=g + gui.title:=t +EXCEPT + -> If there was any problem then it may have been the creation of PLUGINs + -> or addmultiA(). Luckily, addmultiA() (and guiinitA()) will *not* call + -> the EG_CLEAN function if they caused the problem, so we can (safely). + cleanmygui(gui) + ReThrow() +ENDPROC + +-> The custom clean up code for each GUI. +PROC cleanmygui(gui:PTR TO mygui) + IF gui + disposegui(gui.gui) + END gui.ledplug + END gui + ENDIF +ENDPROC + +-> The action function creates a new GUI in the group. +PROC spawn(info:PTR TO mygui) IS create(info.gh.mh) + +-> The run/stop action. +PROC runaction(info:PTR TO mygui) + IF info.going + settext(info.gh,info.title,'You stopped me!') + stop(info) + ELSE + settext(info.gh,info.title,'Started counting...') + Delay(10) + settext(info.gh,info.title,'Counting...') + run(info) + ENDIF +ENDPROC + +PROC stop(info:PTR TO mygui) + -> Going, so stop. + info.going:=FALSE + -> One less is counting. + DEC counting +ENDPROC + +PROC run(info:PTR TO mygui) + DEF mh + -> Stopped, so go. + info.going:=TRUE + -> One more counting. + INC counting + -> We're the first so we're the loop. + IF counting=1 + mh:=info.gh.mh + -> While there is someone counting + WHILE counting + -> Tick each GUI that's going. + multiforall({gh},mh,`next(gh.info)) + checkmulti(mh) + Delay(10) + ENDWHILE + ENDIF +ENDPROC + +-> Next count. +PROC next(info:PTR TO mygui) + DEF l:PTR TO led,h,m + IF info.going + l:=info.ledplug + l.colon:=(l.colon=FALSE) + m:=info.values[1]+1 + IF m=60 + m:=0 + h:=info.values[]+1 + IF h=13 + h:=0 + info.going:=FALSE + DEC counting + settext(info.gh,info.title,'Finished!') + ENDIF + l.values[]:=h + ENDIF + l.values[1]:=m + l.redisplay() + ENDIF +ENDPROC + +-> Close function. +PROC close(info:PTR TO mygui) + -> Stop if running. + IF info.going THEN stop(info) + -> Destroy window. + cleangui(info.gh) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test3.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test3.e new file mode 100644 index 0000000..b8be15a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test3.e @@ -0,0 +1,171 @@ +-> This one shows the use of multi-window GUIs with PLUGINs, and multiple, +-> real asynchronous activities (by creating tasks). +MODULE 'tools/easygui', 'tools/exceptions', + 'graphics/text', 'intuition/intuition', + 'plugins/led', + 'amigalib/tasks', 'amigalib/time', 'other/ecode', + 'devices/timer', 'exec/tasks' + +-> Global for multiexists(). +DEF gh:PTR TO guihandle + +CONST NUM_VALUES=2 + +-> Store all the GUI data in one place. +OBJECT mygui + -> In particular, keep PLUGIN references here. + ledplug:PTR TO led + gh:PTR TO guihandle + gui + title + going + values[NUM_VALUES]:ARRAY OF INT + task +ENDOBJECT + +-> The main loop: create one window to start with. +PROC main() HANDLE + DEF mh=NIL + mh:=multiinit() + create(mh) + multiloop(mh) +EXCEPT DO + cleanmulti(mh) + report_exception() +ENDPROC + +-> Create a new GUI. +PROC create(mh) HANDLE + DEF t, g, gui=NIL:PTR TO mygui + NEW gui + -> Allocate all PLUGINs for the GUI like this. + NEW gui.ledplug.led(NUM_VALUES,gui.values,TRUE) + -> Now we can try opening a GUI. + gui.gh:=addmultiA(mh,'BOOPSI in EasyGUI!', + g:=NEW [ROWS, + t:=NEW [TEXT,'LED Boopsi image tester...',NIL,TRUE,16], + NEW [COLS, + NEW [EQROWS, + NEW [BUTTON,{runaction},'Run/Stop'], + NEW [BUTTON,{spawn},'Spawn'], + NEW [BUTTON,{quit},'Quit'] + ], + NEW [PLUGIN,0,gui.ledplug] + ] + ], + [EG_INFO,gui, EG_LEFT,Rnd(400), EG_TOP,Rnd(400), + -> The cleanup routine will deallocate the PLUGINs used. + EG_CLEAN,{cleanmygui}, EG_CLOSE,{close}, NIL]) + gui.gui:=g + gui.title:=t +EXCEPT + -> If there was any problem then it may have been the creation of PLUGINs + -> or addmultiA(). Luckily, addmultiA() (and guiinitA()) will *not* call + -> the EG_CLEAN function if they caused the problem, so we can (safely). + cleanmygui(gui) + ReThrow() +ENDPROC + +PROC quit(info) IS quitgui(0) + +-> The custom clean up code for each GUI. +PROC cleanmygui(gui:PTR TO mygui) + IF gui + -> Stop and destroy task, if necessary. + stop(gui) + disposegui(gui.gui) + END gui.ledplug + END gui + ENDIF +ENDPROC + +-> The action function creates a new GUI in the group. +PROC spawn(info:PTR TO mygui) IS create(info.gh.mh) + +-> The run/stop action. +PROC runaction(info:PTR TO mygui) + IF info.going + settext(info.gh,info.title,'You stopped me!') + stop(info) + ELSE + settext(info.gh,info.title,'Started counting...') + Delay(10) + settext(info.gh,info.title,'Counting...') + run(info) + ENDIF +ENDPROC + +PROC stop(info:PTR TO mygui) + -> Going, so stop. + info.going:=FALSE + -> Temporarily make it high priority to die quicker. + Forbid() + IF info.task THEN SetTaskPri(info.task,5) + Permit() + -> Wait for task to die. + WHILE info.task DO Delay(1) +ENDPROC + +PROC run(info:PTR TO mygui) + DEF taskcode + IF info.task=NIL + IF taskcode:=eCodeTask({taskloop}) + -> Make new Counter task, low priority. + info.task:=createTask('Counter',-5,taskcode,1000,info) + ENDIF + ENDIF +ENDPROC + +-> The loop the task will execute. +PROC taskloop() + DEF task:PTR TO tc, info:PTR TO mygui, error=FALSE + task:=FindTask(NIL) + info:=task.userdata + info.going:=TRUE + -> While there is something to do. + WHILE next(info) + -> Cannot Delay() since this code is run by a Task (not a Process). + -> (200000 is a fifth of a second, or 10 ticks) + EXIT error:=timeDelay(UNIT_MICROHZ,0,200000) + ENDWHILE + -> Kill ourself safely. + Forbid() + -> This GUI update is safe, since within Forbid()/Permit(). + IF error THEN settext(info.gh,info.title,'Timer error!') + info.task:=NIL + deleteTask(task) + Permit() +ENDPROC + +-> Next count. +PROC next(info:PTR TO mygui) + DEF l:PTR TO led,h,m + IF info.going + l:=info.ledplug + l.colon:=(l.colon=FALSE) + m:=info.values[1]+1 + IF m=60 + m:=0 + h:=info.values[]+1 + IF h=13 + h:=0 + info.going:=FALSE + -> Must Forbid()/Permit() since we're a different task to the GUI. + Forbid() + settext(info.gh,info.title,'Finished!') + Permit() + RETURN FALSE + ENDIF + l.values[]:=h + ENDIF + l.values[1]:=m + -> Must Forbid()/Permit() since we're a different task to the GUI. + Forbid() + l.redisplay() + Permit() + RETURN TRUE + ENDIF +ENDPROC FALSE + +-> Close function. +PROC close(info:PTR TO mygui) IS cleangui(info.gh) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test4.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test4.e new file mode 100644 index 0000000..76c65a0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/led_test4.e @@ -0,0 +1,127 @@ +-> This one shows the use of multi-window GUIs with PLUGINs. A ticker is +-> used, so the counting stops when none of the windows in the group is +-> active! +MODULE 'tools/easygui', 'tools/exceptions', + 'graphics/text', 'intuition/intuition', + 'plugins/led', 'plugins/ticker' + +-> Global for multiforall(). +DEF gh:PTR TO guihandle + +CONST NUM_VALUES=2 + +-> Store all the GUI data in one place. +OBJECT mygui + -> In particular, keep PLUGIN references here. + ledplug:PTR TO led + ticker:PTR TO ticker + gh:PTR TO guihandle + gui + title + going + values[NUM_VALUES]:ARRAY OF INT +ENDOBJECT + +-> The main loop: create one window to start with. +PROC main() HANDLE + DEF mh=NIL + mh:=multiinit() + create(mh) + multiloop(mh) +EXCEPT DO + cleanmulti(mh) + report_exception() +ENDPROC + +-> Create a new GUI. +PROC create(mh) HANDLE + DEF t, g, gui=NIL:PTR TO mygui + NEW gui + -> Allocate all PLUGINs for the GUI like this. + NEW gui.ledplug.led(NUM_VALUES,gui.values,TRUE) + NEW gui.ticker + -> Now we can try opening a GUI. + gui.gh:=addmultiA(mh,'BOOPSI in EasyGUI!', + g:=NEW [ROWS, + t:=NEW [TEXT,'LED Boopsi image tester...',NIL,TRUE,16], + NEW [PLUGIN,{tick},gui.ticker], + NEW [COLS, + NEW [EQROWS, + NEW [BUTTON,{runaction},'Run/Stop'], + NEW [BUTTON,{spawn},'Spawn'], + NEW [BUTTON,0,'Quit'] + ], + NEW [PLUGIN,0,gui.ledplug] + ] + ], + [EG_INFO,gui, EG_LEFT,Rnd(400), EG_TOP,Rnd(400), + -> The cleanup routine will deallocate the PLUGINs used. + EG_CLEAN,{cleanmygui}, EG_CLOSE,{close}, NIL]) + gui.gui:=g + gui.title:=t +EXCEPT + -> If there was any problem then it may have been the creation of PLUGINs + -> or addmultiA(). Luckily, addmultiA() (and guiinitA()) will *not* call + -> the EG_CLEAN function if they caused the problem, so we can (safely). + cleanmygui(gui) + ReThrow() +ENDPROC + +-> The custom clean up code for each GUI. +PROC cleanmygui(gui:PTR TO mygui) + IF gui + disposegui(gui.gui) + END gui.ticker + END gui.ledplug + END gui + ENDIF +ENDPROC + +-> The action function creates a new GUI in the group. +PROC spawn(info:PTR TO mygui) IS create(info.gh.mh) + +-> The run/stop action. +PROC runaction(info:PTR TO mygui) + IF info.going + -> Going, so stop. + info.going:=FALSE + settext(info.gh,info.title,'You stopped me!') + ELSE + -> Stopped, so go. + info.going:=TRUE + settext(info.gh,info.title,'Started counting...') + Delay(10) + settext(info.gh,info.title,'Counting...') + ENDIF +ENDPROC + +-> Tick! +PROC tick(info:PTR TO mygui,t) + -> Go to next count for all open windows. + multiforall({gh},info.gh.mh,`IF gh.wnd THEN next(gh.info) ELSE 0) +ENDPROC + +-> Next count. +PROC next(info:PTR TO mygui) + DEF l:PTR TO led,h,m + IF info.going + l:=info.ledplug + l.colon:=(l.colon=FALSE) + m:=info.values[1]+1 + IF m=60 + m:=0 + h:=info.values[]+1 + IF h=13 + h:=0 + info.going:=FALSE + settext(info.gh,info.title,'Finished!') + ENDIF + l.values[]:=h + ENDIF + l.values[1]:=m + l.redisplay() + ENDIF +ENDPROC + +-> Close function. +PROC close(info:PTR TO mygui) IS cleangui(info.gh) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/password_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/password_test.e new file mode 100644 index 0000000..1025855 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/password_test.e @@ -0,0 +1,41 @@ +MODULE 'tools/exceptions', + 'tools/easygui', + 'plugins/password' + +DEF default + +PROC main() HANDLE + DEF p=NIL:PTR TO password, s[20]:STRING + default:='My Password!' + StrCopy(s,default) + NEW p.password(s,'Password:',TRUE,10) + easyguiA('GadTools in EasyGUI!', + [ROWS, + [TEXT,'Password test...',NIL,TRUE,1], + [PLUGIN,{passaction},p,TRUE], + [COLS, + [BUTTON,{show},'Show',p], + [BUTTON,{reset},'Reset',p], + [BUTTON,{toggle_enabled},'Toggle Enabled',p] + ] + ]) +EXCEPT DO + END p + report_exception() +ENDPROC + +PROC passaction(i,p:PTR TO password) + PrintF('Action: "\s"\n',p.estr) +ENDPROC + +PROC show(p:PTR TO password,i) + PrintF('Show: "\s"\n', p.estr) +ENDPROC + +PROC reset(p:PTR TO password,i) + p.setpass(default) +ENDPROC + +PROC toggle_enabled(p:PTR TO password,i) + p.setdisabled(p.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test.e new file mode 100644 index 0000000..a69cf35 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test.e @@ -0,0 +1,36 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'gadgets/tabs', + 'plugins/tabs' + +PROC main() HANDLE + DEF t=NIL:PTR TO tabs + NEW t.tabs(['Display', -1,-1,-1,-1, NIL, + 'Edit', -1,-1,-1,-1, NIL, + 'File', -1,-1,-1,-1, NIL, + NIL]:tablabel, + 0,FALSE) + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + [TEXT,'Tabs test...',NIL,TRUE,5], + [PLUGIN,{tabsaction},t], + [EQCOLS, + [BUTTON,{reset},'Reset',t], + [BUTTON,{toggle_enabled},'Toggle Enabled',t] + ] + ]) +EXCEPT DO + END t + report_exception() +ENDPROC + +PROC tabsaction(i,t:PTR TO tabs) + WriteF('tabs value = \d\n',t.current) +ENDPROC + +PROC reset(t:PTR TO tabs,i) + t.setcurrent(0) +ENDPROC + +PROC toggle_enabled(t:PTR TO tabs,i) + t.setdisabled(t.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test2.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test2.e new file mode 100644 index 0000000..1a7374d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tabs_test2.e @@ -0,0 +1,28 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'gadgets/tabs', + 'plugins/tabs' + +DEF labels:PTR TO tablabel, gui:PTR TO LONG + +PROC main() + DEF top, t=NIL:PTR TO tabs + labels:=['Slide', -1,-1,-1,-1, NIL, + 'Check', -1,-1,-1,-1, NIL, + 'Palette', -1,-1,-1,-1, NIL, + NIL]:tablabel + NEW t.tabs(labels) + top:=[PLUGIN,{tabsaction},t] + gui:=[ + [ROWS,top,[SPACE],[SLIDE,{ignore},'Colors:',FALSE,1,8,3,5,'']], + [ROWS,top,[SPACE],[CHECK,{ignore},'Ignore case',TRUE,FALSE]], + [ROWS,top,[SPACE],[PALETTE,{ignore},'Palette:',3,5,2,0]] + ] + easyguiA('Tabs Test 2', gui[]) +ENDPROC + +PROC ignore(i,x) IS EMPTY + +PROC tabsaction(gh,t:PTR TO tabs) + changegui(gh,gui[t.current]) + changetitle(gh,labels[t.current].label) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tapedeck_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tapedeck_test.e new file mode 100644 index 0000000..a4b9f35 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/tapedeck_test.e @@ -0,0 +1,32 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'plugins/tapedeck' + +PROC main() HANDLE + DEF t=NIL:PTR TO tapedeck + NEW t.tapedeck() + easyguiA('BOOPSI in EasyGUI!', + [ROWS, + [TEXT,'Tapedeck test...',NIL,TRUE,1], + [PLUGIN,{tapedeckaction},t], + [EQCOLS, + [BUTTON,{reset},'Reset',t], + [BUTTON,{toggle_enabled},'Toggle Enabled',t] + ] + ]) +EXCEPT DO + END t + report_exception() +ENDPROC + +PROC tapedeckaction(i,t:PTR TO tapedeck) + PrintF('Action: mode=\d\s\n', t.mode, IF t.paused THEN ' (paused)' ELSE '') +ENDPROC + +PROC reset(t:PTR TO tapedeck,i) + t.setmode() + t.setpaused(FALSE) +ENDPROC + +PROC toggle_enabled(t:PTR TO tapedeck,i) + t.setdisabled(t.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testaw.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testaw.e new file mode 100644 index 0000000..a4d8d63 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testaw.e @@ -0,0 +1,59 @@ +-> testaw.e - shows use of AppWindow handling and changing GUIs +MODULE 'tools/easygui', + 'workbench/startup', 'workbench/workbench' + +CONST MAXLEN=20 + +DEF current=0, gui:PTR TO LONG + +PROC main() + DEF s[MAXLEN]:STRING + -> Have a list of three different GUIs + gui:=[ + [LISTV,{ignore},'Drop Icons on Me!',15,7,NIL,0,1,0,0,0,{gadappw}], + [ROWS,[STR,{ignore},'Drop Icons on Me:',s,MAXLEN,5,0,0,0,{gadappw}], + [SPACEV],[BUTTON,{ignore},'But Not on Me']], + [ROWS,[BUTTON,{ignore},'Drop Icons on Me:',0,0,{gadappw}], + [SPACEV],[STR,{ignore},'Not on Me:',s,MAXLEN,5]] + ] + easyguiA('Test App Window', gui[current], + [EG_AWPROC,{winappw}, NIL]) +ENDPROC + +-> Ignore button presses etc. +PROC ignore(info,num) IS EMPTY + +-> Show next GUI in list +PROC nextgui(gh) + current++ + IF current>=ListLen(gui) THEN current:=0 + changegui(gh, gui[current]) +ENDPROC + +-> Default (window) App message handler +PROC winappw(info,awmsg) + PrintF('You missed the gadget... try again!\n') +ENDPROC + +-> App message handler for a gadget +PROC gadappw(info,awmsg) + PrintF('You hit the gadget! ') + showappmsg(awmsg) + nextgui(info) +ENDPROC + +CONST NAMELEN=256 + +-> Show the contents of the App message +PROC showappmsg(amsg:PTR TO appmessage) + DEF i, args:PTR TO wbarg, name[NAMELEN]:ARRAY + PrintF('Hit at (\d,\d)\n', amsg.mousex, amsg.mousey) + args:=amsg.arglist + FOR i:=1 TO amsg.numargs + NameFromLock(args.lock,name,NAMELEN) + PrintF(' arg(\d): Name="\s", Lock=$\h ("\s")\n', + i, args.name, args.lock, name) + args++ + ENDFOR + PrintF('\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange.e new file mode 100644 index 0000000..df944d9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange.e @@ -0,0 +1,32 @@ +-> testchange.e - show use of changegui() and BUTTON data field +MODULE 'tools/easygui' + +DEF gui:PTR TO LONG, titles:PTR TO LONG + +PROC main() + DEF top + top:=[COLS, + [SPACEH], + -> Use generic action function, with BUTTON data 0, 1 or 2. + [BUTTON,{change},'GUI _A',0,"a"], + [SPACEH], + [BUTTON,{change},'GUI _B',1,"b"], + [SPACEH], + [BUTTON,{change},'GUI _C',2,"c"], + [SPACEH] + ] + titles:=['GUI A','GUI B','GUI C'] + gui:=[ + [ROWS,top,[SPACE],[SLIDE,{ignore},'Colors:',FALSE,1,8,3,5,'']], + [ROWS,top,[SPACE],[CHECK,{ignore},'Ignore case',TRUE,FALSE]], + [ROWS,top,[SPACE],[PALETTE,{ignore},'Palette:',3,5,2,0]] + ] + easyguiA('Change Test', gui[]) +ENDPROC + +PROC ignore(info,x) IS EMPTY + +PROC change(index,gh) + changegui(gh,gui[index]) + changetitle(gh,titles[index]) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange2.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange2.e new file mode 100644 index 0000000..862b694 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testchange2.e @@ -0,0 +1,277 @@ +-> testchange2.e - shows use of some changeXXX() functions +MODULE 'tools/exceptions', + 'exec/lists', 'exec/nodes', + 'graphics/text', 'graphics/view', + 'libraries/gadtools', + 'amigalib/lists', + 'tools/easygui' + +RAISE "SCRN" IF OpenS()=NIL + +-> Index of the sub-GUI in the main GUI list. +CONST SUB_POS=3 + +-> The custom screen. +DEF scr=NIL + +-> The main GUI, the list of sub-GUIs, the titles and the menus. +DEF gui:PTR TO LONG, subguis:PTR TO LONG, titles:PTR TO LONG, menus + +-> The connected window, the main window, a gh for multiforall() and a tmp. +DEF ghconn=NIL, ghmain, forall, tmp + +-> The slider in the connected and main windows, and the check in main. +DEF connsl=NIL, mainsl=NIL:PTR TO LONG, mainchk=NIL + +PROC main() HANDLE + DEF mh=NIL + -> The list of GUIs we'll use (and change) as sub-GUIs in the main GUI. + subguis:=[ + [COLS, + [TEXT,'Try the menus!',NIL,TRUE,1], + [SLIDE,{ignore},'Colors:',FALSE,1,8,3,5,''] + ], + [COLS, + [SLIDE,{ignore},'Colors:',FALSE,1,8,3,5,''], + [CHECK,{ignore},'Ignore case',TRUE,FALSE] + ], + [COLS, + [CHECK,{ignore},'Ignore case',TRUE,TRUE], + [PALETTE,{ignore},'Palette:',3,5,2,0] + ] + ] + -> The main GUI. + gui:=[ROWS, + [COLS, + [SPACEH], + -> Use generic action function, with BUTTON data 0, 1 or 2. + [BUTTON,{change_gui},'GUI _X',0,"x"], + [SPACEH], + [BUTTON,{change_gui},'GUI _Y',1,"y"], + [SPACEH], + [BUTTON,{change_gui},'GUI _Z',2,"z"], + [SPACEH] + ], + [SPACE], + 0, -> The sub-GUI, initialise this below... + [SPACE], + [COLS, + [SBUTTON,{block_all},'_Block All',0,"b"], + [SBUTTON,{close_all},'_Close All',0,"c"] + ], + [BAR], + mainchk:=[CHECK,{connected_win},'Create/Destroy Connected Window', + FALSE,FALSE], + mainsl:=[SLIDE,{main_sl_fun},'Connected: ',FALSE,1,20,3,5,'\d[2]'] + ] + -> Initially, use the first sub-GUI. + gui[SUB_POS]:=subguis[] + titles:=['GUI X','GUI Y','GUI Z'] + -> We're going to share the menus between our two windows. + menus:=[NM_TITLE,0,'Project', NIL,0,0,0, + NM_ITEM,0,'Quit', 'Q',0,0,0, + NM_TITLE,0,'Screen', NIL,0,0,0, + NM_ITEM,0,'Default', 'D',0,0,{default}, + NM_ITEM,0,'Custom', 'C',0,0,{custom}, + NM_TITLE,0,'Window Type', NIL,0,0,0, + NM_ITEM,0,'No Border', 'N',0,0,{noborder}, + NM_ITEM,0,'Basic', 'B',0,0,{basic}, + NM_ITEM,0,'No Size', 'O',0,0,{nosize}, + NM_ITEM,0,'Size', 'S',0,0,{size}, + NM_TITLE,0,'GUI', NIL,0,0,0, + NM_ITEM,0,'X', 'X',0,0,{x}, + NM_ITEM,0,'Y', 'Y',0,0,{y}, + NM_ITEM,0,'Z', 'Z',0,0,{z}, + NM_TITLE,0,'Font', NIL,0,0,0, + NM_ITEM,0,'Screen', 'F',0,0,{font}, + NM_ITEM,0,'Topaz', 'T',0,0,{topaz}, + NM_END, 0,NIL, NIL,0,0,0]:newmenu + -> Start a multi-window group. + mh:=multiinit() + -> Open the main GUI. + ghmain:=addmultiA(mh, 'Check out the menus...', gui, + [EG_MENU,menus, EG_CLOSE,{closemain}, NIL]) + -> Process messages. + multiloop(mh) +EXCEPT DO + cleanmulti(mh) + -> If we opened the screen, close it. + IF scr THEN CloseS(scr) + report_exception() +ENDPROC + + +->>> Main GUI/shared action functions <<<- + +-> Close all windows, prompt then reopen. +PROC close_all(gh) HANDLE + allclose(gh) + easyguiA('New GUI', + [ROWS, + [TEXT,'Old GUIs closed',NIL,TRUE,15], + [TEXT,'Close me to reopen!',NIL,TRUE,15] + ]) +EXCEPT DO + allopen(gh) + ReThrow() +ENDPROC + +-> Block all windows, prompt then unblock. +PROC block_all(gh:PTR TO guihandle) HANDLE + multiforall({forall},gh.mh,`blockwin(forall)) + easyguiA('New GUI', + [ROWS, + [TEXT,'Old GUIs blocked',NIL,TRUE,15], + [TEXT,'Close me to unblock!',NIL,TRUE,15] + ]) +EXCEPT DO + multiforall({forall},gh.mh,`unblockwin(forall)) + ReThrow() +ENDPROC + +-> Change the font to default (screen) or Topaz. +PROC font(info) IS change_font(info,NIL) +PROC topaz(info) IS change_font(info,['topaz.font',8,0,0]:textattr) + +-> Change to the default public screen. +PROC default(gh:PTR TO guihandle) HANDLE + allclose(gh) + IF scr + CloseS(scr) + -> The screen is now invalid. + scr:=NIL + ENDIF + multiforall({forall},gh.mh,`changescreen(forall,NIL)) +EXCEPT DO + allopen(gh) + ReThrow() +ENDPROC + +-> Change to a custom screen. +PROC custom(gh:PTR TO guihandle) HANDLE + allclose(gh) + IF scr=NIL THEN scr:=OpenS(640,400,4,V_HIRES OR V_LACE,'Custom Screen') + tmp:=scr + multiforall({forall},gh.mh,`changescreen(forall,tmp)) +EXCEPT DO + allopen(gh) + ReThrow() +ENDPROC + +-> Change the window type. +PROC noborder(info) IS change_type(info,WTYPE_NOBORDER) +PROC basic(info) IS change_type(info,WTYPE_BASIC) +PROC nosize(info) IS change_type(info,WTYPE_NOSIZE) +PROC size(info) IS change_type(info,WTYPE_SIZE) + +-> Change the main GUI. +PROC x(info) IS change_gui(0,ghmain) +PROC y(info) IS change_gui(1,ghmain) +PROC z(info) IS change_gui(2,ghmain) + +PROC change_gui(index,gh) + changetitle(gh,titles[index]) + gui[SUB_POS]:=subguis[index] + changegui(gh,gui) +ENDPROC + +PROC ignore(info,x) IS EMPTY + + +->>> Connection code <<<- + +-> Connected slider on main GUI. +PROC main_sl_fun(info,cur) + IF ghconn THEN setslide(ghconn,connsl,cur) +ENDPROC + +-> Connected slider on the other GUI. +PROC conn_sl_fun(info,cur) + IF ghmain THEN setslide(ghmain,mainsl,cur) +ENDPROC + + +->>> Closing code <<<- + +-> Closing the main GUI quits. +PROC closemain(mh,gh) IS quitgui(0) + +-> Closing the other GUI destroys it. +PROC closeconn(mh,info) + cleangui(ghconn) + -> The guihandle is now invalid. + ghconn:=NIL + -> Uncheck the check in the main GUI. + IF mainchk THEN setcheck(ghmain,mainchk,FALSE) +ENDPROC + + +->>> Other GUI functions <<<- + +-> React to check changes on main GUI. +PROC connected_win(gh:PTR TO guihandle,bool) + IF bool + -> If it's been created reopen it, else create and add it to the group. + IF ghconn + openwin(ghconn) + ELSE + ghconn:=addmultiA(gh.mh, 'Connected Window', + [ROWS, + connsl:=[SLIDE,{conn_sl_fun},'Connected: ',FALSE,1,20, + IF mainsl THEN mainsl[SLI_CURR] ELSE 3,10,'\d[2]'], + [COLS, + [SBUTTON,{block_all},'_Block All',0,"b"], + [SBUTTON,{close_all},'_Close All',0,"c"] + ], + [SBUTTON,{clean_gui},'cl_eangui()',0,"e"] + ], + [EG_TOP,0, EG_LEFT,0, EG_MENU,menus, + EG_SCRN,scr, EG_CLOSE,{closeconn}, NIL]) + ENDIF + ELSEIF ghconn + -> If it's been created, destroy it. + cleangui(ghconn) + -> The guihandle is now invalid. + ghconn:=NIL + ENDIF +ENDPROC + +-> Action function for cleangui() button (reuse closeconn()). +PROC clean_gui(info) IS closeconn(0,0) + + +->>> Auxiliary functions <<<- + +-> Close all GUIs (and update check on main GUI) +PROC allclose(gh:PTR TO guihandle) + multiforall({forall},gh.mh,`closewin(forall)) + -> Make check false only if the other window exists + IF ghconn THEN setcheck(ghmain,mainchk,FALSE) +ENDPROC + +-> Open all GUIs (and update check on main GUI) +PROC allopen(gh:PTR TO guihandle) + multiforall({forall},gh.mh,`openwin(forall)) + -> Make check true only if the other window exists + IF ghconn THEN setcheck(ghmain,mainchk,TRUE) +ENDPROC + +-> Change the window type. +PROC change_type(gh:PTR TO guihandle,t) HANDLE + allclose(gh) + tmp:=t + multiforall({forall},gh.mh,`changewintype(forall,tmp)) +EXCEPT DO + allopen(gh) + ReThrow() +ENDPROC + +-> Change the window font. +PROC change_font(gh:PTR TO guihandle,tattr) HANDLE + allclose(gh) + tmp:=tattr + multiforall({forall},gh.mh,`changefont(forall,tmp)) +EXCEPT DO + allopen(gh) + ReThrow() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testkey.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testkey.e new file mode 100644 index 0000000..bc435b1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testkey.e @@ -0,0 +1,83 @@ +-> testkey.e - shows use of keyboard short-cuts +MODULE 'tools/easygui', + 'exec/lists', 'exec/nodes', + 'graphics/text', + 'amigalib/lists' + +CONST MAXLEN=20 + +DEF gad, disabled=TRUE + +PROC main() + DEF s[MAXLEN]:STRING, list:lh, choices + newList(list) + AddTail(list, [0,0,0,0,'Item']:ln) + AddTail(list, [0,0,0,0,'Item-2']:ln) + AddTail(list, [0,0,0,0,'Item-3']:ln) + AddTail(list, [0,0,0,0,'Item-4']:ln) + AddTail(list, [0,0,0,0,'Item-5']:ln) + AddTail(list, [0,0,0,0,'Item-6']:ln) + choices:=['Zero','One','Two',NIL] + StrCopy(s,'Hello') + easyguiA('Press Some Keys!', + [COLS, + [EQROWS, + [CYCLE,{cycle},'_Cycle:',choices,1,0,"c"], + [STR,{password},'S_tring:',s,MAXLEN,5,FALSE,0,"t"], + [BAR], + -> Show new CHECK and MX alignments + [CHECK,{check},'C_heck:',TRUE,TRUE,0,"h"], + [MX,{mx},'_MX:',choices,TRUE,0,0,"m"], + [BAR], + -> Show new CHECK and MX right text + [CHECK,{check2},'Ch_eck2 (Right)',TRUE,FALSE,0,"e"], + [MX,{mx2},'M_X2 (Right)',choices,FALSE,0,0,"x"] + ], + [BAR], + [ROWS, + -> Show new LISTV label and show selected + [LISTV,{listv},'_List:',8,5,list,FALSE,1,0,0,"l",0], + [SLIDE,{slide},'_Slide:',FALSE,1,8,3,3,'',0,"s"], +-> [SCROLL,{slide},FALSE,80,10,3,3,0,"i"], + -> Show new PALETTE current field, min size and show selected + [PALETTE,{palette},'_Palette:',3,5,2,2,0,"p"], + gad:=[SBUTTON,{button},'_blockwin()',0,"b",0,disabled], + [SBUTTON,{disable},'_disable()',0,"d"] + ] + ]) +ENDPROC + +PROC button(gh) HANDLE + blockwin(gh) + easyguiA('New GUI', + [ROWS, + [TEXT,'Old GUI blocked',NIL,TRUE,15], + [BUTTON,0,'_Unblock',0,"u"] + ]) +EXCEPT DO + unblockwin(gh) + ReThrow() +ENDPROC + +PROC disable(gh) + disabled:=disabled=FALSE + setdisabled(gh,gad,disabled) +ENDPROC + +PROC slide(info,val) IS PrintF('Slide has moved to \d\n', val) + +PROC cycle(info,val) IS PrintF('Cycle choice is now \d\n', val) + +PROC check(info,val) IS PrintF('Check is now \s\n', + IF val THEN 'TRUE' ELSE 'FALSE') +PROC check2(info,val) IS PrintF('Check2 is now \s\n', + IF val THEN 'TRUE' ELSE 'FALSE') + +PROC mx(info,val) IS PrintF('MX choice is now \d\n', val) +PROC mx2(info,val) IS PrintF('MX2 choice is now \d\n', val) + +PROC password(info,val) IS PrintF('Password is now "\s"\n', val) + +PROC palette(info,val) IS PrintF('Palette pen is now \d\n', val) + +PROC listv(info,val) IS PrintF('List selection moved to \d\n', val) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti.e new file mode 100644 index 0000000..4b479cc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti.e @@ -0,0 +1,59 @@ +-> testmulti.e - Simple (recursive) use of multi-window GUI support. +-> (Note: Intuition gets a bit weird with lots of windows -- lockups or +-> crashes with huge numbers of windows are not EasyGUI's fault...) +MODULE 'tools/easygui', 'tools/exceptions' + +RAISE "MEM" IF String()=NIL + +DEF guis=1 + +PROC main() HANDLE + DEF mh=NIL + mh:=multiinit() + -> Start at level 0. + create(mh,0) + multiloop(mh) +EXCEPT DO + cleanmulti(mh) + report_exception() +ENDPROC + +-> Add a new window to the group mh at level i. +PROC add(level,gh:PTR TO guihandle) IS create(gh.mh,level) + +-> Add a new window to the group mh at level i. +PROC create(mh,level) + DEF s + -> Next level. + INC level + s:=StringF(String(10),'GUI \d',guis) + -> Got to NEW the gui since the same one is being used multiple times. + addmultiA(mh, s, + NEW [ROWS, + NEW [TEXT,'Multi GUI Test',NIL,TRUE,10], + NEW [COLS, + NEW [NUM,level,'Level:',0,1], + NEW [NUM,guis,'GUI:',0,1] + ], + NEW [COLS, + -> Recursive call to create() via add()! + NEW [BUTTON,{add},'_Add',level,"a"], + NEW [SPACE], + -> Pressing the Quit button quits multiloop() and so + -> then all windows are closed. + NEW [BUTTON,0,'_Quit',0,"q"] + ] + ], + -> Open at a random position, with level as info. + [EG_LEFT,Rnd(400), EG_TOP,Rnd(400), EG_CLOSE,{close}, NIL]) + -> Now another GUI. + INC guis +ENDPROC + +-> This function is called when the GUI close gadget is hit. +-> (Hitting the close gadget closes only that window, unless it is the last.) +PROC close(mh:PTR TO multihandle,info) + WriteF('GUIs left with open windows = \d\n',mh.opencount) + -> Is this the last open window? + IF mh.opencount=1 THEN quitgui(0) ELSE closewin(info) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti2.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti2.e new file mode 100644 index 0000000..2220a8d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testmulti2.e @@ -0,0 +1,44 @@ +-> testmulti2.e - Another very simple use of multi-window GUI support. +MODULE 'tools/easygui', 'tools/exceptions', 'intuition/intuition' + +-> The global for use with multiforall(). +DEF gh:PTR TO guihandle + +PROC main() HANDLE + DEF mh=NIL, gh1:PTR TO guihandle,res + mh:=multiinit() + gh1:=addmultiA(mh,'GUI One', + [ROWS, + [TEXT,'The first GUI.',NIL,TRUE,13], + [SBUTTON,{but1},'Press Me'] + ], + [EG_LEFT,10, EG_TOP,20, NIL]) + addmultiA(mh,'GUI Two', + [ROWS, + [TEXT,'And the second GUI.',NIL,TRUE,13], + [SBUTTON,{but2},'Press Me'] + ], + -> Put the second window below the first, but hidden. + [EG_LEFT,10, EG_TOP,gh1.wnd.topedge+gh1.wnd.height, + EG_HIDE,TRUE, NIL]) + -> Could add more... + res:=multiloop(mh) +EXCEPT DO + cleanmulti(mh) + report_exception() +ENDPROC + +-> Button on GUI one does something special. +PROC but1(info:PTR TO guihandle) + WriteF('Hit button on GUI One. Closing then opening.\n') + multiforall({gh},info.mh, + `IF gh.wnd THEN WriteF('Title="\s"\n',gh.wnd.title) BUT closewin(gh) ELSE 0) + WriteF('Sleeping a bit...\n') + Delay(100) + WriteF('Awake!\n') + -> This shows that gh.wnd is NIL when the window is closed. + multiforall({gh},info.mh, + `WriteF('Win=$\h\n',gh.wnd) BUT openwin(gh)) +ENDPROC + +PROC but2(i) IS WriteF('Hit button on GUI Two\n') diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testqual.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testqual.e new file mode 100644 index 0000000..cdffad9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/testqual.e @@ -0,0 +1,14 @@ +MODULE 'tools/easygui', 'devices/inputevent' + +PROC main() + easyguiA('Qualifier Test', + [SBUTTON,{buttonaction},'Press Me! (With/Without Shift)']) +ENDPROC + +PROC buttonaction(qual,data,info) + IF qual AND (IEQUALIFIER_LSHIFT OR IEQUALIFIER_RSHIFT) + PrintF('You were pressing a shift key when you clicked on me!\n') + ELSE + PrintF('Nope, no shift key this time...\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/ticker_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/ticker_test.e new file mode 100644 index 0000000..582cd02 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/ticker_test.e @@ -0,0 +1,19 @@ +MODULE 'tools/easygui', 'tools/exceptions', + 'plugins/ticker' + +PROC main() HANDLE + DEF t=NIL:PTR TO ticker + NEW t + easyguiA('Ticker!', + [ROWS, + [TEXT,'Ticker test:',NIL,TRUE,10], + [PLUGIN,{tickaction},t] + ]) +EXCEPT DO + END t + report_exception() +ENDPROC + +PROC tickaction(i,t) + WriteF('Tick!\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/toolify_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/toolify_test.e new file mode 100644 index 0000000..6a65304 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Examples/toolify_test.e @@ -0,0 +1,23 @@ +MODULE 'tools/exceptions', + 'tools/easygui', + 'plugins/toolify' + +PROC main() HANDLE + DEF p=NIL:PTR TO toolify + NEW p.toolify('Toolify','Hello from Toolify',TRUE) + easyguiA('GadTools in EasyGUI!', + [ROWS, + [TEXT,'Toolify test...',NIL,TRUE,1], + [SPACE], + [PLUGIN,0,p,TRUE], + [SPACE], + [BUTTON,{toggle_enabled},'Toggle Enabled',p] + ]) +EXCEPT DO + END p + report_exception() +ENDPROC + +PROC toggle_enabled(p:PTR TO toolify,i) + p.setdisabled(p.disabled=FALSE) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/animcontrol.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/animcontrol.e new file mode 100644 index 0000000..b7eed95 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/animcontrol.e @@ -0,0 +1,100 @@ +OPT MODULE, PREPROCESS + +MODULE 'tools/EasyGUI', 'tools/ghost', + 'intuition/intuition', 'intuition/gadgetclass', + 'gadgets/tapedeck' + +EXPORT OBJECT animcontrol OF plugin + frame + mode + disabled +PRIVATE + animcontrol:PTR TO gadget + animcontrolbase + frames + downmode +ENDOBJECT + +PROC animcontrol(frame=0,frames=8,play=FALSE,disabled=FALSE) OF animcontrol + self.animcontrolbase:=OpenLibrary('gadgets/tapedeck.gadget',39) + IF self.animcontrolbase=NIL THEN Raise("anim") + self.frame:=frame + self.frames:=frames + self.mode:=IF play THEN BUT_PLAY ELSE BUT_STOP + self.disabled:=disabled +ENDPROC + +PROC end() OF animcontrol + IF self.animcontrolbase THEN CloseLibrary(self.animcontrolbase) +ENDPROC + +PROC min_size(ta,fh) OF animcontrol +ENDPROC 203,15 + +PROC will_resize() OF animcontrol IS 0 + +PROC render(ta,x,y,xs,ys,w) OF animcontrol + self.animcontrol:=NewObjectA(NIL,'tapedeck.gadget', + [GA_TOP,y, GA_LEFT,x, GA_WIDTH,xs, GA_HEIGHT,ys, + TDECK_MODE,self.mode, TDECK_FRAMES,self.frames, + TDECK_CURRENTFRAME,self.frame, TDECK_TAPE,FALSE, + GA_DISABLED,self.disabled, + GA_RELVERIFY,TRUE, GA_IMMEDIATE,TRUE, NIL]) + IF self.animcontrol=NIL THEN Raise("anim") + AddGList(w,self.animcontrol,-1,1,NIL) + RefreshGList(self.animcontrol,w,NIL,1) + IF self.disabled THEN ghost(w,self.x,self.y,self.xs,self.ys) +ENDPROC + +PROC clear_render(win:PTR TO window) OF animcontrol + IF self.animcontrol + RemoveGList(win,self.animcontrol,1) + DisposeObject(self.animcontrol) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF animcontrol + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.animcontrol + IF imsg.class=IDCMP_GADGETDOWN THEN RETURN imsg.iaddress=self.animcontrol +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF animcontrol + DEF mode, frame + GetAttr(TDECK_MODE,self.animcontrol,{mode}) + GetAttr(TDECK_CURRENTFRAME,self.animcontrol,{frame}) + IF class=IDCMP_GADGETDOWN + self.downmode:=mode + IF mode=BUT_FRAME THEN mode:=BUT_STOP + self.mode:=mode + IF (mode<>BUT_REWIND) AND (mode<>BUT_FORWARD) THEN RETURN FALSE + ELSE + IF self.downmode=BUT_FRAME + mode:=BUT_STOP + self.downmode:=BUT_STOP + ENDIF + self.mode:=mode + ENDIF + self.frame:=frame +ENDPROC TRUE + +PROC setframe(n) OF animcontrol + self.frame:=n + SetGadgetAttrsA(self.animcontrol,self.gh.wnd,NIL,[TDECK_CURRENTFRAME,n,NIL]) + IF self.disabled THEN ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) +ENDPROC + +PROC setplay(play=TRUE) OF animcontrol + self.mode:=IF play THEN BUT_PLAY ELSE BUT_STOP + SetGadgetAttrsA(self.animcontrol,self.gh.wnd,NIL,[TDECK_MODE,self.mode,NIL]) + IF self.disabled THEN ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) +ENDPROC + +PROC setdisabled(disabled=TRUE) OF animcontrol + SetGadgetAttrsA(self.animcontrol,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + IF disabled + ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) + ELSE + unghost(self.animcontrol,self.gh.wnd) + ENDIF + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/button.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/button.e new file mode 100644 index 0000000..f277c07 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/button.e @@ -0,0 +1,92 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', 'tools/textlen', + 'intuition/intuition', 'intuition/gadgetclass', + 'gadgets/button' + +EXPORT OBJECT button OF plugin + selected + disabled +PRIVATE + button:PTR TO gadget + buttonbase + text + toggle, push, resize +ENDOBJECT + +PROC button(text,resizex=FALSE,resizey=FALSE,disabled=FALSE) OF button + self.buttonbase:=OpenLibrary('gadgets/button.gadget',37) + IF self.buttonbase=NIL THEN Raise("butt") + self.text:=text + self.toggle:=FALSE + self.push:=FALSE + self.selected:=FALSE + self.resize:=(IF resizex THEN RESIZEX ELSE 0) OR + (IF resizey THEN RESIZEY ELSE 0) + self.disabled:=disabled +ENDPROC + +PROC togglebutton(text,selected=FALSE,resizex=FALSE,resizey=FALSE,disabled=FALSE) OF button + self.button(text,resizex,resizey) + self.toggle:=TRUE + self.selected:=selected +ENDPROC + +PROC pushbutton(text,selected=FALSE,resizex=FALSE,resizey=FALSE,disabled=FALSE) OF button + self.button(text,resizex,resizey) + self.push:=TRUE + self.selected:=selected +ENDPROC + +PROC end() OF button + IF self.buttonbase THEN CloseLibrary(self.buttonbase) +ENDPROC + +PROC min_size(ta,fh) OF button +ENDPROC textlen(self.text,ta)+16,fh+6 + +PROC will_resize() OF button IS self.resize + +PROC render(ta,x,y,xs,ys,w) OF button + self.button:=NewObjectA(NIL,'button.gadget', + [GA_TOP,y, GA_LEFT,x, GA_WIDTH,xs, GA_HEIGHT,ys, + GA_TEXT,self.text, GA_TOGGLESELECT,self.toggle, + BUTTON_PUSHBUTTON,self.push, GA_TEXTATTR,ta, + GA_DISABLED,self.disabled, GA_SELECTED,self.selected, + GA_RELVERIFY,TRUE, NIL]) + IF self.button=NIL THEN Raise("butt") + AddGList(w,self.button,-1,1,NIL) + RefreshGList(self.button,w,NIL,1) +ENDPROC + +PROC clear_render(win:PTR TO window) OF button + IF self.button + RemoveGList(win,self.button,1) + DisposeObject(self.button) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF button + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.button +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF button + self.selected:=code +ENDPROC TRUE + +PROC setselected(selected=TRUE) OF button + IF self.toggle OR self.push + SetGadgetAttrsA(self.button,self.gh.wnd,NIL,[GA_SELECTED,selected,NIL]) + self.selected:=selected + ENDIF +ENDPROC + +PROC settext(text) OF button + SetGadgetAttrsA(self.button,self.gh.wnd,NIL,[GA_TEXT,text,NIL]) + self.text:=text +ENDPROC + +PROC setdisabled(disabled=TRUE) OF button + SetGadgetAttrsA(self.button,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/calendar.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/calendar.e new file mode 100644 index 0000000..7642634 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/calendar.e @@ -0,0 +1,68 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', 'tools/textlen', + 'intuition/intuition', 'intuition/gadgetclass', + 'gadgets/calendar', 'graphics/text', + 'utility/date' + +EXPORT OBJECT calendar OF plugin + date:PTR TO clockdata + disabled +PRIVATE + calendar:PTR TO gadget + calendarbase + resize +ENDOBJECT + +PROC calendar(date,resizex=FALSE,resizey=FALSE,disabled=FALSE) OF calendar + self.calendarbase:=OpenLibrary('gadgets/calendar.gadget',37) + IF self.calendarbase=NIL THEN Raise("cal") + self.date:=date + self.resize:=(IF resizex THEN RESIZEX ELSE 0) OR + (IF resizey THEN RESIZEY ELSE 0) + self.disabled:=disabled +ENDPROC + +PROC end() OF calendar + IF self.calendarbase THEN CloseLibrary(self.calendarbase) +ENDPROC + +PROC min_size(ta,fh) OF calendar IS textlen('Wed',ta)+2*7,fh*7+13 + +PROC will_resize() OF calendar IS self.resize + +PROC render(ta,x,y,xs,ys,w) OF calendar + self.calendar:=NewObjectA(NIL,'calendar.gadget', + [GA_TOP,y, GA_LEFT,x, GA_WIDTH,xs, GA_HEIGHT,ys, + GA_TEXTATTR,ta, GA_RELVERIFY,TRUE, + GA_DISABLED,self.disabled, + CALENDAR_CLOCKDATA,self.date, NIL]) + IF self.calendar=NIL THEN Raise("cal") + AddGList(w,self.calendar,-1,1,NIL) + RefreshGList(self.calendar,w,NIL,1) +ENDPROC + +PROC clear_render(win:PTR TO window) OF calendar + IF self.calendar + RemoveGList(win,self.calendar,1) + DisposeObject(self.calendar) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF calendar + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.calendar +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF calendar + self.date.mday:=code +ENDPROC TRUE + +PROC setdate(date=NIL) OF calendar + IF date THEN self.date:=date + SetGadgetAttrsA(self.calendar,self.gh.wnd,NIL,[CALENDAR_CLOCKDATA,self.date,NIL]) +ENDPROC + +PROC setdisabled(disabled=TRUE) OF calendar + SetGadgetAttrsA(self.calendar,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/colorwheel.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/colorwheel.e new file mode 100644 index 0000000..83327cd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/colorwheel.e @@ -0,0 +1,114 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', 'tools/ghost', + 'intuition/intuition', 'intuition/gadgetclass', 'intuition/screens', + 'gadgets/colorwheel' + +EXPORT OBJECT colorwheel OF plugin + rgb:PTR TO colorwheelrgb + hsb:PTR TO colorwheelhsb + disabled +PRIVATE + colorwheel:PTR TO gadget + colorwheelbase + box +ENDOBJECT + +PROC colorwheel(rgb,hsb=NIL,box=FALSE,disabled=FALSE) OF colorwheel + self.colorwheelbase:=OpenLibrary('gadgets/colorwheel.gadget',39) + IF self.colorwheelbase=NIL THEN Raise("colw") + IF rgb + self.rgb:=rgb + self.hsb:=NIL + ELSE + self.rgb:=NIL + self.hsb:=hsb + ENDIF + self.box:=box + self.disabled:=disabled +ENDPROC + +PROC end() OF colorwheel + IF self.colorwheelbase THEN CloseLibrary(self.colorwheelbase) +ENDPROC + +PROC min_size(ta,fh) OF colorwheel +ENDPROC 50,50 + +PROC will_resize() OF colorwheel IS RESIZEX OR RESIZEY + +PROC render(ta,x,y,xs,ys,w:PTR TO window) OF colorwheel + self.colorwheel:=NewObjectA(NIL,'colorwheel.gadget', + [GA_TOP,y+IF self.box THEN 0 ELSE 2, + GA_LEFT,x+IF self.box THEN 0 ELSE 2, + GA_WIDTH,xs-IF self.box THEN 0 ELSE 4, + GA_HEIGHT,ys-IF self.box THEN 0 ELSE 4, + IF self.hsb THEN WHEEL_HSB ELSE WHEEL_RGB, + IF self.hsb THEN self.hsb ELSE self.rgb, + GA_RELVERIFY,TRUE, WHEEL_SCREEN,w.wscreen, + WHEEL_BEVELBOX,self.box, GA_DISABLED,self.disabled, + NIL]) + IF self.colorwheel=NIL THEN Raise("colw") + AddGList(w,self.colorwheel,-1,1,NIL) + RefreshGList(self.colorwheel,w,NIL,1) + IF self.disabled THEN IF self.box=FALSE THEN ghost(w,self.x,self.y,self.xs,self.ys) +ENDPROC + +PROC clear_render(win:PTR TO window) OF colorwheel + IF self.colorwheel + RemoveGList(win,self.colorwheel,1) + DisposeObject(self.colorwheel) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF colorwheel + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.colorwheel +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF colorwheel + IF self.rgb + GetAttr(WHEEL_RGB,self.colorwheel,self.rgb) + ELSE + GetAttr(WHEEL_HSB,self.colorwheel,self.hsb) + ENDIF +ENDPROC TRUE + +PROC getrgb(rgb) OF colorwheel + GetAttr(WHEEL_RGB,self.colorwheel,rgb) +ENDPROC rgb + +PROC gethsb(hsb) OF colorwheel + GetAttr(WHEEL_HSB,self.colorwheel,hsb) +ENDPROC hsb + +PROC setrgb(rgb=NIL) OF colorwheel + IF rgb + self.rgb:=rgb + self.hsb:=NIL + ENDIF + IF self.rgb THEN SetGadgetAttrsA(self.colorwheel,self.gh.wnd,NIL, + [WHEEL_RGB,self.rgb,NIL]) +ENDPROC + +PROC sethsb(hsb) OF colorwheel + IF hsb + self.rgb:=NIL + self.hsb:=hsb + ENDIF + IF self.hsb THEN SetGadgetAttrsA(self.colorwheel,self.gh.wnd,NIL, + [WHEEL_HSB,self.hsb,NIL]) +ENDPROC + +PROC setdisabled(disabled=TRUE) OF colorwheel + SetGadgetAttrsA(self.colorwheel,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + IF disabled + IF self.box=FALSE + ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) + ELSE + unghost(self.colorwheel,self.gh.wnd) + ENDIF + ELSE + unghost_clear(self.colorwheel,self.gh.wnd,self.x,self.y,self.xs,self.ys) + ENDIF + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/gradient.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/gradient.e new file mode 100644 index 0000000..afb0214 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/gradient.e @@ -0,0 +1,86 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', 'tools/ghost', + 'intuition/gadgetclass', 'intuition/intuition', + 'gadgets/gradientslider' + +EXPORT OBJECT gradient OF plugin + curval + pens:PTR TO INT + disabled +PRIVATE + grad:PTR TO gadget + gradbase + vert + rel +ENDOBJECT + +PROC gradient(vert=FALSE,curval=0,rel=5,pens=NIL,disabled=FALSE) OF gradient + self.gradbase:=OpenLibrary('gadgets/gradientslider.gadget',39) + IF self.gradbase=NIL THEN Raise("grad") + self.curval:=curval + self.vert:=vert + self.rel:=rel + self.pens:=pens + self.disabled:=disabled +ENDPROC + +PROC end() OF gradient + IF self.gradbase THEN CloseLibrary(self.gradbase) +ENDPROC + +PROC min_size(ta,fh) OF gradient IS + IF self.vert THEN (fh+6) ELSE (fh*self.rel), + IF self.vert THEN (fh*self.rel) ELSE (fh+6) + +PROC will_resize() OF gradient IS IF self.vert THEN RESIZEY ELSE RESIZEX + +PROC render(ta,x,y,xs,ys,w) OF gradient + self.grad:=NewObjectA(NIL,'gradientslider.gadget', + [GA_TOP,y, GA_LEFT,x, GA_WIDTH,xs, GA_HEIGHT,ys, + GRAD_CURVAL,self.curval, GRAD_PENARRAY,self.pens, + PGA_FREEDOM,IF self.vert THEN LORIENT_VERT ELSE LORIENT_HORIZ, + GA_RELVERIFY,TRUE, GA_DISABLED,self.disabled, NIL]) + IF self.grad=NIL THEN Raise("grad") + AddGList(w,self.grad,-1,1,NIL) + RefreshGList(self.grad,w,NIL,1) + IF self.disabled THEN ghost(w,self.x,self.y,self.xs,self.ys) +ENDPROC + +PROC clear_render(win:PTR TO window) OF gradient + IF self.grad + RemoveGList(win,self.grad,1) + DisposeObject(self.grad) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF gradient + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.grad +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF gradient + DEF val=0 + GetAttr(GRAD_CURVAL,self.grad,{val}) + self.curval:=val +ENDPROC TRUE + +PROC setcurval(x) OF gradient + self.curval:=x + SetGadgetAttrsA(self.grad,self.gh.wnd,NIL,[GRAD_CURVAL,x,NIL]) +ENDPROC + +PROC setpens(pens=NIL) OF gradient + IF pens THEN self.pens:=pens + self.clear_render(self.gh.wnd) + self.render(NIL,self.x,self.y,self.xs,self.ys,self.gh.wnd) +ENDPROC + +PROC setdisabled(disabled=TRUE) OF gradient + SetGadgetAttrsA(self.grad,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + IF disabled + ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) + ELSE + unghost(self.grad,self.gh.wnd) + ENDIF + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/iconify.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/iconify.e new file mode 100644 index 0000000..b71f669 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/iconify.e @@ -0,0 +1,94 @@ +OPT MODULE, PREPROCESS + +MODULE 'intuition/intuition', 'intuition/gadgetclass', + 'libraries/gadtools', + 'tools/textlen', + 'tools/EasyGUI', + 'workbench/startup', 'workbench/workbench', + 'gadtools', 'icon', 'wb' + +RAISE "icfy" IF AddAppIconA()=NIL, + "icfy" IF OpenLibrary()=NIL, + "icfy" IF CreateMsgPort()=NIL + +DEF iconbase -> Redefine for privateness + +-> Share gadtoolbase and workbenchbase with EasyGUI... + +#define DEFICON 'env:sys/def_tool' + +EXPORT OBJECT iconify OF plugin + disabled +PRIVATE + iconify:PTR TO gadget + iconopen + label, icon, iconlabel + resize +ENDOBJECT + +PROC iconify(label,icon=NIL,iconlabel=NIL, + resizex=FALSE,resizey=FALSE,disabled=FALSE) OF iconify + iconbase:=OpenLibrary('icon.library',37) + self.iconopen:=TRUE + self.label:=IF label THEN label ELSE '' + self.icon:=IF icon THEN icon ELSE DEFICON + self.iconlabel:=IF iconlabel THEN iconlabel ELSE self.label + self.disabled:=disabled + self.resize:=(IF resizex THEN RESIZEX ELSE 0) OR + (IF resizey THEN RESIZEY ELSE 0) +ENDPROC + +PROC end() OF iconify + IF self.iconopen + CloseLibrary(iconbase) + self.iconopen:=FALSE + ENDIF +ENDPROC + +PROC min_size(ta,fh) OF iconify IS textlen(self.label,ta)+16,fh+6 + +PROC will_resize() OF iconify IS self.resize + +-> Don't need to define this: +->PROC render(ta,x,y,xs,ys,w) OF iconify IS EMPTY + +PROC gtrender(gl,vis,ta,x,y,xs,ys,w) OF iconify + -> Or, a gadget in the title bar would have also been nice... + self.iconify:=CreateGadgetA(BUTTON_KIND,gl, + [x,y,xs,ys,self.label,ta,0, + PLACETEXT_IN,vis,NIL]:newgadget, [NIL]) + IF self.iconify=NIL THEN Raise("icfy") +ENDPROC self.iconify + +-> Don't need to define this: +-> PROC clear_render(win:PTR TO window) OF iconify IS EMPTY + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF iconify + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.iconify +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF iconify HANDLE + DEF dobj=NIL:PTR TO diskobject, myport=NIL, appicon=NIL, + appmsg:PTR TO appmessage + closewin(self.gh) + -> Fallback to using a default icon if not found... + IF NIL=(dobj:=GetDiskObjectNew(self.icon)) THEN dobj:=GetDiskObjectNew(DEFICON) + dobj.type:=NIL + myport:=CreateMsgPort() + appicon:=AddAppIconA(0,0,self.iconlabel,myport,NIL,dobj,NIL) + WaitPort(myport) +EXCEPT DO + IF appicon THEN RemoveAppIcon(appicon) + IF myport + -> Clear away any messages that arrived at the last moment + WHILE appmsg:=GetMsg(myport) DO ReplyMsg(appmsg) + DeleteMsgPort(myport) + ENDIF + IF dobj THEN FreeDiskObject(dobj) + openwin(self.gh) +ENDPROC FALSE + +PROC setdisabled(disabled=TRUE) OF iconify + Gt_SetGadgetAttrsA(self.iconify,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/imagebutton.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/imagebutton.e new file mode 100644 index 0000000..b630ac3 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/imagebutton.e @@ -0,0 +1,101 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', + 'graphics/rastport', + 'intuition/intuition', 'intuition/gadgetclass', + 'gadgets/button' + +EXPORT OBJECT imagebutton OF plugin + selected + disabled +PRIVATE + button:PTR TO gadget + buttonbase + image:PTR TO image + toggle, push, resize + width, height +ENDOBJECT + +PROC imagebutton(image:PTR TO image,width=0,height=0,resizex=FALSE, + resizey=FALSE,disabled=FALSE) OF imagebutton + self.buttonbase:=OpenLibrary('gadgets/button.gadget',37) + IF self.buttonbase=NIL THEN Raise("butt") + self.image:=image + self.toggle:=FALSE + self.push:=FALSE + self.selected:=FALSE + self.resize:=(IF resizex THEN RESIZEX ELSE 0) OR + (IF resizey THEN RESIZEY ELSE 0) + self.disabled:=disabled + self.width:=Max(width,image.width) + self.height:=Max(height,image.height) +ENDPROC + +PROC toggleimagebutton(image,width=0,height=0,selected=FALSE,resizex=FALSE, + resizey=FALSE,disabled=FALSE) OF imagebutton + self.imagebutton(image,width,height,resizex,resizey) + self.toggle:=TRUE + self.selected:=selected +ENDPROC + +PROC pushimagebutton(image,width=0,height=0,selected=FALSE,resizex=FALSE, + resizey=FALSE,disabled=FALSE) OF imagebutton + self.imagebutton(image,width,height,resizex,resizey) + self.push:=TRUE + self.selected:=selected +ENDPROC + +PROC end() OF imagebutton + IF self.buttonbase THEN CloseLibrary(self.buttonbase) +ENDPROC + +PROC min_size(ta,fh) OF imagebutton +ENDPROC self.width+4, self.height+2 + +PROC will_resize() OF imagebutton IS self.resize + +PROC render(ta,x,y,xs,ys,w:PTR TO window) OF imagebutton + self.button:=NewObjectA(NIL,'button.gadget', + [GA_TOP,y, GA_LEFT,x, GA_WIDTH,xs, GA_HEIGHT,ys, + GA_IMAGE,self.image, GA_TOGGLESELECT,self.toggle, + BUTTON_PUSHBUTTON,self.push, + GA_DISABLED,self.disabled, GA_SELECTED,self.selected, + GA_RELVERIFY,TRUE, BUTTON_FILLPEN,w.rport.bgpen, NIL]) + IF self.button=NIL THEN Raise("butt") + AddGList(w,self.button,-1,1,NIL) + RefreshGList(self.button,w,NIL,1) +ENDPROC + +PROC clear_render(win:PTR TO window) OF imagebutton + IF self.button + RemoveGList(win,self.button,1) + DisposeObject(self.button) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win) OF imagebutton + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.button +ENDPROC FALSE + +PROC message_action(class,qual,code,win) OF imagebutton + self.selected:=code +ENDPROC TRUE + +PROC setselected(selected=TRUE) OF imagebutton + IF self.toggle OR self.push + SetGadgetAttrsA(self.button,self.gh.wnd,NIL,[GA_SELECTED,selected,NIL]) + self.selected:=selected + ENDIF +ENDPROC + +PROC setimage(image:PTR TO image) OF imagebutton + IF (image.width<=self.width) AND (image.height<=self.height) + SetGadgetAttrsA(self.button,self.gh.wnd,NIL,[GA_IMAGE,image,NIL]) + self.image:=image + ENDIF +ENDPROC + +PROC setdisabled(disabled=TRUE) OF imagebutton + SetGadgetAttrsA(self.button,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/led.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/led.e new file mode 100644 index 0000000..2224d00 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/led.e @@ -0,0 +1,52 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', 'graphics/rastport', + 'intuition/intuition', 'intuition/imageclass', + 'images/led', 'utility/tagitem' + +EXPORT OBJECT led OF plugin + pairs + values:PTR TO INT + colon + signed + negative + pen +PRIVATE + ledbase +ENDOBJECT + +PROC led(pairs=2,values=NIL,colon=FALSE,signed=FALSE,negative=FALSE,pen=1) OF led + self.ledbase:=OpenLibrary('images/led.image',37) + IF self.ledbase=NIL THEN Raise("led") + self.pairs:=pairs + self.values:=values + self.colon:=colon + self.signed:=signed + self.negative:=negative + self.pen:=pen +ENDPROC + +PROC end() OF led + IF self.ledbase THEN CloseLibrary(self.ledbase) +ENDPROC + +PROC min_size(ta,fh) OF led +ENDPROC self.pairs*19-IF self.signed THEN 0 ELSE 5,12 + +PROC will_resize() OF led IS RESIZEX OR RESIZEY + +PROC render(ta,x,y,xs,ys,w:PTR TO window) OF led + DEF led + IF (led:=NewObjectA(NIL,'led.image', + [IA_FGPEN,self.pen, IA_WIDTH,xs-1, IA_HEIGHT,ys, + IF self.values THEN LED_VALUES ELSE TAG_IGNORE,self.values, + LED_PAIRS,self.pairs, LED_COLON,self.colon, + LED_SIGNED,self.signed, LED_NEGATIVE,self.negative, + NIL]))=NIL THEN Raise("led") + DrawImage(w.rport,led,x,y) + DisposeObject(led) +ENDPROC + +PROC redisplay() OF led + IF self.gh.wnd THEN self.render(NIL,self.x,self.y,self.xs,self.ys,self.gh.wnd) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/password.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/password.e new file mode 100644 index 0000000..10504cd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/password.e @@ -0,0 +1,132 @@ +OPT MODULE, PREPROCESS + +MODULE 'intuition/intuition', 'intuition/sghooks', 'intuition/gadgetclass', + 'gadtools', + 'libraries/gadtools', + 'tools/textlen', 'tools/inithook', + 'utility/hooks', + 'tools/EasyGUI' + +RAISE "MEM" IF String()=NIL + +CONST NUM_EOS=EO_SPECIAL+1 + +-> Share gadtoolsbase with EasyGUI + +EXPORT OBJECT password OF plugin + estr + disabled +PRIVATE + password:PTR TO gadget + label + over + relx + mid + hook:hook +ENDOBJECT + +PROC password(estr,label=NIL,over=FALSE,relx=0,disabled=FALSE) OF password + self.estr:=estr + self.label:=IF label THEN label ELSE '' + self.over:=over + self.relx:=IF relx THEN relx ELSE 5 + self.disabled:=disabled + inithook(self.hook,{passHookCode},estr) +ENDPROC + +PROC end() OF password IS EMPTY + +PROC min_size(ta,fh) OF password + self.mid:=textlen(self.label,ta)+8 +ENDPROC self.relx*fh+self.mid, fh+6 + +PROC will_resize() OF password IS RESIZEX + +-> Don't need to define this: +->PROC render(ta,x,y,xs,ys,w) OF password IS EMPTY + +PROC gtrender(gl,vis,ta,x,y,xs,ys,w) OF password HANDLE + DEF len, pass=NIL + pass:=makePass(self.estr) + len:=textlen(self.label,ta) + self.password:=CreateGadgetA(STRING_KIND,gl, + [x+self.mid,y,xs-self.mid,ys,self.label,ta,0, + PLACETEXT_LEFT,vis,NIL]:newgadget, + [GTST_STRING,pass, GTST_EDITHOOK,self.hook, + GTST_MAXCHARS,StrMax(self.estr), GA_DISABLED,self.disabled, + STRINGA_REPLACEMODE,self.over, NIL]) + IF self.password=NIL THEN Raise("pass") +EXCEPT DO + DisposeLink(pass) + ReThrow() +ENDPROC self.password + +-> Don't need to define this: +-> PROC clear_render(win:PTR TO window) OF password IS EMPTY + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF password + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.password +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF password +ENDPROC TRUE + +PROC setpass(str) OF password HANDLE + DEF pass=NIL + pass:=makePass(str) + Gt_SetGadgetAttrsA(self.password,self.gh.wnd,NIL,[GTST_STRING,pass,NIL]) + StrCopy(self.estr,str) +EXCEPT DO + DisposeLink(pass) +ENDPROC + +PROC setdisabled(disabled=TRUE) OF password + Gt_SetGadgetAttrsA(self.password,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + self.disabled:=disabled +ENDPROC + +PROC makePass(s) + DEF len, p=NIL + IF s + IF len:=StrLen(s) + SetStr(p:=String(len),len) + WHILE len DO p[len--]:="*" + ENDIF + ENDIF +ENDPROC p + +PROC passHookCode(hook:PTR TO hook, sgw:PTR TO sgwork, msg:PTR TO LONG) + DEF realBuff:PTR TO CHAR, bp + IF msg[]=SGH_KEY + realBuff:=hook.data + bp:=sgw.bufferpos + SELECT NUM_EOS OF sgw.editop + CASE EO_DELBACKWARD + IF bp<>sgw.numchars + sgw.actions:=(sgw.actions OR SGA_BEEP) AND Not(SGA_USE) + ELSE + SetStr(realBuff, bp) + ENDIF + CASE EO_REPLACECHAR + realBuff[bp--]:=sgw.code + sgw.workbuffer[bp]:="*" + CASE EO_INSERTCHAR + IF bp<>sgw.numchars + sgw.actions:=(sgw.actions OR SGA_BEEP) AND Not(SGA_USE) + ELSE + SetStr(realBuff, bp) + realBuff[bp--]:=sgw.code + sgw.workbuffer[bp]:="*" + ENDIF + CASE EO_NOOP, EO_MOVECURSOR, EO_ENTER, EO_BADFORMAT + -> Safely ignore + DEFAULT + -> EO_DELFORWARD, EO_BIGCHANGE, EO_RESET, EO_UNDO, EO_CLEAR, EO_SPECIAL + -> Disallow + sgw.actions:=(sgw.actions OR SGA_BEEP) AND Not(SGA_USE) + ENDSELECT + RETURN -1 + ENDIF + -> UNKNOWN COMMAND + -> Hook should return zero if the command is not supported +ENDPROC 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tabs.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tabs.e new file mode 100644 index 0000000..4d042dd --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tabs.e @@ -0,0 +1,89 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', 'tools/ghost', 'tools/textlen', + 'intuition/intuition', 'intuition/gadgetclass', + 'gadgets/tabs' + +EXPORT OBJECT tabs OF plugin + current + disabled +PRIVATE + tabs:PTR TO gadget + tabsbase + tabslist + max +ENDOBJECT + +PROC tabs(tabslist,current=0,max=TRUE,disabled=FALSE) OF tabs + self.tabsbase:=OpenLibrary('gadgets/tabs.gadget',37) + IF self.tabsbase=NIL THEN Raise("tabs") + self.tabslist:=tabslist + self.current:=current + self.max:=max + self.disabled:=disabled +ENDPROC + +PROC end() OF tabs + IF self.tabsbase THEN CloseLibrary(self.tabsbase) +ENDPROC + +PROC min_size(ta,fh) OF tabs + DEF p:PTR TO tablabel, w=0, n=0 + p:=self.tabslist + IF self.max + WHILE p.label + w:=Max(w,textlen(p.label,ta)) + n++ + p++ + ENDWHILE + w:=w*n + ELSE + WHILE p.label + w:=w+textlen(p.label,ta) + n++ + p++ + ENDWHILE + ENDIF +ENDPROC n*20+w+7,fh+5 + +PROC will_resize() OF tabs IS COND_RESIZEX + +PROC render(ta,x,y,xs,ys,w) OF tabs + self.tabs:=NewObjectA(NIL,'tabs.gadget', + [GA_TOP,y, GA_LEFT,x, GA_WIDTH,xs-1, GA_HEIGHT,ys, + GA_TEXTATTR,ta, GA_RELVERIFY,TRUE, + TABS_CURRENT,self.current, TABS_LABELS,self.tabslist, + LAYOUTA_CHILDMAXWIDTH,self.max, + GA_DISABLED,self.disabled, NIL]) + IF self.tabs=NIL THEN Raise("tabs") + AddGList(w,self.tabs,-1,1,NIL) + RefreshGList(self.tabs,w,NIL,1) +ENDPROC + +PROC clear_render(win:PTR TO window) OF tabs + IF self.tabs + RemoveGList(win,self.tabs,1) + DisposeObject(self.tabs) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF tabs + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.tabs +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF tabs + self.current:=code +ENDPROC TRUE + +PROC setcurrent(x) OF tabs + self.current:=x + SetGadgetAttrsA(self.tabs,self.gh.wnd,NIL,[TABS_CURRENT,x,NIL]) +ENDPROC + +PROC setdisabled(disabled=TRUE) OF tabs + SetGadgetAttrsA(self.tabs,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + self.disabled:=disabled + IF disabled=FALSE + unghost_clear(self.tabs,self.gh.wnd,self.x,self.y,self.xs,self.ys) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tapedeck.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tapedeck.e new file mode 100644 index 0000000..b4ea1f5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/tapedeck.e @@ -0,0 +1,87 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', 'tools/ghost', + 'intuition/intuition', 'intuition/gadgetclass', + 'gadgets/tapedeck' + +EXPORT OBJECT tapedeck OF plugin + mode + paused + disabled +PRIVATE + tapedeck:PTR TO gadget + tapedeckbase +ENDOBJECT + +PROC tapedeck(mode=BUT_STOP,paused=FALSE,disabled=FALSE) OF tapedeck + self.tapedeckbase:=OpenLibrary('gadgets/tapedeck.gadget',39) + IF self.tapedeckbase=NIL THEN Raise("tape") + self.mode:=mode + self.paused:=paused + self.disabled:=disabled +ENDPROC + +PROC end() OF tapedeck + IF self.tapedeckbase THEN CloseLibrary(self.tapedeckbase) +ENDPROC + +PROC min_size(ta,fh) OF tapedeck +ENDPROC 201,15 + +PROC will_resize() OF tapedeck IS 0 + +PROC render(ta,x,y,xs,ys,w) OF tapedeck + self.tapedeck:=NewObjectA(NIL,'tapedeck.gadget', + [GA_TOP,y, GA_LEFT,x, GA_WIDTH,xs, GA_HEIGHT,ys, + TDECK_MODE,self.mode, TDECK_PAUSED,self.paused, + TDECK_TAPE,TRUE, GA_DISABLED,self.disabled, + GA_RELVERIFY,TRUE, NIL]) + IF self.tapedeck=NIL THEN Raise("tape") + AddGList(w,self.tapedeck,-1,1,NIL) + RefreshGList(self.tapedeck,w,NIL,1) + IF self.disabled THEN ghost(w,self.x,self.y,self.xs,self.ys) +ENDPROC + +PROC clear_render(win:PTR TO window) OF tapedeck + IF self.tapedeck + RemoveGList(win,self.tapedeck,1) + DisposeObject(self.tapedeck) + ENDIF +ENDPROC + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF tapedeck + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.tapedeck +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF tapedeck + DEF x + GetAttr(TDECK_MODE,self.tapedeck,{x}) + self.mode:=x + GetAttr(TDECK_PAUSED,self.tapedeck,{x}) + self.paused:=IF x THEN TRUE ELSE FALSE +ENDPROC TRUE + +PROC setmode(mode=BUT_STOP) OF tapedeck + self.mode:=mode + IF mode=BUT_PAUSE THEN self.paused:=self.paused=FALSE + SetGadgetAttrsA(self.tapedeck,self.gh.wnd,NIL,[TDECK_MODE,mode,NIL]) + IF self.disabled THEN ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) +ENDPROC + +PROC setpaused(paused=TRUE) OF tapedeck + IF self.paused<>paused + SetGadgetAttrsA(self.tapedeck,self.gh.wnd,NIL,[TDECK_MODE,BUT_PAUSE,NIL]) + IF self.disabled THEN ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) + ENDIF + self.paused:=paused +ENDPROC + +PROC setdisabled(disabled=TRUE) OF tapedeck + SetGadgetAttrsA(self.tapedeck,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + IF disabled + ghost(self.gh.wnd,self.x,self.y,self.xs,self.ys) + ELSE + unghost_clear(self.tapedeck,self.gh.wnd,self.x,self.y,self.xs,self.ys) + ENDIF + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/ticker.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/ticker.e new file mode 100644 index 0000000..54e4880 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/ticker.e @@ -0,0 +1,18 @@ +OPT MODULE + +MODULE 'tools/EasyGUI', + 'intuition/intuition' + +EXPORT OBJECT ticker OF plugin +ENDOBJECT + +PROC min_size(ta,fh) OF ticker IS 0,0 + +PROC will_resize() OF ticker IS FALSE + +PROC render(ta,x,y,xs,ys,w:PTR TO window) OF ticker IS EMPTY + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF ticker +ENDPROC imsg.class=IDCMP_INTUITICKS + +PROC message_action(class,qual,code,win) OF ticker IS TRUE diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/toolify.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/toolify.e new file mode 100644 index 0000000..13fe83e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Plugins/toolify.e @@ -0,0 +1,75 @@ +OPT MODULE, PREPROCESS + +MODULE 'intuition/intuition', 'intuition/gadgetclass', + 'libraries/gadtools', + 'tools/textlen', + 'tools/EasyGUI', + 'workbench/startup', 'workbench/workbench', + 'gadtools', 'wb' + +RAISE "tlfy" IF AddAppMenuItemA()=NIL, + "tlfy" IF CreateMsgPort()=NIL + +-> Share gadtoolsbase and workbenchbase with EasyGUI + +EXPORT OBJECT toolify OF plugin + disabled +PRIVATE + toolify:PTR TO gadget + label, toollabel + resize +ENDOBJECT + +PROC toolify(label,toollabel=NIL, + resizex=FALSE,resizey=FALSE,disabled=FALSE) OF toolify + self.label:=IF label THEN label ELSE '' + self.toollabel:=IF toollabel THEN toollabel ELSE self.label + self.disabled:=disabled + self.resize:=(IF resizex THEN RESIZEX ELSE 0) OR + (IF resizey THEN RESIZEY ELSE 0) +ENDPROC + +PROC end() OF toolify IS EMPTY + +PROC min_size(ta,fh) OF toolify IS textlen(self.label,ta)+16,fh+6 + +PROC will_resize() OF toolify IS self.resize + +-> Don't need to define this: +->PROC render(ta,x,y,xs,ys,w) OF toolify IS EMPTY + +PROC gtrender(gl,vis,ta,x,y,xs,ys,w) OF toolify + -> Or, a gadget in the title bar would have also been nice... + self.toolify:=CreateGadgetA(BUTTON_KIND,gl, + [x,y,xs,ys,self.label,ta,0, + PLACETEXT_IN,vis,NIL]:newgadget, [NIL]) + IF self.toolify=NIL THEN Raise("tlfy") +ENDPROC self.toolify + +-> Don't need to define this: +-> PROC clear_render(win:PTR TO window) OF toolify IS EMPTY + +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF toolify + IF imsg.class=IDCMP_GADGETUP THEN RETURN imsg.iaddress=self.toolify +ENDPROC FALSE + +PROC message_action(class,qual,code,win:PTR TO window) OF toolify HANDLE + DEF myport=NIL, appitem=NIL, appmsg:PTR TO appmessage + closewin(self.gh) + myport:=CreateMsgPort() + appitem:=AddAppMenuItemA(0,0,self.toollabel,myport,NIL) + WaitPort(myport) +EXCEPT DO + IF appitem THEN RemoveAppMenuItem(appitem) + IF myport + -> Clear away any messages that arrived at the last moment + WHILE appmsg:=GetMsg(myport) DO ReplyMsg(appmsg) + DeleteMsgPort(myport) + ENDIF + openwin(self.gh) +ENDPROC FALSE + +PROC setdisabled(disabled=TRUE) OF toolify + Gt_SetGadgetAttrsA(self.toolify,self.gh.wnd,NIL,[GA_DISABLED,disabled,NIL]) + self.disabled:=disabled +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/README b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/README new file mode 100644 index 0000000..28e1279 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/README @@ -0,0 +1,83 @@ +Short: EasyGUI v3.3b.3 (multiple windows!) +Type: dev/e +Author: jason@fsel.com (Jason R. Hulance) + +New v3.3b.3 EasyGUI package +=========================== + +(v3.3b.3 is a minor update that fixes a bug with AppWindow messages +that crept in under the guise of a safety feature in v3.3b...) + +Re-read Docs/EasyGUI.doc! + +For the impatient, here is the big news: + +- MAJOR CHANGE: made the main functions use a taglist for their optional + arguments (it was getting a bit ridiculous...). This gives a bit more + flexibility for the programmer and makes for much more readable code, so + I'm afraid it was inevitable. To ease the change-over a bit there is an + example module which gives the old style versions of the functions (just + for EasyGUI.m; you can do your own for EasyGUI_lite.m). +- MAJOR ADDITION: support for multi-window GUIs. This is via the + multiinit(), addmultiA(), multimessage(), cleanmulti() and checkmulti() + functions. The new scheme shares message ports, and efficiently + dispatches on the message data. This is *massively* more efficient than + using the old scheme (OR-ing the signal masks of each window), and + effectively removes the limit of windows that a GUI can use. + + +Installing the modules +---------------------- +Copy the files from the sub-directories of the Modules directory to the +same place in your emodules: directory. Note: there are some updates to +the typed modules of the v3.2a distribution included. + +Installing the .gadget and .image files +--------------------------------------- +Copy the .gadget and .image files from the sub-directories of the Classes +directory to the same place in your sys:classes directory (or at least, +somewhere so that libs:gadgets/x.gadget and libs:images/x.image find the +appropriate files). + +PLUGINS +------- +There are now lots of examples of PLUGINs with full source code and some +documentation. Hopefully this will provoke some more interest in this +area... Also, there is a simplified way of using GadTools gadgets as +PLUGINs, via gtrender(). + +Test files +---------- +There are several test files showing how to use the new features and new +PLUGINs (in Src/EasyGUI/). + +Feedback +-------- +Please let me have some... + +Copyright +--------- + +The .gadget and .image files are: + + Copyright (c) 1994 Commodore-Amiga, Inc. + +and discussed further in Classes/GI1.Readme and Classes/GI1.License. + +EasyGUI.m, EasyGUI_lite.m and alldist.e are: + + Copyright (c) 1994-6, Wouter van Oortmerssen and Jason R. Hulance. + +All other files in this archive are: + + Copyright (c) 1996, Jason R. Hulance. + +You are free to use these files in your own programs, and you may modify +the souces supplied for your own purposes. But it would be nice if you +mention the wonderful Wouter and his amazing Amiga E every now and then... + + +Well, have fun! + + +Jason (jason@fsel.com) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/EasyGUI.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/EasyGUI.e new file mode 100644 index 0000000..0881a36 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/EasyGUI.e @@ -0,0 +1,2008 @@ +-> EasyGui.m, constructs fast nononsense font sensitive resizable gui's. + +OPT MODULE, OSVERSION=37, PREPROCESS + +-> Let only one of the following be defined: + +->#define EASYGUI_LITE +#define EASYGUI_FULL +->#define EASYGUI_DEBUG + + +-> This selects various components based on above choice. +#ifndef EASYGUI_LITE +#define EASY_KEYBOARD +#ifdef EASYGUI_DEBUG +#ifndef EASYGUI_FULL +#define EASYGUI_FULL +#endif +#endif +#ifdef EASYGUI_FULL +#define EASY_APPWINDOW +#define EASY_EXTRAS +#endif +#endif + +-> This enables a descriptive message before an exception is raised. +#ifdef EASYGUI_DEBUG +#define RaiseX(x,l,s) myraise(x,l,s) +MODULE 'tools/exceptions' +#endif +#ifndef EASYGUI_DEBUG +#define RaiseX(x,l,s) Raise(x) +#endif + +MODULE 'gadtools', + 'exec/libraries', 'exec/lists', 'exec/nodes', 'exec/ports', + 'graphics/rastport', 'graphics/text', + 'graphics/gfx', 'graphics/videocontrol', 'graphics/view', + 'intuition/gadgetclass', 'intuition/imageclass', 'intuition/intuition', + 'intuition/screens', + 'libraries/gadtools', + 'tools/textlen', 'amigalib/lists', + 'utility/tagitem', + 'utility' + +#ifdef EASY_APPWINDOW +MODULE 'wb', 'workbench/workbench' +#endif + +#ifdef EASY_KEYBOARD +MODULE 'tools/ctype' +#endif + +DEF utilitybase -> Redefine for privateness + +#ifdef EASY_EXTRAS +/************ multihandle ************/ +EXPORT OBJECT multihandle + sig + opencount +PRIVATE +#ifdef EASY_APPWINDOW + awport:PTR TO mp +#endif + wndport:PTR TO mp + guis:lh +ENDOBJECT +#endif + +-> The offset of the `link' node in a guihandle. Used for getting +-> back to the guihandle from the node in the list. +CONST GH_LINK_OFFSET=16 + +/************ guihandle ************/ +EXPORT OBJECT guihandle + -> Window, Signal Mask (not Bit), Info + wnd:PTR TO window,sig,info +#ifdef EASY_EXTRAS + -> Multi-Window Handle + mh:PTR TO multihandle +#endif +PRIVATE +#ifdef EASY_EXTRAS + -> Node for Linking GUIs in Multi-Window GUIs + link:ln +#endif + -> Private Window Pointer (so that wnd is a flag for GUI validity, too) + pwnd:PTR TO window + -> Last Gadget, VisualInfo, Font, Font_uses_screen, GT_lib_is_open + gl:PTR TO gadget,visual,tattr:PTR TO textattr,ta_scr,gt_isopen + -> Gadget desc, Gadget list, Screen, Screen_is_WB + base:PTR TO g,glist,scr:PTR TO screen,is_wb + -> Min Width and Height, X and Y Offset Past Window Borders + xsize,ysize,xoff,yoff + -> Menus, Plugins + menus, plugins:PTR TO plugin +#ifndef EASY_KEYBOARD + -> First String Gadget + firststr +#endif +#ifdef EASY_KEYBOARD + -> Map of Key to Gadget + keys[26]:ARRAY OF LONG +#endif +#ifdef EASY_APPWINDOW + -> AppWindow Port, AppWindow, WB_lib_is_open + awport:PTR TO mp,appwin,wb_isopen +#endif +#ifdef EASY_EXTRAS + -> Requester used for Blocking + req:PTR TO requester +#endif + -> GUI X and Y, GUI Desc, Window Title, Menu Desc + x,y,gui,wtitle,awproc,newmenus + -> Window Port, OnClose Proc, Window Type, OnClean Proc + wndport:PTR TO mp,onclose,wtype,onclean + -> Hack to make menu selections safe + menuitem:PTR TO LONG +#ifdef EASY_EXTRAS + -> Count of blockwin() calls + blockcnt +#endif +ENDOBJECT + +-> Flag set for resizing constants. +SET CRSZ_X, CRSZ_Y, UNCOND_X, UNCOND_Y + +EXPORT CONST COND_RESIZEX=CRSZ_X, COND_RESIZEY=CRSZ_Y +EXPORT CONST RESIZEX=COND_RESIZEX OR UNCOND_X, RESIZEY=COND_RESIZEY OR UNCOND_Y + +CONST RESIZEXANDY=RESIZEX OR RESIZEY + +-> Resize testing macros. +#define DoesXResize(flag) ((flag) AND COND_RESIZEX) +#define DoesYResize(flag) ((flag) AND COND_RESIZEY) +#define DoesXUncond(flag) ((flag) AND RESIZEX=RESIZEX) +#define DoesYUncond(flag) ((flag) AND RESIZEY=RESIZEY) + +-> Gadget type constants. +-> 0 1 2 3 4 5 +EXPORT ENUM ROWS,EQROWS,COLS,EQCOLS,BEVEL,BEVELR, +-> 6 7 8 9 10 11 12 13 14 15 16 17 + BUTTON,CHECK,INTEGER,LISTV,MX,CYCLE,PALETTE,SCROLL,SLIDE,STR,TEXT,NUM, +-> 18 19 20 21 22 23 24 25 + SBUTTON,PLUGIN,BAR,SPACEH,SPACE,SPACEV,RBUTTON,MAXGUI + +-> ROWS... BUTTON... PALETTE... SBUTTON... RBUTTON... +-> Mapping of gadget type to GT KIND. +#define KINDTAB \ + [0,0,0,0,0,0, 1,2,3,4,5,7,8,9,11,12,13,6, 1, 0, 0,0,0,0, 1,12]:CHAR +-> Mapping of gadget type to number of required arguments. +#define MINARGS \ + [2,2,2,2,2,2, 3,5,5,9,6,4,7,7, 9, 6, 5,5, 3, 3, 1,1,1,1, 3,6]:CHAR + +-> Constants to index gadget desc lists. +EXPORT ENUM BEV_GUI=1, + BUT_ACT=1, BUT_TXT, BUT_DATA, BUT_KEY, BUT_APPW, BUT_DIS, + CHK_ACT=1, CHK_TXT, CHK_VAL, CHK_LEFT, CHK_DATA, CHK_KEY, CHK_DIS, + INT_ACT=1, INT_TXT, INT_VAL, INT_REL, INT_DATA, INT_KEY, INT_DIS, + LST_ACT=1, LST_TXT, LST_RELX, LST_RELY, LST_LIST, LST_RO, LST_SHOW, + LST_CURR, LST_DATA, LST_KEY, LST_APPW, LST_DIS, + MX_ACT=1, MX_TXT, MX_LIST, MX_LEFT, MX_CURR, MX_DATA, MX_KEY, + MX_DIS, + CYC_ACT=1, CYC_TXT, CYC_LIST, CYC_CURR, CYC_DATA, CYC_KEY, CYC_DIS, + PAL_ACT=1, PAL_TXT, PAL_DEP, PAL_RELX, PAL_RELY, PAL_CURR, PAL_DATA, + PAL_KEY, PAL_DIS, + SCR_ACT=1, SCR_VERT, SCR_TOTL, SCR_TOP, SCR_VIS, SCR_REL, SCR_DATA, + SCR_KEY, SCR_DIS, + SLI_ACT=1, SLI_TXT, SLI_VERT, SLI_MIN, SLI_MAX, SLI_CURR, SLI_REL, + SLI_FMT, SLI_DATA, SLI_KEY, SLI_DIS, + STR_ACT=1, STR_TXT, STR_STR, STR_MAX, STR_REL, STR_OVR, STR_DATA, + STR_KEY, STR_APPW, STR_DIS, + TXT_VAL=1, TXT_TXT, TXT_BORD, TXT_REL, + NUM_VAL=1, NUM_TXT, NUM_BORD, NUM_REL, + PLG_ACT=1, PLG_OBJ, PLG_GT, PLG_APPW + +ENUM EG_TYPE=0, EG_ACT, EG_TXT + +-> Test group type macros. +#define IsRow(type) ((type)<=EQROWS) +#define IsCol(type) ((type)>EQROWS) +#define IsRowOrCol(type) ((type) Test space sizing macros. +#define HasHSpace(type) ((type)<=SPACE) +#define HasVSpace(type) ((type)>=SPACE) +#define HSpace(type) (IF HasHSpace(type) THEN RESIZEX ELSE 0) +#define VSpace(type) (IF HasVSpace(type) THEN RESIZEY ELSE 0) +#define SpaceFlags(type) (HSpace(type) OR VSpace(type)) + +-> Test button sizing macros. +#define HasHButtSp(type) ((type)>=SBUTTON) +#define HasVButtSp(type) ((type)=RBUTTON) +#define HButtSp(type) (IF HasHButtSp(type) THEN RESIZEX ELSE 0) +#define VButtSp(type) (IF HasVButtSp(type) THEN RESIZEY ELSE 0) +#define ButtSpFlags(type) (HButtSp(type) OR VButtSp(type)) + +CONST SP=2,YSP=3 -> very basic spacing (Y=nonsense!?!) +CONST XSPACING=YSP,YSPACING=SP, -> basic spacing between gadgets + SIDESPACE=YSP,TOPSPACE=SP, -> spacing to window border + BUTXSPACE=16,BUTYSPACE=6, -> space around text in button (min) + BEVELXSPACE=4,BEVELYSPACE=3, -> between bevelbox and inner gadgets + MXSPACE=2,CHECKSPACE=2 -> between two mx and check gads + +EXPORT ENUM WTYPE_NOBORDER, WTYPE_BASIC, WTYPE_NOSIZE, WTYPE_SIZE + +-> Window flags. +CONST WIN_FBASIC=WFLG_ACTIVATE OR WFLG_NEWLOOKMENUS +CONST WIN_FNOBORD=WFLG_BORDERLESS OR WIN_FBASIC +CONST WIN_FNOSIZE=WIN_FBASIC OR WFLG_DRAGBAR OR WFLG_DEPTHGADGET OR + WFLG_CLOSEGADGET +CONST WIN_FSIZE=WIN_FNOSIZE OR WFLG_SIZEBBOTTOM OR WFLG_SIZEGADGET + +-> Gadget click IDCMP. +CONST GAD_IDCMP=IDCMP_GADGETDOWN OR IDCMP_GADGETUP OR IDCMP_MOUSEMOVE + +-> Window IDMCP (without NEWSIZE). +CONST WIN_IDCMP_NS=GAD_IDCMP OR IDCMP_REFRESHWINDOW OR IDCMP_MOUSEBUTTONS OR + IDCMP_MENUPICK OR IDCMP_CLOSEWINDOW OR IDCMP_RAWKEY OR + IDCMP_ACTIVEWINDOW OR IDCMP_INACTIVEWINDOW OR + IDCMP_INTUITICKS OR IDCMP_CHANGEWINDOW OR IDCMP_VANILLAKEY + +-> Window IDMCP (with NEWSIZE). +CONST WIN_IDCMP=IDCMP_NEWSIZE OR WIN_IDCMP_NS + +-> Message loop constants. +CONST GUI_CONT=-1, GUI_QUIT=0 + +-> Action function test macro. +#define IsActionFun(ret) (((ret)<0) OR ((ret)>1000)) + +-> Convert to unsigned INT. +#define Unsigned(x) ((x) AND $FFFF) + +-> System gadget aspect ratio macro. +#define SysISize(flags) \ + (IF (flags) AND SCREENHIRES THEN SYSISIZE_MEDRES ELSE SYSISIZE_LOWRES) + +-> Gadget information extraction macros. +#define GadLongInt(gad) (gad.specialinfo::stringinfo.longint) +#define GadString(gad) (gad.specialinfo::stringinfo.buffer) +#define IsChecked(gad) ((gad.flags AND GFLG_SELECTED)<>0) + +-> Constant to mark gadget has no mid-point. +CONST NO_MID=-1 + +-> Gadget data (intermediate level). +OBJECT g + -> Link, X, Y, Width, Height + next,x,y,xs,ys + -> Gadget Type, Gadget Desc, Flags, Mid-Point + type,list:PTR TO LONG,flags,mid +ENDOBJECT + +/************ plugin ************/ +EXPORT OBJECT plugin PRIVATE + -> Gadget Data, Link + base:PTR TO g, next:PTR TO plugin +PUBLIC + -> X, Y, Width, Height + x:INT,y:INT,xs:INT,ys:INT + -> guihandle + gh:PTR TO guihandle +ENDOBJECT + +PROC min_size(ta,fontheight) OF plugin IS fontheight,fontheight +PROC will_resize() OF plugin IS RESIZEXANDY +PROC message_test(imsg:PTR TO intuimessage,win:PTR TO window) OF plugin IS FALSE +PROC message_action(class,qual,code,win:PTR TO window) OF plugin IS FALSE +PROC clear_render(win:PTR TO window) OF plugin IS EMPTY + +PROC render(ta:PTR TO textattr,x,y,xs,ys,win:PTR TO window) OF plugin + fillbox(win.rport,1,x,y,x+xs-1,y+ys-1) +ENDPROC + +PROC appmessage(amsg,win:PTR TO window) OF plugin IS FALSE +PROC gtrender(gl,vis,ta,x,y,xs,ys,win) OF plugin IS gl +/************ plugin end ************/ + +-> Magic idenitifier for AppWindow gadgets. +CONST EG_MAGIC=$EA51EA51 + +-> Tag list constants +CONST EG_TAGBASE=TAG_USER+$4000 + +EXPORT ENUM EG_TITLE=EG_TAGBASE, EG_GUI, EG_INFO, EG_SCRN, EG_FONT, EG_MENU, + EG_GHVAR, EG_AWPROC, EG_LEFT, EG_TOP, EG_MAXW, EG_MAXH, EG_WTYPE, + EG_CLOSE, EG_CLEAN, EG_HIDE + +-> Gadget list attribute selection. +#define ATTR(gui,n) gui[(n)] +#define HasATTR(list,n) (ListLen((list))>n) +#define OptATTR(list,n) optattr(list,n) +#define OptDefATTR(list,n) optdefattr(list,n) + +PROC optattr(list:PTR TO LONG,n) IS IF HasATTR(list,n) THEN ATTR(list,n) ELSE 0 + +PROC optdefattr(list:PTR TO LONG,n) + DEF res=-1 + IF HasATTR(list,n) THEN res:=ATTR(list,n) +ENDPROC IF res<>-1 THEN res ELSE list + +PROC indexdata(type) + DEF index, but=FALSE, val=0 + SELECT MAXGUI OF type + CASE BUTTON,SBUTTON,RBUTTON; index:=BUT_DATA; but:=TRUE + CASE CHECK; index:=CHK_DATA; val:=CHK_VAL + CASE LISTV; index:=LST_DATA + CASE MX; index:= MX_DATA + CASE STR; index:=STR_DATA; val:=STR_STR + CASE INTEGER; index:=INT_DATA; val:=INT_VAL + CASE CYCLE; index:=CYC_DATA + CASE PALETTE; index:=PAL_DATA + CASE SCROLL; index:=SCR_DATA + CASE SLIDE; index:=SLI_DATA + ENDSELECT +ENDPROC index, but, val + +#ifndef EASY_KEYBOARD +#ifndef EASY_EXTRAS +#define EASY_NOKEYBEXTRA +#endif +#endif + +#ifndef EASY_NOKEYBEXTRA +-> Optional value based on index. +PROC optindex(i:PTR TO LONG,index) IS IF index THEN OptATTR(i,index) ELSE 0 +#endif + +#ifdef EASY_KEYBOARD +#define optkey(t,i) optindex(i,indexkey(t)) +PROC indexkey(type) + DEF index + SELECT MAXGUI OF type + CASE BUTTON,SBUTTON,RBUTTON; index:=BUT_KEY + CASE CHECK; index:=CHK_KEY + CASE LISTV; index:=LST_KEY + CASE MX; index:= MX_KEY + CASE STR; index:=STR_KEY + CASE INTEGER; index:=INT_KEY + CASE CYCLE; index:=CYC_KEY + CASE PALETTE; index:=PAL_KEY + CASE SCROLL; index:=SCR_KEY + CASE SLIDE; index:=SLI_KEY + ENDSELECT +ENDPROC index +#endif + +#ifndef EASY_EXTRAS +#define optdis(t,i) 0 +#endif +#ifdef EASY_EXTRAS +#define optdis(t,i) optindex(i,indexdis(t)) +PROC indexdis(type) + DEF index=0 + SELECT MAXGUI OF type + CASE BUTTON,SBUTTON,RBUTTON; index:=BUT_DIS + CASE CHECK; index:=CHK_DIS + CASE LISTV; index:=LST_DIS + CASE MX; index:= MX_DIS + CASE STR; index:=STR_DIS + CASE INTEGER; index:=INT_DIS + CASE CYCLE; index:=CYC_DIS + CASE PALETTE; index:=PAL_DIS + CASE SCROLL; index:=SCR_DIS + CASE SLIDE; index:=SLI_DIS + ENDSELECT +ENDPROC index + +/********** setdisabled **********/ +EXPORT PROC setdisabled(gh,gad:PTR TO LONG,disabled=TRUE) + DEF index + index:=indexdis(ATTR(gad,EG_TYPE)) + IF HasATTR(gad,index) THEN setattr(gh,gad,disabled,GA_DISABLED,index) +ENDPROC +#endif + +-> Clear window contents and redraw frame. +PROC clearwindow(w:PTR TO window) + fillbox(w.rport,0,w.borderleft,w.bordertop, + w.width-w.borderright-1, w.height-w.borderbottom-1) + RefreshWindowFrame(w) +ENDPROC + +PROC fillbox(rport,pen,x,y,x2,y2) + SetAPen(rport,pen) + RectFill(rport,x,y,x2,y2) +ENDPROC + +-> Create new gadget data. +PROC newg(xs,ys,type,list,flags=0,mid=NO_MID) IS NEW [0,0,0,xs,ys,type,list,flags,mid]:g + +-> Access functions for gadget type mapping lists. +PROC minARGS() IS MINARGS +PROC kindTAB() IS KINDTAB + +#ifdef EASYGUI_DEBUG +-> In debug version this will be called instead of raising an exception. +PROC myraise(x,l,s) + exception:=x; exceptioninfo:=0 + WriteF('Just about to raise exception:\n') + report_exception() + IF (l>0) AND (l<2000) + WriteF(' Error ref \d: \s\n',l,s) + ELSE + WriteF(' \s (Gadget list $\h)\n',s,l) + ENDIF + Raise(x) +ENDPROC +#endif + +/********** easyguiA() **********/ +EXPORT PROC easyguiA(title,gui,tags=NIL) HANDLE + DEF gh=NIL:PTR TO guihandle,res=-1 + gh:=guiinitA(title,gui,tags) + WHILE res<0 + Wait(gh.sig) + res:=guimessage(gh) + ENDWHILE +EXCEPT DO + cleangui(gh) + ReThrow() +ENDPROC res + +/********** easygui_fallbackA() **********/ +EXPORT PROC easygui_fallbackA(title,gui,tags=NIL) HANDLE + RETURN easyguiA(title,gui,tags) +EXCEPT + IF exception="bigg" + RETURN easyguiA(title,gui,[EG_FONT,['topaz.font',8,0,0]:textattr, + TAG_MORE,tags]) + ENDIF + ReThrow() +ENDPROC + +-> Init font. +PROC initfont(gh:PTR TO guihandle,tattr) + gh.tattr:=tattr + gh.ta_scr:=(tattr=NIL) +ENDPROC + +-> Init screen. +PROC initscr(gh:PTR TO guihandle,scr) + gh.scr:=scr + gh.is_wb:=(scr=NIL) +ENDPROC + +-> Set up menus. +PROC setmenus(gh:PTR TO guihandle) + -> setup menus + IF gh.newmenus + gh.menus:=CreateMenusA(gh.newmenus,NIL) + IF gh.menus=NIL THEN RaiseX("GUI",431,'Could not create menus. Bad menu description? Or out of memory?') + IF LayoutMenusA(gh.menus,gh.visual,[GTMN_NEWLOOKMENUS,TRUE,NIL])=FALSE THEN RaiseX("GUI",432,'Could not layout menus. Out of memory?') + IF SetMenuStrip(gh.pwnd,gh.menus)=FALSE THEN RaiseX("GUI",433,'Could not set menu strip. Should never happen!') + ENDIF +ENDPROC + +PROC win_off(n,s:PTR TO screen) + DEF y + IF n=WTYPE_NOBORDER THEN RETURN 1,1 + y:=s.wbortop+TOPSPACE + IF n>WTYPE_BASIC THEN y:=y+s.rastport.txheight+1 +ENDPROC s.wborleft+SIDESPACE,y + +PROC win_pad(n,s:PTR TO screen) + DEF y=TOPSPACE + IF n=WTYPE_NOBORDER THEN RETURN 1,1 + y:=y+IF n=WTYPE_SIZE THEN getrealbot(s) ELSE s.wborbottom +ENDPROC s.wborright+SIDESPACE,y + +-> Set up GUI. +PROC setgui(gh:PTR TO guihandle) + DEF base:PTR TO g,s:PTR TO screen,w:PTR TO window,xsize,ysize, + cm,h=NIL:PTR TO LONG,vpe=NIL:PTR TO viewportextra,x,y + s:=gh.scr + w:=gh.pwnd + + -> Get gadget data and calculate minimum GUI size. + gh.base:=base:=minsize(gh.gui,gh) + IF w=NIL + -> Calculate offset of borders in window. + x,y:=win_off(gh.wtype,s) + gh.xoff:=x + gh.yoff:=y + ENDIF + -> Calculate minimum width and height of window. + x,y:=win_pad(gh.wtype,s) + xsize:=x+gh.xoff+base.xs + ysize:=y+gh.yoff+base.ys + + IF (xsize>s.width) OR (ysize>s.height) THEN RaiseX("bigg",455,'Size is too big for the screen.') + +#ifdef EASY_EXTRAS + -> If window open then adjust sizing. + IF w + -> Calculate X size and pos delta if needed. + cm:=IF (w.width>=xsize) AND DoesXResize(base.flags) THEN w.width ELSE xsize + x:=IF cm+w.leftedge>s.width THEN s.width-cm ELSE w.leftedge + -> Calculate Y size and pos delta if needed. + h:=IF (w.height>=ysize) AND DoesYResize(base.flags) THEN w.height ELSE ysize + y:=IF h+w.topedge>s.height THEN s.height-h ELSE w.topedge + -> Disallow window sizing. + ModifyIDCMP(w, WIN_IDCMP_NS) + -> Temporarily allow window to grow as large and small as possible. + WindowLimits(w,8,8,-1,-1) + -> Move and size window. + ChangeWindowBox(w,x,y,cm,h) + -> Set window to proper limits. + setwinlimits(w,xsize,ysize, + IF DoesXResize(base.flags) THEN -1 ELSE xsize, + IF DoesYResize(base.flags) THEN -1 ELSE ysize) + -> Remove mess. + clearwindow(w) + -> Allow resizing (maybe) again. + ModifyIDCMP(w, WIN_IDCMP) + ELSE +#endif + -> Window not open so create it. + -> get visual infos + gh.visual:=GetVisualInfoA(gh.scr,NIL) + IF gh.visual=NIL THEN RaiseX("GUI",482,'Could not get visual info. Out of memory?') + + -> calc window position (centre of visible part of screen) + h:=VTAG_VIEWPORTEXTRA_GET -> Ack! VideoControl changes tag! + IF IF cm:=s.viewport.colormap THEN VideoControl(cm, h:=[h,NIL,NIL]) BUT vpe:=h[1] ELSE vpe:=NIL + x:=Min(vpe.displayclip.maxx-vpe.displayclip.minx+1,s.width)-xsize/2-s.viewport.dxoffset + y:=Min(vpe.displayclip.maxy-vpe.displayclip.miny+1,s.height)-ysize/2-s.viewport.dyoffset + ELSE + x:=s.width-xsize/2 + y:=s.height-ysize/2 + ENDIF + w:=s.width + h:=s.height + -> If position stored use that, else centred. And adjust max size. + IF gh.x<>-1 + x:=gh.x + -> Offset the maximum + w:=Bounds(w-x,xsize,w) + ENDIF + IF gh.y<>-1 + y:=gh.y + h:=Bounds(h-y,ysize,h) + ENDIF + -> Use minimum or stored size (default is maximum). + IF gh.xsize=0 + w:=xsize + ELSEIF DoesXResize(base.flags)=FALSE + w:=xsize + ELSEIF gh.xsize<>-1 + w:=Bounds(gh.xsize,xsize,s.width) + ENDIF + IF gh.ysize=0 + h:=ysize + ELSEIF DoesYResize(base.flags)=FALSE + h:=ysize + ELSEIF gh.ysize<>-1 + h:=Bounds(gh.ysize,ysize,s.height) + ENDIF + + -> open the window + gh.pwnd:=w:=OpenWindowTagList(NIL, + [WA_LEFT, Bounds(x,0,s.width-w), + WA_TOP, Bounds(y,0,s.height-h), + WA_WIDTH, w, + WA_HEIGHT, h, + WA_IDCMP, 0, -> Was WIN_IDCMP: now ports are shared. + WA_FLAGS, ListItem([WIN_FNOBORD,WIN_FBASIC, + WIN_FNOSIZE,WIN_FSIZE], gh.wtype), + WA_TITLE, IF gh.wtype>WTYPE_BASIC THEN gh.wtitle ELSE NIL, + WA_CUSTOMSCREEN, gh.scr, + WA_MINWIDTH, xsize, + WA_MINHEIGHT, ysize, + WA_MAXWIDTH, IF DoesXResize(base.flags) THEN -1 ELSE xsize, + WA_MAXHEIGHT, IF DoesYResize(base.flags) THEN -1 ELSE ysize, + ->WA_AUTOADJUST,1, + NIL]) + IF w=NIL THEN RaiseX("GUI",537,'Could not open window. Too many layers?') + w.userdata:=gh + -> Set up window IDCMP port. + w.userport:=gh.wndport + ModifyIDCMP(w,WIN_IDCMP) + +#ifdef EASY_APPWINDOW + IF gh.awproc THEN gh.appwin:=AddAppWindowA(gh,gh.awproc,gh.pwnd,gh.awport,NIL) +#endif + stdrast:=w.rport +#ifdef EASY_EXTRAS + ENDIF +#endif + -> Remember minimum window size. + gh.xsize:=xsize + gh.ysize:=ysize + -> Now render the gadgets. + gh.glist:=rendergui(gh) +ENDPROC + +/********** guiinitA() **********/ +#ifdef EASY_EXTRAS +EXPORT PROC guiinitA(title,gui,tags=NIL) IS addmultiA(NIL,title,gui,tags) +#endif +#ifndef EASY_EXTRAS +EXPORT PROC guiinitA(title,gui,tags=NIL) HANDLE + DEF gh=NIL:PTR TO guihandle + gh:=makehandle(title,gui,NIL,tags) +EXCEPT + -> Stop the user cleanup in this case. + gh.onclean:=NIL + cleangui(gh) + ReThrow() +ENDPROC gh +#endif + +PROC openlibrary(s) + DEF lib + IF (lib:=OpenLibrary(s,37))=NIL THEN RaiseX("LIB",613,s) +ENDPROC lib + +-> Make a handle and initialise from the tags. +PROC makehandle(title,gui,mh,tags) HANDLE + DEF gh=NIL:PTR TO guihandle, temp:PTR TO LONG, isopen=FALSE + NEW gh + utilitybase:=openlibrary('utility.library') + isopen:=TRUE + IF temp:=GetTagData(EG_GHVAR,NIL,tags) THEN temp[]:=gh + gh.wtype:=GetTagData(EG_WTYPE,WTYPE_SIZE,tags) + gh.wtitle:=title + gh.gui:=gui + gh.info:=IF -1<>(temp:=GetTagData(EG_INFO,-1,tags)) THEN temp ELSE gh + initscr(gh,GetTagData(EG_SCRN,NIL,tags)) + initfont(gh,GetTagData(EG_FONT,NIL,tags)) + gh.newmenus:=GetTagData(EG_MENU,NIL,tags) + gh.awproc:=GetTagData(EG_AWPROC,NIL,tags) + gh.x:=GetTagData(EG_LEFT,-1,tags) + gh.y:=GetTagData(EG_TOP,-1,tags) + gh.onclose:=GetTagData(EG_CLOSE,NIL,tags) + gh.onclean:=GetTagData(EG_CLEAN,NIL,tags) + IF GetTagData(EG_MAXW,FALSE,tags) THEN gh.xsize:=-1 + IF GetTagData(EG_MAXH,FALSE,tags) THEN gh.ysize:=-1 +#ifdef EASY_EXTRAS + gh.mh:=mh +#endif + setinit(gh) +EXCEPT DO + IF exception + END gh + ReThrow() + ELSE + IF GetTagData(EG_HIDE,FALSE,tags)=FALSE THEN openwin(gh) + ENDIF + IF isopen THEN CloseLibrary(utilitybase) +ENDPROC gh + +-> Initialisation stuff. +PROC setinit(gh:PTR TO guihandle) HANDLE + -> Open library safely. + gadtoolsbase:=openlibrary('gadtools.library') + gh.gt_isopen:=TRUE +#ifdef EASY_EXTRAS + -> Window IDCMP port. + IF gh.mh + -> If multi-window then share port. + gh.wndport:=gh.mh.wndport + -> Also, share the *complete* signal mask. + -> (This ensures that guimessage() works...) + gh.sig:=gh.mh.sig + ELSE +#endif + gh.wndport:=makeport() + gh.sig:=Shl(1,gh.wndport.sigbit) +#ifdef EASY_EXTRAS + ENDIF +#endif +#ifdef EASY_APPWINDOW + -> Open library safely. + workbenchbase:=openlibrary('workbench.library') + gh.wb_isopen:=TRUE +#ifdef EASY_EXTRAS + -> AppWindow port + IF gh.mh + -> If multi-window then share port (even if no awproc) + -> (This ensures that guimessage() works...) + gh.awport:=gh.mh.awport + ELSEIF gh.awproc +#endif +#ifndef EASY_EXTRAS + IF gh.awproc +#endif + gh.awport:=makeport() + gh.sig:=gh.sig OR Shl(1,gh.awport.sigbit) + ELSE + gh.awport:=NIL + ENDIF +#endif +EXCEPT + cleaninit(gh) + ReThrow() +ENDPROC + +/********** openwin() **********/ +EXPORT PROC openwin(gh:PTR TO guihandle) + IF gh.pwnd=NIL + -> Set up screen. + IF gh.is_wb + IF gh.scr=NIL THEN gh.scr:=LockPubScreen(NIL) + IF gh.scr=NIL THEN RaiseX("GUI",417,'Could not lock default public screen (Workbench?). Is it open?') + ENDIF + -> Set up font. + IF gh.ta_scr THEN gh.tattr:=gh.scr.font + -> Set up window and GUI. + setgui(gh) + -> Set up menus. + setmenus(gh) +#ifdef EASY_EXTRAS + -> If multi then bump count of open windows. + IF gh.mh THEN gh.mh.opencount:=gh.mh.opencount+1 +#endif + ENDIF +ENDPROC gh + +#ifdef EASY_EXTRAS +/********** changescreen() **********/ +EXPORT PROC changescreen(gh:PTR TO guihandle,scr=NIL) + IF gh.wnd=NIL THEN initscr(gh,scr) +ENDPROC + +/********** changefont() **********/ +EXPORT PROC changefont(gh:PTR TO guihandle,tattr=NIL) + IF gh.wnd=NIL THEN initfont(gh,tattr) +ENDPROC + +/********** changewintype() **********/ +EXPORT PROC changewintype(gh:PTR TO guihandle,wintype=WTYPE_SIZE) + IF gh.wnd=NIL THEN gh.wtype:=wintype +ENDPROC + +/********** changeinfo() **********/ +EXPORT PROC changeinfo(gh:PTR TO guihandle,info=-1) + gh.info:=IF info<>-1 THEN info ELSE gh +ENDPROC + +/********** changetitle() **********/ +EXPORT PROC changetitle(gh:PTR TO guihandle,windowtitle=NIL) + IF gh.wnd + IF (windowtitle=NIL) OR (gh.wtype>WTYPE_BASIC) + SetWindowTitles(gh.wnd, windowtitle, -1) + ENDIF + ENDIF + gh.wtitle:=windowtitle +ENDPROC + +/********** changemenus() **********/ +EXPORT PROC changemenus(gh:PTR TO guihandle,newmenus=NIL) HANDLE + IF gh.wnd THEN removemenus(gh) + gh.newmenus:=newmenus + IF gh.wnd THEN setmenus(gh) +EXCEPT + removemenus(gh) + ReThrow() +ENDPROC + +/********** changegui() **********/ +EXPORT PROC changegui(gh:PTR TO guihandle,gui) + IF gui + IF gh.pwnd THEN removegui(gh) + gh.gui:=gui + IF gh.pwnd THEN setgui(gh) + ENDIF +ENDPROC + +/********** movewin() **********/ +EXPORT PROC movewin(gh:PTR TO guihandle,x=-1,y=-1) + DEF w:PTR TO window + IF w:=gh.wnd + MoveWindow(w, IF x=-1 THEN 0 ELSE (x-w.leftedge), + IF y=-1 THEN 0 ELSE (y-w.topedge)) + ENDIF +ENDPROC + +/********** sizewin() **********/ +EXPORT PROC sizewin(gh:PTR TO guihandle,xs=-1,ys=-1) + DEF w:PTR TO window + IF w:=gh.wnd + SizeWindow(w, IF xs=-1 THEN 0 ELSE (xs-w.width), + IF ys=-1 THEN 0 ELSE (ys-w.height)) + ENDIF +ENDPROC + +-> Try setting window limits a few times. +PROC setwinlimits(w,minx,miny,maxx,maxy) + DEF i + FOR i:=0 TO 3 + EXIT WindowLimits(w,minx,miny,maxx,maxy) + Delay(1) + ENDFOR +ENDPROC + +/********** blockwin() **********/ +EXPORT PROC blockwin(gh:PTR TO guihandle) + DEF lib:PTR TO lib,c,w:PTR TO window + gh.blockcnt:=(c:=gh.blockcnt)+1 + IF c=0 + -> Only works if window open and not already blocked. + IF (w:=gh.wnd) AND (gh.req=NIL) + -> Only allow window refresh messages. + ModifyIDCMP(w, IDCMP_REFRESHWINDOW) + -> Stop window sizing. + setwinlimits(w,w.width,w.height,w.width,w.height) + NEW gh.req + -> Block window with requester. + InitRequester(gh.req) + Request(gh.req, w) + lib:=intuitionbase + IF lib.version>=39 THEN SetWindowPointerA(w,[WA_BUSYPOINTER,TRUE, + WA_POINTERDELAY,TRUE,NIL]) + ENDIF + ENDIF +ENDPROC + +/********** unblockwin() **********/ +EXPORT PROC unblockwin(gh:PTR TO guihandle) + DEF lib:PTR TO lib,c,w:PTR TO window + IF (c:=gh.blockcnt)>0 + gh.blockcnt:=c-1 + IF c=1 + -> Only works if window open and blocked. + IF (w:=gh.wnd) AND (gh.req<>NIL) + -> Remove requester. + EndRequest(gh.req, w) + -> Reset window limits. + setwinlimits(w,gh.xsize,gh.ysize, + IF DoesXResize(gh.base.flags) THEN -1 ELSE gh.xsize, + IF DoesYResize(gh.base.flags) THEN -1 ELSE gh.ysize) + -> Reset IDCMP. + ModifyIDCMP(w, WIN_IDCMP) + END gh.req + lib:=intuitionbase + IF lib.version>=39 THEN SetWindowPointerA(w,[WA_BUSYPOINTER,FALSE,NIL]) + ENDIF + ENDIF + ENDIF +ENDPROC +#endif + +#ifdef EASY_APPWINDOW +-> Handle AppWindow messages. +PROC appwmessage(port) HANDLE + DEF ret,data,list:PTR TO LONG,amsg=NIL:PTR TO appmessage,gh:PTR TO guihandle, + pl:PTR TO plugin + IF port + WHILE amsg:=GetMsg(port) + -> Get guihandle from message ID. + gh:=amsg.id + -> See if any PLUGIN wants it. + pl:=gh.plugins + WHILE pl + IF OptATTR(pl.base.list,PLG_APPW)=NIL THEN JUMP plugin_appw_skip + EXIT pl.appmessage(amsg,gh.pwnd) +plugin_appw_skip: + pl:=pl.next + ENDWHILE + ret:=NIL + data:=NIL + -> Get awproc (in ret) and data. + IF pl + ret:=OptATTR(pl.base.list,PLG_APPW) + data:=pl + ELSE + IF list:=findxy(gh,amsg.mousex,amsg.mousey) + SELECT MAXGUI OF ATTR(list,EG_TYPE) + CASE BUTTON, SBUTTON, RBUTTON + ret:=OptATTR(list,BUT_APPW) + data:=OptDefATTR(list,BUT_DATA) + CASE LISTV + ret:=OptATTR(list,LST_APPW) + data:=OptDefATTR(list,LST_DATA) + CASE STR + ret:=OptATTR(list,STR_APPW) + data:=OptDefATTR(list,STR_DATA) + ENDSELECT + ENDIF + ENDIF + -> If no gadget awproc then use window one. + IF ret=NIL + ret:=amsg.userdata + data:=NIL + ENDIF + -> Call the awproc. + IF ret THEN ret(data,gh.info,amsg) + -> Now we can reply to the message. + ReplyMsg(amsg) + amsg:=NIL + ENDWHILE + ENDIF +EXCEPT + -> Still need to reply if exception happened at a bad point + IF amsg THEN ReplyMsg(amsg) + ReThrow() +ENDPROC +#endif + +-> Handle menu messages. +PROC menumessage(gh:PTR TO guihandle,code) HANDLE + DEF ret=GUI_CONT,menunum,item:PTR TO menuitem + menunum:=Unsigned(code) + -> Stop if the window's gone away. + WHILE (menunum<>MENUNULL) AND gh.pwnd + item:=ItemAddress(gh.menus,menunum) + -> Get action value/function. + ret:=GTMENUITEM_USERDATA(item) + -> Stop if action value. + EXIT IsActionFun(ret)=FALSE + gh.menuitem:={item} + -> Call action function. + ret(NIL,NIL,gh.info) + ret:=GUI_CONT + EXIT item=NIL + menunum:=Unsigned(item.nextselect) + ENDWHILE +EXCEPT DO + gh.menuitem:=NIL + ReThrow() +ENDPROC ret + +-> Handle GadTools/window messages. +PROC gtmessage(port) HANDLE + DEF ret=GUI_CONT,mes=NIL:PTR TO intuimessage,type,gh:PTR TO guihandle, + gs:PTR TO gadget,list:PTR TO LONG,code,pl:PTR TO plugin,qual + WHILE mes:=Gt_GetIMsg(port) + -> Get guihandle from window userdata. + gh:=mes.idcmpwindow.userdata + -> See if any PLUGIN wants it. + pl:=gh.plugins + WHILE pl + EXIT pl.message_test(mes,gh.pwnd) + pl:=pl.next + ENDWHILE + -> Copy important bits of the message. + type:=mes.class + code:=mes.code + gs:=mes.iaddress + qual:=Unsigned(mes.qualifier) + -> Now we can reply to the message. + Gt_ReplyIMsg(mes) + mes:=NIL + IF pl + -> Call the PLUGIN's action function if necessary. + IF pl.message_action(type,qual,code,gh.pwnd) + ret:=ATTR(pl.base.list,PLG_ACT) + IF IsActionFun(ret) + ret(gh.info,pl) + ret:=GUI_CONT + ENDIF + ENDIF + ELSE + -> Gadget click. + IF type AND GAD_IDCMP +->WriteF('type=$\h, code=$\h, gad=$\h\n', type, code, gs) + -> Protect from stray IDCMP_MOUSEMOVE. + IF gs AND (gs<>gh.pwnd) + -> Get gadget description list. + list:=gs.userdata + -> Set new attribute. + performset(gs,code,list) + -> Get action value/function. + ret:=ATTR(list,EG_ACT) + IF IsActionFun(ret) + performaction(ret,gs,gh.info,code,list,qual) + ret:=GUI_CONT + ENDIF + ENDIF +#ifdef EASY_KEYBOARD + -> Key press. + ELSEIF type=IDCMP_VANILLAKEY + ret:=performkey(gh,code) +#endif + -> Window refresh. + ELSEIF type=IDCMP_REFRESHWINDOW + Gt_BeginRefresh(gh.pwnd) + Gt_EndRefresh(gh.pwnd,TRUE) + -> Window size change. + ELSEIF type=IDCMP_NEWSIZE + -> Remove the gadgets, clear and recreate. + removegads(gh) + clearwindow(gh.pwnd) + gh.glist:=rendergui(gh) + -> Close gadget click. + ELSEIF type=IDCMP_CLOSEWINDOW + -> Find action value/function. + ret:=gh.onclose + IF IsActionFun(ret) +#ifdef EASY_EXTRAS + ret(gh.mh,gh.info) +#endif +#ifndef EASY_EXTRAS + ret(NIL,gh.info) +#endif + ret:=GUI_CONT + ENDIF + -> Menu choice(s). + ELSEIF type=IDCMP_MENUPICK + ret:=menumessage(gh,code) + ENDIF + ENDIF + EXIT ret<>GUI_CONT + ENDWHILE +#ifdef EASY_EXTRAS + IF ret<>GUI_CONT THEN IF gh.mh THEN cleangui(gh) +#endif +EXCEPT + -> Still need to reply if exception happened in PLUGIN message_test(). + IF mes THEN Gt_ReplyIMsg(mes) + ReThrow() +ENDPROC ret + +#ifdef EASY_EXTRAS +/********** multiinit() **********/ +EXPORT PROC multiinit() HANDLE + DEF mh=NIL:PTR TO multihandle + NEW mh + newList(mh.guis) + mh.wndport:=makeport() + mh.sig:=Shl(1,mh.wndport.sigbit) +#ifdef EASY_APPWINDOW + mh.awport:=makeport() + mh.sig:=mh.sig OR Shl(1,mh.awport.sigbit) +#endif +EXCEPT + cleanmulti(mh) + ReThrow() +ENDPROC mh + +/********** addmultiA() **********/ +EXPORT PROC addmultiA(mh:PTR TO multihandle,title,gui,tags=NIL) HANDLE + DEF gh=NIL:PTR TO guihandle + gh:=makehandle(title,gui,mh,tags) + IF mh THEN AddHead(mh.guis,gh.link) +EXCEPT + -> Stop the user cleanup in this case. + gh.onclean:=NIL + cleangui(gh) + ReThrow() +ENDPROC gh + +/********** multiforall() **********/ +EXPORT PROC multiforall(varaddr:PTR TO LONG,mh:PTR TO multihandle,expr) IS + multieval(varaddr,mh,expr,FALSE) + +/********** multiexists() **********/ +EXPORT PROC multiexists(varaddr:PTR TO LONG,mh:PTR TO multihandle,expr) IS + multieval(varaddr,mh,expr,TRUE) + +-> Evaluate and maybe stop... +PROC multieval(varaddr:PTR TO LONG,mh:PTR TO multihandle,expr,exists) + DEF node:PTR TO ln, next, this, res + -> If empty then TRUE for forall, but FALSE for exists + res:=(exists=FALSE) + IF mh + node:=mh.guis.head + WHILE next:=node.succ + varaddr[]:=node-GH_LINK_OFFSET + IF this:=Eval(expr) + -> If exists then we've found a match. + IF exists THEN RETURN this + ELSE + -> Forall is FALSE. Exists is still FALSE. + res:=FALSE + ENDIF + node:=next + ENDWHILE + ENDIF + -> Invalidate for case where exists fails. + varaddr[]:=NIL +ENDPROC res + +/********** multiempty() **********/ +EXPORT PROC multiempty(mh:PTR TO multihandle) IS mh.guis.tailpred=mh.guis + +/********** multiloop() **********/ +EXPORT PROC multiloop(mh:PTR TO multihandle) + DEF res=-1 + WHILE res<0 + EXIT mh.opencount=0 + Wait(mh.sig) + res:=multimessage(mh) + ENDWHILE +ENDPROC res + +/********** cleanmulti() **********/ +EXPORT PROC cleanmulti(mh:PTR TO multihandle) + IF mh + -> Clean up any remaining guihandles. + WHILE multiempty(mh)=FALSE DO cleangui(mh.guis.head-GH_LINK_OFFSET) +#ifdef EASY_APPWINDOW + IF mh.awport + DeleteMsgPort(mh.awport) + mh.awport:=NIL + ENDIF +#endif + IF mh.wndport + DeleteMsgPort(mh.wndport) + mh.wndport:=NIL + ENDIF + END mh + ENDIF +ENDPROC + +/********** checkmulti() **********/ +EXPORT PROC checkmulti(mh:PTR TO multihandle) + DEF ret + -> Check if there a message waiting on our ports. + IF SetSignal(0,0) AND mh.sig + IF (ret:=multimessage(mh))>=0 THEN quitgui(ret) + ENDIF +ENDPROC +#endif + +-> Note: as long as gh is valid, guimessage() can be used in place of +-> multimessage() for multi-window GUIs. But remember that gh could +-> be invalidated by an action function when guimessage() is called. + +/********** guimessage() **********/ +/********** multimessage() **********/ +#ifdef EASY_APPWINDOW +EXPORT PROC guimessage(gh:PTR TO guihandle) IS message(gh.wndport,gh.awport) +#ifdef EASY_EXTRAS +EXPORT PROC multimessage(mh:PTR TO multihandle) IS message(mh.wndport,mh.awport) +#endif +#endif +#ifndef EASY_APPWINDOW +EXPORT PROC guimessage(gh:PTR TO guihandle) IS message(gh.wndport,NIL) +#ifdef EASY_EXTRAS +EXPORT PROC multimessage(mh:PTR TO multihandle) IS message(mh.wndport,NIL) +#endif +#endif + +-> Handle messages from the ports. +PROC message(wndport,awport) HANDLE + DEF ret=-1 +#ifdef EASY_APPWINDOW + appwmessage(awport) +#endif + ret:=gtmessage(wndport) +EXCEPT + -> If we got "QUIT" then return value is in exceptioninfo. + IF exception="QUIT" + ret:=exceptioninfo + ELSE + ReThrow() + ENDIF +ENDPROC ret + +/********** quitgui() **********/ +EXPORT PROC quitgui(ret=0) IS Throw("QUIT",ret) + +-> Note: as above, checkgui() is safe for multi-window GUIs as long as +-> gh is valid. + +/********** checkgui() **********/ +EXPORT PROC checkgui(gh:PTR TO guihandle) + DEF ret + -> Check if there a message waiting on our ports. + IF SetSignal(0,0) AND gh.sig + IF (ret:=guimessage(gh))>=0 THEN quitgui(ret) + ENDIF +ENDPROC + +-> Remove menus and reset handle. +PROC removemenus(gh:PTR TO guihandle) + IF gh.menus + -> Hack to prevent the item.nextselect if closed from menu action function. + IF gh.menuitem THEN gh.menuitem[]:=NIL + IF gh.pwnd THEN ClearMenuStrip(gh.pwnd) + FreeMenus(gh.menus) + gh.menus:=NIL + ENDIF +ENDPROC + +-> Remove GUI and reset handle. +PROC removegui(gh:PTR TO guihandle) + clean(gh.base) + gh.base:=NIL + removegads(gh) + gh.glist:=NIL + gh.plugins:=NIL +ENDPROC + +-> Check if is this an IDCMP message for the window. +PROC testintuimsg(msg:PTR TO intuimessage,data) IS msg.idcmpwindow=data + +#ifdef EASY_APPWINDOW +-> Check if is this an appmessage for the AppWindow. +PROC testappwmsg(msg:PTR TO appmessage,data) IS msg.id=data +#endif + +-> Selectively remove messages from the port. +PROC clearmsgs(mp:PTR TO mp,f,data) + DEF msg:PTR TO mn, succ + -> Must be in Forbid()/Permit() brackets... + Forbid() + msg:=mp.msglist.head + WHILE succ:=msg.ln.succ + IF f(msg,data) + Remove(msg) + ReplyMsg(msg) + ENDIF + msg:=succ + ENDWHILE + Permit() +ENDPROC + +-> Create a new message port. +PROC makeport() + DEF port:PTR TO mp + IF (port:=CreateMsgPort())=NIL THEN RaiseX("GUI",1065,'Could not create message port. Run out of signal bits?') +ENDPROC port + +-> Clean initialisation stuff and reset handle. +PROC cleaninit(gh:PTR TO guihandle) + -> Clean ports. +#ifdef EASY_APPWINDOW +#ifdef EASY_EXTRAS + IF (gh.mh=NIL) AND gh.awport THEN DeleteMsgPort(gh.awport) +#endif +#ifndef EASY_EXTRAS + IF gh.awport THEN DeleteMsgPort(gh.awport) +#endif + gh.awport:=NIL + IF gh.wb_isopen + CloseLibrary(workbenchbase) + gh.wb_isopen:=FALSE + ENDIF +#endif +#ifdef EASY_EXTRAS + IF (gh.mh=NIL) AND gh.wndport THEN DeleteMsgPort(gh.wndport) +#endif +#ifndef EASY_EXTRAS + IF gh.wndport THEN DeleteMsgPort(gh.wndport) +#endif + gh.wndport:=NIL + IF gh.gt_isopen + CloseLibrary(gadtoolsbase) + gh.gt_isopen:=FALSE + ENDIF +ENDPROC + +/********** cleangui() **********/ +EXPORT PROC cleangui(gh:PTR TO guihandle) + DEF f + IF gh + -> Close window if necessary. + closewin(gh) + IF f:=gh.onclean THEN f(gh.info) + cleaninit(gh) +#ifdef EASY_EXTRAS + IF gh.mh + -> Unlink from multi-window list. + Remove(gh.link) + gh.mh:=NIL + ENDIF +#endif + END gh + ENDIF +ENDPROC + +/********** closewin() **********/ +EXPORT PROC closewin(gh:PTR TO guihandle) + DEF w:PTR TO window + IF w:=gh.wnd + -> Remember window size and position. + gh.x:=w.leftedge + gh.y:=w.topedge + gh.xsize:=w.width + gh.ysize:=w.height +#ifdef EASY_EXTRAS + gh.blockcnt:=1 -> Force unblock, if necessary. + unblockwin(gh) -> Just in case! +#endif + removegui(gh) + removemenus(gh) +#ifdef EASY_APPWINDOW + IF gh.appwin + RemoveAppWindow(gh.appwin) + gh.appwin:=NIL + ENDIF + -> Remove any last minute messages safely. + IF gh.awport THEN clearmsgs(gh.awport,{testappwmsg},gh) +#endif + IF w + -> Must be in Forbid()/Permit() brackets. + Forbid() + -> Remove any last minute messages safely. + clearmsgs(gh.wndport,{testintuimsg},w) + -> Make sure no more messages get sent. + w.userport:=NIL + ModifyIDCMP(w,0) + Permit() + -> Now the window can be closed safely. + CloseWindow(w) + gh.pwnd:=NIL + ENDIF + stdrast:=NIL + IF gh.visual + FreeVisualInfo(gh.visual) + gh.visual:=NIL + ENDIF +#ifdef EASY_EXTRAS + -> If multi then decrement count of open windows. + IF gh.mh THEN gh.mh.opencount:=gh.mh.opencount-1 +#endif + IF gh.is_wb + IF gh.scr THEN UnlockPubScreen(NIL,gh.scr) + gh.scr:=NIL + ENDIF + -> If the font is linked to the screen, it's no longer valid. + IF gh.ta_scr THEN gh.tattr:=NIL + ENDIF +ENDPROC + +-> Render the gadgets on the window. +PROC rendergui(gh:PTR TO guihandle) + DEF glist=0,w:PTR TO window,base:PTR TO g + w:=gh.pwnd + base:=gh.base + gh.gl:=CreateContext({glist}) + IF gh.gl=NIL THEN RaiseX("GUI",1183,'Could not create gadget context. Out of memory?') + stdrast:=w.rport + -> Adjust intermediate gadgets to be real gadgets fitting in window. + adjust(base, gh.xoff,gh.yoff, + w.width-gh.xsize+base.xs,w.height-gh.ysize+base.ys, gh) + AddGList(w,glist,-1,-1,NIL) +#ifndef EASY_KEYBOARD + -> If no keyboard support, activate first sting gadget. + IF gh.firststr THEN ActivateGadget(gh.firststr,w,NIL) +#endif + RefreshGList(glist,w,NIL,-1) + Gt_RefreshWindow(w,NIL) + -> Set public pointer, as a flag to say it's OK to play with the GUI, now. + gh.wnd:=w +ENDPROC glist + +-> Remove PLUGINs and gadgets from window. +PROC removegads(gh:PTR TO guihandle) + DEF pl:PTR TO plugin + -> Set public pointer to NIL, to say it's no longer safe to play with the GUI. + gh.wnd:=NIL + pl:=gh.plugins + WHILE pl + pl.clear_render(gh.pwnd) + pl:=pl.next + ENDWHILE + IF gh.glist + RemoveGList(gh.pwnd,gh.glist,-1) + FreeGadgets(gh.glist) + ENDIF +ENDPROC + +-> Decide what the real screen bottom is by getting size gadget height. +PROC getrealbot(s:PTR TO screen) + DEF dri,bot,im:PTR TO image + bot:=s.wborbottom + IF dri:=GetScreenDrawInfo(s) + IF im:=NewObjectA(NIL,'sysiclass', + [SYSIA_DRAWINFO,dri, SYSIA_WHICH,SIZEIMAGE, + SYSIA_SIZE,SysISize(s.flags), NIL]) + bot:=im.height + DisposeObject(im) + ENDIF + FreeScreenDrawInfo(s,dri) + ENDIF +ENDPROC bot + +#ifdef EASY_KEYBOARD +-> Fiddled so actually one less than length... +PROC execlistlen(list:PTR TO mlh) + DEF len=-1, node:PTR TO mln + -> Catch the case where the LISTV is being cleanly updated. + IF list<>-1 + IF list + node:=list.head + WHILE node:=node.succ DO len++ + ENDIF + ENDIF +ENDPROC len + +-> Do action appropriate to key press. +PROC performkey(gh:PTR TO guihandle,code) + DEF list:PTR TO LONG,ret,val,tag,index,data,gad=NIL:PTR TO gadget,inc + -> Look up gadget in key index. + IF islower(code) -> Positive action + gad:=gh.keys[code-"a"] + inc:=TRUE + ELSEIF isupper(code) -> Negative action + gad:=gh.keys[code-"A"] + inc:=FALSE + ENDIF + IF gad=NIL THEN RETURN GUI_CONT +/* Ack! Doesn't work under OS2.0... +#ifdef EASY_EXTRAS + Gt_GetGadgetAttrsA(gad,gh.pwnd,NIL,[GA_DISABLED,{ret},NIL]) + IF ret THEN RETURN GUI_CONT +#endif +*/ + list:=gad.userdata + ret:=ATTR(list,EG_ACT) +#ifdef EASY_EXTRAS + -> If disabled then don't react. + IF optdis(gad.gadgetid,list) THEN RETURN GUI_CONT +#endif + -> Tag is TRUE if a button. + data,tag:=indexdata(gad.gadgetid) + data:=OptDefATTR(list,data) + SELECT MAXGUI OF gad.gadgetid + -> Just press button. + -> CASE BUTTON,SBUTTON,RBUTTON + CASE STR,INTEGER + -> Activate string and integer gadgets. + ActivateGadget(gad,gh.pwnd,NIL) + CASE CHECK + -> Toggle check gadgets. + tag:=GTCB_CHECKED + index:=CHK_VAL + val:=(IsChecked(gad)=FALSE) + CASE MX + -> Next/prev item, wrapping. + tag:=GTMX_ACTIVE + index:=ListLen(ATTR(list,MX_LIST))-2 + val:=ATTR(list,MX_CURR) + IF inc + IF val++>=index THEN val:=0 + ELSE + IF val--<0 THEN val:=index + ENDIF + index:=MX_CURR + CASE CYCLE + -> Next/prev item, wrapping. + tag:=GTCY_ACTIVE + index:=ListLen(ATTR(list,CYC_LIST))-2 + val:=ATTR(list,CYC_CURR) + IF inc + IF val++>=index THEN val:=0 + ELSE + IF val--<0 THEN val:=index + ENDIF + index:=CYC_CURR + CASE SCROLL + -> Inc/dec, stopping at ends. + tag:=GTSC_TOP + val:=ATTR(list,SCR_TOP) + IF inc + IF val++>=(ATTR(list,SCR_TOTL)-ATTR(list,SCR_VIS)) THEN tag:=0 + ELSE + IF val--<0 THEN tag:=0 + ENDIF + index:=SCR_TOP + CASE SLIDE + -> Inc/dec, stopping at ends. + tag:=GTSL_LEVEL + val:=ATTR(list,SLI_CURR) + IF inc + IF val++>=ATTR(list,SLI_MAX) THEN tag:=0 + ELSE + IF val-- Next/prev, stopping at ends. + tag:=GTLV_SELECTED + val:=ATTR(list,LST_CURR) + IF inc + IF val++>=execlistlen(ATTR(list,LST_LIST)) THEN tag:=0 + ELSE + IF val--<0 THEN tag:=0 + ENDIF + index:=LST_CURR + CASE PALETTE + -> Next/prev, wrapping. + tag:=GTPA_COLOR + val:=ATTR(list,PAL_CURR) + index:=Shl(1,ATTR(list,PAL_DEP))-1 + IF inc + IF val++>=index THEN val:=0 + ELSE + IF val--<0 THEN val:=index + ENDIF + index:=PAL_CURR + ENDSELECT + -> Perform change if required. + IF tag + IF tag<>TRUE -> If not a button (non-zero is tag value). + setgadattr(gad,gh.pwnd,list,val,tag,index) + IF gad.gadgetid=LISTV THEN setgadattr(gad,gh.pwnd,list,val,GTLV_MAKEVISIBLE) + ENDIF + -> Do action. + IF IsActionFun(ret) + -> If button (non-zero is tag value). + IF tag=TRUE THEN ret(0,data,gh.info) ELSE ret(0,data,gh.info,val) + ret:=GUI_CONT + ENDIF + ELSE + ret:=GUI_CONT + ENDIF +ENDPROC ret +#endif + +-> Call action function based on new code. +PROC performaction(fun,gad:PTR TO gadget,info,code,l:PTR TO LONG,qual) + DEF data,but,val + data,but,val:=indexdata(gad.gadgetid) + data:=OptDefATTR(l,data) +ENDPROC (IF but THEN fun(qual,data,info) ELSE + fun(qual,data,info,IF val THEN ATTR(l,val) ELSE code)) + +/********** getstr **********/ +EXPORT PROC getstr(gh,g) IS gadstr(g,findgadget(gh,g)) + +/********** getinteger **********/ +EXPORT PROC getinteger(gh,g) IS gadinteger(g,findgadget(gh,g)) + +-> Copy buffer string to gadget E-string. +PROC gadstr(l:PTR TO LONG, gad:PTR TO gadget) IS + IF gad THEN StrCopy(ATTR(l,STR_STR),GadString(gad)) ELSE 0 + +-> Copy buffer integer to gadget integer. +PROC gadinteger(l:PTR TO LONG, gad:PTR TO gadget) + DEF x=0 + IF gad THEN ATTR(l,INT_VAL):=x:=GadLongInt(gad) +ENDPROC x + +-> Record new gadget value. +PROC performset(gad:PTR TO gadget,code,l:PTR TO LONG) + SELECT MAXGUI OF gad.gadgetid + CASE STR; gadstr(l,gad) + CASE INTEGER; gadinteger(l,gad) + CASE CHECK; ATTR(l,CHK_VAL):=IsChecked(gad) + CASE MX; ATTR(l,MX_CURR):=code + CASE CYCLE; ATTR(l,CYC_CURR):=code + CASE SCROLL; ATTR(l,SCR_TOP):=code + CASE SLIDE; ATTR(l,SLI_CURR):=code + CASE LISTV; ATTR(l,LST_CURR):=code + CASE PALETTE; ATTR(l,PAL_CURR):=code + ENDSELECT +ENDPROC + +-> Clean gadget description objects. +PROC clean(base:PTR TO g) + DEF i:PTR TO g,j + IF base + IF IsRowOrCol(base.type) + i:=base.list + WHILE i + j:=i + i:=i.next + clean(j) + ENDWHILE + ELSEIF IsBevel(base.type) + clean(base.list) + ENDIF + END base + ENDIF +ENDPROC + +-> Length of text, ignoring a "_" if present. +#ifdef EASY_KEYBOARD +#define textlenkey(s,g,k) textlen_key(s,g,k) +#endif +#ifndef EASY_KEYBOARD +#define textlenkey(s,g,k) textlen(s,g) +#endif + +-> Calculate minimum size for a PALETTE gadget showing depth d +-> Ack! Fiddled to compensate for OS2.0 indicator +PROC min_pal(x,y,d) + DEF dy + IF (x+y)=0 THEN RETURN RaiseX("Egui",1441,'Bad PALETTE gadget sizes.') + dy:=Div(Mul(y,d),x+y) +ENDPROC Max(Mul(Shl(1,d-dy),7)+21,x), Max(Shl(4,dy)+3,y) + +-> Calculate minimum size of GUI. +PROC minsize(gui:PTR TO LONG,gh:PTR TO guihandle,isinrows=TRUE,eql=FALSE) + DEF p:PTR TO g,h,minargs,a,b:PTR TO LONG,c,pl:PTR TO plugin,type, + ta:PTR TO textattr + minargs:=minARGS() + ta:=gh.tattr + h:=ta.ysize + type:=ATTR(gui,EG_TYPE) + IF (type<0) OR (type>=MAXGUI) THEN RaiseX("Egui",gui,'Bad gadget type.') + IF (ListLen(gui) Calculate minimum size of group. +PROC foreach(guilist:PTR TO LONG,type,gh:PTR TO guihandle,row,eq) + DEF l,x=0,y=0,z=0,zmid=NO_MID,zother=0,a,p:PTR TO g,list=NIL, + last:PTR TO g,resize=0,xs,t + last:={list} + l:=ListLen(guilist)-1 + FOR a:=1 TO l + p:=minsize(guilist[a],gh,row,eq) + resize:=resize OR p.flags + xs:=p.xs + IF row + x:=Max(xs,x) + y:=y+p.ys+IF y THEN YSPACING ELSE 0 + ELSE + y:=Max(p.ys,y) + x:=x+xs+IF x THEN XSPACING ELSE 0 + ENDIF + z:=Max(z,xs) -> for EQ(ROWS/COLS) + t:=p.mid + zmid:=Max(zmid,t) + zother:=Max(zother,IF t<>NO_MID THEN (xs-t) ELSE xs) + last.next:=p + last:=p + ENDFOR + IF eq + last:=list + z:=IF zmid<>NO_MID THEN (zmid+zother) ELSE zother + WHILE last + last.xs:=z + last.mid:=IF last.mid<>NO_MID THEN zmid ELSE 0 + last:=last.next + ENDWHILE + x:=IF row THEN z ELSE (z+XSPACING*l-XSPACING) + ENDIF + resize:=(IF DoesXUncond(resize) THEN RESIZEX ELSE 0) OR + (IF DoesYUncond(resize) THEN RESIZEY ELSE 0) +ENDPROC newg(x,y,type,list,resize) + +-> Calculate real positions and sizes, and create real gadgets. +PROC adjust(base:PTR TO g,x,y,xs,ys,gh:PTR TO guihandle,isinrow=TRUE) + DEF pl:PTR TO plugin + IF DoesXResize(base.flags)=FALSE THEN (x:=xs-base.xs/2+x) BUT xs:=base.xs + IF DoesYResize(base.flags)=FALSE THEN (y:=ys-base.ys/2+y) BUT ys:=base.ys + SELECT MAXGUI OF base.type + CASE ROWS,EQROWS,COLS,EQCOLS + adjustall(base,x,y,xs,ys,gh) + CASE BEVEL,BEVELR + adjust(base.list,BEVELXSPACE+x,BEVELYSPACE+y, + xs-(BEVELXSPACE*2),ys-(BEVELYSPACE*2),gh) + DrawBevelBoxA(gh.pwnd.rport,x,y,xs,ys, + [GT_VISUALINFO,gh.visual,GTBB_FRAMETYPE,BBFT_BUTTON, + IF base.type=BEVELR THEN GTBB_RECESSED ELSE TAG_IGNORE,0,NIL]) + CASE BAR + IF isinrow + Line(x,y+1,x+xs-1,y+1,1) + Line(x,y+2,x+xs-1,y+2,2) + ELSE + Line(x+1,y,x+1,y+ys-1,1) + Line(x+2,y,x+2,y+ys-1,2) + ENDIF + CASE PLUGIN + pl:=ATTR(base.list,PLG_OBJ) + pl.x:=x; pl.y:=y; pl.xs:=xs; pl.ys:=ys + IF OptATTR(base.list,PLG_GT) + gh.gl:=pl.gtrender(gh.gl,gh.visual,gh.tattr,x,y,xs,ys,gh.pwnd) + ELSE + pl.render(gh.tattr,x,y,xs,ys,gh.pwnd) + ENDIF + DEFAULT + base.x:=x; base.y:=y + creategadget(base,xs,ys,gh) + ENDSELECT +ENDPROC x+xs+XSPACING,y+ys+YSPACING + +-> adjust over column and row groups. +PROC adjustall(base:PTR TO g,x,y,xs,ys,gh) + DEF p:PTR TO g,rs=0,fs=0,sp=0,ds=0,t,rg=0,u,row + -> fs is fixed-width total, rs is resize total + -> ds is gad count, sp is space gad count + p:=base.list + row:=IsRow(base.type) + WHILE p + t:=IF row THEN p.ys ELSE p.xs + IF (row AND DoesYResize(p.flags)) OR (row=FALSE AND DoesXResize(p.flags)) + IF t<=0 THEN sp++ ELSE ((rs:=rs+t) BUT rg++) + ELSE + fs:=fs+t + ENDIF + p:=p.next + ds++ + ENDWHILE + p:=base.list + ds:=(IF row THEN ys ELSE xs)-rs-fs-(ds-1*IF row THEN YSPACING ELSE XSPACING) + -> ds is now difference in space reqts + WHILE p + t:=IF row THEN p.ys ELSE p.xs + IF (row AND DoesYResize(p.flags)) OR (row=FALSE AND DoesXResize(p.flags)) + IF t<=0 + IF rg + IF row THEN ys:=0 ELSE xs:=0 + ELSE -> If only space gads can resize... + fs:=((sp-1)/2+ds)/sp -> Share space completely and fairly + ds:=ds-fs + sp-- + IF row THEN ys:=fs ELSE xs:=fs + ENDIF + ELSE + fs:=((t*ds)+((rs-1)/2))/rs -> Share space completely and fairly + ds:=ds-fs + rs:=rs-t + IF row THEN ys:=t+fs ELSE xs:=t+fs + ENDIF + ELSE + IF row THEN ys:=t ELSE xs:=t + ENDIF + t,u:=adjust(p,x,y,xs,ys,gh,row) + IF row THEN y:=u ELSE x:=t + p:=p.next + ENDWHILE +ENDPROC + +-> Create real gadget. +PROC creategadget(base:PTR TO g,lxs,lys,gh:PTR TO guihandle) + DEF tl,i:PTR TO LONG,minargs,text,flags=0,kindtab,h,textl,x,y,xs,ys, + mid,domid=FALSE,key=0,appw=0 + minargs:=minARGS() + -> Args at least two, so not SPACE* (never called for other possibilities) + IF minargs[base.type]>=2 + i:=base.list + h:=gh.tattr.ysize + flags:=PLACETEXT_RIGHT + x:=base.x + y:=base.y + xs:=base.xs + ys:=base.ys + mid:=IF (base.mid<>NO_MID) AND base.mid THEN (base.mid) ELSE 0 + text:=ATTR(i,EG_TXT) -> speculative + IF text=NIL THEN text:='' + SELECT MAXGUI OF base.type + CASE BUTTON,SBUTTON,RBUTTON + tl:=[NIL] + flags:=PLACETEXT_IN + IF HasHButtSp(base.type) THEN xs:=lxs + IF HasVButtSp(base.type) THEN ys:=lys +#ifdef EASY_APPWINDOW + appw:=OptATTR(i,BUT_APPW) +#endif + CASE CHECK + tl:=[GTCB_CHECKED,IF ATTR(i,CHK_VAL) THEN 1 ELSE 0, GTCB_SCALED,TRUE, NIL] + textl:=IF StrLen(text) THEN mid ELSE 0 + x:=x+textl + IF ATTR(i,CHK_LEFT) THEN flags:=PLACETEXT_LEFT + xs:=h*2+2 + ys:=h+1 + CASE LISTV + xs:=ATTR(i,LST_CURR) + tl:=[GTLV_LABELS,ATTR(i,LST_LIST), GTLV_SELECTED,xs, + IF ATTR(i,LST_SHOW)>=1 THEN GTLV_SHOWSELECTED ELSE TAG_IGNORE,NIL, + -> GTLV_SCROLLWIDTH,h*2, + GTLV_READONLY,ATTR(i,LST_RO), +-> IF xs<>-1 THEN GTLV_TOP ELSE TAG_IGNORE, xs, + IF xs<>-1 THEN GTLV_MAKEVISIBLE ELSE TAG_IGNORE, xs, NIL] + flags:=PLACETEXT_ABOVE + xs:=lxs + IF StrLen(text) + ys:=lys-h-6 + y:=y+h+6 + ELSE + ys:=lys + ENDIF +#ifdef EASY_APPWINDOW + appw:=OptATTR(i,LST_APPW) +#endif + CASE MX + tl:=[GTMX_LABELS,ATTR(i,MX_LIST), GTMX_ACTIVE,ATTR(i,MX_CURR), + GTMX_TITLEPLACE,IF ATTR(i,MX_LEFT) THEN PLACETEXT_LEFT ELSE PLACETEXT_RIGHT, + GTMX_SPACING,MXSPACE, GTMX_SCALED,TRUE, NIL] + textl:=IF StrLen(text) THEN mid ELSE 0 + x:=x+textl + IF ATTR(i,MX_LEFT)=FALSE THEN flags:=PLACETEXT_RIGHT + xs:=h + ys:=h + CASE STR + tl:=[GTST_STRING,ATTR(i,STR_STR), STRINGA_REPLACEMODE,OptATTR(i,STR_OVR), + GTST_MAXCHARS,Min(StrMax(ATTR(i,STR_STR)),ATTR(i,STR_MAX)), NIL] + domid:=TRUE +#ifdef EASY_APPWINDOW + appw:=OptATTR(i,STR_APPW) +#endif + CASE INTEGER + tl:=[GTIN_NUMBER,ATTR(i,INT_VAL), GTIN_MAXCHARS,15, NIL] + domid:=TRUE + lxs-- + CASE CYCLE + tl:=[GTCY_LABELS,ATTR(i,CYC_LIST), GTCY_ACTIVE,ATTR(i,CYC_CURR), NIL] + domid:=TRUE + CASE PALETTE + -> Ack! Indicator width is large for OS2.0 compatibility + tl:=[GTPA_DEPTH,ATTR(i,PAL_DEP), GTPA_INDICATORWIDTH,16, + GTPA_COLOR,ATTR(i,PAL_CURR), NIL] + domid:=TRUE + CASE SCROLL + tl:=[GTSC_TOP,ATTR(i,SCR_TOP), GTSC_TOTAL,ATTR(i,SCR_TOTL), + PGA_FREEDOM,IF ATTR(i,SCR_VERT) THEN LORIENT_VERT ELSE LORIENT_HORIZ, + GTSC_VISIBLE,ATTR(i,SCR_VIS), GTSC_ARROWS,12, NIL] + xs:=lxs + ys:=lys + text:='' + CASE SLIDE + tl:=[GTSL_MIN,ATTR(i,SLI_MIN), GTSL_MAX,ATTR(i,SLI_MAX), + GTSL_LEVEL,ATTR(i,SLI_CURR), GTSL_LEVELFORMAT,ATTR(i,SLI_FMT), + PGA_FREEDOM,IF ATTR(i,SLI_VERT) THEN LORIENT_VERT ELSE LORIENT_HORIZ, + GTSL_MAXLEVELLEN,3, NIL] + domid:=TRUE + CASE TEXT + tl:=[GTTX_TEXT,ATTR(i,TXT_VAL), GTTX_BORDER,ATTR(i,TXT_BORD), NIL] + domid:=TRUE + CASE NUM + tl:=[GTNM_NUMBER,ATTR(i,NUM_VAL), GTNM_BORDER,ATTR(i,NUM_BORD), NIL] + domid:=TRUE + ENDSELECT + IF domid + flags:=PLACETEXT_LEFT + textl:=IF StrLen(text) THEN mid ELSE 0 +-> textl:=IF mid<>NO_MID THEN mid ELSE 0 + x:=x+textl + xs:=lxs-textl + ys:=lys + ENDIF +#ifdef EASY_KEYBOARD + key:=optkey(base.type,i) +#endif + kindtab:=kindTAB() + gh.gl:=CreateGadgetA(kindtab[base.type],gh.gl, + [x,y,xs,ys,text,gh.tattr,base.type,flags,gh.visual,NIL]:newgadget, + [IF key THEN GT_UNDERSCORE ELSE TAG_IGNORE,"_", + IF optdis(base.type,i) THEN GA_DISABLED ELSE TAG_IGNORE,TRUE, + TAG_MORE,tl]) + IF gh.gl=NIL THEN RaiseX("GUI",i,'Could not create gadget. Out of memory?') + gh.gl.userdata:=i +#ifdef EASY_APPWINDOW + IF appw THEN gh.gl.mutualexclude:=EG_MAGIC -> AppW magic identifier. +#endif +#ifndef EASY_KEYBOARD + IF base.type=STR THEN IF gh.firststr=NIL THEN gh.firststr:=gh.gl +#endif +#ifdef EASY_KEYBOARD + -> Remember gadget in key index. Key must be lowercase. + IF islower(key) THEN gh.keys[key-"a"]:=gh.gl +#endif + ENDIF +ENDPROC + +/********** findgadget **********/ +EXPORT PROC findgadget(gh:PTR TO guihandle,list) + DEF gad:PTR TO gadget + IF gh.wnd + gad:=gh.glist + WHILE gad + IF gad.userdata=list THEN RETURN gad + gad:=gad.nextgadget + ENDWHILE + ENDIF +ENDPROC NIL + +#ifdef EASY_APPWINDOW +-> Search for gadget desc list based on mouse position. +PROC findxy(gh:PTR TO guihandle,x,y) + DEF gad:PTR TO gadget,offx=0,offy=0 + gad:=gh.glist + WHILE gad + IF gad.mutualexclude=EG_MAGIC -> Then it's an EasyGUI AppW gadget... + -> The only gadgets (so far) have a label on the left or the top, + -> so compensate and calculate the offset. + IF gad.gadgettext + offx:=gad.gadgettext.leftedge + IF offx>0 THEN offx:=0 + offy:=gad.gadgettext.topedge + IF offy>0 THEN offy:=0 + ENDIF + IF x>=(gad.leftedge+offx) THEN + IF y>=(gad.topedge+offy) THEN + IF gad.leftedge+gad.width>x THEN + IF gad.topedge+gad.height>y THEN RETURN gad.userdata + ENDIF + gad:=gad.nextgadget + ENDWHILE +ENDPROC NIL +#endif + +-> Set gadget attribute based on real gadget. +PROC setgadattr(g,w,gad:PTR TO LONG,value,tag,index=0) + IF g THEN Gt_SetGadgetAttrsA(g,w,NIL,[tag,value,NIL]) + IF index THEN ATTR(gad,index):=value +ENDPROC + +-> Set gadget attribute based on gadget desc list. +PROC setattr(gh:PTR TO guihandle,gad,value,tag,index=0) IS + setgadattr(findgadget(gh,gad),gh.wnd,gad,value,tag,index) + +/********** setXXXXX **********/ +EXPORT PROC setcheck(gh,gad,bool) IS setattr(gh,gad,bool,GTCB_CHECKED,CHK_VAL) +EXPORT PROC setinteger(gh,gad,new) IS setattr(gh,gad,new,GTIN_NUMBER,INT_VAL) +EXPORT PROC setmx(gh,gad,active) IS setattr(gh,gad,active,GTMX_ACTIVE,MX_CURR) +EXPORT PROC setcycle(gh,gad,active) IS setattr(gh,gad,active,GTCY_ACTIVE,CYC_CURR) +EXPORT PROC setpalette(gh,gad,colour) IS setattr(gh,gad,colour,GTPA_COLOR,PAL_CURR) +EXPORT PROC setscrolltop(gh,gad,top) IS setattr(gh,gad,top,GTSC_TOP,SCR_TOP) +EXPORT PROC setscrolltotal(gh,gad,total) IS setattr(gh,gad,total,GTSC_TOTAL,SCR_TOTL) +EXPORT PROC setscrollvisible(gh,gad,visible) IS setattr(gh,gad,visible,GTSC_VISIBLE,SCR_VIS) +EXPORT PROC setslide(gh,gad,new) IS setattr(gh,gad,new,GTSL_LEVEL,SLI_CURR) +EXPORT PROC settext(gh,gad,new) IS setattr(gh,gad,new,GTTX_TEXT,TXT_VAL) +EXPORT PROC setnum(gh,gad,new) IS setattr(gh,gad,new,GTNM_NUMBER,NUM_VAL) +EXPORT PROC setlistvlabels(gh,gad,labs) IS setattr(gh,gad,labs,GTLV_LABELS,LST_LIST) +EXPORT PROC setlistvvisible(gh:PTR TO guihandle,gad,vis) IS setattr(gh,gad,vis,GTLV_MAKEVISIBLE) + +EXPORT PROC setlistvselected(gh:PTR TO guihandle,gad,active) + DEF g + setgadattr(g:=findgadget(gh,gad),gh.wnd,gad,active,GTLV_SELECTED,LST_CURR) + IF active<>-1 THEN setgadattr(g,gh.wnd,gad,active,GTLV_MAKEVISIBLE) +ENDPROC + +EXPORT PROC setstr(gh,gad:PTR TO LONG,new) + setattr(gh,gad,new,GTST_STRING) +ENDPROC StrCopy(ATTR(gad,STR_STR),new) + +/********** disposegui **********/ +EXPORT PROC disposegui(gui:PTR TO LONG) + DEF a,l + IF gui + IF IsGroup(ATTR(gui,EG_TYPE)) + l:=ListLen(gui)-1 + FOR a:=1 TO l DO disposegui(gui[a]) + ENDIF + FastDisposeList(gui) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/README_IMPORTANT b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/README_IMPORTANT new file mode 100644 index 0000000..50e575b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Source/README_IMPORTANT @@ -0,0 +1,26 @@ +TERMS AND CONDITIONS FOR USING THE EASYGUI SOURCECODE + +* modifying or reusing part or whole of easygui.e for your + own project is always allowed: giving credit is encouraged. +* making new versions of easygui public is discouraged in + general. if you still feel that need, try in this order: + - be aware that often extensions can be implemented without + modifying the EasyGUI module, by using PLUGINs. + - suggest the extension to the maintainer of the "official" + EasyGUI, currently Jason Hulance. + - cooperate with other people that may be working on a + custom EasyGUI (try discussing this on the E mailing list). + - if you HAVE to start your own spin-off project, make sure + your release is heavily marked as being different from the + official version while still giving credit. e.g. + "Harry's TurboGUI v1.0a featuring virtual groups, + based on Wouter and Jason's original EasyGUI v3.3b4". + After you start your own version, don't come and + bother us about making it the official version. + Doing your own commercial version or anything else related + to money won't be tolerated at all. + +The purpose of this release is first and foremost educational. + +If you intend to do something with this code which doesn't +seem to be covered by the above, ask me (Wouter) or Jason first. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/EasyGUI_notag.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/EasyGUI_notag.e new file mode 100644 index 0000000..3c421f8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/EasyGUI_notag.e @@ -0,0 +1,29 @@ +OPT MODULE + +MODULE 'tools/easygui' + +EXPORT PROC easygui(windowtitle,gui,info=NIL,screen=NIL,textattr=NIL, + newmenus=NIL,ghaddr=NIL:PTR TO LONG,awproc=NIL, + x=-1,y=-1) IS + easyguiA(windowtitle,gui, + [EG_INFO, info, + EG_SCRN, screen, + EG_FONT, textattr, + EG_MENU, newmenus, + EG_GHVAR, ghaddr, + EG_AWPROC, awproc, + EG_LEFT, x, + EG_TOP, y, + NIL]) + +EXPORT PROC guiinit(windowtitle,gui,info=NIL,screen=NIL,textattr=NIL, + newmenus=NIL,awproc=NIL,x=-1,y=-1) IS + guiinitA(windowtitle,gui, + [EG_INFO, info, + EG_SCRN, screen, + EG_FONT, textattr, + EG_MENU, newmenus, + EG_AWPROC, awproc, + EG_LEFT, x, + EG_TOP, y, + NIL]) diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/copylist.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/copylist.e new file mode 100644 index 0000000..8b32ea0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/copylist.e @@ -0,0 +1,11 @@ +OPT MODULE +OPT EXPORT + +MODULE 'exec/memory' + +PROC copyListToChip(data) + DEF size, mem + size:=ListLen(data)*SIZEOF LONG + mem:=NewM(size, MEMF_CHIP) + CopyMemQuick(data, mem, size) +ENDPROC mem diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/easygui_notag.m b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/easygui_notag.m new file mode 100644 index 0000000000000000000000000000000000000000..ee4efc41144144d1e36839b6a804ea943a63017f GIT binary patch literal 712 zcmbVJO-sW-5PfZ<#!#?A4a}{uY&){ zyO%mUU5dTB*?p|Dv&anj@$3Tl0L=G<+#N*%w@Ou!1uG@p>gV<&6Fds0t znOn?FX4}W`1CDFo1DDu;#-OgJQr2^IwoGPys<%zOW3p}XuFg7+?r=spB?y8?=n&e3 zCc*L%yy|_UcQk|BpfujQjC!2)laU!bNg$jWZHr)!(uTlV|@jn#=pRCuxf1b z(gX%ooJLutVwFfir$wATWTKelQl>)5xeAraMJlVAOv^${AHyihMOZ!M*+k660 Ghosts the specified area of the window (splats dots) + +Unghosting: + + unghost(gad,win:PTR TO window) + -> Redisplays the indicated gadget + clear(win:PTR TO window,x,y,xs,ys) + -> Clears the specified area of the window + unghost_clear(gad,win:PTR TO window,x,y,xs,ys) + -> Clears the specified area then redisplays gadget + +If you're ghosting a gadget then ghost()/unghost() should be sufficient. +If not then try unghost_clear() instead of unghost(). + +If you're ghosting any other kind of area then use ghost() for ghosting and +redrawing for unghosting. To help with this, you might like to use clear() +and then do your normal redrawing. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/ghost.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/ghost.e new file mode 100644 index 0000000..6168a17 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/ghost.e @@ -0,0 +1,32 @@ +OPT MODULE, PREPROCESS +OPT EXPORT + +MODULE 'graphics/gfxmacros', 'graphics/rastport', + 'intuition/intuition', 'intuition/gadgetclass' + +PROC ghost(win:PTR TO window,x,y,xs,ys) + DEF apen, afpt, afptsz, drmd, r:PTR TO rastport + r:=win.rport + apen:=r.fgpen + SetAPen(r,1) + afpt:=r.areaptrn; afptsz:=r.areaptsz + SetAfPt(r,[$1111,$4444]:INT,1) + drmd:=r.drawmode + SetDrMd(r,RP_JAM1) + RectFill(r,x,y,x+xs-1,y+ys-1) + SetAPen(r,apen) + SetAfPt(r,afpt,afptsz) + SetDrMd(r,drmd) +ENDPROC + +PROC unghost(gad,win) IS RefreshGList(gad,win,NIL,1) + +PROC unghost_clear(gad,win,x,y,xs,ys) + clear(win,x,y,xs,ys) + unghost(gad,win) +ENDPROC + +PROC clear(win:PTR TO window,x,y,xs,ys) + SetAPen(win.rport,0) + RectFill(win.rport,x,y,x+xs-1,y+ys-1) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/textlen.e b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/textlen.e new file mode 100644 index 0000000..5341120 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/EasyGUI/Tools/textlen.e @@ -0,0 +1,16 @@ +OPT MODULE +OPT EXPORT + +MODULE 'intuition/intuition' + +PROC textlen(s,ta) IS IF s THEN IntuiTextLength([0,0,0,0,0,ta,s,NIL]:intuitext) ELSE 0 + +PROC textlen_key(s,ta,key) + DEF len=0 + IF s + len:=textlen(s,ta) + IF key + IF InStr(s,'_')<>-1 THEN len:=len-textlen('_',ta) + ENDIF + ENDIF +ENDPROC len diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptions.e b/amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptions.e new file mode 100644 index 0000000..22c93f4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptions.e @@ -0,0 +1,26 @@ +-> general exception catcher for test purposes + +OPT MODULE + +EXPORT PROC report_exception() + DEF e[5]:ARRAY + IF exception + WriteF('Program caused exception: ') + IF exception<10000 + WriteF('\d\n',exception) + ELSE + SELECT exception + CASE "MEM"; WriteF('no memory\n') + CASE "OPEN"; WriteF('could not open file \s\n',IF exceptioninfo THEN exceptioninfo ELSE '') + CASE "^C"; WriteF('***BREAK\n') + -> and others... + DEFAULT + e[4]:=0 + ^e:=exception + WHILE e[]=0 DO e++ + WriteF('"\s" ',e) + WriteF(IF exceptioninfo<1000 THEN '[\d]\n' ELSE '[\h]\n',exceptioninfo) + ENDSELECT + ENDIF + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptionstest.e b/amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptionstest.e new file mode 100644 index 0000000..d38a3f5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Exceptions/exceptionstest.e @@ -0,0 +1,18 @@ +MODULE 'tools/exceptions' + +PROC main() + t(0) -> NOP + t(10) + t("MEM") + t("OPEN") + t("^C") + t("BL") + t("BLA") + t("BLAA") +ENDPROC + +PROC t(x) HANDLE + Throw(x,'bla') +EXCEPT + report_exception() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/File/file.doc b/amigae33a/E_v3.3a/Src/Src/Tools/File/file.doc new file mode 100644 index 0000000..3e5d19c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/File/file.doc @@ -0,0 +1,35 @@ +FILE.M: general file handling functions. + + mem,len:=readfile(filename,trailbyte="\n",memflags=0) + +reads file "filename", trailing both at begin and end with 4 bytes each. +The purpose of trailing is to enable fast searching; "\n" makes sense +if filename is a text file, 0 for binary files. +returns: ptr file was loaded to, and length. +raises: "NEW", "OPEN" filename, "IN" + + freefile(mem) + +frees memory allocated by readfile(). if you don't call freefile(), +memory is deallocated at the end of the program. + + writefile(filename,mem,len) + +writes a block of memory as file. +raises: "OPEN" filename, "OUT" + + num:=countstrings(mem,len) + +counts strings in memory block. mem must be "\n" trailed. +returns: #of strings + + list:=stringsinfile(mem,len,max) + +builds a LIST of nil-terminated strings, gathered from mem. +max is maxsize of list, which can either be obtained from countstrings() +(slow but accurate) or from your own guess (fast but inaccurate) +returns: LIST of C-string pointers +raises: "MEM" +notes: - the contents of mem will be altered (i.e. "\n" bytes changed to 0) + - mem must be "\n" trailed. + - if ListLen(list) is equal to max, most likely max was too small diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/File/file.e b/amigae33a/E_v3.3a/Src/Src/Tools/File/file.e new file mode 100644 index 0000000..8ff4fd9 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/File/file.e @@ -0,0 +1,71 @@ +/* file.m */ + +OPT MODULE + +EXPORT PROC readfile(filename,trailbyte="\n",memflags=0) + DEF len,m,rl,fh,a + IF (len:=FileLength(filename))<1 THEN Throw("OPEN",filename) + m:=NewM(len+8,memflags) + FOR a:=0 TO 3 + m[a]:=trailbyte + m[len+4+a]:=trailbyte + ENDFOR + m:=m+4 + IF (fh:=Open(filename,OLDFILE))=NIL THEN Raise("OPEN") + rl:=Read(fh,m,len) + Close(fh) + IF rl<>len THEN Raise("IN") +ENDPROC m,len + +EXPORT PROC freefile(mem) + Dispose(mem-4) +ENDPROC + +EXPORT PROC writefile(filename,mem,len) + DEF fh,wl + IF (fh:=Open(filename,NEWFILE))=NIL THEN Throw("OPEN",filename) + wl:=Write(fh,mem,len) + Close(fh) + IF wl<>len THEN Raise("OUT") +ENDPROC + +EXPORT PROC countstrings(mem,len) + MOVE.L mem,A0 + MOVE.L A0,D1 + ADD.L len,D1 + MOVEQ #0,D0 + MOVEQ #10,D2 +strings: + ADDQ.L #1,D0 +findstring: + CMP.B (A0)+,D2 + BNE.S findstring + CMPA.L D1,A0 + BMI.S strings +ENDPROC D0 + +EXPORT PROC stringsinfile(mem,len,max) + DEF list,l + IF (list:=List(max))=NIL THEN Raise("MEM") + MOVE.L list,A1 + MOVE.L max,D3 + MOVE.L mem,A0 + MOVE.L A0,D1 + ADD.L len,D1 + MOVEQ #0,D0 + MOVEQ #10,D2 +stringsl: + CMP.L D3,D0 + BPL.S done + ADDQ.L #1,D0 + MOVE.L A0,(A1)+ +findstringl: + CMP.B (A0)+,D2 + BNE.S findstringl + CLR.B -1(A0) + CMPA.L D1,A0 + BMI.S stringsl +done: + MOVE.L D0,l + SetList(list,l) +ENDPROC list diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/File/filetest.e b/amigae33a/E_v3.3a/Src/Src/Tools/File/filetest.e new file mode 100644 index 0000000..a4247d4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/File/filetest.e @@ -0,0 +1,13 @@ +-> test files + +MODULE 'tools/file', 'tools/exceptions' + +PROC main() HANDLE + DEF m,l,n,list,x,y=1 + m,l:=readfile(arg) + WriteF('file has \d lines:\n\n',n:=countstrings(m,l)) + list:=stringsinfile(m,l,n) + ForAll({x},list,`WriteF('\d\t\s\n',y++,x)) +EXCEPT + report_exception() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/FilledVector.guide b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/FilledVector.guide new file mode 100644 index 0000000..a3f4b1e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/FilledVector.guide @@ -0,0 +1,1084 @@ +@database FilledVector.guide + +Docs for filled vector module + +© 1993,1994 Michael Zucchi +All rights reserved + +@node Main "FilledVector.guide" + +Filled Vector Module for AmigaE 2.5+ + +© 1993,1994 @{"Michael Zucchi" Link "Author"} +All Rights Reserved + +This document describes the usage of a suite of 3d filled vector routines +compiled for the AmigaE language. + +The following sections are available: + + @{" OverView " Link "OverView"} some of the ideas behind the module + + @{" Polygon Context " Link "Polygon Context"} describing destination memory + + @{" Vector Object " Link VectorObject} vector object creation/manipulation + + @{" Rendering " Link "Rendering"} rendering functions + + @{" Matrix " Link "Matrix"} coordinate manupulation functions + + + @{Examples link examples} a few playthings i came up with ... + +@{b}NOTE:@{ub} You need to have: + +MODULE 'tools/filledvector', 'tools/filledvdefs' + +Somewhere in your MODULE include section + + + +This module should work with all Amiga's + +@endnode + +@node OverView + +@{u}Filled Vector Module Overview@{uu} + +Whats this module all about? + +This module contains some reasonably 'optimised' rendering code +to render 3d polygon filled vectors. This includes some a +reasonably complex and versatile object format that can be +used to create complex iconvex vector objects. + +Because it uses the blitter to do rendering, it means you +can have very complex objects (ones with holes in them +and so on) without slowing it down too much. Unfortunately, +performance on accelerated machines isn't so hot ... + +BTW, i say "optimised", but its not that fast really ... one +reason is because i'm keeping the system intact :) +Another reason, is this code is somewhat old by now, and i +dont really have the time to update it to the latest +kill-os version i have (the kill-os version uses a very +interrupt-intensive customblitter queue, and it operates +on parameters fixed at compile-time. It is also a LOT +faster though ...). It also uses some more efficient +data structures and algorithms that i havent had time +to put into this one. + +One of the "cool" features it DOES have though, is the ability +to perform z clipping as its rendering objects. This allows +you to smoothly run through objects as you run into them, +rather than having them dissapear just as they start to get big. +It doesn't use a particularaly reliable or fast z clipping +algorithm but its still not too bad. (again, my kill-os +vector code uses a much more efficient version ...). + + +Hopefully someone out there will be able to do more with it +than just another version of ZedWB :) (although, for +full-on vector world creation, you need some more +tools ...) + + MZ + +@endnode + +@node "Author" + +I'm another one of these poor students, but i live in Australia, not Europe! +I've been stuffing about with this vector shit since i had a '64, but never +really got to do anything with it ... + +Presently, i study 'from time to time' :-) in order to obtain a Computer +Systems Engineering degree from the Univerity Of South Australia. +I'm the 'Zed' of FRONTIER in my anti-os hours. + +I can be contacted in the following ways: + +Internet email: + +9107047w@lux.levels.unisa.edu.au + till the end of '94 at least - reliable + +zucchi@hal9000.apana.org.au +zucchi@bkroom.apana.org.au + until i keep acounts there (?) + +`Real Mode' (tm) mail: + +Michael Zucchi +PO BOX 824 +Waikerie +South Australia 5330 + slow, but very reliable - till mum sells the house :) + +Michael Zucchi +110 Dunrobin Rd +Warradale +South Australia 5046 + till end of '94 + +@endnode + + +;--------------------------------------------------------------------------- +;--------------------------------------------------------------------------- +; Polygon Context Functions + + +@node "Polygon Context" + +This section describes the functions used for creating and manipulating +'polygon contexts'. + + @{" Polygon Context OverView " Link "Polygon Context Overview"} + + @{"newPolyContext() " Link "newPolyContext"} create a new one + @{"freePolyContext()" Link "freePolyContext"} free one + @{"setPolyBitMap() " Link "setPolyBitMap"} change where it renders + @{"setPolyClipRect()" Link "setPolyClipRect"} change clipping window + +All of these functions operate with system libraries starting from V33 +(workbench 1.2). However, @{u}please note@{uu} that interleaved bitmaps are +only possible when using @{b}V39@{ub} libraries (WB3.0+). + +@endnode + + + +@node "Polygon Context Overview" + +A polygon context is similar to a rastport, but instead of containing +all and sundry general purpose drawing variables as a rastport must, +it only contains data necessary for polygon rendering. + +The following is an example of some of the information that is stored in +the polygon context: + + clipping rectangle + minimum dimensions of current polygon (for blitting) + size of destination bitmap + bytesperrow of bitmap and screen + + pointer to a bitplane to render polygons into + pointer to bitmap to blit thus renderd polygons + some temporary storage + +Because of the context sensitive nature of this data object, when one +is allocated it must be attached to a specific screen or bitmap - and MUST NOT +be used for another screen or bitmap, unless it is absolutely clear that +they are of the same dimensions (the buffered screen routines guaruntee this). + +All fields of the polygon context are !PRIVATE! and must only be +accessed via the provided functions! + +@endnode + + +@node "newPolyContext" +@{u}filledvector.m/newPolyContext filledvector.m/newPolyContext@{uu} + + @{b}SYNTAX@{ub} + + polycontext:=newPolyContext( bitmap, workspace ) + + @{b}PURPOSE@{ub} + + Allocates memmory required for the polygon context and associated + memory. A single bitplane the same size as the bitmap is allocated + for blitting into along with some work memory. + + @{b}INPUTS@{ub} + bitmap a standard 'Amiga bitmap' that is to be the destination + for rendering operations. This may be changed during runtime + with the @{"setPolyBitMap()" Link "setPolyBitMap"} function. + workspace a number used to allocate workspace for the polygon + rendering functions. Currrently make this the maximum number + of points in any single object, plus 16. + + @{b}OUTPUTS@{ub} + polycontext + pointer to a private polgon context handle that can + be passed to the other functions + + @{b}SEE ALSO@{ub} + @{"freePolyContext()" Link "freePolyContext"}, @{"Rendering functions" Link Rendering} +@endnode + +@node "freePolyContext" +@{u}filledvector.m/freePolyContext filledvector.m/freePolyContext@{uu} + + @{b}SYNTAX@{ub} + + VOID freePolyContext( poly context ) + + @{b}PURPOSE@{ub} + + Frees the memory associated with a given polygon context. This + function should always be called before a program exits. + + @{b}INPUTS@{ub} + polycontext + Pointer to a polygon context handle that was previously + allocated with @{"newPolyContext()" Link "newPolyContext"}. It MUST have + been allocated with this function. This value MUST NOT + be NIL. + + @{b}SEE ALSO@{ub} + @{"newPolyContext()" Link "newPolyContext"} +@endnode + + +@node "setPolyBitMap" +@{u}filledvector.m/setPolyBitMap filledvector.m/setPolyBitMap@{uu} + + @{b}SYNTAX@{ub} + + VOID setPolyBitMap( poly context, bitmap ) + + @{b}PURPOSE@{ub} + + Sets the bitmap that the rendering functions will render into. This + bitmap must be either the one used to allocate the polygon context, + or one with identical structure. + + @{b}INPUTS@{ub} + polycontext + Previously allocated (using @{"newPolyContext()" Link "newPolyContext"}), valid polygon + context. Must not be NIL. + bitmap + Pointer to a standard Amiga bimap that is to become the new + destination for rendering. + + @{b}SEE ALSO@{ub} + @{"newPolyContext()" Link "newPolyContext"} +@endnode + + +@node "setPolyClipRect" +@{u}filledvector.m/setPolyClipRect filledvector.m/setPolyClipRect@{uu} + + @{b}SYNTAX@{ub} + + VOID setPolyClipRect( poly context, [minx, miny, maxx, maxy]:INT ) + + @{b}PURPOSE@{ub} + + This function sets the viewport through which all rendering will + take place. The values supplied, minx/miny/maxx and maxy must + all be within the size of the bitmap being rendered into, with a + further restriction that maxx>minx and so on. + + @{b}INPUTS@{ub} + polycontext + Previously allocated (using @{"newPolyContext()" Link "newPolyContext"}), valid polygon + context. Must not be NIL. + [minx, miny, maxx, maxy]:INT + An array of 4 16 bit numbers that describe the clipping + rectangle to be used. + + @{b}SEE ALSO@{ub} + @{"newPolyContext()" Link "newPolyContext"}, @{"Rendering functions" Link Rendering} +@endnode + + +@node setPolyFlags +@{u}filledvector.m/setPolyFlags filledvector.m/setPolyFlags@{uu} + + @{b}SYNTAX@{ub} + + VOID setPolyFlags( poly context, newflags, mask ) + + @{b}PURPOSE@{ub} + + This function sets the polygon context flags (see below) for + the given polygon context. Not much can be changed just yet. + Like several Amiga system functions, the mask value sets + which of the bits in the newflags will become set to those + values (0 or 1, or whatever). + + PCF_ZCLIP + This flag will set zclipping on or off. If this bit + is on, zclipping will be performed for all polygons + rendered. Turning off zclipping can reduce + calulcations somewhat, but they can't get too close + to the virtual eye-level of the viewer, without + stuffing up. + + @{b}INPUTS@{ub} + polycontext + Previously allocated (using @{"newPolyContext()" Link "newPolyContext"}), valid polygon + context. Must not be NIL. + newflags + State of new flags + mask A 1 in a bit position of the mask indicates that the + corresponding bit in the newflags parameter is to be + copied to the polygon context flags field. A 0 + indicates that that bit is to remain unchanged. + + @{b}SEE ALSO@{ub} + @{"newPolyContext()" Link "newPolyContext"} +@endnode + + +;--------------------------------------------------------------------------- +;--------------------------------------------------------------------------- +; Vector Object Functions + + +@node VectorObject + +This section describes the functions available for creating, destroying, +and working with `vector objects'. These are high level object +definitions that can be used to describe quite complex objects, which +can then be rendered very efficiently. + +Creating new objects can be difficult, @{"designing objects" link ObjectDesign.guide/main} explains +more information about how to go about this. + + + @{"newVectorObject() " Link "newVectorObject"} create a new vector object + @{"freeVectorObject() " Link "freeVectorObject"} free a vector object + @{"copyVectorObject() " Link "copyVectorObject"} make an efficient copy of an object + @{"cloneVectorObject()" Link "cloneVectorObject"} make a minimal copy of an object + + @{"getVObjectPoints() " Link "getVObjectPoints"} access the array of vertices + + + @{"newVList() " Link "newVList"} create a list header for linking objects + @{"freeVList() " Link "freeVList"} free the list, and optionally all objects in it + @{"addVObject()" Link "addVObject"} add an object to an object list + @{"remVObject()" Link "remVObject"} remove an object from an object list + + @{"sortVList() " Link "sortVList"} do a fast sort in descending Z order of the list + + + @{"drawVObject() " Link "drawVObject"} draw a single vector object + @{"drawVList() " Link "drawVList"} draw a list of objects + @{"moveDrawVList()" Link moveDrawVList} render a scene of objects + +All of these functions operate with system libraries starting from V33 +(workbench 1.2). + +@endnode + +@node newVectorObject +@{u}filledvector.m/newVectorObject filledvector.m/newVectorObject@{uu} + + @{b}SYNTAX@{ub} + + vobject := newVectorObject( type, numpoints, numfaces, points, faces ) + + @{b}PURPOSE@{ub} + + Creates a new vector object, and initialises its fields to those + supplied. + + @{b}INPUTS@{ub} + type type of object, currently only '0' is valid + numpoints + the number of vertices/points in the object + numfaces + the number of faces in the object + points an array of INT's which are the vertices used by the object. + Each entry in the list consists of 3 words the X, Y and Z + coordinates of that point. There must be at least + numpoints*3 INT's in this list. + faces an array of "vface" data structures which describe the faces + of the object. There must be at least as many of these + as the numfaces argument. See @{"designing objects" Link Design} for more + information. + + @{b}OUTPUTS@{ub} + vobject Pointer to a vobject type OBJECT that can be used to manipulate + the object in some ways. + + @{b}SEE ALSO@{ub} + @{"freeVectorObject()" Link freeVectorObject}, @{"copyVectorObject()" Link copyVectorObject}, @{"cloneVectorObject()" link cloneVectorObject}, + @{"Designing objects" Link objectdesign.guide/main} +@endnode + +@node freeVectorObject +@{u}filledvector.m/freeVectorObject filledvector.m/freeVectorObject@{uu} + + @{b}SYNTAX@{ub} + + VOID freeVectorObject( vobject ) + + @{b}PURPOSE@{ub} + + Free's a vector object, and any associated memory. This function + should be used to free all objects previously created or copied, + before the program exits. + + @{b}INPUTS@{ub} + vobject previously allocated vector object (either using + @{"newVectorObject()" Link newVectorObject}, @{"copyVectorObject()" link copyVectorObject} or @{"cloneVectorObject()" Link cloneVectorObject}), + it may also be NIL, in which case it does nothing. + + @{b}SEE ALSO@{ub} + @{"newVectorObject()" Link newVectorObject}, @{"copyVectorObject()" Link copyVectorObject}, @{"cloneVectorObject()" link cloneVectorObject}, +@endnode + +@node copyVectorObject +@{u}filledvector.m/copyVectorObject filledvector.m/copyVectorObject@{uu} + + @{b}SYNTAX@{ub} + + vobject := copyVectorObject( vobject ) + + @{b}PURPOSE@{ub} + + Makes an efficient copy of a vector object. The entire object is + copied, including the points, the face definitions (colours etc), + but the polygon definitions are not copied to save space. + + @{b}INPUTS@{ub} + vobject previously allocated vector object (either using + @{"newVectorObject()" Link newVectorObject}, @{"copyVectorObject()" link copyVectorObject} or @{"cloneVectorObject()" Link cloneVectorObject}), + it may also be NIL, in which case it returns NIL. + + @{b}OUTPUTS@{ub} + vobject a copied vector object. + + @{b}SEE ALSO@{ub} + @{"newVectorObject()" Link newVectorObject}, @{"freeVectorObject()" Link freeVectorObject}, @{"cloneVectorObject()" link cloneVectorObject} +@endnode + + +@node cloneVectorObject +@{u}filledvector.m/cloneVectorObject filledvector.m/cloneVectorObject@{uu} + + @{b}SYNTAX@{ub} + + vobject := copyVectorObject( vobject ) + + @{b}PURPOSE@{ub} + + Makes a minimal copy of a vector object. The points array, and the + face array are NOT copied. This allows an identical object to be + created and positioned independently of the original, but any + manipulation of either object (colours or points) will affect the + other. + + @{b}INPUTS@{ub} + vobject previously allocated vector object (either using + @{"newVectorObject()" Link newVectorObject}, @{"copyVectorObject()" link copyVectorObject} or @{"cloneVectorObject()" Link cloneVectorObject}), + it may also be NIL, in which case it returns NIL. + + @{b}OUTPUTS@{ub} + vobject a cloned vector object. + + @{b}SEE ALSO@{ub} + @{"newVectorObject()" Link newVectorObject}, @{"freeVectorObject()" Link freeVectorObject}, @{"copyVectorObject()" link copyVectorObject} +@endnode + +@node getVObjectPoints +@{u}filledvector.m/getVObjectPoints filledvector.m/getVObjectPoints@{uu} + + @{b}SYNTAX@{ub} + + points := getVObjectPoints( vobject ) + + @{b}PURPOSE@{ub} + + Allows a pointer to the internal point/vertice array to be obtained. + This can be used with the @{matrix link Matrix} and other manipulation + functions (you are free to do what you like) for post-processing the + object. + + This array will contain as many points as the number of points used + in the argument to the initial @{"newVectorObject()" link newVectorObject} call. + + @{b}INPUTS@{ub} + vobject previously allocated vector object (either using + @{"newVectorObject()" Link newVectorObject}, @{"copyVectorObject()" link copyVectorObject} or @{"cloneVectorObject()" Link cloneVectorObject}), + it may also be NIL, in which case it returns NIL. + + @{b}OUTPUTS@{ub} + points A pointer to an array of INT's that are the 3d points of the + object. If the object has been cloned, this will point to + the same physical array as the parent's point list. + + @{b}SEE ALSO@{ub} + @{"newVectorObject()" Link newVectorObject} +@endnode + + +@node newVlist +@{u}filledvector.m/newVList filledvector.m/newVList@{uu} + + @{b}SYNTAX@{ub} + + vlist := newVList() + + @{b}PURPOSE@{ub} + + Creates a new list header,and initialises it. This is used for + linking several objects into a bigger object, or as a way of + efficiently manipulating several objects at a time. + + @{b}OUTPUTS@{ub} + vlist pointer to a newly allocated vlist header, or NIL incase of + failure. + + @{b}SEE ALSO@{ub} + @{"freeVList()" Link freeVList}, @{addVObject() link addVObject}, @{remVObject() link remVObject}, + @{sortVList() link sortVList}, @{drawVlist() link drawVList}, @{moveDrawVlist link moveDrawVlist} +@endnode + + +@node freeVlist +@{u}filledvector.m/freeVList filledvector.m/freeVList@{uu} + + @{b}SYNTAX@{ub} + + VOID freeVList( vlist, freenodes ) + + @{b}PURPOSE@{ub} + + Free's a vector object list header, and optionally, all of the + vector objects connected to the list. + + @{b}INPUTS@{ub} + vlist pointer to a previously allocated vlist header, allocated with + @{newVList() link newVList}, this must not be NIL! + freenodes + Boolean value which indicates whether all of the objects in + the vlist are also to be free'd. + + @{b}SEE ALSO@{ub} + @{"newVList()" Link newVList} +@endnode + + +@node addVlist +@{u}filledvector.m/addVList filledvector.m/addVList@{uu} + + @{b}SYNTAX@{ub} + + VOID addVList( vlist, vobject ) + + @{b}PURPOSE@{ub} + + Adds a vector object to the vlist. + + @{b}INPUTS@{ub} + vlist pointer to a previously allocated vlist header, allocated with + @{newVList() link newVList}, this must not be NIL! + vobject previously allocated vector object (either using + @{"newVectorObject()" Link newVectorObject}, @{"copyVectorObject()" link copyVectorObject} or @{"cloneVectorObject()" Link cloneVectorObject}), + it may also be NIL, in which case it returns NIL. + + @{b}SEE ALSO@{ub} + @{"newVList()" Link newVList}, @{remVList() link remVlist} +@endnode + + +@node remVlist +@{u}filledvector.m/remVList filledvector.m/remVList@{uu} + + @{b}SYNTAX@{ub} + + VOID addVList( vlist, vobject ) + + @{b}PURPOSE@{ub} + + Removes the vector object from the vlist. + + @{b}INPUTS@{ub} + vlist pointer to a previously allocated vlist header, allocated with + @{newVList() link newVList}, this must not be NIL! + (currently, this field is unused, since the list uses a doubly + linked list. If int he future, this changes, then this + will become important) + vobject a vobject that has previosly been added to the vlist using + @{addVList() link addVList}. + + @{b}SEE ALSO@{ub} + @{"newVList()" Link newVList}, @{addVList() link addVlist} +@endnode + + + +@node sortVlist +@{u}filledvector.m/sortVList filledvector.m/sortVList@{uu} + + @{b}SYNTAX@{ub} + + VOID sortVList( vlist ) + + @{b}PURPOSE@{ub} + + Takes the vlist argument, and scans all of the vector objects on + the list. It looks at the vobject.pz value, and uses this to + sort the list indescending Z order. + + The algorithm used by this sort is a modified mergesort, which + uses a prescan stage to break the list into already-sorted + sublists, which it then takes pairs of, and merges to create + larger sublists, until sorted. This will mean that a nearly + sorted list can be sorted VERY quickly. Even with a completely + reversed list, the properties of the mergesort algorithm + guarentee a very fast worst case performance. + + @{b}INPUTS@{ub} + vlist pointer to a previously allocated vlist header, allocated with + @{newVList() link newVList}, this must not be NIL! + vobject a vobject that has previosly been added to the vlist using + @{addVList() link addVList}. + + @{b}SEE ALSO@{ub} + @{"newVList()" Link newVList}, @{drawVList() link drawVlist} +@endnode + + +@node drawVObject +@{u}filledvector.m/drawVObject filledvector.m/drawVObject@{uu} + + @{b}SYNTAX@{ub} + + VOID drawVObject( polygon context, vobject ) + + @{b}PURPOSE@{ub} + + Draws a single vector object into the polygon context described. + The object's position and angles are taken into account, resulting + in a positioned and rotated object being rendered into the + destination bitmap. + + @{b}INPUTS@{ub} + poly context + Pointer to a polygon context handle that was previously + allocated with @{"newPolyContext()" Link "newPolyContext"}. It MUST have + been allocated with this function. This value MUST NOT + be NIL. + vobject previously allocated vector object (either using + @{"newVectorObject()" Link newVectorObject}, @{"copyVectorObject()" link copyVectorObject} or @{"cloneVectorObject()" Link cloneVectorObject}), + it must NOT be NIL. + + @{b}SEE ALSO@{ub} + @{"Polygon Context" link "Polygon Context"}, @{"Vector Objects" link VectorObject} +@endnode + + +@node drawVList +@{u}filledvector.m/drawVList filledvector.m/drawVList@{uu} + + @{b}SYNTAX@{ub} + + VOID drawVList( polygon context, vlist ) + + @{b}PURPOSE@{ub} + + Scans the vector object list, and draws all of the items contained + within it. No sorting of the objects is done whatsoever, so if + you wish to have correctly depth sorted (i.e. painters algorithm) + objects, @{sortVList() link sortVList} must be called first. + + Each object is rendered using its position and angles as specified + in the vobject OBJECT. + + @{b}INPUTS@{ub} + poly context + Pointer to a polygon context handle that was previously + allocated with @{"newPolyContext()" Link "newPolyContext"}. It MUST have + been allocated with this function. This value MUST NOT + be NIL. + vlist pointer to a previously allocated vlist header, allocated with + @{newVList() link newVList}, this must not be NIL! + + @{b}SEE ALSO@{ub} + @{"newVList()" Link newVList}, @{"Polygon Context" link "Polygon Context"}, @{"Vector Objects" link VectorObject} +@endnode + + +@node moveDrawVList +@{u}filledvector.m/moveDrawVList filledvector.m/movewDrawVList@{uu} + + @{b}SYNTAX@{ub} + + VOID movewDrawVList( polygon context, vlist, position ) + + @{b}PURPOSE@{ub} + + This is a high level function which performs a lot of processing + in one step. Initially, it scans the list of objects, and + uses the supplied position OBJECT to rotate and position all + of the objects into an internal list. Once this has taken place, + this list is depth sorted, and all objects in the list are + rendered, starting from the back. + + The positions within each vobject now become relative to the + position supplied as an argument above. The angles should + be relative too, but currently the angles stored in each vobject + are ignored when this function is called. + + @{b}INPUTS@{ub} + poly context + Pointer to a polygon context handle that was previously + allocated with @{"newPolyContext()" Link "newPolyContext"}. It MUST have + been allocated with this function. This value MUST NOT + be NIL. + vlist pointer to a previously allocated vlist header, allocated with + @{newVList() link newVList}, this must not be NIL! + position + an OBJECT position object, which describes the position + and angle at which the object list is to be drawn. + + @{b}SEE ALSO@{ub} + @{"newVList()" Link newVList}, @{"Polygon Context" link "Polygon Context"}, @{"Vector Objects" link VectorObject} +@endnode + + +;--------------------------------------------------------------------------- +;--------------------------------------------------------------------------- +; Rendering Functions + +@node Rendering + + + Currently, the only available rendering functions are + those in the @{"vector object" link VectorObject} section. + + Sometime in the future, some more low-level, but simple + to use polygon rendering functions will be provided. + +@endnode + +;--------------------------------------------------------------------------- +;--------------------------------------------------------------------------- +; Matrix Functions + + +@node Matrix + +This section describes the range of general purpose matrix-based functions +that are available for manipulating sets of points in 2d and 3d. + +Have a look at @{"matrix information" link matrixinfo} on just how to use these +functions. + + @{"setMatIdent() " link setMatIdent} setup a matrix to do nothing (identity matrix) + @{"setMatRotate()" link setMatRotate} setup a matrix to perform a rotation + @{"setMatScale() " link setMatScale} setup a matrix to perform a scaling operation + + @{"matSize() " link matSize} scale the rows of a matrix + @{"matMult() " link matMult} multiply two matrices + + @{"matApply3() " link matApply3} apply a matrix to a set of 3d points + +All functions here work with all machines. + +@endnode + +@node matrixinfo + +So, there's all of these matrix functions - just what the hell do you do with +them? Well, matrices are an efficient way to manipulate things like points +in 3d. You can do things like scaling, rotation, shearing, and so on all using +a single matrix. You can also combine operations, like doing several rotations +at once, or a rotation and a scale, by combining the individual transformations +into one matrix, and then applying this matrix in one go to the points. + +Ok, how about an example. Say we wish to rotate several points, and then scale +them up by 100%, in the X direction. + + +DEF matrotate:matrix, matscale:matrix + +setMatRotate(matrotate, anglex, angley, anglez); -> rotate angles +setMatScale(matscale, 2048, 1024, 1024); -> scale 2x in x +matMult(matscale, matrotate) -> create new transform + +matApply3(matrotate, 10, points, buffer); -> apply the matrix + + +Because the scaling matrix is left-multiplied with the rotation matrix +(the matMult call above), then the new matrix will act as if two seperate +transformations had occured, the first being a rotate, and the second +a scaling. + +If the order of multiplication of the matrices was reversed, then the +matrix would represent first a scaling operation, and THEN a rotation. +These two different matrices result in quite different outputs. + +This operation (multiplying the two matrices) is known as concatenation, +and is mentioned throughout the function descriptions. + +Another way to perform scaling is to use the matSize() function. This +modifies the rows of the matrix directly, and will produce similar +results (and is actually more efficient), but it always acts as if +it is the last operation. + +See the various functions for more information about what is available. +A textbook on 3d graphics, or simply one on linear algebra which talks +about affine transformations may also be handy. + +@endnode + + +@node setMatIdent +@{u}filledvector.m/setMatIdent filledvector.m/setMatIdent@{uu} + + @{b}SYNTAX@{ub} + + VOID setMatIdent( matrix ) + + @{b}PURPOSE@{ub} + + Sets up the contents of the matrix pointed to by matrix to + the internal identity matrix value. + + @{b}OUTPUTS@{ub} + matrix Matrix setup to do nothing. + + @{b}SEE ALSO@{ub} + @{setMatRotate() link setMatRotate}, @{setMatScale() link setMatScale} +@endnode + + +@node setMatRotate +@{u}filledvector.m/setMatRotate filledvector.m/setMatRotate@{uu} + + @{b}SYNTAX@{ub} + + VOID setMatRotate( matrix, anglex, angley, anglez ) + + @{b}PURPOSE@{ub} + + Sets up the contents of the matrix pointed to by matrix to + a rotation matrix which represents the rotations provided + in the arguments. This matrix is itself a concatentated + matrix (but calculated much more efficiently than taking + 3 2d rotations and multiplying them together), and as such + has certain properties. For example, the order of rotations + becomes important - i think the order is anglez, angly then + anglex. + + If you wish to rotate with other angle ordering, then + you can make 2d rotation matrices using this function, + and setting two of the angles to 0, then concatenating + the resultant matrices yourself (using @{matMult() link matMult}). + + @{b}INPUTS@{ub} + anglex, angley, anglez + The angles to use as the basis of the rotations. + 0 = 0 degrees, and 512 = 360 degrees. + +OUTPUS + matrix Matrix setup with a rotation matrix + + @{b}SEE ALSO@{ub} + @{setMatIdent() link setMatIdent}, @{setMatScale() link setMatScale} +@endnode + + +@node setMatScale +@{u}filledvector.m/setMatScale filledvector.m/setMatScale@{uu} + + @{b}SYNTAX@{ub} + + VOID setMatScale( matrix, scalex, scaley, scalez ) + + @{b}PURPOSE@{ub} + + Sets up the contents of the matrix pointed to by matrix to + a scaling matrix which represents the scaling provided + in the arguments. + + This provides a true mathematicall accurate scaling operation, + that can be concatenated and ordered correctly. For a simpler + version, see @{matSize() link matSize}. + + @{b}INPUTS@{ub} + scalex, scaley, scalez + The scaling values (fixed point) to be used to setup + the matrix. These fixed point values are normalised + to 1024. This means a value of 512 will mean a + halving along that axis, and a value of 2048 + a doubling etc. + + @{b}OUTPUTS@{ub} + matrix Matrix setup with a scaling operation + + @{b}NOTES@{ub} + Dont try to scale above 32 times larger! (32767), negative + values are also acceptable, and will tend to flip the + object inside out along that axis (odd results). + + @{b}SEE ALSO@{ub} + @{setMatIdent() link setMatIdent}, @{setMatRotate() link setMatRotate}, @{matSize() link matSize} +@endnode + + +@node matSize +@{u}filledvector.m/matSize filledvector.m/matSize@{uu} + + @{b}SYNTAX@{ub} + + VOID matSize( matrix, scalex, scaley, scalez ) + + @{b}PURPOSE@{ub} + + Modifies the matrix, by scaling each of its rows by the + 3 values provided. This provides a more efficient + way to add a scaling operation to a matrix, but it always + acts as if it was the last operation performed on the + matrix. + + @{b}INPUTS@{ub} + scalex, scaley, scalez + The scaling values (fixed point) to be used to setup + the matrix. These fixed point values are normalised + to 1024. This means a value of 512 will mean a + halving along that axis, and a value of 2048 + a doubling etc. + + @{b}OUTPUTS@{ub} + matrix Matrix modified with the scaling factors above + + @{b}SEE ALSO@{ub} + @{setMatScale() link setMatScale} +@endnode + + +@node matMult +@{u}filledvector.m/matMult filledvector.m/matMult@{uu} + + @{b}SYNTAX@{ub} + + VOID matMult( source matrix, dest matrix ) + + @{b}PURPOSE@{ub} + + Concatenates the two matrix operations, by left multiplying + (go look in a maths book!) the destination matrix by the + source matrix, and storing the result in the dest matrix. + The net result is that the two transformation matrices are + combined, with the effect being that the resultant matrix + will represent the operation originally performed by the + dest matrix, followed by the operation performed by the + source matrix. + + Maybe an @{example link matrixinfo} would help! + + @{b}INPUTS@{ub} + source matrix + operation to be performed by the concatenated result + last. This matrix is left-multiplied with the + dest matrix. + dest matrix + operation to be performed by the concatenated result + first. The result of the entire operation is also + stored in here + + @{b}OUTPUTS@{ub} + dest matrix + the result of the operation is stored in the dest matrix + + @{b}NOTES@{ub} + The result of any concatenation must fit within the size + of the numbers used to prevent any errors. This means + that the net result of any operation must not result + in a scaling up of more than 32x. + + @{b}SEE ALSO@{ub} + @{setMatRotate() link setMatRotate}, @{setMatScale() link setMatScale}, @{setMatIdent() link setMatIdent} +@endnode + + +@node matApply3 +@{u}filledvector.m/matApply3 filledvector.m/matApply3@{uu} + + @{b}SYNTAX@{ub} + + VOID matApply3( matrix, number, source points, dest points ) + + @{b}PURPOSE@{ub} + + Multiplies each 3d point in the points list by the matrix, + and stores the result somewhere else. + + The matrix can be setup to perform any affine transformation + that it has been setup to (currently functions exist for + setting up scaling and rotation matrices only). + + @{b}INPUTS@{ub} + matrix matrix containing transformation to apply. + number the number of points to apply the operation to. + Currently, must be >0. + source points + An array of INT's which contains the 3d coordinates + to process + + @{b}OUTPUTS@{ub} + dest points + An array, at least as big as number*3 INT's in which + to store the result. This value may be the same + as the source points parameter, if you just wish to + process an existing list of points. + + @{b}SEE ALSO@{ub} + @{setMatRotate() link setMatRotate}, @{setMatScale() link setMatScale}, @{setMatIdent() link setMatIdent}, + @{matMult() link matMult} +@endnode + + +@node Examples "Example code" + + + I've had this module floating around on my hdd for 6-12 months + actually ... i just needed to gt my finger out and write + all this damn documentation :) + + (i was going to recode it using some ideas i've had since then, + but i never got around to it ..!) + + Anyway, it means i've had time to come up with some decent + (if still trivial) examples. + + The Vxx+ below shows which versions of the OS the examples work + with. Since some use the ScrBuffer module, they require + Workbench 3.0+ (V39+). + + @{cube link cube.e/main} V33+ + + A very simple example which demonstrates the basics required to + get a vector object spinning on the screen. It uses the + cube designed in the @{tutorial link objectdesign.guide/main}, and also some + simple Workbench 1.2 functions to do the page flipping. + + @{cube39 link cube39.e/main} V39+ + + Another simple demo of the module. This one also uses the + Workbench 3.0+ double buffering routines to make it run smoother, + and allow you to drag the screen. + + @{zed link zed.e/main} V39+ + + One of the first examples i coded :) Its a spinning Zed logo, + and uses WB3.0 double buffering, and demonstrates the use + of that, the vector module, multiple part objects, and some + of the matrix routines. Use the left mousebutton to make it + go away, and right to make it come closer. (you can still + drag its screen BTW). Both to exit. + + @{wb1200 link wb1200.e/main} V37+ + + An animated workbench backdrop! Uses an offscreen render bitmap to + draw a picture, which is then blitted to the workbench screen. + This has been tested and works on machines with custom graphics + cards! (if slowly ...) + + @{torus link torus.e/main} V37+ + + Identical to wb1200, but uses a different object. The object + in this one was created in imagine, and converted using a + longwinded and labourious process ... + +@endnode diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/ObjectDesign.guide b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/ObjectDesign.guide new file mode 100644 index 0000000..d43bfab --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/ObjectDesign.guide @@ -0,0 +1,524 @@ +@database ObjectDesign.guide + +Docs for filled vector module, designing objects + +© 1994 Michael Zucchi +All rights reserved + +@node Main "ObjectDesign.guide" + +Documentation for Filled Vector Module for AmigaE 3.0+, object design + +© 1994 @{"Michael Zucchi" Link "FilledVector.guide/Author"} +All Rights Reserved + + + @{"Creating new objects" link Create} + + @{"Modifying objects" link Modify} + + @{"Using objects" link Using} + +@endnode + +@node Create "Creating Objects" + +@{u}Object Creation@{uu} + + +Creating objects by hand is very difficult ... unfortunately, +this is the iinly real way to create objects at the moment. + +The utility @{ReadNFF link ReadNFF} can however be used to simplify +the entry of data into the computer, and if you dont mind +being limited to objects made of triangles, you can even use it +to read in objects created with Imagine (not without more +work mind you). + +The following steps need to be taken whether designing objects +with or without using ReadNFF, its just the final stages that +can be simplified using it. + +@{u}Starting@{uu} + +First, you need an idea. This can often be difficult, especially +since you will want to create the object so it uses as few polygons +as possible, yet still gets drawn correctly. + +@{u}Working out the points@{uu} + +Once you have the idea though, it helps to draw it down on a piece +of paper. You need to be able to identify and number all of +the vertices or points in the object. The actual coordinates +of these vertices will also need to be calculated - in 3d. Drawing +several views of the object may help with this. + +After this stage, you should have a list of coordinates, and you +should also have identified each of the points by an index (start +it at 0). + +For example, a cube. + + 4-----5 + /| /| + 0-----1 | + | | | | + | | | | + | 7---|-6 + |/ |/ + 3-----2 + + + +'ve Y + ^ + | ^+'ve Z + |/ + o--> +'ve X + +The numbers show the points we have assigned to each of the 8 +corners of the cube. + +Say, we want the cube to be 200*200*200 in size, we also would +like to have centered about its centre of gravity (in the middle) +so we place each point 100 from the origin. + +This, our points table becomes: + + -100,100,-100 0 + 100,100,-100 1 + 100,-100,-100 2 + -100,-100,-100 3 + -100,100,100 4 + 100,100,100 5 + 100,-100,100 6 + -100,-100,100 7 + +Ok, so far so good, this is actually the easy part for most objects ... + + +@{u}Working out the polygons@{uu} + +This is where it starts to get tricky. Each "face" of an object +(i.e. polygon) requires several pieces of information. + +Firstly, it requires a set of line end-points which go up to make +lines which form the polygon edges. This list of points must +form a CLOSED shape. It can however form this shape in whatever +way it likes, including crossing lines, and even several closed +shapes. If multiple shapes are present, then they act as if each +of them is complemented together (i.e. they will be transparent +where they overlap). There is one restriction however for +each polygon or face formed, all of the points of the face +should be in the same "plane" otherwise it wont draw correctly. + +So, going back to our cube example, the front face would consist +of the following linking lines: + +point 0 connected to 1, 1 to 2, 2 to 3 and 3 to 0. + +This is 4 lines, so our polygon definition becomes: + +[4, 0,1,1,2,2,3,3,0]:INT + +The other polygons can be similarly defined. + +@{u}Working out the order@{uu} + +One very important thing to note about how this vector module works +is that individual polygons are NOT depth sorted! And yet, even +very complex shapes like the 2 from the A1200 logo are drawn +correctly. How can this be so? + +This is where the 2 other pieces of information provided to the +rendering engine are used. Firstly, the "crossn" members of +the face OBJECT are used to describe which way a given polygon +is facing (out or in), this allows the render engine to automatically +forget about drawing the back sides of objects (known as backface +removal). Secondly, the order in which the polygons are drawn +(which is the same as the order they are defined in the creation +function) becomes important. + +This takes a bit of a mind-leap, but if you think about it carefully +enough, you can see that only drawing faces of objects that are indeed +facing you, and drawing them in the right order, you can get away +without having to do any depth sorting for most objects you are +likely to try to design. + +Take a table as an example. If you wish to create a 3d table, with +a solid, filled tabletop, and 4 square legs, you order the polygons +like this: + +draw the underside of the table +draw the 2 inside (the ones facing the centre of the table) faces of all + legs +draw the 2 outside faces of all of the legs +draw the sides of the table +draw the tabletop + +Since faces which are not "facing" the viewer are automatically culled, +it can see that the above scheme can be used to draw the table +accurately from EVERY concievable external view. + +And whats more, since no depth sorting step is required, computation +time is reduced. + +Some objects however cannot be drawn accurately all the time using this +technique - either make sure you get it right for the cases where +it is visible, break it into seperate objects, or simplify your object +:) + +In the case of this simple cube, the order is unimportant, since +there are no overlapping polygons (when drawn). + +@{u}Cross product indices@{uu} + +The cross product points (the "crossn" members mentioned above) are +very necessary though. Its not too difficult to work out these +either, provided you have a good spatial sense (unless you want +to keep drawing rotated views of your object anyway!). + +What you need to do for each face, is work out 3 points that +are in the same plane as the face (usually 3 points of the +face/polygon itself). Ideally, the 3 points should be as far apart +as possible, and lines from the middle one to the other 2 should +be close to 90 degrees (this is not necessary, but it provides +for a more accurate result). These 3 points must then be ordered +so that if you were to draw a line from point 0 to point 1, then +point 1 to point 2, the lines would move around in a clockwise +direction - this is if the object were rotated so that the given +polygon was facing you. + +So, for the cube, for front face, the 3 points could be: +0,1,2 +They could also be 1,2,3 or 2,3,0 or 3,0,1 as well. + +As an example, the back face would have to use 6,5,4 or +and combination in the same direction. If we used 4,5,6 +then it would mean that that back face was facing inwards +instead of outwards, and the object wouldn't be drawn +properly. Remember, the points need to traverse in a +clockwise direction around the polygon. + +Incidentally, theres nothing stopping you defining 2 faces +with the same points, but one facing outwards, and one inwards, +if you really needed two sided polygons. + +Finally, choose which colour index you want for each of the +polygons, taking into account the palette of the screen on +which you willbe working. + +You now basically have all the information required to generate +a new vector object. The following sections describe how you +do this by hand, or alternatively, how to use @{ReadNFF link ReadNFF} to +help you. + +@{u}Putting it together, all by hand@{uu} + +For the cube, we have: +front face: + [0,1,2, 1, [4, 0,1,1,2,2,3,3,0]:INT, 0]:face + + ^^^^^ - The 3 cross product indices calculated above + + ^ - The colour of this polygon + + ^ - The number of edges in the polygon + + ^^^^^^^^^^^^^^^ - The edge link table, + pairs of line endpoints + + ^ - padding + +This can be done for all of the 6 faces of the cube to create +the face array that needs to be fed into the newVectorObject() +call. + +With a bit more work, we get: + + [0,1,2, 1, [4, 0,1,1,2,2,3,3,0]:INT, 0, -> front + 6,5,4, 2, [4, 4,5,5,6,6,7,7,4]:INT, 0, -> back + 2,1,5, 3, [4, 1,5,5,6,6,2,2,1]:INT, 0, -> right + 4,0,3, 4, [4, 4,0,0,3,3,7,7,4]:INT, 0, -> left + 1,0,4, 5, [4, 0,1,1,5,5,4,4,0]:INT, 0, -> top + 7,3,2, 6, [4, 3,2,2,6,6,7,7,3]:INT, 0]:face -> bottom + +And in this case, the ordering is unimportant. + +Although above i usually defined the polygon using point indices +which followed on from each other around the edges of the +polygon, any ordering is allowed. For example, the front +could also have been defined as: + + [0,1,2, 1, [4, 3,2,0,1,0,3,1,2]:INT, 0, -> front + +Since, the lines formed still create the same shape. + +Combining everything so far, we can come up with the function call +required to make our cube exist. + + cube:=newVectorObject(0, -> basic type + 8, -> 8 points + 6, -> 6 faces + [-100,100,-100, -> 0 -> points array + 100,100,-100, -> 1 + 100,-100,-100, -> 2 + -100,-100,-100, -> 3 + -100,100,100, -> 4 + 100,100,100, -> 5 + 100,-100,100, -> 6 + -100,-100,100]:INT, -> 7 -> faces array below + [0,1,2, 1, [4, 0,1,1,2,2,3,3,0]:INT, 0, -> front + 6,5,4, 2, [4, 4,5,5,6,6,7,7,4]:INT, 0, -> back + 2,1,5, 3, [4, 1,5,5,6,6,2,2,1]:INT, 0, -> right + 4,0,3, 4, [4, 4,0,0,3,3,7,7,4]:INT, 0, -> left + 1,0,4, 5, [4, 0,1,1,5,5,4,4,0]:INT, 0, -> top + 7,3,2, 6, [4, 3,2,2,6,6,7,7,3]:INT, 0]:face); -> bottom + +And thats it! _phew_ Have a look at some of the examples, you +can appreciate how difficult some of them were to make :) + +@{u}Putting it together, using ReadNFF@{uu} + +Checkout the @{ReadNFF link ReadNFF} section for this. + +@endnode + +@node ReadNFF + +@{u}ReadNFF information@{uu} + +This is a badly written, kludgy, and awkward to use utility +that can however greatly simplify object creation. + +There not many @{options link rnffOptions} that need explaining. + +It reads in a file in NFF format (neutral file format?) and +converts it to sourcecode for the function call to create +the object in AmigaE format. + +Apart from designing objects using NFF by hand, there are +utilities such as tddd2nff which can be used to convert +Imagine objects to NFF, then NFF can be read by ReadNFF +to create a function call. However, imagine doesn't +know anything about polygon ordering, or correct +cross product direction (since imagine uses triangles, +ReadNFF is able to create the right cross product for +you - but it will often be in reverse of what you want) +doesn't work. So, it often requires a lot of hand-work +to get the objects to work anyway ... + +Going back to the cube example, we'll see how to use +ReadNFF to do some of the work. + + + 4-----5 + /| /| + 0-----1 | + | | | | + | | | | + | 7---|-6 + |/ |/ + 3-----2 + +For the ReadNFF file, what we need to do is to define all +of the coordinates for each polygon. We can also try +to order these points so that the polygons themselves +are defined in clockwise order (to help the code +create accurate cross product points), but this wont +always work if the object has >3 points because +of the point optimisation method used. + +So, we come up with the following definition for our cube: + +# a cube, in NFF format +# Comments start with #, and can be anywhere outside of +# polygon definitions +# A polygon definition is started with a p, followed by +# exactly one space, then a number which defines +# the number of points in that polygon +# There is 1 point per line, seperated with spaces +# with the x coordinate flush left (no leading +# spaces), with spaces (not tabs!) seperating +# each number +# front face +p 4 +-100 100 -100 +100 100 -100 +100 -100 -100 +-100 -100 -100 +# back face +p 4 +-100 -100 100 +100 -100 100 +100 100 100 +-100 100 100 +# right +p 4 +100 100 -100 +100 100 100 +100 -100 100 +100 -100 -100 +# left +p 4 +-100 100 -100 +-100 -100 -100 +-100 -100 100 +-100 100 100 +# top +p 4 +-100 100 -100 +-100 100 100 +100 100 100 +100 100 -100 +# bottom +p 4 +100 -100 -100 +-100 -100 -100 +-100 -100 100 +100 -100 100 + + +Ok, this can be fed into ReadNFF, and it comes up with: +(with a little editing) + + + obj:=newVectorObject(0,8,6, + [-100,100,-100, + 100,100,-100, + 100,-100,-100, + -100,-100,-100, + -100,-100,100, + 100,-100,100, + 100,100,100, + -100,100,100]:INT, + [0,1,2,0,[4,0,1,1,2,2,3,3,0]:INT,0, + 4,5,6,1,[4,4,5,5,6,6,7,7,4]:INT,0, + 1,6,5,2,[4,1,6,6,5,5,2,2,1]:INT,0, + 0,3,4,3,[4,0,3,3,4,4,7,7,0]:INT,0, + 0,7,6,4,[4,0,7,7,6,6,1,1,0]:INT,0, + 2,3,4,5,[4,2,3,3,4,4,5,5,2]:INT,0]:face + +The editing involved: + deleting a spurios point at the end of the point array + (ok, so its buggy as hell!) + adding the []:face to the face array, and moving + it from the start of the output to the end + and thats about it ... + +So, will this object work all on its own? I think so, since +because the way the points were ordered in the file, they +came out the same as the original. In this case, no more +editing is required, luckily. All that needs to be modified +is the colours, which isn't too difficult. + +With more complex objects, you may have to manually enter +in the cross product indices as well as the colours. It +does save a bit of work though. @{Torus link torus.e/main} shows +an example of an object created in Imagine 2.0 (using +create primitive/torus), which was then hand-edited to make +it work (every second polygon needed its cross indices +reversed). + +Hopefully one day i'll sit down and design either a proper +script language to make designing objects simpler, or +a 3d editor ... (although, other commitments may affect +this!). + +@endnode + + +@node rnffoptions "ReadNFF command line options" + + ReadNFF options: + + When you run it, it will open a window and the file, and as the + file is read in, a wireframe version of the object will + be displayed. The output of the program is simply dumped + to the cli inwhich it was run. Once finished, it will + automatically close the window. + + NAME/A + Supply the filename of the NFF file to read. Not much + error checking is done, so if this is in an invalid + format, you're not going to get much more than a bloody + mess out of it :) + + SHIFT/N + Amount to shift values before they are output. This is + only important with floating point input, or where + some scaling is needed. Each number conforms to a shift + up by 1. So, a shift value of 2 will mean the values + are multiplied by 4 before being converted to ingeter + format. + +@endnode + +@node Modify "Modifying Objects" + +@{u}Modifying Objects@{uu} + +Currently there is really only one way to modify objects - the +points in the object can be modified. + +You can't even modify the colours of polygons and so on +for copied objects (which would be handy ...) this should +be fixed soon ... + +@{u}Playing with Points@{uu} + +Using @{getVObjectPoints() link filledvector.guide/getvobjectpoints} the application programmer +has direct access to the coordinate table used by the object. +This can be modified in any way you see fit, say by scaling +the object and so on. + +One thing that must be noted thouh, is that the points should +continue to retain the same relationship to each other as +when the object was defined - otherwise the face setup, +backface removal and so on will not operate correctly. + +This still allows a bit of scope for object morhping and things +like that. (If i had the effort, i'd give you an example +of morphing objects :) + + +For objects that have been copied using @{copyVectorObject() link filledvector.guide/copyvectorobject} +you can modify the points freely, as each copy of the object +gets its own points. For cloned objects (@{cloneVectorObject() link filledvector.guide/clonevectorobject} +the point lists are NOT copied, so in this case, you must +be careful you dont accidentally change the wrong points! + + +When objects have been copied, this is where being able +to modify them becomes useful. You can use the rotation +and scaling functions in @{"matrix operations" link filledvector.guide/matrix} to +modify the copied object to create new versions. + +@endnode + +@node Using "Using Objects" + +@{u}Using Objects@{uu} + +Its all very well being able to create and bend objects and so +on, but how do you get them onto the screen usefully? + +One-off objects, like a swirling Zed logo are easy enough. +This uses a vector object list to allow the system itself +to handle the nitty gritty of depth sorting and so on, +and then uses the object's positions to position the +letters within their own "space". + +Using the @{matrix link filledvector.guide/matrix} functions, you +could build up your own library of functions designed to +position the objects (using thier position specifiers), +rotate them to the view you want, and then use the +@{"vector object list functions" link filledvector.guide/VectorObject} to do the depth sorting +and rendering for you. + +Finally, you could code everything yourself except for the +object rendering function, and just use @{drawVObject() link filledvector.guide/drawVObject} +to do the hard work, at reasonable speed. + + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube.e b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube.e new file mode 100644 index 0000000..167a81b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube.e @@ -0,0 +1,69 @@ + +/* + + A _simple_ cube example, using Workbench 1.3 code + + FilledVector.m module example code, Michael Zucchi + + This code in the public domain + +*/ + +OPT OSVERSION=33 + +MODULE 'intuition/intuition', 'intuition/screens', + 'tools/filledvector', 'tools/filledvdefs' + +DEF s0:PTR TO screen, s1:PTR TO screen, scr:PTR TO screen, + pc,cube:PTR TO vobject, destz=2000; + +PROC main() + +s0:=OpenS(320,200,4,0,'3d Cube'); -> 2 screens for doublebuffering +s1:=OpenS(320,200,4,0,'3d Cube'); + +pc:=newPolyContext(s0.bitmap,20) -> create context +setPolyFlags(pc,1,1) -> turn on zclipping + + cube:=newVectorObject(0, -> basic type + 8, -> 8 points + 6, -> 6 faces + [-100,100,-100, -> 0 -> points array + 100,100,-100, -> 1 + 100,-100,-100, -> 2 + -100,-100,-100, -> 3 + -100,100,100, -> 4 + 100,100,100, -> 5 + 100,-100,100, -> 6 + -100,-100,100]:INT, -> 7 -> faces array below + [0,1,2, 1, [4, 0,1,1,2,2,3,3,0]:INT, 0, -> front + 6,5,4, 2, [4, 4,5,5,6,6,7,7,4]:INT, 0, -> back + 2,1,5, 3, [4, 1,5,5,6,6,2,2,1]:INT, 0, -> right + 4,0,3, 4, [4, 4,0,0,3,3,7,7,4]:INT, 0, -> left + 1,0,4, 5, [4, 0,1,1,5,5,4,4,0]:INT, 0, -> top + 7,3,2, 6, [4, 3,2,2,6,6,7,7,3]:INT, 0]:face); -> bottom + +scr:=s0 +cube.pz:=1000; + +WHILE Mouse()<>3 + SetRast(scr.rastport,0); -> clear the screen + setPolyBitMap(pc, scr.bitmap); -> take note of change + drawVObject(pc, cube); -> draw to off-screen + + ScreenToFront(scr); -> bring it to the front + + cube.ax:=cube.ax+1 -> move object + cube.ay:=cube.ay+2 + cube.az:=cube.az+3 + cube.pz:=cube.pz+((destz-cube.pz)/6) + IF Abs(cube.pz-destz)<6 THEN destz:=Rnd(2000)+10 + + IF scr=s0 THEN scr:=s1 ELSE scr:=s0; -> swap screens +ENDWHILE + +freeVectorObject(cube); +CloseS(s0) +CloseS(s1) + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube39.e b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube39.e new file mode 100644 index 0000000..b037a6d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/cube39.e @@ -0,0 +1,67 @@ + +/* + + A _simple_ cube example, using Workbench 3.0 code + + FilledVector.m module example code, Michael Zucchi + + This code in the public domain + +*/ + +OPT OSVERSION=39 + +MODULE 'intuition/intuition', 'intuition/screens', + 'tools/filledvector', 'tools/filledvdefs', + 'tools/scrbuffer', + 'graphics/rastport' + +DEF scr,pc,cube:PTR TO vobject, destz=2000, + rast:rastport; + +PROC main() + +InitRastPort(rast); + +scr:=sb_OpenScreen([SA_DEPTH,4,SA_WIDTH,320,SA_HEIGHT,200,0],0); + +pc:=newPolyContext(sb_GetBitMap(scr),20) -> create context +setPolyFlags(pc,1,1) -> turn on zclipping + + cube:=newVectorObject(0, -> basic type + 8, -> 8 points + 6, -> 6 faces + [-100,100,-100, -> 0 -> points array + 100,100,-100, -> 1 + 100,-100,-100, -> 2 + -100,-100,-100, -> 3 + -100,100,100, -> 4 + 100,100,100, -> 5 + 100,-100,100, -> 6 + -100,-100,100]:INT, -> 7 -> faces array below + [0,1,2, 1, [4, 0,1,1,2,2,3,3,0]:INT, 0, -> front + 6,5,4, 2, [4, 4,5,5,6,6,7,7,4]:INT, 0, -> back + 2,1,5, 3, [4, 1,5,5,6,6,2,2,1]:INT, 0, -> right + 4,0,3, 4, [4, 4,0,0,3,3,7,7,4]:INT, 0, -> left + 1,0,4, 5, [4, 0,1,1,5,5,4,4,0]:INT, 0, -> top + 7,3,2, 6, [4, 3,2,2,6,6,7,7,3]:INT, 0]:face); -> bottom + +cube.pz:=1000; + +WHILE Mouse()<>3 + rast.bitmap:=sb_NextBuffer(scr); -> next screen + SetRast(rast,0); -> clear the off-screen + setPolyBitMap(pc, rast.bitmap); -> take note of change + drawVObject(pc, cube); -> draw to off-screen + + cube.ax:=cube.ax+1 -> move object + cube.ay:=cube.ay+2 + cube.az:=cube.az+3 + cube.pz:=cube.pz+((destz-cube.pz)/6) + IF Abs(cube.pz-destz)<6 THEN destz:=Rnd(2000)+10 +ENDWHILE + +freeVectorObject(cube); +sb_CloseScreen(scr); + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/torus.e b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/torus.e new file mode 100644 index 0000000..3c05163 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/torus.e @@ -0,0 +1,373 @@ + +/* + + Complex Workbench2.0+ Example of FilledVector.m + + This program creates a spinning Torus that spins + around on the back of Workbench. On a 1200 without + fastmem, it can hapily be run in the background without + causing noticeable delays. This object is a bit + more 'chunky' than the a1200 logo in wb1200, and + it can make the system feel a bit jerky. + + On the command line, specify the number of columns, + followed by the number of rows of images you want, + it defaults to 2x2. + + Run it with Workbench NOT inbackdrop mode, and to + remove it, run it again (it will interact with + the other wbbackdrop code in this archive) + + + The Torus was created in Imagine 2.0, and then saved. + The program tddd2nff (from t3dlib) was then used to + decompose the object into NFF. ReadNFF was then + used to convert the object to FilledVector.m format, + and following this, some hand editing (quite a lot ...) + was used to create a useable object. + + + Michael Zucchi, 1994. Program in public domain. + + (this is identical to wb1200.e, but has a different + object) +*/ + + + +OPT OSVERSION=37 + +MODULE 'tools/filledvector', 'tools/filledvdefs', + 'exec/lists', 'exec/ports', 'exec/nodes', 'exec/libraries', + 'intuition/screens', 'intuition/intuition', 'intuition/intuitionbase', + 'graphics/gfx', 'graphics/rastport', 'graphics/layers' + +DEF list:PTR TO mlh,pc, + ball:PTR TO vobject, + scr:PTR TO screen,abitm:PTR TO bitmap, + win:PTR TO window, + myrast:rastport, + mport:PTR TO mp, + width,height,depth, + rows,cols + +DEF dx,dy,dz + +/******************************************************************** + + main + + */ + +PROC main() +DEF rdargs, args:PTR TO LONG,p:PTR TO LONG, i, gfx:PTR TO lib + +cols:=2; +rows:=2; + +-> check arguments +args:=[0,0]; +IF rdargs:=ReadArgs('cols/N,rows/N', args, 0) + IF p:=args[0] THEN cols:=p[0] + IF p:=args[1] THEN rows:=p[0] + FreeArgs(rdargs); +ENDIF + +-> see if we're already running, if yes, signal the other version +Forbid(); +mport:=FindPort('backdrop'); +IF mport + Signal(mport.sigtask, Shl(1,mport.sigbit)) +ENDIF +Permit(); + +-> if we are not already running, start doing our thing +IF mport=0 + + -> create a public port where we can be found later + mport:=CreateMsgPort(); + mport::ln.name:='backdrop'; + mport::ln.pri:=-128; + AddPort(mport); + + -> open the backdrop window + win:=OpenWindowTagList(0, [WA_FLAGS, WFLG_BACKDROP OR WFLG_BORDERLESS OR WFLG_SIMPLE_REFRESH OR WFLG_NOCAREREFRESH, + WA_BACKFILL, LAYERS_NOBACKFILL, 0]); + + -> calculate size of each tile + width:=win.width/cols + height:=win.height/rows + IF height AND 1 THEN height++ + IF width AND 31 THEN width:=width+(32-(width AND 31)) + + -> find the depth of workbench, and open our rendering bitmap + scr:=LockPubScreen(0); + + depth:=scr.rastport::rastport.bitmap::bitmap.depth + gfx:=gfxbase; + + IF gfx.version<39 + abitm:=New(SIZEOF bitmap+(8*4)); + p:=abitm.planes + FOR i:=0 TO depth-1 DO p[i]:=AllocRaster(width,height); + InitBitMap(abitm,depth,width,height); + ELSE + abitm:=AllocBitMap(width,height,depth, + BMF_CLEAR+BMF_INTERLEAVED,0); + ENDIF + + UnlockPubScreen(0, scr); + + -> finish of setting up, then goto the main loop + SetTaskPri(FindTask(0), -128); + InitRastPort(myrast); + myrast.bitmap:=abitm; + + IF win + IF createobjects() + IF pc:=newPolyContext(abitm,50) + demo() + freePolyContext(pc) + ENDIF + freeobjects() + ENDIF + CloseWindow(win); + ENDIF + + IF gfx.version<39 + p:=abitm.planes + FOR i:=0 TO depth-1 DO FreeRaster(p[i], width,height); + InitBitMap(abitm,depth,width,height); + ELSE + FreeBitMap(abitm); + ENDIF + + RemPort(mport); + DeleteMsgPort(mport); + +ENDIF -> IF mport=0 + +ENDPROC + +/******************************************************************** + + Main loop. Render/move the object until we get told to stop + + */ + +PROC demo() + DEF p:position,x,y,c, sigbit, destz + + c:=0; + p.ax:=0;p.ay:=0;p.az:=0;p.px:=0;p.py:=0;p.pz:=750; + + destz:=Rnd(1000)+400; + sigbit:=Shl(1, mport.sigbit); + setPolyFlags(pc,1,1) + + -> main loop + WHILE (SetSignal(0, sigbit) AND sigbit)=0 -> see if we've been told to stop? + + cls() + setPolyBitMap(pc, abitm) + + IF c--<0 + setangles() + c:=60; + ENDIF + + -> pri back to 0, this will stop us losing cpu while blitter owned (hang!) + SetTaskPri(FindTask(0), 0); + + moveDrawVList(pc, list, p) + FOR x:=0 TO cols-1 + FOR y:=0 TO rows-1 + BltBitMapRastPort(abitm, 0,0, win.rport, x*width,y*height,width,height,$c0); + ENDFOR + ENDFOR + + -> its safe to go back to low pri again + SetTaskPri(FindTask(0), -128); + + -> move object + p.pz:=p.pz+((destz-p.pz)/6) + IF Abs(p.pz-destz)<6 THEN destz:=Rnd(4000)+200 + p.az:=p.az+dz; + p.ax:=p.ax-dx; + p.ay:=p.ay+dy; + + ENDWHILE +ENDPROC + +PROC setangles() +dx:=Rnd(9)-4 +dy:=Rnd(9)-4 +dz:=Rnd(9)-4 +ENDPROC + + +/******************************************************************** + + Clears the bitmap we're rendering into, then fills it with the + stipple pattern + + */ + +PROC cls() + SetRast(myrast, 0); + WaitBlit() + + MOVE.L abitm,A2 + MOVE.L 8(A2),A1 + MOVE.L height,D3 + LSR.L #1,D3 + SUBQ.L #1,D3 + MOVE.L #$55555555,D0 + MOVE.L #$AAAAAAAA,D1 +d_lp0: + MOVE.L A1,A0 + ADDA.W (A2),A1 + MOVE.L width,D2 + LSR.W #5,D2 + SUBQ.W #1,D2 +d_lp1: + MOVE.L D0,(A0)+ + DBF D2,d_lp1 + MOVE.L A1,A0 + ADDA.W (A2),A1 + MOVE.L width,D2 + LSR.W #5,D2 + SUBQ.W #1,D2 +d_lp2: + MOVE.L D1,(A0)+ + DBF D2,d_lp2 + DBF D3,d_lp0 +ENDPROC + +/******************************************************************** + + Create all of the objects + + */ + +PROC createobjects() + DEF stat=-1, + tmp:PTR TO vobject + + /* allocate a list, and add them to it */ + list:=newVList() + + ball:=newVectorObject(0,32,64, ->64, + [141,-142,100, + 200,0,100, + 277,-115,0, + 277,114,0, + 141,141,100, + 114,277,0, + 0,200,100, + -115,277,0, + -142,141,100, + -278,114,0, + -200,0,100, + -278,-115,0, + -142,-142,100, + -115,-278,0, + 0,-200,100, + 114,-278,0, + 200,0,-100, + 141,141,-100, + 0,200,-100, + -142,141,-100, + -200,0,-100, + -142,-142,-100, + 0,-200,-100, + 141,-142,-100, + 92,38,0, + 38,92,0, + -39,92,0, + -93,38,0, + -93,-39,0, + -39,-93,0, + 38,-93,0, + 92,-39,0, + 0,0,0]:INT, +[24,17,16,32,[3,16,17,17,24,24,16]:INT,0, -> all of these lines had their +24,25,17,33,[3,24,25,25,17,17,24]:INT,0, +25,18,17,34,[3,17,18,18,25,25,17]:INT,0, -> cross product numbers swapped +25,26,18,35,[3,25,26,26,18,18,25]:INT,0, +26,19,18,36,[3,18,19,19,26,26,18]:INT,0, -> +26,27,19,37,[3,26,27,27,19,19,26]:INT,0, +27,20,19,38,[3,19,20,20,27,27,19]:INT,0, -> +27,28,20,39,[3,27,28,28,20,20,27]:INT,0, +28,21,20,40,[3,20,21,21,28,28,20]:INT,0, -> +28,29,21,41,[3,28,29,29,21,21,28]:INT,0, +29,22,21,42,[3,21,22,22,29,29,21]:INT,0, -> +29,30,22,43,[3,29,30,30,22,22,29]:INT,0, +30,23,22,44,[3,22,23,23,30,30,22]:INT,0, -> +30,31,23,45,[3,30,31,31,23,23,30]:INT,0, +31,16,23,46,[3,23,16,16,31,31,23]:INT,0, -> +31,24,16,47,[3,31,24,24,16,16,31]:INT,0, +4,25,24,48,[3,24,25,25,4,4,24]:INT,0, -> +4,6,25,49,[3,4,6,6,25,25,4]:INT,0, +6,26,25,50,[3,25,26,26,6,6,25]:INT,0, -> +6,8,26,51,[3,6,8,8,26,26,6]:INT,0, +8,27,26,52,[3,26,27,27,8,8,26]:INT,0, -> +8,10,27,53,[3,8,10,10,27,27,8]:INT,0, +10,28,27,54,[3,27,28,28,10,10,27]:INT,0, -> +10,12,28,55,[3,10,12,12,28,28,10]:INT,0, +12,29,28,56,[3,28,29,29,12,12,28]:INT,0, -> +12,14,29,57,[3,12,14,14,29,29,12]:INT,0, +14,30,29,58,[3,29,30,30,14,14,29]:INT,0, -> +14,0,30,59,[3,14,0,0,30,30,14]:INT,0, +0,31,30,60,[3,30,31,31,0,0,30]:INT,0, -> +0,1,31,61,[3,0,1,1,31,31,0]:INT,0, +1,24,31,62,[3,31,24,24,1,1,31]:INT,0, -> +1,4,24,63,[3,1,4,4,24,24,1]:INT,0, + +16,3,2,16,[3,2,3,3,16,16,2]:INT,0, -> +16,17,3,17,[3,16,17,17,3,3,16]:INT,0, +17,5,3,18,[3,3,5,5,17,17,3]:INT,0, -> +17,18,5,19,[3,17,18,18,5,5,17]:INT,0, +18,7,5,20,[3,5,7,7,18,18,5]:INT,0, -> +18,19,7,21,[3,18,19,19,7,7,18]:INT,0, +19,9,7,22,[3,7,9,9,19,19,7]:INT,0, -> +19,20,9,23,[3,19,20,20,9,9,19]:INT,0, +20,11,9,24,[3,9,11,11,20,20,9]:INT,0, -> +20,21,11,25,[3,20,21,21,11,11,20]:INT,0, +21,13,11,26,[3,11,13,13,21,21,11]:INT,0, -> +21,22,13,27,[3,21,22,22,13,13,21]:INT,0, +22,15,13,28,[3,13,15,15,22,22,13]:INT,0, -> +22,23,15,29,[3,22,23,23,15,15,22]:INT,0, +23,2,15,30,[3,15,2,2,23,23,15]:INT,0, -> +23,16,2,31,[3,23,16,16,2,2,23]:INT,0, + +2,1,0,0,[3,0,1,1,2,2,0]:INT,0, -> +2,3,1,1,[3,2,3,3,1,1,2]:INT,0, +3,4,1,2,[3,1,4,4,3,3,1]:INT,0, -> +3,5,4,3,[3,3,5,5,4,4,3]:INT,0, +5,6,4,4,[3,4,6,6,5,5,4]:INT,0, -> +5,7,6,5,[3,5,7,7,6,6,5]:INT,0, +7,8,6,6,[3,6,8,8,7,7,6]:INT,0, -> +7,9,8,7,[3,7,9,9,8,8,7]:INT,0, +9,10,8,8,[3,8,10,10,9,9,8]:INT,0, -> +9,11,10,9,[3,9,11,11,10,10,9]:INT,0, +11,12,10,10,[3,10,12,12,11,11,10]:INT,0, -> +11,13,12,11,[3,11,13,13,12,12,11]:INT,0, +13,14,12,12,[3,12,14,14,13,13,12]:INT,0, -> +13,15,14,13,[3,13,15,15,14,14,13]:INT,0, +15,0,14,14,[3,14,0,0,15,15,14]:INT,0, -> +15,2,0,15,[3,15,2,2,0,0,15]:INT,0]:face) + + + ball.pz:=0 + addVObject(list,ball) + + +ENDPROC stat + +PROC freeobjects() + freeVList(list,1) /* also free nodes */ +ENDPROC + + + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/wb1200.e b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/wb1200.e new file mode 100644 index 0000000..ceba044 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/wb1200.e @@ -0,0 +1,444 @@ + +/* + + Complex Workbench2.0+ Example of FilledVector.m + + This program creates a spinning "A1200" logo that spins + around on the back of Workbench. On a 1200 without + fastmem, it can hapily be run in the background without + causing noticeable delays. + + On the command line, specify the number of columns, + followed by the number of rows of images you want, + it defaults to 2x2. + + Run it with Workbench NOT inbackdrop mode, and to + remove it, run it again. + + Michael Zucchi, 1994. Program in public domain. + +*/ + + + +OPT OSVERSION=37 + +MODULE 'tools/filledvector', 'tools/filledvdefs', + 'exec/lists', 'exec/ports', 'exec/nodes', 'exec/libraries', + 'intuition/screens', 'intuition/intuition', 'intuition/intuitionbase', + 'graphics/gfx', 'graphics/rastport', 'graphics/layers' + +DEF list:PTR TO mlh,pc, + let_0:PTR TO vobject, + let_1:PTR TO vobject, + let_2:PTR TO vobject, + let_A:PTR TO vobject, + scr:PTR TO screen,abitm:PTR TO bitmap, + win:PTR TO window, + myrast:rastport, + mport:PTR TO mp, + width,height,depth, + rows,cols + +DEF dx,dy,dz + +/******************************************************************** + + main + + */ + +PROC main() +DEF rdargs, args:PTR TO LONG,p:PTR TO LONG, i, gfx:PTR TO lib + +cols:=2; +rows:=2; + +-> check arguments +args:=[0,0]; +IF rdargs:=ReadArgs('cols/N,rows/N', args, 0) + IF p:=args[0] THEN cols:=p[0] + IF p:=args[1] THEN rows:=p[0] + FreeArgs(rdargs); +ENDIF + +-> see if we're already running, if yes, signal the other version +Forbid(); +mport:=FindPort('backdrop'); +IF mport + Signal(mport.sigtask, Shl(1,mport.sigbit)) +ENDIF +Permit(); + +-> if we are not already running, start doing our thing +IF mport=0 + + -> create a public port where we can be found later + mport:=CreateMsgPort(); + mport::ln.name:='backdrop'; + mport::ln.pri:=-128; + AddPort(mport); + + -> open the backdrop window + win:=OpenWindowTagList(0, [WA_FLAGS, WFLG_BACKDROP OR WFLG_BORDERLESS OR WFLG_SIMPLE_REFRESH OR WFLG_NOCAREREFRESH, + WA_BACKFILL, LAYERS_NOBACKFILL, 0]); + + -> calculate size of each tile + width:=win.width/cols + height:=win.height/rows + IF height AND 1 THEN height++ + IF width AND 31 THEN width:=width+(32-(width AND 31)) + + -> find the depth of workbench, and open our rendering bitmap + scr:=LockPubScreen(0); + + depth:=scr.rastport::rastport.bitmap::bitmap.depth + gfx:=gfxbase; + + IF gfx.version<39 + abitm:=New(SIZEOF bitmap+(8*4)); + p:=abitm.planes + FOR i:=0 TO depth-1 DO p[i]:=AllocRaster(width,height); + InitBitMap(abitm,depth,width,height); + ELSE + abitm:=AllocBitMap(width,height,depth, + BMF_CLEAR+BMF_INTERLEAVED,0); + ENDIF + + UnlockPubScreen(0, scr); + + -> finish of setting up, then goto the main loop + SetTaskPri(FindTask(0), -128); + InitRastPort(myrast); + myrast.bitmap:=abitm; + + IF win + IF createobjects() + IF pc:=newPolyContext(abitm,50) + demo() + freePolyContext(pc) + ENDIF + freeobjects() + ENDIF + CloseWindow(win); + ENDIF + + IF gfx.version<39 + p:=abitm.planes + FOR i:=0 TO depth-1 DO FreeRaster(p[i], width,height); + InitBitMap(abitm,depth,width,height); + ELSE + FreeBitMap(abitm); + ENDIF + + RemPort(mport); + DeleteMsgPort(mport); + +ENDIF -> IF mport=0 + +ENDPROC + +/******************************************************************** + + Main loop. Render/move the object until we get told to stop + + */ + +PROC demo() + DEF p:position,x,y,c, sigbit, destz + + c:=0; + p.ax:=0;p.ay:=0;p.az:=0;p.px:=0;p.py:=0;p.pz:=750; + + destz:=Rnd(1000)+400; + sigbit:=Shl(1, mport.sigbit); + setPolyFlags(pc,1,1) + + -> main loop + WHILE (SetSignal(0, sigbit) AND sigbit)=0 -> see if we've been told to stop? + + cls() + setPolyBitMap(pc, abitm) + + IF c--<0 + setangles() + c:=60; + ENDIF + + -> pri back to 0, this will stop us losing cpu while blitter owned (hang!) + SetTaskPri(FindTask(0), 0); + + moveDrawVList(pc, list, p) + FOR x:=0 TO cols-1 + FOR y:=0 TO rows-1 + BltBitMapRastPort(abitm, 0,0, win.rport, x*width,y*height,width,height,$c0); + ENDFOR + ENDFOR + + -> its safe to go back to low pri again + SetTaskPri(FindTask(0), -128); + + -> move object + p.pz:=p.pz+((destz-p.pz)/6) + IF Abs(p.pz-destz)<6 THEN destz:=Rnd(4000)+200 + p.az:=p.az+dz; + p.ax:=p.ax-dx; + p.ay:=p.ay+dy; + + ENDWHILE +ENDPROC + +PROC setangles() +dx:=Rnd(9)-4 +dy:=Rnd(9)-4 +dz:=Rnd(9)-4 +ENDPROC + + +/******************************************************************** + + Clears the bitmap we're rendering into, then fills it with the + stipple pattern + + */ + +PROC cls() + SetRast(myrast, 0); + WaitBlit() + + MOVE.L abitm,A2 + MOVE.L 8(A2),A1 + MOVE.L height,D3 + LSR.L #1,D3 + SUBQ.L #1,D3 + MOVE.L #$55555555,D0 + MOVE.L #$AAAAAAAA,D1 +d_lp0: + MOVE.L A1,A0 + ADDA.W (A2),A1 + MOVE.L width,D2 + LSR.W #5,D2 + SUBQ.W #1,D2 +d_lp1: + MOVE.L D0,(A0)+ + DBF D2,d_lp1 + MOVE.L A1,A0 + ADDA.W (A2),A1 + MOVE.L width,D2 + LSR.W #5,D2 + SUBQ.W #1,D2 +d_lp2: + MOVE.L D1,(A0)+ + DBF D2,d_lp2 + DBF D3,d_lp0 +ENDPROC + +/******************************************************************** + + Create all of the objects + + */ + +PROC createobjects() + DEF stat=-1, + tmp:PTR TO vobject + + /* allocate a list, and add them to it */ + list:=newVList() + + let_0:=newVectorObject(0,16,10, + [8*3,126*3,-20*4, + 37*3,30*3,-20*4, + 83*3,0*3,-20*4, + 134*3,0*3,-20*4, + 153*3,31*3,-20*4, + 111*3,144*3,-20*4, + 79*3,165*3,-20*4, + 20*3,165*3,-20*4, + 8*3,126*3,20*4, + 37*3,30*3,20*4, + 83*3,0*3,20*4, + 134*3,0*3,20*4, + 153*3,31*3,20*4, + 111*3,144*3,20*4, + 79*3,165*3,20*4, + 20*3,165*3,20*4]:INT, + [0,1,9,1, + [4,0,1,1,9,9,8,8,0]:INT,0, + 0+1,1+1,9+1,2, + [4,0+1,1+1,1+1,9+1,9+1,8+1,8+1,0+1]:INT,0, + 0+2,1+2,9+2,3, + [4,0+2,1+2,1+2,9+2,9+2,8+2,8+2,0+2]:INT,0, + 0+3,1+3,9+3,4, + [4,0+3,1+3,1+3,9+3,9+3,8+3,8+3,0+3]:INT,0, + 0+4,1+4,9+4,5, + [4,0+4,1+4,1+4,9+4,9+4,8+4,8+4,0+4]:INT,0, + 0+5,1+5,9+5,6, + [4,0+5,1+5,1+5,9+5,9+5,8+5,8+5,0+5]:INT,0, + 0+6,1+6,9+6,7, + [4,0+6,1+6,1+6,9+6,9+6,8+6,8+6,0+6]:INT,0, + 7,0,8,8, + [4,7,0,0,8,8,15,15,7]:INT,0, + -> front/back + 4,1,0,9, + [8,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,0]:INT,0, + 8,9,12,10, + [8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,8]:INT,0]:face); + + + + let_1:=newVectorObject(0,8,6, + [1*3,165*3,-20*4, + 22*3,165*3,-20*4, + 105*3,0*3,-20*4, + 84*3,0*3,-20*4, + 1*3,165*3,20*4, + 22*3,165*3,20*4, + 105*3,0*3,20*4, + 84*3,0*3,20*4]:INT, + [0,1,2,1, + [4,1,2,2,3,3,0,0,1]:INT,0, + 6,5,4,2, + [4,7,6,6,5,5,4,4,7]:INT,0, + 5,6,2,3, + [4,6,2,6,5,5,1,1,2]:INT,0, + 7,4,0,4, + [4,3,7,7,4,4,0,0,3]:INT,0, + 5,1,0,5, + [4,4,5,5,1,1,0,0,4]:INT,0, + 6,7,3,6, + [4,6,7,7,3,3,2,2,6]:INT,0]:face); + + let_A:=newVectorObject(0,22,13, + [2*3,165*3,-20*4, + 128*3,0*3,-20*4, + 148*3,0*3,-20*4, + 148*3,165*3,-20*4, + 127*3,165*3,-20*4, + 127*3,100*3,-20*4, + 76*3,100*3,-20*4, + 27*3,165*3,-20*4, + 127*3,84*3,-20*4, + 127*3,33*3,-20*4, + 88*3,84*3,-20*4, + 2*3,165*3,20*4, + 128*3,0*3,20*4, + 148*3,0*3,20*4, + 148*3,165*3,20*4, + 127*3,165*3,20*4, + 127*3,100*3,20*4, + 76*3,100*3,20*4, + 27*3,165*3,20*4, + 127*3,84*3,20*4, + 127*3,33*3,20*4, + 88*3,84*3,20*4]:INT, + [ + 9,10,21,2, -> left inside A + [4,9,10,10,21,21,20,20,9]:INT,0, + 8,9,20,1, -> inside right A + [4,8,9,9,20,20,19,19,8]:INT,0, + 4,5,16,4, -> right inside A + [4,4,5,5,16,16,15,15,4]:INT,0, + 5,6,17,5, -> inside top leg + [4,5,6,6,17,17,16,16,5]:INT,0, + 6,7,18,6, -> left inside leg + [4,6,7,7,18,18,17,17,6]:INT,0, + 10,8,19,3, -> bottom inside A + [4,10,8,8,19,19,21,21,10]:INT,0, + 0,1,12,7, -> left out + [4,0,1,1,12,12,11,11,0]:INT,0, + 1,2,13,8, -> top + [4,1,2,2,13,13,12,12,1]:INT,0, + 2,3,14,9, -> right out + [4,2,3,3,14,14,13,13,2]:INT,0, + 3,4,15,10, -> bottom leg right + [4,3,4,4,15,15,14,14,3]:INT,0, + 7,0,11,11, -> bottom leg left + [4,7,0,0,11,11,18,18,7]:INT,0, + 3,2,0,12, -> front + [11,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,0,8,9,9,10,10,8]:INT,0, + 11,13,14,13, -> back + [11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,11,19,20,20,21,21,19]:INT,0]:face); + + + let_2:=newVectorObject(0,24,14, + [54*3,40*3,-20*4, + 27*3,34*3,-20*4, + 92*3,-2*3,-20*4, + 159*3,22*3,-20*4, + 141*3,74*3,-20*4, + 52*3,149*3,-20*4, + 137*3,149*3,-20*4, + 137*3,165*3,-20*4, + 2*3,165*3,-20*4, + 119*3,63*3,-20*4, + 125*3,31*3,-20*4, + 93*3,21*3,-20*4, + + 54*3,40*3,20*4, + 27*3,34*3,20*4, + 92*3,-2*3,20*4, + 159*3,22*3,20*4, + 141*3,74*3,20*4, + 52*3,149*3,20*4, + 137*3,149*3,20*4, + 137*3,165*3,20*4, + 2*3,165*3,20*4, + 119*3,63*3,20*4, + 125*3,31*3,20*4, + 93*3,21*3,20*4]:INT, + + /* since no 'depth' sorting is done - ensure innermost surfaces drawn first */ + [ + 5,6,18,19, -> top of base + [4,5,6,6,18,18,17,17,5]:INT,0, + 9,10,22,21, -> inside top left + [4,9,10,10,22,22,21,21,9]:INT,0, + 10,11,23,23, -> inside top mid + [4,10,11,11,23,23,22,22,10]:INT,0, + 11,0,12,24, -> inside top left + [4,11,0,0,12,12,23,23,11]:INT,0, + 8,9,21,16, -> top of rasier + [4,8,9,9,21,21,20,20,8]:INT,0, + 0,1,13,22, -> front edge + [4,0,1,1,13,13,12,12,0]:INT,0, + 4,5,17,17, -> bottom of raiser + [4,4,5,5,17,17,16,16,4]:INT,0, + 3,4,16,13, -> right side + [4,3,4,4,16,16,15,15,3]:INT,0, + 6,7,19,18, -> right side of base + [4,6,7,7,19,19,18,18,6]:INT,0, + 7,8,20,14, -> base + [4,7,8,8,20,20,19,19,7]:INT,0, + 2,3,15,15, -> top right + [4,2,3,3,15,15,14,14,2]:INT,0, + 1,2,14,20, -> top left + [4,1,2,2,14,14,13,13,1]:INT,0, + + 2,1,0,25, /* front face */ + [12,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,0]:INT,0, + 12,13,14,26, /* rear face */ + [12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,12]:INT,0]:face); + + + /* add objects to the list, and position them accordingly */ + addVObject(list,let_A) + let_A.px:=-1275-100 + addVObject(list,let_1) + let_1.px:=-735-100 + addVObject(list,let_2) + let_2.px:=-345-100 + tmp:=cloneVectorObject(let_0); + addVObject(list,let_0) + let_0.px:=195-100 + addVObject(list,tmp); + tmp.px:=735-100 + +ENDPROC stat + +PROC freeobjects() + freeVList(list,1) /* also free nodes */ +ENDPROC + + + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/zed.e b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/zed.e new file mode 100644 index 0000000..19d8e4c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/examples/zed.e @@ -0,0 +1,267 @@ +/* + More complex demonstration of filledvector.m, with + a multiple object display, and using the matrix + functions to modify an object after its been made + + Michael Zucchi, 1994, This code in the public domain + */ + +OPT OSVERSION=39 + +MODULE 'tools/filledvector', 'tools/filledvdefs', 'exec/lists', 'intuition/screens', + 'tools/scrbuffer', 'graphics/rastport' + +DEF list:PTR TO mlh,screen,pc, + zed:PTR TO vobject,eee:PTR TO vobject,dee:PTR TO vobject, + scr:PTR TO screen + +PROC main() + /* create objects, and add to list */ + IF createobjects() + warpobjects() + IF screen:=sb_OpenScreen([SA_DEPTH,4,SA_WIDTH,320,SA_HEIGHT,256,SA_DISPLAYID,$0000,0],0) + IF pc:=newPolyContext(sb_GetBitMap(screen),50) + demo() + freePolyContext(pc) + ENDIF + sb_CloseScreen(screen) + ENDIF + freeobjects() + ENDIF +ENDPROC + +/* just demos basic rendering until the user chooses to exit */ + +PROC demo() + DEF p:position,bitm,myrp:rastport + + p.ax:=0;p.ay:=0;p.az:=0;p.px:=80;p.py:=0;p.pz:=8000; + + setPolyFlags(pc,1,1) -> z clipping on + + bitm:=sb_NextBuffer(screen) + sb_NextBuffer(screen) + scr:=sb_GetScreen(screen); + InitRastPort(myrp); + + WHILE Mouse()<>3 + bitm:=sb_NextBuffer(screen) + myrp.bitmap:=bitm + SetRast(myrp,0); + setPolyBitMap(pc, bitm) + + moveDrawVList(pc, list, p) + p.az:=p.az+1; + p.ax:=p.ax-2; + p.ay:=p.ay+3; + + IF Mouse()=1 THEN p.pz:=p.pz+35 + IF Mouse()=2 THEN p.pz:=p.pz-35 + ENDWHILE + + +ENDPROC + +PROC createobjects() + DEF stat=-1 + + /* allocate a list, and add them to it */ + list:=newVList() + + /* the letter z */ + zed:=newVectorObject(0,20,12, + [-178*3,98*3,20*4, /* points */ + -34*3,98*3,20*4, + -34*3,66*3,20*4, + -146*3,-50*3,20*4, + -34*3,-50*3,20*4, + -34*3,-82*3,20*4, + -178*3,-82*3,20*4, + -178*3,-50*3,20*4, + -66*3,66*3,20*4, + -178*3,66*3,20*4, + -178*3,98*3,-20*4, /* lower side */ + -34*3,98*3,-20*4, + -34*3,66*3,-20*4, + -146*3,-50*3,-20*4, + -34*3,-50*3,-20*4, + -34*3,-82*3,-20*4, + -178*3,-82*3,-20*4, + -178*3,-50*3,-20*4, + -66*3,66*3,-20*4, + -178*3,66*3,-20*4]:INT, + /* since no 'depth' sorting is done - ensure innermost surfaces drawn first */ + [3,4,14,1, /* bottom inside edge */ + [4,3,4,4,14,14,13,13,3]:INT,0, + 8,9,19,2, /* top inside edge */ + [4,8,9,9,19,19,18,18,8]:INT,0, + + 2,3,13,3, /* sloping inside edge */ + [4,2,3,3,13,13,12,12,2]:INT,0, + 7,8,18,4, /* sloping inside edge-left */ + [4,7,8,8,18,18,17,17,7]:INT,0, + + 2,1,0,5, /* front face */ + [10,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,0]:INT,0, + 10,11,12,6, /* back face */ + [10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,10]:INT,0, + 0,1,11,7, /* top bar of z */ + [4,0,1,1,11,11,10,10,0]:INT,0, + 5,6,16,8, /* bottom bar of z */ + [4,5,6,6,16,16,15,15,5]:INT,0, + 1,2,12,9, /* first back end */ + [4,1,2,2,12,12,11,11,1]:INT,0, + 4,5,15,10, /* next back end */ + [4,4,5,5,15,15,14,14,4]:INT,0, + 6,7,17,11, /* left lower end */ + [4,6,7,7,17,17,16,16,6]:INT,0, + 9,0,10,12, /* upper left end */ + [4,9,0,0,10,10,19,19,9]:INT,0]:face); + + /* the letter e */ + eee:=newVectorObject(0,24,14, + [0*3,0*3,20*4, + 66*3,0*3,20*4, + 66*3,-18*3,20*4, + 18*3,-18*3,20*4, + 18*3,-34*3,20*4, + 50*3,-34*3,20*4, + 50*3,-50*3,20*4, + 18*3,-50*3,20*4, + 18*3,-66*3,20*4, + 66*3,-66*3,20*4, + 66*3,-82*3,20*4, + 0*3,-82*3,20*4, + 0*3,0*3,-20*4, + 66*3,0*3,-20*4, + 66*3,-18*3,-20*4, + 18*3,-18*3,-20*4, + 18*3,-34*3,-20*4, + 50*3,-34*3,-20*4, + 50*3,-50*3,-20*4, + 18*3,-50*3,-20*4, + 18*3,-66*3,-20*4, + 66*3,-66*3,-20*4, + 66*3,-82*3,-20*4, + 0*3,-82*3,-20*4]:INT, + + /* since no 'depth' sorting is done - ensure innermost surfaces drawn first */ + [3,4,16,13, /* inside top right of E */ + [4,3,4,4,16,16,15,15,3]:INT,0, + 7,8,20,14, /* inside lower right of E */ + [4,7,8,8,20,20,19,19,7]:INT,0, + 2,3,15,15, /* upper inner E */ + [4,2,3,3,15,15,14,14,2]:INT,0, + 8,9,21,16, /* lower inner */ + [4,8,9,9,21,21,20,20,8]:INT,0, + 4,5,17,17, /* top of bar */ + [4,4,5,5,17,17,16,16,4]:INT,0, + 6,7,19,18, /* bottom of bar */ + [4,6,7,7,19,19,18,18,6]:INT,0, + 5,6,18,19, /* front of bar */ + [4,5,6,6,18,18,17,17,5]:INT,0, + /* all outside surfaces */ + 1,2,14,20, /* top front cap */ + [4,1,2,2,14,14,13,13,1]:INT,0, + 9,10,22,21, /* bottom front cap */ + [4,9,10,10,22,22,21,21,9]:INT,0, + + 0,1,13,22, /* top */ + [4,0,1,1,13,13,12,12,0]:INT,0, + 10,11,23,23, /* bottom */ + [4,10,11,11,23,23,22,22,10]:INT,0, + 11,0,12,24, /* back */ + [4,11,0,0,12,12,23,23,11]:INT,0, + + 2,1,0,25, /* front face */ + [12,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,0]:INT,0, + 12,13,14,26, /* rear face */ + [12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,12]:INT,0]:face); + + + /* the letter d */ + dee:=newVectorObject(0,24,14, + [-34*3,42*3,20*4, + 18*3,42*3,20*4, + 34*3,26*3,20*4, + 34*3,-26*3,20*4, + 18*3,-42*3,20*4, + -34*3,-42*3,20*4, + -18*3,26*3,20*4, + 0,26*3,20*4, + 18*3,10*3,20*4, + 18*3,-10*3,20*4, + 0,-26*3,20*4, + -18*3,-26*3,20*4, + + -34*3,42*3,-20*4, + 18*3,42*3,-20*4, + 34*3,26*3,-20*4, + 34*3,-26*3,-20*4, + 18*3,-42*3,-20*4, + -34*3,-42*3,-20*4, + -18*3,26*3,-20*4, + 0,26*3,-20*4, + 18*3,10*3,-20*4, + 18*3,-10*3,-20*4, + 0,-26*3,-20*4, + -18*3,-26*3,-20*4]:INT, + + [19,7,6,27, /* top inner */ + [4,6,7,7,19,19,18,18,6]:INT,0, + 20,8,7,28, /* top right inner */ + [4,7,8,8,20,20,19,19,7]:INT,0, + 21,9,8,29, /* right inner */ + [4,8,9,9,21,21,20,20,8]:INT,0, + 22,10,9,30, /* lower right inner */ + [4,9,10,10,22,22,21,21,9]:INT,0, + 23,11,10,31, /* lower inner */ + [4,10,11,11,23,23,22,22,10]:INT,0, + 18,6,11,32, /* inner left */ + [4,11,6,6,18,18,23,23,11]:INT,0, + + 0,1,13,33, /* top */ + [4,0,1,1,13,13,12,12,0]:INT,0, + 1,2,14,34, /* top right */ + [4,1,2,2,14,14,13,13,1]:INT,0, + 2,3,15,35, /* right */ + [4,2,3,3,15,15,14,14,2]:INT,0, + 3,4,16,36, /* lower right */ + [4,3,4,4,16,16,15,15,3]:INT,0, + 4,5,17,37, /* bottom */ + [4,4,5,5,17,17,16,16,4]:INT,0, + + 5,0,12,38, /* back */ + [4,5,0,0,12,12,17,17,5]:INT,0, + + 2,1,0,39, /* front face */ + [12,0,1,1,2,2,3,3,4,4,5,5,0,6,7,7,8,8,9,9,10,10,11,11,6]:INT,0, + 12,13,14,40, /* rear face */ + [12,12,13,13,14,14,15,15,16,16,17,17,12,18,19,19,20,20,21,21,22,22,23,23,18]:INT,0]:face); + + dee.px:=130*3;dee.py:=-42*3; -> real position + + addVObject(list,zed) + addVObject(list,eee) + addVObject(list,dee) + +ENDPROC stat + +PROC freeobjects() + freeVList(list,1) /* also free nodes */ +ENDPROC + +/* + Use the matrix functions to modify the objects a little bit + */ + +PROC warpobjects() +DEF mat:matrix + +setMatRotate(mat, 0,40,0); +matApply3(mat,24,getVObjectPoints(dee),getVObjectPoints(dee)) +setMatRotate(mat, 0,-40,0); +matApply3(mat,20,getVObjectPoints(zed),getVObjectPoints(zed)) + +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/filledvdefs.e b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/filledvdefs.e new file mode 100644 index 0000000..15b373f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/filledvdefs.e @@ -0,0 +1,80 @@ +/* + FilledVDefs.e + + Module for FilledVector.m definitions + + 1994 Michael Zucchi +*/ + +OPT MODULE + +/* + * Polygon Context Flags + */ + +EXPORT CONST PCF_ZCLIP = 1 -> perform z clipping? + + +/* + * A position object which is used by several function to define + * a locality and an orientation in one. + * (i.e. a position and angle) + */ + +EXPORT OBJECT position + ax:INT -> x,y,z angles + ay:INT + az:INT + px:INT -> x,y,z position + py:INT + pz:INT +ENDOBJECT + +/* + * Each VObject allocated will return one of these. They can be linked + * into lists using the VList functions. + * The position/orientation of the object can also be conveniently + * stoed and accessed from here. Note however that there is considerably + * more PRIVATE data following ... + */ + +EXPORT OBJECT vobject + next:LONG -> next field for a linked list + prev:LONG -> prev field + ax:INT -> angles of object (depends on rendering function used) + ay:INT + az:INT + px:INT -> position of object + py:INT + pz:INT +ENDOBJECT -> more data, PRIVATE + +/* + * Each face of an object uses one of these. These are used also + * to define a new object. + */ + +EXPORT OBJECT face + cross0:INT -> the 3 points used for the cross-product visibility test + cross1:INT + cross2:INT + colour:INT -> the colour of the object, the bottom 8 bits represent the + -> base colour. In the future, the top 8 bits MAY be used + -> to represent an alternate colour for stipling. + facelist:PTR TO INT -> pointer to the polygon definition, which + -> includes first: + -> a INT which says how many lines are in this polygon + -> pairs of INT's which point to the vertices used by + -> each of the lines of the polygon + pad00:LONG -> future expansion maybe (makes the OBJECT 16 bytes long) +ENDOBJECT + +/* + * A matix object, as used by the various matrix manipulation + * functions. Currently uses 3x3 matrices, but perhaps + * some 4x4 matrix routines will be written someday (?) + */ + +EXPORT OBJECT matrix + matdata[10]:ARRAY OF INT +ENDOBJECT diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/readnff b/amigae33a/E_v3.3a/Src/Src/Tools/FilledVector/readnff new file mode 100644 index 0000000000000000000000000000000000000000..307eaadf623520f095c019bdc8ae32ced6de29c1 GIT binary patch literal 2700 zcmb_eeP~-%6hHY``*t>l`u6m)X`i+@?vlCGD2B&o0>} z+aK8nV~FTviZEn~i2vA?BKu?h*KQ(HhXg57q_8rB#u;7EAR)Z$`aAEX-R2i4CcJmv z{oV6*&pqedOXT>Kte>q(LF{i5IeuWO9wBE}G)PJ}Q9$-|6S%yjO^S`Ne9Eb}YdMt) zCon!X^IC{*7_37ZXejko0&`9~$0smxYohn#+T+A~p5x`sh_d2J%bu9hg;5{ypyEnZJdnZa2SKkl zX@RLv74vBqxQ=;xF+S~8MN!*j#j+Xq7p}(7O`Ce`S}uOuAb-43N>b~0@NETiItlA5 zYB}v0QPyp1BBB~H_bN%!j`(eI`XdcP2T!AFzH5lAOOX;pZnE>9@efk9==UfJ|HgaJUNkLEunyA?+4LWo>-ee3&AzuFjyJ(=`8U3}VnuC~O@6geVs4JSL*VP4 zHQ$-yHJes~N~TfLNtWGkiXMSm9rqzR9BxUH&6gl?!2{hKIar;tX(MP1DBrP)#DOu;8s$i!2Y<}vZs2m^~g!EBUy6O#x z%C|4WiV+TXlBokoU*1diqUH*L5BwSDU2((KS=egd4*gic8_?hSKkE;(ex0=4X4V$s zx9`vz)F;+e>dRw)DoJwe$J5PuY36i^a}g^p9U$9<|F&)@?rqy>rlyU9#)= zo&~Mr*^BQ&C?MuS$W_E)GiN9B0-J4O>^oz#zzR)lWfQYxnHO`=-wxaj-Xgp&hPa+e z{dw=InN8S_5n-&&cQQ6NW7t&8BI|5w;i4#bNLh7!COX}M{IW$LzW}b;f8wHR;F@Rs zW=`6Wf$&{aIpa{1>o}J&y8y}-=Q#(Eeb=|%use{A@|qE`AS!szi!$CtQB4p9|Ahuu zAND3ecb@wTnM%_t*Vw&QT|IUCTV`gJIT~Tv%vk>FBztt4xlJ5B#T-e^ig05ETp2R5 zwH>>56H#6XU0Y0D#$8>QcVhku@50?I>gUQq9?=%aw3#wBR8Gm-lf}yUBf{QTm1rM_ zKG|BYnChw9F8__)7~AceXrQZcpSCyiok*u~%F_C7^x;gSf<<(=?G#8kkJ!wwV7lFD zr|?J@(6&+Uv_Y=Ii9|6AJ`;by#NE+Nr>=f=;#15fiqS~e=8rZiu~TXL=Dbx`Y$r=> zp((e*l#`nJZZZENCv&+wNJ-cGaq2cIi?vB~gnZ~Wr_q!8PaVcK-~xtzK&C#%MeDmMU9ePae(e z-M#TiZ9omHF2X?N$NX3tEuuTkskX%-s3qy5doieSxm?QF;Qoz|kM29Xeczt!*m!(! zKWJyz)XoZAZ98dTY)l!+?HN)I4h^TWs**c6JepS4u6L1^9N8D@QTrJWX_OV{kh$1| zsNs~^(u>ZcgisZSCFzMet>YVqFC(VC%W(?+hC4}3*%a$YkuYAr;_LNE{U@yxMidl> zZ@HFxa9YdZZ0+($UOwS|ZqDLF6ji<};a>N)-p;oPB_m2&p*OB=42RaP4XuAH9NG{L z#dBFbmqiDG57vEf8_p2+0zCw`!nCYJlnGH@y@_ufqP#7y<-jX>z<={yEl2n{%6Q=> M$v>ORqK;pF2Z$;8uK)l5 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Hook/hooktest.e b/amigae33a/E_v3.3a/Src/Src/Tools/Hook/hooktest.e new file mode 100644 index 0000000..0ab3556 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Hook/hooktest.e @@ -0,0 +1,16 @@ +-> test hooks + +MODULE 'utility', 'utility/hooks', 'tools/installhook' + +PROC main() + DEF myhook:hook + IF utilitybase:=OpenLibrary('utility.library',37) + installhook(myhook,{myfunction}) + CallHookPkt(myhook,1,2) + CloseLibrary(utilitybase) + ENDIF +ENDPROC + +PROC myfunction(hook,obj,msg) + WriteF('hook: $\h, obj: \d, msg: \d\n',hook,obj,msg) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Hook/installhook.e b/amigae33a/E_v3.3a/Src/Src/Tools/Hook/installhook.e new file mode 100644 index 0000000..c33ec9b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Hook/installhook.e @@ -0,0 +1,22 @@ +OPT MODULE + +EXPORT PROC installhook(hook,func) + MOVE.L hook,A0 + MOVE.L func,12(A0) + LEA hookentry(PC),A1 + MOVE.L A1,8(A0) + MOVE.L A4,16(A0) + MOVE.L A0,D0 +ENDPROC D0 + +hookentry: + MOVEM.L D2-D7/A2-A6,-(A7) + MOVE.L 16(A0),A4 + MOVE.L A0,-(A7) + MOVE.L A2,-(A7) + MOVE.L A1,-(A7) + MOVE.L 12(A0),A0 + JSR (A0) + LEA 12(A7),A7 + MOVEM.L (A7)+,D2-D7/A2-A6 + RTS diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/ilbm.guide b/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/ilbm.guide new file mode 100644 index 0000000..7cde5f8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/ilbm.guide @@ -0,0 +1,335 @@ +@database ilbm.guide + +@$VER: ilbm.Guide 1.0 (14.02.94). +@toc ilbm.m/main +@author Michael Zucchi +@(c) 1994 Michael Zucchi, All right reserved + + +@node Main "ilbm.guide" +@next "Commands" + +IFF ILBM picture loading module for AmigaE2.5+ + +© 1993 @{"Michael Zucchi" Link "Author"} +All Rights Reserved + +This document describes the ilbm.m module, which includes commands for loading +and displaying (if possible) IFF ilbm pictures. The functions provided are +intended to be as easy to use as possible, while providing a lot of flexibility. + +The following sections are available: + + @{" OverView " Link "OverView"} some of the ideas behind the module + + @{u}Module functions@{uu} + + @{"ilbm_New() " Link "ilbm_New"} to open a picture + @{"ilbm_Dispose() " Link "ilbm_Dispose"} to cleanup + + @{"ilbm_PictureInfo()" Link "ilbm_PictureInfo"} to get picture size/palette etc + @{"ilbm_LoadPicture()" Link "ilbm_LoadPicture"} loads data into a bitmap/screen + + @{"ilbm_FreeBitMap() " Link "ilbm_FreeBitMap"} to free a bitmap allocated by LoadPicture + + @{" Examples " Link Examples} + + @{b}NOTE: This module @{i}requires @{ui}Workbench 2.0 (V36) or higher! Please + make sure that this version of the system libraries is present before + using these functions.@{ub} + + @{b}NOTE!!! Due to a small oversight, only COMPRESSED ilbm's currently work. + This will be fixed soon ... i hope?@{ub} (uncompressed ilbm's are uncommon anyway) + +@endnode + +@node OverView "Module overview" + +Not much to say really - this module is just for loading/saving IFF ILBM's! +Designed to be used to easily load ilbm's for picture screens, or into bitmaps +for later blitting, or anywhere else where an ilbm would be useful. + +One thing - this module will work on V36 systems, however, on V39+ systems, +new graphics.library functions are used wherever possible. e.g. LoadRGB32() +for full 24-bit palettes on AGA+ machines. + +@{b}future plans@{ub} + +As it stands, the module is ideal for loading pictures for displaying. Another +idea that may be implemented is a 'chunky' mode loading function (e.g. +ILBML_CHUNKY) whereby the data is converted to byte-per-pixel format before +being output to a byte array. +A save function would also be useful - i havent implemented it yet because of +lack of time, and also to keep the module small. + +Actually ... + +This sort of thing should be handled much better using datatypes. Unfortunately, +they're a bit of a pain to use at the moment - and very inefficient. I see +this module being primarily used for loading ILBM's for graphics for +games/applications, rather than for writing picture viewers. + +@endnode + +@node "Author" "The guy who wrote it" + +The iff unpacker i wrote a long time ago for zgif, its reasonably fast, but +it doesn't go all out for speed! + +Presently, i study `from time to time' (:-) in order to obtain a Computer +Systems Engineering degree from the Univerity Of South Australia. (1994=final year) +I'm also currently `Zed' of FRONTIER in my anti-os hours. + +I can be contacted in the following ways: + +Internet email: + +9107047w@lux.levels.unisa.edu.au + till the end of '94 at least - reliable + +`Real Mode' (tm) mail: + +Michael Zucchi +PO BOX 824 +Waikerie +South Australia 5330 + slow, but very reliable - till mum sells the house :) + +Michael Zucchi +110 Dunrobin Rd +Warradale +South Australia 5046 + to my door - till i move (?) + +@endnode + + +@node ilbm_New +@{u}ilbm.m/ilbm_New ilbm.m/ilbm_New@{uu} + +@{b}SYNTAX@{ub} + + ilbmhandle := ilbm_New( name:PTR TO CHAR, + flags:LONG ); + +@{b}PURPOSE@{ub} + Creates a (private!) ilbm handle structure, and fills in several + fields. The file specified by 'name' is opened, and the IFF ILBM + chunks BMHD, CAMG, and CMAP are parsed. + +@{b}INPUTS@{ub} + name A NULL terminated string, specifying the name of the + picture. This MUST be present! + flags A mask of options, current flags are: + + ILBMF_COLOURS4 + create a LoadRGB4() compatible version of the + palette, and store a pointer to it in the picture + info block as 'pal4' (see @{"ilbm_PictureInfo()" Link ilbm_PictureInfo} + + ILBMF_COLOURS32 + create a LoadRGB32() compatible version of the + palette, and store a pointer to it in the picture + info block as 'pal32' (see @{"ilbm_PictureInfo()" Link ilbm_PictureInfo} + +@{b}OUTPUTS@{ub} + ilbmhandle A !!PRIVATE!! handle used with the other ilbm_xxx + functions. If for some reason something didn't work, it + will be 0. + +@{b}NOTES@{ub} + +@{b}SEE ALSO@{ub} + @{"ilbm_Dispose()" Link ilbm_Dispose}, @{"ilbm_LoadPicture()" link ilbm_LoadPicture}, @{"ilbm_PictureInfo()" Link ilbm_PictureInfo} + +@endnode + +@node ilbm_Dispose +@{u}ilbm.m/ilbm_Dispose ilbm.m/ilbm_Dispose@{uu} + +@{b}SYNTAX@{ub} + + ilbm_Dispose( iffhandle:LONG ); + +@{b}PURPOSE@{ub} + Closes the original file, free's the iffparse.library stuff, and + closes some libraries. Use this to free uneeded data once the + picture has been loaded. + +@{b}INPUTS@{ub} + iffhandle An iffhandle obtained from @{"ilbm_New()" Link ilbm_New}, or 0. + +@{b}OUTPUTS@{ub} + +@{b}NOTES@{ub} + It is safe to pass iffhandle:=0 to this function. + +@{b}SEE ALSO@{ub} + @{"ilbm_New()" Link "ilbm_New()"} + +@endnode + +@node ilbm_PictureInfo +@{u}ilbm.m/ilbm_PictureInfo ilbm.m/ilbm_PictureInfo@{uu} + +@{b}SYNTAX@{ub} + + pictureinfo := ilbm_PictureInfo( iffhandle:LONG ) + +@{b}PURPOSE@{ub} + Returns a pointer to a pictureinfo object which contains information + about the picture being loaded. + +@{b}INPUTS@{ub} + iffhandle A VALID iffhandle obtained from @{"ilbm_New()" Link ilbm_New}. + +@{b}OUTPUTS@{ub} + pictureinfo A pointer to an object of type 'pictureinfo'. + The fields will be set-up as following: + + bmhd pointer to the BitMapHeader from the IFF file + modeid the modeid, as obtained from the CAMG chunk - or 0. + This may also be set by the application before calling + @{"ilbm_LoadPicture()" Link ilbm_LoadPicture} + colours number of colours represented in the picture. An + IFF-24 picture will have 16,777,216 stored here! + palraw If the number of colours (above) is 256 or less, and + a CMAP chunk was present, palraw is a pointer to the + raw 24-bit palette read from the IFF file. The colours + are stores as groups of 3 bytes - Red/Green/Blue + pal4 If ILBMF_COLOURS4 was specified when the iffhandle + was created, and there was a CMAP present, AND + there was enough memory, pal4 is a pointer to + a LoadRGB4() compatible array of colours - 'colours' + of them. + pal32 If ILBMF_COLOURS32 was specified when the iffhandle + was created, and there was a CMAP present, AND + there was enough memory, pal32 is a pointer to + a LoadRGB32() compatible array of colours - 'colours' + of them. + +@{b}NOTES@{ub} + The modeid field is the only one writeable! All others are read-only. + + If memory is tight, the pal4 and pal32 fields may still be zero, even + if they were requested originally. It would be a good idea always + to check these fields before use. + +@{b}SEE ALSO@{ub} + @{"ilbm_New()" Link ilbm_New}, @{"ilbm_Dispose()" Link ilbm_Dispose}, @{"ilbm_LoadPicture()" link ilbm_LoadPicture} + +@endnode + +@node ilbm_LoadPicture +@{u}ilbm.m/ilbm_LoadPicture ilbm.m/ilbm_LoadPicture@{uu} + +@{b}SYNTAX@{ub} + + status := ilbm_LoadPicture ( iffhandle:LONG, + taglist:LONG ) + +@{b}PURPOSE@{ub} + Loads the picture into the specified enviroment. + +@{b}INPUTS@{ub} + iffhandle An iffhandle obtained using @{"ilbm_New()" link ilbm_New}, or 0 + in which case an error will be returned + tags A tag-list specifying the loading options. Currently defiend + tags are: + + ILBML_BITMAP tag.data points to an existing bitmap in which + to load the picture data. The bitmap needs + to be big enough ... + ILBML_SCREEN tag.data points to an existing screen in which + to load the picture/palette. + ILBML_CHUNKY tag.data specifies a byte array to store a + chunky-pixel version of the picture + NOT IMPLEMENTED + ILBML_GETBITMAP This specifies that ilbm_LoadPicture() will + allocate its own bitmap. In this case, + tag.data is a pointer to a variable, which + will hold the obtained bitmap. + @{"ilbm_FreeBitMap()" link ilbm_FreeBitMap} @{b}MUST@{ub} be used to free this + bitmap. + ILBML_GETSCREEN Specifies that ilbm_LoadPicture() will open the + screen for you. tag.data points to a variable + that will hold the screen pointer once obtained. + If the screen could not open, zero is stored + that variable. The screen must be closed by + a CloseScreen() call - this can be after + @{"ilbm_Dispose()" link ilbm_Dispose} is called. + ILBML_GETCHUNKY guess! NOT IMPLEMENTED + ILBML_SCREENTAGS If ILBML_GETSCREEN was used, then this tag + can be used to specify additional tags to be + used when opening the screen. The following + tags must NOT be used: SA_WIDTH, SA_HEIGHT, + SA_DEPTH, SA_DISPLAYID. + ILBML_NOCOLOUR If SA_SCREEN/SA_GETSCREEN have been specified, + then using this BOOL tag will prevent + ilbm_LoadPicture() from setting the palette + for the screen. Only specify if it is to be + true. + +@{b}OUTPUTS@{ub} + status =0 if all went OK, or negative for errors (see ilbmdefs.m) + +@{b}NOTES@{ub} + Remember, if one of the 'GET' tags is used, it is up to the application + to free whatever was got. + +@{b}SEE ALSO@{ub} + @{"ilbm_New()" Link ilbm_New}, @{"ilbm_Dispose()" Link ilbm_Dispose}, @{"ilbm_PictureInfo()" link ilbm_PictureInfo}, @{"ilbm_FreeBitMap()" Link ilbm_FreeBitMap} + +@endnode + +@node ilbm_FreeBitMap +@{u}ilbm.m/ilbm_FreeBitMap ilbm.m/ilbm_FreeBitMap@{uu} + +@{b}SYNTAX@{ub} + + ilbm_FreeBitMap( bitmap ) + +@{b}PURPOSE@{ub} + Free's a bitmap returned by @{"ilbm_LoadPicture()" link ilbm_LoadPicture}, via the ILBML_GETBITMAP + tag. + +@{b}INPUTS@{ub} + bitmap a VALID bitmap, as returned by the ILBML_GETBITMAP tag. + +@{b}OUTPUTS@{ub} + +@{b}NOTES@{ub} + If V39 is present, this function just calls FreeBitMap() - otherwise, + it uses its own custom routines. + +@{b}SEE ALSO@{ub} + @{"ilbm_LoadPicture()" link ilbm_LoadPicture} + +@endnode + + +@node Examples "Information about the examples" + +This section describes the source-form examples so far provided. + +@{u}showpic@{uu} + + A simple picture-viewer. It demonstrates an easy way to load and + display a picture in an Amiga Screen. The use of the asl.library's + file requester is also demonstrated. + + usage: + @{"showpic" Link showpic.e/main} + +@{u}picwindow@{uu} + + Another simple picture-viewer. This one displays the picture on + the workbench screen, in a suitably sized window. It demonstrates + loading into bitmaps, obtaining information about the picture + before it is displayed, and blitting into workbench windows. + + usage: + @{"picwindow" Link picwindow.e/main} + +@endnode + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/picwindow.e b/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/picwindow.e new file mode 100644 index 0000000..2b91da5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/picwindow.e @@ -0,0 +1,92 @@ +/* + + picwindow.e Michael Zucchi 1994 + + Loads a picture into a window on workbench (without colours ...) + Demonstrates use of the ILBM MODULE - loading into bitmaps, and obtaining + picture information. It also demonstrates asl file requester + + This program may be freely distributed only among registered + AmigaE owners. + */ + + +MODULE 'tools/ilbm', 'tools/ilbmdefs', + 'intuition/intuition', + 'asl', 'libraries/ASL' + +DEF bm,win:PTR TO window, + buffer[256]:ARRAY + +PROC main() +DEF ilbm,filename,width,height,bmh:PTR TO bmhd,pi:PTR TO picinfo + +IF filename:=requestfile('Select picture') + IF ilbm:=ilbm_New(filename,0) + ilbm_LoadPicture(ilbm,[ILBML_GETBITMAP,{bm},0]) + + -> get a pointer TO the images picture-info, we extract the bitmap header, + -> and read the picture's size. + pi:=ilbm_PictureInfo(ilbm) + bmh:=pi.bmhd; + width:=bmh.w; + height:=bmh.h; + + -> the ilbm-handle is no longer needed, we can free it + ilbm_Dispose(ilbm) + + -> if a bitmap actually opened, open a window, and blit it in + IF bm + IF win:=OpenWindowTagList(0,[WA_INNERWIDTH,width,WA_INNERHEIGHT,height, + WA_AUTOADJUST,-1, + WA_IDCMP,IDCMP_CLOSEWINDOW, + WA_FLAGS,WFLG_CLOSEGADGET+WFLG_DRAGBAR+WFLG_DEPTHGADGET, + WA_TITLE,filename, + WA_SCREENTITLE,'Pic-Window 0.1 1994 Michael Zucchi',0]) + + -> bit into actual dimensions the OS could give us (the window might not be as big as the picture) + BltBitMapRastPort(bm,0,0,win.rport, + win.borderleft,win.bordertop, + win.width-win.borderright-win.borderleft, + win.height-win.borderbottom-win.bordertop,$c0); + + WaitPort(win.userport) + CloseWindow(win) + + ENDIF + ilbm_FreeBitMap(bm) + ENDIF + ENDIF +ENDIF + +ENDPROC + +/* + Presents an ASL load-file requester. If the user selected a file, it is + expanded to a full path-name. + */ +PROC requestfile(title) +DEF name=0,fr:PTR TO filerequester + +IF aslbase:=OpenLibrary('asl.library',36) + IF fr:=AllocAslRequest(ASL_FILEREQUEST,[ASLFR_TITLETEXT,title,0]) + IF AslRequest(fr,0) + + -> sorry, a bit of ASM here. Well ... how ELSE? + -> this does a strcpy() ... + MOVE.L fr,A0 + MOVE.L 8(A0),A0 -> directory pointer from 'filerequester' + MOVE.L buffer,A1 + cp: MOVE.B (A0)+,(A1)+ + BNE.S cp + + AddPart(buffer,fr.file,256) + name:=buffer + ENDIF + FreeAslRequest(fr) + ENDIF + CloseLibrary(aslbase) +ENDIF + +ENDPROC name + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/showpic.e b/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/showpic.e new file mode 100644 index 0000000..36da0fa --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/ILBM/showpic.e @@ -0,0 +1,70 @@ +/* + + showpic.e Michael Zucchi 1994 + + Simple IFF ILBM picture viewer + Demonstrates use of the ILBM module, and the asl file requester + + This program may be freely distributed only among registered + AmigaE owners. + */ + + +MODULE 'tools/ilbm', 'tools/ilbmdefs', + 'intuition/intuition', + 'asl', 'libraries/ASL' + +DEF scr, + buffer[256]:ARRAY + +PROC main() +DEF ilbm,filename + +IF filename:=requestfile('Select picture') + IF ilbm:=ilbm_New(filename,0) + ilbm_LoadPicture(ilbm,[ILBML_GETSCREEN,{scr},0]) + ilbm_Dispose(ilbm) -> no longer needed ... + + -> this is only an example! In a real application, always use IDCMP ports, + -> and windows + + IF scr -> only if one was created. + WHILE Mouse()<>1 + Delay(4) + ENDWHILE + CloseScreen(scr) + ENDIF + ENDIF +ENDIF + +ENDPROC + +/* + Presents an ASL load-file requester. If the user selected a file, it is + expanded to a full path-name. + */ +PROC requestfile(title) +DEF name=0,fr:PTR TO filerequester + +IF aslbase:=OpenLibrary('asl.library',36) + IF fr:=AllocAslRequest(ASL_FILEREQUEST,[ASLFR_TITLETEXT,title,0]) + IF AslRequest(fr,0) + + -> sorry, a bit of ASM here. Well ... how ELSE? + -> this does a strcpy() ... + MOVE.L fr,A0 + MOVE.L 8(A0),A0 -> directory pointer from 'filerequester' + MOVE.L buffer,A1 + cp: MOVE.B (A0)+,(A1)+ + BNE.S cp + + AddPart(buffer,fr.file,256) + name:=buffer + ENDIF + FreeAslRequest(fr) + ENDIF + CloseLibrary(aslbase) +ENDIF + +ENDPROC name + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/InitHook/inithook.e b/amigae33a/E_v3.3a/Src/Src/Tools/InitHook/inithook.e new file mode 100644 index 0000000..cd633d5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/InitHook/inithook.e @@ -0,0 +1,26 @@ +OPT MODULE + +MODULE 'utility/hooks' + +EXPORT PROC inithook(hook:PTR TO hook, func, data=NIL) + hook.subentry:=func + hook.entry:={hookentry} + hook.data:=data + LEA.L storeA4(PC), A0 -> Copy A4 to safe place + MOVE.L A4, (A0) +ENDPROC hook + +storeA4: + LONG 0 + +hookentry: + MOVEM.L D2-D7/A2-A6,-(A7) -> Save regs + MOVE.L A0,-(A7) -> Stuff parameters on stack for proc call + MOVE.L A2,-(A7) + MOVE.L A1,-(A7) + MOVE.L storeA4(PC), A4 -> Reinstate A4 + MOVE.L 12(A0),A0 -> Get sub-entry + JSR (A0) -> Execute function + LEA 12(A7),A7 -> Remove parameters + MOVEM.L (A7)+,D2-D7/A2-A6 -> Restore regs + RTS diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Iterators/iterators_test.e b/amigae33a/E_v3.3a/Src/Src/Tools/Iterators/iterators_test.e new file mode 100644 index 0000000..562e9bf --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Iterators/iterators_test.e @@ -0,0 +1,21 @@ +-> iterators test + +MODULE 'tools/exceptions', 'tools/constructors', '*iterators', + 'exec/lists', 'exec/nodes' + +OBJECT bla OF ln + v:LONG +ENDOBJECT + +PROC main() HANDLE + DEF l,n:PTR TO bla,x=10 + l:=newlist() + WHILE x>0 DO AddHead(l,NEW n.n(x--)) + iterate_exec_list({n},l,`WriteF('v = \d\n',n.v)) +EXCEPT + report_exception() +ENDPROC + +PROC n(v) OF bla + self.v:=v +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.doc b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.doc new file mode 100644 index 0000000..ba5acdf --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.doc @@ -0,0 +1,47 @@ +simplelex.m: very simple general purpose lexical analyser for various tasks. + +This lex() can used there where one quickly needs a lex without +bothering to make one yourself. It may also serve as an example +or starting point on how to make your own lex. See simplelextest.e +for a nice parser example that makes use of this lex. + + + lex_int(start,len,freeform=FALSE,onelinecomment=-2) + +initialises the lex. start and len denote the memory area where +the text is that lex() will take it's tokens from. The memory +needs to be trailed by "\n", readfile() from file.m does this for +you. freeform says wether "\n" should be interpreted as whitespace +or not. onelinecomment allows only one char. + + token,attr:=lex() + +the actual lex. returns a token, and for some tokens also an attribute. + +" ", "\t" whitespace, not returned +"\n" LEX_EOL, or whitespace +"[a-zA-Z_][a-zA-Z0-9_]*" LEX_IDENT, attr=ptr to first char + [same as E's idents] + LEX_INTEGER, attr=value + [everything accepted by Val()] + LEX_EOF +"" LEX_STRINGQ, attr=ptr to first char +'' LEX_STRINGA, idem. + +any other character is returned as token on it's own. + + linenum:=lex_curline() + +returns the current linenumber being lexical-analysed. + + ptr:=lex_current() + +returns the current ptr in the text. Handy for those cases where +lex() returns 'ptr to first char', as this will then be 'ptr past +last char'. + + pos:=lex_getline(estring) + +copies the current line into the estring, and returns the offset +into that string where lex() currently is. Very handy for precise +error-reports, as the simplelextest.e demonstrates. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.e b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.e new file mode 100644 index 0000000..ae88514 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelex.e @@ -0,0 +1,65 @@ +-> very simple lex module + +OPT MODULE + +MODULE 'tools/ctype' + +DEF begin, cur, end, free, line, comment -> private + +EXPORT PROC lex_init(start,size,freeform=FALSE,onelinecomment=-2) + end:=(begin:=cur:=start)+size; free:=freeform; line:=1 + comment:=onelinecomment +ENDPROC + +EXPORT ENUM LEX_EOF=256, LEX_EOL, LEX_INTEGER, LEX_IDENT, + LEX_STRINGA, LEX_STRINGQ + +EXPORT PROC lex() + DEF a,b,c + LOOP + SELECT 256 OF c:=cur[]++ + CASE "\n" + IF cur>end THEN RETURN (cur:=end) BUT LEX_EOF + line++ + IF free=FALSE THEN RETURN LEX_EOL + CASE " ", "\t" + /* whitespace, do nothing */ + CASE "0" TO "9", "$", "%", "-" + a,b:=Val(cur-1) + IF b=0 THEN RETURN c + cur:=cur+b-1 + RETURN LEX_INTEGER, a + CASE "a" TO "z", "A" TO "Z", "_" + a:=cur; c:=cur[] + WHILE isalnum(c) OR (c="_") DO cur++ BUT c:=cur[] + RETURN LEX_IDENT,a + CASE "\q", "\a" + a:=cur + WHILE (a[]<>c) AND (a[]<>"\n") DO a++ + IF a[]="\n" THEN RETURN c + b:=cur + cur:=a+1 + RETURN IF c="\a" THEN LEX_STRINGQ ELSE LEX_STRINGA, b + DEFAULT + IF c=comment + WHILE cur[]++<>"\n" + ENDWHILE + line++ + ELSE + RETURN c + ENDIF + ENDSELECT + ENDLOOP +ENDPROC + +EXPORT PROC lex_curline() IS line +EXPORT PROC lex_current() IS cur + +EXPORT PROC lex_getline(s) + DEF b,e + b:=e:=cur + WHILE b[]--<>"\n" DO NOP + b++ + WHILE e[]<>"\n" DO e++ + StrCopy(s,b,e-b) +ENDPROC cur-b diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelextest.e b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelextest.e new file mode 100644 index 0000000..5458e19 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/simplelextest.e @@ -0,0 +1,73 @@ +-> lex test, parses lists with ints from a file. + +MODULE 'tools/simplelex', 'tools/file', 'tools/lisp' + +DEF t,at -> current token and attribute + +PROC main() HANDLE + DEF m=NIL,l,a + m,l:=readfile('testinput.lists') + lex_init(m,l,TRUE,"#") + t,at:=lex() + WHILE (a:=parse())<>-1 + showcellint(a) + WriteF('\n') + ENDWHILE +EXCEPT DO + IF m THEN freefile(m) + SELECT exception + CASE "OPEN"; WriteF('no file!\n') + CASE "MEM"; WriteF('no mem!\n') + CASE "perr"; printerr(exceptioninfo) + ENDSELECT +ENDPROC + +PROC parse() + DEF a + IF t="<" + t,at:=lex() + IF t=">" + t,at:=lex() + RETURN NIL + ELSE + a:=parse() + RETURN + ENDIF + ELSEIF t=LEX_INTEGER + a:=at + t,at:=lex() + RETURN a + ELSEIF t=LEX_EOF + RETURN -1 + ELSE + Throw("perr",'"<" or integer expected') + ENDIF +ENDPROC + +PROC parsecdr() + DEF a + IF t="," + t,at:=lex() + a:=parse() + RETURN + ELSEIF t="|" + t,at:=lex() + a:=parse() + IF t<>">" THEN Throw("perr",'">" expected') + t,at:=lex() + RETURN a + ELSEIF t=">" + t,at:=lex() + RETURN NIL + ELSE + Throw("perr",'"," or "|" or ">" expected') + ENDIF +ENDPROC + +PROC printerr(s) + DEF ers[200]:STRING,pos,a + pos:=lex_getline(ers)-1 + WriteF('\nERROR: \s\nLINE: \d\n\s\n',s,lex_curline(),ers) + IF pos>0 THEN FOR a:=1 TO pos DO WriteF(' ') + WriteF('^\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Lex/testinput.lists b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/testinput.lists new file mode 100644 index 0000000..0363554 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Lex/testinput.lists @@ -0,0 +1,16 @@ +# examples of cell-expressions to parse + +<1|2> + +<1,2,3> + +<1, + <2|3>, + <4,5|6>| + 7> + +# remove comment for each of the following lines to see error reports: + +# <1,bla> +# <1|2,3> +# <1;2> diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisp.e b/amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisp.e new file mode 100644 index 0000000..6a5e2fb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisp.e @@ -0,0 +1,133 @@ +-> list Tools! + +OPT MODULE +OPT EXPORT + +/*------some-typical-lisp-functions--------*/ + +/* note: these are quite inefficient functions and could be done + much faster using destructive implementations. They are however + very nice as LISP-programming examples */ + +-> appends two lists + +PROC append(x,y) + DEF h,t + IF x + x <=> + RETURN + ENDIF +ENDPROC y + +-> 'naive'-reverses a list. notorious for it's inefficiency. + +PROC nrev(x) + DEF h,t + IF x + x <=> + RETURN append(nrev(t),) + ENDIF +ENDPROC NIL + +-> returns a list of results from applying fun to elements of l + +PROC map(l,fun) + DEF h,t + IF l + l <=> + RETURN + ENDIF +ENDPROC NIL + +-> returns a list of elements in l for which fun returns true + +PROC filter(l,fun) + DEF h,t,r + IF l + l <=> + r:=filter(t,fun) + RETURN IF fun(h) THEN ELSE r + ENDIF +ENDPROC NIL + +-> returns two lists of elements in l for which fun returns true and false + +PROC partition(l,fun) + DEF h,t,rt,rf + IF l + l <=> + rt,rf:=partition(t,fun) + IF fun(h) THEN RETURN ,rf ELSE RETURN rt, + ENDIF +ENDPROC NIL,NIL + +-> folds function through list, i.e.: +-> foldr(<1,2,3>,{add},0) = add(1,add(2,add(3,0))) + +PROC foldr(l,fun,end) + DEF h,t + IF l + l <=> + RETURN fun(h,foldr(t,fun,end)) + ENDIF +ENDPROC end + +-> zip combines two lists into one list of pairs. + +PROC zip(x,y) + DEF a,b,c,d + IF x + IF y + x <=> + y <=> + RETURN <|zip(b,d)> + ENDIF + ENDIF +ENDPROC NIL + +-> length of a list + +PROC length(x) IS IF x THEN length(Cdr(x))+1 ELSE 0 + + +/*--------universal-cell-printing---------*/ + +/* prints any cell structure in memory, proc(v) is called whenever + a value is not a cell. below predefined functions for lists/trees + of ints and strings */ + +EXPORT PROC showcell(cell,proc) + DEF a,c + IF cell + IF Cell(cell) + WriteF('<') + cell <=> + showcell(a,proc) + IF c + WHILE Cell(c) AND (c<>0) + WriteF(',') + c <=> + showcell(a,proc) + ENDWHILE + IF c + WriteF('|') + showcell(c,proc) + ENDIF + WriteF('>') + ELSE + WriteF('>') + ENDIF + ELSE + proc(cell) + ENDIF + ELSE + WriteF('<>') + ENDIF +ENDPROC + +PROC showcellint(cell) IS showcell(cell,{showint}) +PROC showcellstr(cell) IS showcell(cell,{showstr}) + +PROC showint(x) IS WriteF('\d',x) +PROC showstr(x) IS WriteF('\s',x) + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisptest.e b/amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisptest.e new file mode 100644 index 0000000..ea63b38 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Lisp/lisptest.e @@ -0,0 +1,33 @@ +-> test lisp tool module + +MODULE 'tools/lisp' + +PROC main() + DEF a,b + + -> map a reverse over lists + + showcellint(map(<<1,2,3>,<4,5,6>,<7,8,9>>,{nrev})) + + -> sum a list + + WriteF('\n\d\n',foldr(<1,2,3>,{add},0)) + + -> select a list of zipped pairs whose head>tail + + showcellint(filter(zip(<1,2,3,4,5>,<2,1,-1,5,4>),{greater})) + + -> number of positive and negative number of elements in a list + + a,b:=partition(<1,-5,8,2,-2,4,5,7>,{pos}) + WriteF('\n\d \d\n',length(a),length(b)) + +ENDPROC + +PROC add(x,y) IS x+y +PROC pos(x) IS x>=0 + +PROC greater(c) + DEF h,t + c <=> +ENDPROC h>t diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longdemo.e b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longdemo.e new file mode 100644 index 0000000..a37086c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longdemo.e @@ -0,0 +1,85 @@ +/* Example program for longreal module */ +/* By EA van Breemen 1994 */ + + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* In order to use the conversion functions use STRING type */ +/* for the buffers, not ARRAY. Otherwise the functions will */ +/* produce unexpected results */ + +/* Note some roundingerrors may occur due to IEEE maths */ +/* In futher releases this will be fixed */ + + +/* Some notes on the functions in longreal */ + +/* Most functions are described in the ROMKernals. See the */ +/* chapters on IEEE functions */ +/* There are 3 ascii-longreal conversion functions */ + +/* dFormat(buffer,x,num) -> converts fractional number x with + num digits to a string in buffer + + dLFormat(buffer,x,num) -> same as dFormat, but now also large + numbers i.e. 1.2e250 + + a2d(buffer,x) -> the inverse of dLFormat: converting + from asciistring in buffer to + longreal x */ + + +/* Include this module for using longreals */ + +MODULE 'tools/longreal' + + +/* Our small main program */ + +PROC main() + DEF buffer[256]:STRING /* Very important: use STRING for buffer !!!! */ + DEF a:longreal /* Our dummy longreal for results */ + DEF i /* A simple counter */ + + dInit() /* Init the module before using */ + + WriteF('First some conversions:\n') + WriteF('Reading 1.234567 -> gives:') + + a2d('1.234567',a) /* Convert from ascii to longreal */ + dFormat(buffer,a,6) /* And back again (6 digits) */ + WriteF('\s\n',buffer) /* Print it */ + + WriteF('Reading +1.234567e-2 -> gives:') + + a2d('+1.234567e-2',a) /* Convert from ascii to longreal */ + dFormat(buffer,a,6) /* And back again (6 digits) */ + WriteF('\s\n',buffer) /* Print it */ + + + WriteF('Reading -1.234567E100 -> gives:') + + a2d('-1.234567E100',a) /* Convert from ascii to longreal */ + +/* Now the number is too large for dFormat, use dLFormat instead */ + + dLFormat(buffer,a,6) /* And back again (6 digits) */ + WriteF('\s\n',buffer) /* Print it */ + + WriteF('Now some other stuff\n') + + FOR i:=1 TO 16 + WriteF('PI=\s \n',dFormat(buffer,dPi(a),i)) + ENDFOR + + WriteF('A sinus table\n') + FOR i:=0 TO 360 STEP 45 + dFloat(i,a) /* Convert an int to a longreal */ + dSin(dRad(a)) + WriteF('Sin(\d)=\s \n',i,dLFormat(buffer,a,15)) + ENDFOR + + WriteF('End of longdemo\n') + + dCleanup() /* Cleanup the module after using */ + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.doc b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.doc new file mode 100644 index 0000000..2bacd6d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.doc @@ -0,0 +1,99 @@ +longreal.m: A module for 64bit floats in E. + + +The module introduces a type 'longreal' to the E language. +All functions in the module are prefixed by a 'd' (for 'double') +Before you use this module, first call: + +dInit() + +and upon exit _always_ call: + +dCleanup() + +dInit() may raise an "DLIB" exception if +it fails to open one of the IEEE double libraries. If you don't +need any transcendental functions, dInit(FALSE) will cause only the +mathieeedoubbas.library to be opened. + + +Using longreals as a type. +There are various ways to create a longreal variable. simplest is: + +DEF f:longreal + +or: + +DEF f:PTR TO longreal + +and then later: + +NEW f + +also, you can make arrays of longreals, or use them in objects: + +OBJECT bla + x:INT, y:longreal +ENDOBJECT + +DEF a[100]:ARRAY OF longreal, b:bla + +As you see they work just like the builtin types. +In the above examples + +f, a[1], a[10], b.y + +all denote longreal variables. these can be used whereever a +longreal is expected in the functions decribed below. Note however +that, being objects, longreals are passed by reference. + + + i:=dFix(f) dFloat(i,f) + +convert a longreal to a LONG and a LONG to a longreal respectively. +dFloat() returns f + + dAdd(x,y) dAdd(x,y,to) + dSub(x,y) dSub(x,y,to) + dMul(x,y) dMul(x,y,to) + dDiv(x,y) dDiv(x,y,to) + +perform these common operations on their arguments. 'x' and 'y' are in the +same order as their operator-counterparts. The result is stored in 'to', +or in 'x' if only two arguments are passed. (all functions return 'to' or +'x', resp.). + + r:=dCompare(x,y) r:=dTest(x) + +Compare longreals. dTest compares x with 0 as second arg. result 'r' is +positive if x>y, negative for x0. Returns s. +Not great and somewhat slow, but it works :-) + + dSqrt(x) + + +---------------- +NOTE: Erwin has added a large bunch of useful functions, and documentation +on these can be found in the module source, and longdemo.e. +Because the module got rather big, I also included the original longreal +module (now longrealtiny.m) for those who don't need all the bells and +whistles... + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.e b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.e new file mode 100644 index 0000000..e19a675 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longreal.e @@ -0,0 +1,519 @@ +-> longreal module! + +OPT MODULE +OPT EXPORT + +OBJECT longreal + PRIVATE a,b +ENDOBJECT + +MODULE 'mathieeedoubbas', 'mathieeedoubtrans' + +EXPORT DEF mathieeedoubbascount, mathieeedoubtranscount + +RAISE "DLIB" IF OpenLibrary()=NIL + +PROC dInit(trans=TRUE) + IF mathieeedoubbascount=0 + mathieeedoubbasbase:=OpenLibrary('mathieeedoubbas.library',0) + ENDIF + mathieeedoubbascount++ + IF trans + IF mathieeedoubtranscount=0 + mathieeedoubtransbase:=OpenLibrary('mathieeedoubtrans.library',0) + ENDIF + mathieeedoubtranscount++ + ENDIF +ENDPROC + +PROC dCleanup(trans=TRUE) + IF mathieeedoubbasbase + IF mathieeedoubbascount--=0 THEN CloseLibrary(mathieeedoubbasbase) + ENDIF + IF trans + IF mathieeedoubtransbase + IF mathieeedoubtranscount--=0 THEN CloseLibrary(mathieeedoubtransbase) + ENDIF + ENDIF +ENDPROC + +PROC dFloat(int,longreal:PTR TO longreal) + DEF a,b + a,b:=IeeeDPFlt(int) + longreal.a:=a + longreal.b:=b +ENDPROC longreal + +PROC dFix(longreal:PTR TO longreal) IS IeeeDPFix(longreal.a,longreal.b) + +PROC dTst(x:PTR TO longreal) IS IeeeDPTst(x.a,x.b) + +PROC dCompare(x:PTR TO longreal,y:PTR TO longreal) IS IeeeDPCmp(x.a,x.b,y.a,y.b) + +PROC dAdd(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPAdd(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dSub(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPSub(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dMul(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPMul(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dDiv(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPDiv(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dRound(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPFloor(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dRoundUp(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPCeil(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dNeg(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPNeg(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dAbs(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPAbs(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dCopy(x:PTR TO longreal,y:PTR TO longreal) + x.a:=y.a + x.b:=y.b +ENDPROC x + +/*********************************************************************/ +/* Converts a longreal x to ascii in buffer s with num digits */ +/* Only for fraction numbers */ +/* */ +/* PARAM IN s - buffer for ascii representation [STRING] */ +/* x - longreal to be converted */ +/* num - number of digits */ +/* RETURN s - buffer for ascii representation [STRING] */ +/* COMMENT Buffer s must be large enough to contain the string */ +/*********************************************************************/ + +PROC dFormat(s,x,num) + DEF c:longreal, d:longreal, e, f[1]:ARRAY, fmt + IF dTst(x)<0 + dNeg(x) + fmt:='-\d.' + ELSE + fmt:='\d.' + ENDIF + StringF(s,fmt,dFix(x)) + dCopy(c,x) + FOR e:=1 TO num + dCopy(d,c) + dRound(d) + dSub(c,d) + dFloat(10,d) + dMul(c,d) + f[]:="0"+Abs(dFix(c)) + StrAdd(s,f,1) + ENDFOR +ENDPROC s + +/*********************************************************************/ +/* Converts a longreal x to ascii in buffer s with num digits */ +/* Also for 'large' numbers */ +/* */ +/* PARAM IN s - buffer for ascii representation [STRING] */ +/* x - longreal to be converted */ +/* num - number of digits */ +/* RETURN s - buffer for ascii representation [STRING] */ +/* COMMENT Buffer s must be large enough to contain the string */ +/*********************************************************************/ + +PROC dLFormat(s,x:PTR TO longreal,num) + DEF power,a:longreal + DEF one:longreal,ten:longreal + DEF buffer[30]:STRING + DEF sign + + sign:=1 + dDouble(10.0,ten) + dDouble(1.0,one) + dCopy(a,x) + power:=0 + IF dTst(a)=0 + dFormat(s,a,num) + RETURN s + ENDIF + IF (dTst(a)=-1) + sign:=-1 + dNeg(a) + ENDIF + IF dCompare(a,one)=-1 + WHILE dCompare(a,one)=-1 + dMul(a,ten) + power-- + ENDWHILE + ELSE + WHILE dCompare(a,ten)=1 + dDiv(a,ten) + power++ + ENDWHILE + ENDIF + dFormat(buffer,a,num) + IF (sign=1) + StringF(s,'\sE\d',buffer,power) + ELSE + StringF(s,'-\sE\d',buffer,power) + ENDIF +ENDPROC s + +/*********************************************************************/ +/* Converts an ascii representation to a longreal */ +/* */ +/* PARAM IN buffer - buffer with longreal in ascii [STRING] */ +/* x - converted longreal */ +/*********************************************************************/ + +PROC a2d(buffer,x:PTR TO longreal) + DEF divider:longreal + DEF fraction:longreal + DEF ten:longreal + DEF tmp:longreal + DEF longexp:longreal + + DEF i,exp,expsign,sign + + DEF tmpbuffer[256]:STRING + + dFloat(0,x) + dFloat(10,ten) + i:=0 + sign:=1 + IF buffer[i]="-" + sign:=-1 + i++ + ELSE + IF buffer[i]="+" THEN i++ + ENDIF + + WHILE ((buffer[i]>="0") AND (buffer[i]<="9") AND (buffer[i]<>0)) + dFloat(buffer[i]-"0",tmp) + dMul(x,ten) + dAdd(x,tmp) + i++ + ENDWHILE + + + IF (buffer[i]="." AND (buffer[i+1]>="0") AND (buffer[i+1]<="9")) + i++ + dFloat(1,divider) + dFloat(0,fraction) + WHILE ((buffer[i]>="0") AND (buffer[i]<="9") AND (buffer[i]<>0)) + dMul(fraction,ten) + dFloat(buffer[i]-"0",tmp) + dAdd(fraction,tmp) + dMul(divider,ten) + i++ + ENDWHILE + dDiv(fraction,divider) + dAdd(x,fraction) + ENDIF + dFloat(sign,tmp) + dMul(x,tmp) + + IF ((buffer[i]="E") OR (buffer[i]="e")) + i++ + IF buffer[i]="-" + expsign:=-1 + i++ + ELSE + expsign:=1 + IF (buffer[i]="+") THEN i++ + ENDIF + exp:=0 + WHILE ((buffer[i]>="0") AND (buffer[i]<="9") AND (buffer[i]<>0)) + exp:=Mul(exp,10)+buffer[i]-"0" + i++ + ENDWHILE + dFloat(exp*expsign,longexp) + dPow(ten,longexp) + dMul(x,ten) + ENDIF +ENDPROC + + +/* Converts an IEEE single to a longreal */ + +PROC dDouble(x,to:PTR TO longreal) + DEF a,b + a,b:=IeeeDPFieee(x) + to.a:=a + to.b:=b +ENDPROC + + +/* Converts a longreal to an IEEE single */ + +PROC dSingle(x:PTR TO longreal) IS IeeeDPTieee(x.a,x.b) + + +PROC dSqrt(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPSqrt(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC + + +/* Return longreal PI in x */ + +PROC dPi(x:PTR TO longreal) + x.a:=$400921FB /* Dirty but quick 8-) */ + x.b:=$54442D18 +ENDPROC x + +/* Converts x from degrees to radians */ + +PROC dRad(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF s:longreal,t:longreal + + dPi(t) + dDouble(180.0,s) + + dDiv(t,s) + dMul(t,x) + IF to + to.a:=t.a + to.b:=t.b + RETURN to + ELSE + x.a:=t.a + x.b:=t.b + RETURN x + ENDIF +ENDPROC + +PROC dSin(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPSin(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dCos(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPCos(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dTan(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPTan(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dASin(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPAsin(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + + +PROC dACos(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPAcos(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + + +PROC dATan(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPAtan(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dSinh(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPSinh(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dCosh(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPCosh(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dTanh(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPTanh(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + + +PROC dExp(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPExp(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dLn(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPLog(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +PROC dLog(x:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPLog10(x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + +/* Calculates x^y */ + +PROC dPow(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPPow(y.a,y.b,x.a,x.b) + IF to + to.a:=a + to.b:=b + RETURN to + ELSE + x.a:=a + x.b:=b + RETURN x + ENDIF +ENDPROC + + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtest.e b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtest.e new file mode 100644 index 0000000..600ea4d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtest.e @@ -0,0 +1,26 @@ +/* + +idea: Piet Molenaar + +calculates (a*a-4)*3 for a = 2 to .. +finds the "a"'s (integers, a,a+1,a+2 are the lenghts of the sides +of a triangle (with almost equals sides)), such that the surface is +a whole number! how remarkable! + +*/ + +MODULE 'tools/longrealtiny' + +PROC main() + DEF a:longreal, b:longreal, c:longreal, d:longreal, e:longreal, s[100]:STRING, x + dInit() + dFloat(4,b) + dFloat(3,c) + FOR x:=2 TO 40000 + IF (x AND $FFF)=0 THEN WriteF('busy doing: \d\n',x) + IF CtrlC() THEN RETURN + dRound(dCopy(e,dSqrt(dMul(dSub(dMul(dFloat(x,a),a,d),b),c)))) + IF dCompare(e,d)=0 THEN WriteF('\d <=> \s\n',x,dFormat(s,d,20)) + ENDFOR + dCleanup() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtiny.e b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtiny.e new file mode 100644 index 0000000..ea946fa --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/LongReal/longrealtiny.e @@ -0,0 +1,143 @@ +-> longreal module! + +OPT MODULE +OPT EXPORT + +OBJECT longreal + PRIVATE a,b +ENDOBJECT + +MODULE 'mathieeedoubbas', 'mathieeedoubtrans' + +EXPORT DEF mathieeedoubbascount, mathieeedoubtranscount + +RAISE "DLIB" IF OpenLibrary()=NIL + +PROC dInit(trans=TRUE) + IF mathieeedoubbascount=0 + mathieeedoubbasbase:=OpenLibrary('mathieeedoubbas.library',0) + ENDIF + mathieeedoubbascount++ + IF trans + IF mathieeedoubtranscount=0 + mathieeedoubtransbase:=OpenLibrary('mathieeedoubtrans.library',0) + ENDIF + mathieeedoubtranscount++ + ENDIF +ENDPROC + +PROC dCleanup(trans=TRUE) + IF mathieeedoubbasbase + IF mathieeedoubbascount--=0 THEN CloseLibrary(mathieeedoubbasbase) + ENDIF + IF trans + IF mathieeedoubtransbase + IF mathieeedoubtranscount--=0 THEN CloseLibrary(mathieeedoubtransbase) + ENDIF + ENDIF +ENDPROC + +PROC dFloat(int,longreal:PTR TO longreal) + DEF a,b + a,b:=IeeeDPFlt(int) + longreal.a:=a + longreal.b:=b +ENDPROC longreal + +PROC dFix(longreal:PTR TO longreal) IS IeeeDPFix(longreal.a,longreal.b) + +PROC dCompare(x:PTR TO longreal,y:PTR TO longreal) IS IeeeDPCmp(x.a,x.b,y.a,y.b) + +PROC dAdd(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPAdd(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dSub(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPSub(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dMul(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPMul(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dDiv(x:PTR TO longreal,y:PTR TO longreal,to=NIL:PTR TO longreal) + DEF a,b + a,b:=IeeeDPDiv(x.a,x.b,y.a,y.b) + IF to + to.a:=a; to.b:=b + RETURN to + ELSE + x.a:=a; x.b:=b + ENDIF +ENDPROC x + +PROC dRound(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPFloor(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dRoundUp(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPCeil(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dNeg(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPNeg(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dAbs(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPAbs(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x + +PROC dCopy(x:PTR TO longreal,y:PTR TO longreal) + x.a:=y.a + x.b:=y.b +ENDPROC x + +PROC dFormat(s,x,num) + DEF c:longreal, d:longreal, e, f[1]:ARRAY + StringF(s,'\d.',dFix(x)) + dCopy(c,x) + FOR e:=1 TO num + dCopy(d,c) + dRound(d) + dSub(c,d) + dFloat(10,d) + dMul(c,d) + f[]:="0"+dFix(c) + StrAdd(s,f,1) + ENDFOR +ENDPROC s + +PROC dSqrt(x:PTR TO longreal) + DEF a,b + a,b:=IeeeDPSqrt(x.a,x.b) + x.a:=a; x.b:=b +ENDPROC x diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Macros/macros.e b/amigae33a/E_v3.3a/Src/Src/Tools/Macros/macros.e new file mode 100644 index 0000000..cc79c6a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Macros/macros.e @@ -0,0 +1,24 @@ +/* This modules contains some missing 'macros' implemented as functions + as E doesn't support macros +*/ + +OPT MODULE + +MODULE 'graphics/rastport' + +/* Some intuition 'macros' */ + +EXPORT PROC menunum(x) IS x AND $1F + +EXPORT PROC itemnum(x) IS Shr(x,5) AND $3F + +EXPORT PROC subnum(x) IS Shr(x,11) AND $1F + + +/* A graphic 'macro' */ + +EXPORT PROC setdrpt(rport:PTR TO rastport,no) + rport.lineptrn:=no + rport.flags:=rport.flags OR FRST_DOT + rport.linpatcnt:=15 +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Pt/Player.e b/amigae33a/E_v3.3a/Src/Src/Tools/Pt/Player.e new file mode 100644 index 0000000..51e33e0 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Pt/Player.e @@ -0,0 +1,16 @@ +-> protracker player + +MODULE 'tools/file', 'tools/pt', 'tools/exceptions' + +PROC main() HANDLE + DEF m,l + WriteF('Protracker player in E (now playing: "\s", Ctrl-C to stop).\n',arg) + m,l:=readfile(arg,0,2) + pt_play(m) + REPEAT + Delay(10) -> instead, we could be doing something very usefull here + UNTIL CtrlC() + pt_stop() +EXCEPT DO + report_exception() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/README b/amigae33a/E_v3.3a/Src/Src/Tools/README new file mode 100644 index 0000000..b6c4320 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/README @@ -0,0 +1,3 @@ +In this directory you'll find sources to handy modules in +the emodules:tools directory, as well as examples that make use +of them, and sometimes even docs. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/ScrBuffer.guide b/amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/ScrBuffer.guide new file mode 100644 index 0000000..9b2d3f8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/ScrBuffer.guide @@ -0,0 +1,226 @@ +@database ScrBuffer.guide + +Docs for screen buffering module + +© 1993 Michael Zucchi +All rights reserved + +@node Main "ScrBuffer.guide" +@next "sb_OpenScreen" + +Filled Vector Module for AmigaE 3.0+ + +© 1994 @{"Michael Zucchi" Link "Author"} +All Rights Reserved + +Not to be used for commercial software without express written permission +from the author. + +This document describes the functions available for creating and working with +@{b}Workbench 3.0+@{ub} double buffered screen routines. They provide a general +purpose high level suite of routines for accessing these system routines +that can be used for any double buffering system. + +Functions currently available are: + + @{"sb_OpenScreen() " Link "sb_OpenScreen"} to open a screen + @{"sb_CloseScreen()" Link "sb_CloseScreen"} to close a screen + @{"sb_NextBuffer() " Link "sb_NextBuffer"} waits for the next buffer to be displayed + @{"sb_GetBitMap() " Link "sb_GetBitMap"} gives hidden bitmap pointer + @{"sb_GetScreen() " Link "sb_GetScreen"} gives base screen pointer + + @{"examples" Link "examples"} how to use it + +@{b}Remember, use of this module requires that V39 libraries are present +in the target system! Never use these functions without making sure this +is the case.@{ub} + +@endnode + + + +@node "Author" + +I'm another one of these poor students, but i live in Australia, not Europe! + +Presently, i study 'from time to time' :-) in order to obtain a Computer +Systems Engineering degree from the Univerity Of South Australia. Now less +than 6 months to go (at last!) + +Other than this and other AmigaE modules, i've coded a couple of demos for +FRONTIER as the coder 'Zed', along with some small utilities, esp ZGif. + +I can be contacted in the following ways: + +Internet email: + +9107047w@lux.levels.unisa.edu.au + till the end of '94 at least - reliable + +zucchi@hal9000.apana.org.au + if it works it works ... + +`Real Mode' (tm) mail: + +Michael Zucchi +PO BOX 824 +Waikerie +South Australia 5330 + slow, but very reliable + +Michael Zucchi +110 Dunrobin Rd +Warradale +South Australia 5046 + to my door - till i move (?) + + +@endnode + + +@node "sb_OpenScreen" +@prev "Main" +@{u}scrbuffer.m/sb_OpenScreen scrbuffer.m/sb_OpenScreen@{uu} + + @{b}SYNTAX@{ub} + + buffered screen := sb_OpenScreen ( tags, type ) + + @{b}PURPOSE@{ub} + + To open multibuffered screen. Also allocates at least 1 more + buffer to 'multibuffer' and a message port to recieve notification + events. + + @{b}INPUTS@{ub} + tags list of tags as found in "intuition/screens" that describe + the screen you wish to open. All the usual tags such + as SA_WIDTH, SA_HEIGHT, SA_DEPTH etc are used. + type the type of buffered screen to open. Only use 0 for now, + may be enhanced in future to add multi-buffering. + + + @{b}OUTPUTS@{ub} + buffered screen + a pointer to the buffered screen, or 0 if the screen or + asociate memory could not be allocated. All fields of + this structure are @{b}PRIVATE@{ub}. + + @{b}SEE ALSO@{ub} + @{"sb_CloseScreen()" Link "sb_CloseScreen"}, @{"sb_NextBuffer()" Link sb_NextBuffer}, @{"sb_GetBitMap()" Link sb_GetBitMap}, @{"sb_GetScreen()" Link sb_GetScreen} +@endnode + + + +@node "sb_CloseScreen" +@{u}scrbuffer.m/sb_CloseScreen scrbuffer.m/sb_CloseScreen@{uu} + + @{b}SYNTAX@{ub} + + sb_CloseScreen ( buffered screen ) + + @{b}PURPOSE@{ub} + + Closes a buffered screen. All associated resources (buffers, + message ports etc) are returned to the system. + + @{b}INPUTS@{ub} + screen a buffered screen handle, as returned from @{"sb_OpenScreen()" Link "sb_OpenScreen"} + @{b}NOT@{ub} a standard Amiga screen! + + @{b}SEE ALSO@{ub} + @{"sb_OpenScreen()" Link "sb_OpenScreen"} +@endnode + +@node "sb_NextBuffer" +@{u}scrbuffer.m/sb_NextBuffer scrbuffer.m/sb_NextBuffer@{uu} + + @{b}SYNTAX@{ub} + + bitmap = sb_NextBuffer( buffered screen ) + + @{b}PURPOSE@{ub} + + Ask the operating system to change the bitmap of the screen associated + with the double buffered screen, and wait for it to happen so that the + other screen is hidden, ready for rendering. It does this by calling + ChangeScreenBuffer() from the V39 Intuition library, then waiting + for the reply message. + + @{b}INPUTS@{ub} + screen a buffered screen handle, as returned from @{"sb_OpenScreen()" Link "sb_OpenScreen"} + + @{b}OUTPUTS@{ub} + bitmap a standard Amiga bitmap, that represents the currently HIDDEN + display area. This will usually need to be cleared and can + then be rendered into. + + @{b}SEE ALSO@{ub} + @{"sb_OpenScreen()" Link "sb_OpenScreen"}, @{"sb_NextBuffer()" Link sb_NextBuffer}, @{"sb_GetBitMap()" Link sb_GetBitMap}, @{"sb_GetScreen()" Link sb_GetScreen} +@endnode + +@node "sb_GetBitMap" +@{u}scrbuffer.m/sb_GetBitMap scrbuffer.m/sb_GetBitMap@{uu} + + @{b}SYNTAX@{ub} + + bitmap = sb_GetBitMap( buffered screen ) + + @{b}PURPOSE@{ub} + + Returns the currently hidden bitmap. This will be identical to that + returned by @{"sb_NextBuffer()" Link "sb_NextBuffer"}. + + @{b}INPUTS@{ub} + screen a buffered screen handle, as returned from @{"sb_OpenScreen()" Link "sb_OpenScreen"} + + @{b}OUTPUTS@{ub} + bitmap a standard amiga bitmap, that represents the currently HIDDEN + display area. + + @{b}SEE ALSO@{ub} + @{"sb_NextBuffer()" Link "sb_NextBuffer"}, @{"sb_OpenScreen()" Link "sb_OpenScreen"}, @{"sb_GetBitMap()" Link sb_GetBitMap}, @{"sb_GetScreen()" Link sb_GetScreen} +@endnode + + +@node "sb_GetScreen" +@{u}scrbuffer.m/sb_GetScreen scrbuffer.m/sb_GetScreen@{uu} + + @{b}SYNTAX@{ub} + + screen = sb_GetScreen( buffered screen ) + + @{b}PURPOSE@{ub} + + Returns the Amiga screen associated with the double buffered + screen. This is to enable windows and other standard intuition + operations to be performed on the screen. + + @{b}INPUTS@{ub} + screen a buffered screen handle, as returned from @{"sb_OpenScreen()" Link "sb_OpenScreen"} + + @{b}OUTPUTS@{ub} + screen a standard Amiga Screen + + @{b}SEE ALSO@{ub} + @{"sb_NextBuffer()" Link "sb_NextBuffer"}, @{"sb_OpenScreen()" Link "sb_OpenScreen"}, @{"sb_GetBitMap()" Link sb_GetBitMap} +@endnode + + + +@node examples "Information about the examples" + + Only 1 example has been written so far. + + @{"TheBOX" Link "TheBox.e/main"} + + A simple example that shows how to open a simple double buffered screen, + and render into the offscreen bitmap using the system functions. It also + shows how a window can be opened on the screen to get input events. + + +@endnode + + + + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/thebox.e b/amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/thebox.e new file mode 100644 index 0000000..750179a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/ScrBuffer/thebox.e @@ -0,0 +1,75 @@ +/* + + Example for ScrBuffer.m double buffered screen module + + by Michael Zucchi, 1994 this code in the public domain + + */ + + +MODULE 'intuition/intuition', 'intuition/screens', + 'graphics/rastport', + 'tools/scrbuffer' + +DEF bscr, scr:PTR TO screen, win:PTR TO window + +PROC main() + +DEF x,y,x2,y2,x3,y3, dx, dy, rp, myrp:rastport, c, go, im:PTR TO intuimessage + +bscr:=sb_OpenScreen([SA_WIDTH, 320, SA_HEIGHT, 256, SA_DEPTH, 4, + SA_OVERSCAN, OSCAN_STANDARD, SA_AUTOSCROLL, -1, SA_PENS, [-1]:INT, 0], 0); + +-> find the screen we are using, and make a copy of the rastport so we can use it +scr:=sb_GetScreen(bscr); +CopyMem(scr.rastport, myrp, SIZEOF rastport); +myrp.layer:=0; -> must set layer to 0 'cause we dont have one! + +-> open a window so we can get REAL input events +win:=OpenWindowTagList(0, [WA_CUSTOMSCREEN, scr, WA_BACKDROP, -1, + WA_FLAGS, WFLG_BORDERLESS+WFLG_ACTIVATE+WFLG_RMBTRAP, + WA_IDCMP, IDCMP_VANILLAKEY, 0]); + +dx:=2;dy:=1; +x:=50;y:=50; -> position +x2:=0;y2:=0; +x3:=0;y3:=0; -> where to erase +c:=1 -> colour +go:=1; + +WHILE go + IF (im:=GetMsg(win.userport)) -> get any vanillakey events + IF im.class=IDCMP_VANILLAKEY AND im.code=27 THEN go:=0; + ReplyMsg(im); + ENDIF + + myrp.bitmap:=sb_NextBuffer(bscr); -> change screen buffers, and get its bitmap + + SetAPen(myrp, 0); -> erase the old image + RectFill(myrp, x3, y3, x3+100, y3+50); + SetAPen(myrp, c); -> draw the new box + RectFill(myrp, x, y, x+100, y+50); + + Move(myrp, 50,50); + Text(myrp, 'ESC to quit!', 12); + + x3:=x2;y3:=y2; -> roll coordinates + x2:=x;y2:=y; + + x:=x+dx; -> new position + y:=y+dy; + + IF (x>(320-110)) OR (x<10) -> bounce the box off of walls + dx:=-dx;c++ + ENDIF + IF (y>(256-60)) OR (y<10) + dy:=-dy;c++ + ENDIF +ENDWHILE + +-> clean up. In 'real life' all the open functions would be tested after use +CloseWindow(win); +sb_CloseScreen(bscr); + +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/gurutest.e b/amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/gurutest.e new file mode 100644 index 0000000..6f3366b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/gurutest.e @@ -0,0 +1,20 @@ +/* shows ho to catch processor exceptions from own programs + I don't guarantee what the module trapguru.m does is 100% ok + for all CPU's */ + +MODULE 'tools/trapguru' + +PROC main() + DEF a + trapguru() -> install trap handler + FOR a:=1 TO 10 DO bla(a) +ENDPROC + +PROC bla(x) HANDLE + DEF a=0 + a:=a/a -> cause processor exception +EXCEPT + IF exception="GURU" + WriteF('guru \d occured: $\z\h[8]\n',x,exceptioninfo) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/trapguru.e b/amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/trapguru.e new file mode 100644 index 0000000..7497c19 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/TrapGuru/trapguru.e @@ -0,0 +1,45 @@ +/* trapguru.m + + installs a trap-handler in your task-structure, to catch + processor exceptions like zero-divide etc. + When handler gets invoked, it will throw an E-exception + "GURU" with alertnum as info. + + I don't guarantee this is 100% reliable for all CPU's etc. + +*/ + + +OPT MODULE + +MODULE 'exec/tasks' + +EXPORT PROC trapguru() + DEF mytask:PTR TO tc + mytask:=FindTask(NIL) + mytask.trapcode:={tcode} + LEA store(PC),A0 + MOVE.L A4,(A0) +ENDPROC + +tcode: + MOVE.L (A7)+,D0 + LEA store(PC),A0 + MOVE.L D0,4(A0) + MOVEQ #3,D1 + CMP.L D1,D0 + BGT.S noadjust + MOVE.L $4.W,A6 + BTST #0,297(A6) + BNE.S noadjust + ADDQ.L #8,A7 +noadjust: + LEA continue(PC),A0 + MOVE.L A0,2(A7) + RTE +continue: + LEA store(PC),A0 + MOVE.L (A0),A4 + Throw("GURU",Long({store}+4)) +store: + LONG 0,0 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/UsefulV2.doc b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/UsefulV2.doc new file mode 100644 index 0000000..b7984f4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/UsefulV2.doc @@ -0,0 +1,150 @@ +Short: JRH's useful E modules (version 2) +Type: dev/e +Author: jason@fsel.com (Jason R. Hulance) +Uploader: jason@fsel.com (Jason R. Hulance) + +JRH's Useful Modules (Version 2) +================================ + +These modules are Copyright (C) 1995, Jason R. Hulance. + +You are free to use these modules in your programs, whether they are freeware +or commercial. However, if you want to distribute any of this archive you +must include it all, unmodified, together with this file. + +Contents +-------- + +[This version is mainly a bug-fix: the eCodeXXX() routines did not flush the +CPU caches so could fail on a 68040, and the resource modules have been +simplified thanks to a bug-fixed EC v3.2a.] + +Various modules: + + ecode.m: + PROC eCode(func) + PROC eCodePreserve(func) + PROC eCodeTask(func) + PROC eCodeASLHook(func) + PROC eCodeCxCustom(func) + PROC eCodeCollision(func) + PROC eCodeIntHandler(func) + PROC eCodeIntServer(func) + PROC eCodeSoftInt(func) + PROC eCodeSwapArgs(func) + PROC eCodeDispose(addr) + + split.m: + PROC argSplit(str=0) + + +Amiga E does not support Resources (at least, not up to v3.1a, anyway). +These modules rectify this. + + battclock.m: + DEF battclockbase + PROC readBattClock() + PROC resetBattClock() + PROC writeBattClock(time) + + battmem.m: + DEF battmembase + PROC obtainBattSemaphore() + PROC readBattMem(buffer,offset,length) + PROC releaseBattSemaphore() + PROC writeBattMem(buffer,offset,length) + + cia.m: + PROC ableICR(resource,mask) + PROC addICRVector(resource,iCRBit,interrupt) + PROC remICRVector(resource,iCRBit,interrupt) + PROC setICR(resource,mask) + + disk.m: + DEF diskbase + PROC allocUnit(unitNum) + PROC freeUnit(unitNum) + PROC getUnit(unitPointer) + PROC getUnitID(unitNum) + PROC giveUnit() + PROC readUnitID(unitNum) + + misc.m: + DEF miscbase + PROC allocMiscResource(unitNum,name) + PROC freeMiscResource(unitNum) + + potgo.m: + DEF potgobase + PROC allocPotBits(bits) + PROC freePotBits(bits) + PROC writePotgo(word,mask) + + +Documentation +------------- + +The standard documentation on the Resource functions suffices for the +Resource modules. All the other functions (eCodeXXX and split) return NIL +if an error occurred, which is normally "out of memory". + + ecode.m: + o eCode() takes the address of an E function (or a label) and wraps it + so that it can be called from other tasks/processes and still access + the global variables of the main program. This function was created + for use with createTask(), but has other uses. + o eCodePreserve() is similar, but it also protects the function by + preserving the non-scratch registers on the stack. This means the + function can retrieve (and change) registers D2-D7/A2-A6 as local + variables. For instance, + PROC fun(a6,a5,a4,a3,a2,d7,d6,d5,d4,d3,d2) IS d2:=d3+a3 + will have the effect of changing register D2 (and D0) when the + function returns. Note: you do not need to specify all registers, + just the suffix of the above that you are actually interested in. + PROC fun(a3,a2,d7,d6,d5,d4,d3,d2) IS d2:=d3+a3 + would have done... + o eCodeTask() is just eCode() with a more suggestive name. + o eCodeASLHook() takes the address of an E function (or a label) and + returns something usable as an ASL hook function (nothing to do with + the utility library hooks, more's the pity). + o eCodeCxCustom() does the same for CX custom functions. + o eCodeCollision() does the same for GEL collision functions. + o eCodeIntHandler() is for interrupt handlers: you get A1 and D1 as + arguments (in that order) to your function. (A1 is the data element + of your interrupt, and D1 contains the interrupt flags.) + o eCodeIntServer() is for interrupt servers: you get A1 (the data + element of your interrupt) as an argument. + o eCodeSoftInt() is the same, but for software interrupts. + o eCodeSwapArgs() is like eCode() except it swaps the order of two + arguments on the stack. This means the E function can have its + arguments in the same order as a similar C function. For example, + you can use this instead of eCodeCollision() if your collision code is + simple (i.e., doesn't use PrintF() and the like). + o eCodeDispose() is passed the result of the one of the above + functions, and will to dispose the memory used by the special wrapper. + You will rarely need to use this, as the memory will be freed + automatically at the end of the program. + o eCodeASLHook(), eCodeCxCustom(), eCodeIntHandler(), eCodeIntServer() + and eCodeSoftInt() all use their own private scratch area to preserve + registers, thus saving crucial stack space. This has the disadvantage + of making the code non-reentrant, so if you need to use the same + function as multiple interrupt servers you must use eCodeIntServer() + multiple times. Apart from that they should be OK, since they do + not get called from multiple tasks. (If you find this a problem then + you can use eCodePreserve()...) + o eCodePreserve() uses a big bit of STACK to store registers, so be + careful... + + split.m: + o argSplit(str=NIL) splits a string of arguments like "arg" (which is + the default), handling quoted arguments correctly. The result is an + E-list of strings, or NIL if an error occurred. The list is also + NIL-terminated so you have a choice of ways to manipulate it. The + string passed to this function (or "arg" by default) is *altered* by + this function, so you shouldn't try using it directly. You can + DisposeLink() the resulting list if you want to free it before the end + of the program. (You are also responsible for freeing the string when + you are done with it, unless it was the default "arg", of course.) + +The main reason for the creation of these modules was my translations of the +RKRM examples. These provide many examples of the use of these functions. diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/battclock.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/battclock.e new file mode 100644 index 0000000..8e2ec01 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/battclock.e @@ -0,0 +1,19 @@ +OPT MODULE + +EXPORT DEF battclockbase + +EXPORT PROC resetBattClock() + MOVE.L battclockbase, A6 + JSR -6(A6) -> Offset of real ResetBattClock +ENDPROC + +EXPORT PROC readBattClock() + MOVE.L battclockbase, A6 + JSR -12(A6) -> Offset of real ReadBattClock +ENDPROC D0 + +EXPORT PROC writeBattClock(time) + MOVE.L time, D0 + MOVE.L battclockbase, A6 + JSR -18(A6) -> Offset of real WriteBattClock +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/battmem.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/battmem.e new file mode 100644 index 0000000..7b3f7aa --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/battmem.e @@ -0,0 +1,29 @@ +OPT MODULE + +EXPORT DEF battmembase + +EXPORT PROC obtainBattSemaphore() + MOVE.L battmembase, A6 + JSR -6(A6) -> Offset of real ObtainBattSemaphore +ENDPROC + +EXPORT PROC releaseBattSemaphore() + MOVE.L battmembase, A6 + JSR -12(A6) -> Offset of real ReleaseBattSemaphore +ENDPROC + +EXPORT PROC readBattMem(buffer, offset, length) + MOVE.L buffer, A0 + MOVE.L offset, D0 + MOVE.L length, D1 + MOVE.L battmembase, A6 + JSR -18(A6) -> Offset of real ReadBattMem +ENDPROC D0 + +EXPORT PROC writeBattMem(buffer, offset, length) + MOVE.L buffer, A0 + MOVE.L offset, D0 + MOVE.L length, D1 + MOVE.L battmembase, A6 + JSR -24(A6) -> Offset of real WriteBattMem +ENDPROC D0 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/bitfield.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/bitfield.e new file mode 100644 index 0000000..381690e --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/bitfield.e @@ -0,0 +1,18 @@ +OPT MODULE, PREPROCESS +OPT EXPORT + +#define NBITMASK(n) (Shl(1,(n))-1) + +#define NBITSATX(n,x) (Shl(NBITMASK(n),(x))) + +#define NOTNBITSATX(n,x) (Not(NBITSATX(n,x))) + +#define GETNBITSATX(n,x,f) (lshr((f) AND NBITSATX(n,x), (x))) + +#define SETNBITSATX(n,x,f,v) (((f) AND NOTNBITSATX(n,x)) OR Shl((v) AND NBITMASK(n), x)) + +PROC lshr(x,y) + MOVE.L x, D0 + MOVE.L y, D1 + LSR.L D1, D0 +ENDPROC D0 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/cia.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/cia.e new file mode 100644 index 0000000..06d7eca --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/cia.e @@ -0,0 +1,27 @@ +OPT MODULE + +EXPORT PROC addICRVector(resource, iCRBit, interrupt) + MOVE.L iCRBit, D0 + MOVE.L interrupt, A1 + MOVE.L resource, A6 + JSR -6(A6) -> Offset of real AddICRVector +ENDPROC D0 + +EXPORT PROC remICRVector(resource, iCRBit, interrupt) + MOVE.L iCRBit, D0 + MOVE.L interrupt, A1 + MOVE.L resource, A6 + JSR -12(A6) -> Offset of real RemICRVector +ENDPROC + +EXPORT PROC ableICR(resource, mask) + MOVE.L mask, D0 + MOVE.L resource, A6 + JSR -18(A6) -> Offset of real AbleICR +ENDPROC D0 + +EXPORT PROC setICR(resource, mask) + MOVE.L mask, D0 + MOVE.L resource, A6 + JSR -24(A6) -> Offset of real SetICR +ENDPROC D0 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/disk.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/disk.e new file mode 100644 index 0000000..e67c377 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/disk.e @@ -0,0 +1,38 @@ +OPT MODULE + +EXPORT DEF diskbase + +EXPORT PROC allocUnit(unitNum) + MOVE.L unitNum, D0 + MOVE.L diskbase, A6 + JSR -6(A6) -> Offset of real AllocUnit +ENDPROC D0 + +EXPORT PROC freeUnit(unitNum) + MOVE.L unitNum, D0 + MOVE.L diskbase, A6 + JSR -12(A6) -> Offset of real FreeUnit +ENDPROC + +EXPORT PROC getUnit(unitPointer) + MOVE.L unitPointer, A1 + MOVE.L diskbase, A6 + JSR -18(A6) -> Offset of real GetUnit +ENDPROC D0 + +EXPORT PROC giveUnit() + MOVE.L diskbase, A6 + JSR -24(A6) -> Offset of real GiveUnit +ENDPROC + +EXPORT PROC getUnitID(unitNum) + MOVE.L unitNum, D0 + MOVE.L diskbase, A6 + JSR -30(A6) -> Offset of real GetUnitID +ENDPROC D0 + +EXPORT PROC readUnitID(unitNum) + MOVE.L unitNum, D0 + MOVE.L diskbase, A6 + JSR -36(A6) -> Offset of real ReadUnitID +ENDPROC D0 diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/ecode.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/ecode.e new file mode 100644 index 0000000..650c899 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/ecode.e @@ -0,0 +1,207 @@ +OPT MODULE + +MODULE 'exec/memory', + 'hardware/custom' + +-> Wraps an E function so it can still access globals, even from other tasks. +EXPORT PROC eCode(func) IS setup(func,{start},{end}-{start}) + +-> Wraps an E function as above, but also preserves the non-scratch registers. +EXPORT PROC eCodePreserve(func) IS setup(func,{pStart},{pEnd}-{pStart}) + +-> Wraps an E function for use with createTask() +EXPORT PROC eCodeTask(func) IS eCode(func) + +-> Wraps an E function for use as an ASL hook +EXPORT PROC eCodeASLHook(func) IS setup(func,{aStart},{aEnd}-{aStart}) + +-> Wraps an E function for use as an CX custom function +EXPORT PROC eCodeCxCustom(func) IS setup(func,{cStart},{cEnd}-{cStart}) + +-> Wraps an E function for use as a GEL collision function +EXPORT PROC eCodeCollision(func) IS eCodeCxCustom(func) + +-> Wraps an E function for use as an interrupt handler +EXPORT PROC eCodeIntHandler(func) IS setup(func,{hStart},{hEnd}-{hStart}) + +-> Wraps an E function for use as an interrupt server +EXPORT PROC eCodeIntServer(func) IS setup(func,{sStart},{sEnd}-{sStart}) + +-> Wraps an E function for use as a software interrupt +EXPORT PROC eCodeSoftInt(func) IS setup(func,{iStart},{iEnd}-{iStart}) + +-> Wraps an E function as eCode(), but swaps the order of two args +EXPORT PROC eCodeSwapArgs(func) IS setup(func,{oStart},{oEnd}-{oStart}) + +EXPORT PROC eCodeDispose(mem) IS IF mem THEN Dispose(mem-8) ELSE NIL + +PROC setup(func, addr, len) HANDLE + DEF mem:PTR TO LONG, a4 + mem:=NewM(len, MEMF_PUBLIC) + -> Fully relocatable code can be copied to another memory location + CopyMem(addr, mem, len) + mem[]++:=func + MOVE.L A4, a4 + mem[]++:=a4 + IF KickVersion(36) THEN CacheClearU() -> Write out the cache (68040 especially bad...) + RETURN mem +EXCEPT + RETURN NIL +ENDPROC + +start: +function: + LONG 0 +storeA4: + LONG 0 +entry: + MOVE.L storeA4(PC), A4 -> Restore A4 + MOVE.L function(PC), -(A7) + RTS -> Call real function +end: + NOP + +pStart: +pFunction: + LONG 0 +pStoreA4: + LONG 0 +pEntry: + MOVEM.L D2-D7/A2-A6, -(A7) -> Preserve registers + MOVE.L pStoreA4(PC), A4 -> Restore A4 + MOVE.L pFunction(PC), A5 + JSR (A5) -> Call real function + MOVEM.L (A7)+, D2-D7/A2-A6 -> Restore registers + RTS +pEnd: + NOP + +aStart: +aFunction: + LONG 0 +aStoreA4: + LONG 0 +aEntry: + MOVE.L (A7)+, A1 -> Remember the caller + MOVE.L (A7), A0 -> Swap 3 arguments + MOVE.L 8(A7), (A7) + MOVE.L A0, 8(A7) + LEA aStack(PC), A0 + MOVEM.L D2-D7/A1-A6, (A0) -> Preserve registers + MOVE.L aStoreA4(PC), A4 -> Restore A4 + MOVE.L aFunction(PC), A0 + JSR (A0) -> Call real function + LEA aStack(PC), A0 + MOVEM.L (A0), D2-D7/A1-A6 -> Restore registers + MOVE.L A1, -(A7) -> Restore caller + RTS +aStack: + LONG 2,3,4,5,6,7,1,2,3,4,5,6,0 +aEnd: + NOP + +cStart: +cFunction: + LONG 0 +cStoreA4: + LONG 0 +cEntry: + MOVE.L (A7)+, A1 -> Remember the caller + MOVE.L (A7), A0 -> Swap 2 arguments + MOVE.L 4(A7), (A7) + MOVE.L A0, 4(A7) + LEA cStack(PC), A0 + MOVEM.L D2-D7/A1-A6, (A0) -> Preserve registers + MOVE.L cStoreA4(PC), A4 -> Restore A4 + MOVE.L cFunction(PC), A0 + JSR (A0) -> Call real function + LEA cStack(PC), A0 + MOVEM.L (A0), D2-D7/A1-A6 -> Restore registers + MOVE.L A1, -(A7) -> Restore caller + RTS +cStack: + LONG 2,3,4,5,6,7,1,2,3,4,5,6,0 +cEnd: + NOP + +hStart: +hFunction: + LONG 0 +hStoreA4: + LONG 0 +hEntry: + LEA hStack(PC), A0 + MOVEM.L D2-D7/A2-A4, (A0) -> Preserve registers + MOVE.L hStoreA4(PC), A4 -> Restore A4 + MOVE.L hFunction(PC), A0 + MOVEM.L D1/A1, -(A7) -> Push D1 and A1 as arguments + JSR (A0) -> Call real function + LEA 8(A7), A7 -> Remove arguments + LEA hStack(PC), A0 + MOVEM.L (A0), D2-D7/A2-A4 -> Restore registers + RTS +hStack: + LONG 2,3,4,5,6,7,2,3,4,0 +hEnd: + NOP + +sStart: +sFunction: + LONG 0 +sStoreA4: + LONG 0 +sEntry: + LEA sStack(PC), A6 + MOVEM.L D2-D7/A2-A4, (A6) -> Preserve registers + MOVE.L sStoreA4(PC), A4 -> Restore A4 + MOVE.L sFunction(PC), A6 + MOVE.L A1, -(A7) -> Push A1 as an argument + JSR (A6) -> Call real function + LEA 4(A7), A7 -> Remove argument + LEA sStack(PC), A6 + MOVEM.L (A6), D2-D7/A2-A4 -> Restore registers + MOVE.L #CUSTOMADDR, A0 -> Reset A0 to custom base + TST.L D0 -> Set Z flag according to func result + RTS +sStack: + LONG 2,3,4,5,6,7,2,3,4,0 +sEnd: + NOP + +iStart: +iFunction: + LONG 0 +iStoreA4: + LONG 0 +iEntry: + LEA iStack(PC), A0 + MOVEM.L D2-D7/A2-A4/A6, (A0) -> Preserve registers + MOVE.L iStoreA4(PC), A4 -> Restore A4 + MOVE.L iFunction(PC), A0 + MOVE.L A1, -(A7) -> Push A1 as an argument + JSR (A0) -> Call real function + LEA 4(A7), A7 -> Remove argument + LEA iStack(PC), A0 + MOVEM.L (A0), D2-D7/A2-A4/A6 -> Restore registers + RTS +iStack: + LONG 2,3,4,5,6,7,2,3,4,6,0 +iEnd: + NOP + +oStart: +oFunction: + LONG 0 +oStoreA4: + LONG 0 +oEntry: + MOVE.L 4(A7), A0 -> Swap 2 arguments + MOVE.L 8(A7), 4(A7) + MOVE.L A0, 8(A7) + MOVE.L oStoreA4(PC), A4 -> Restore A4 + MOVE.L oFunction(PC), -(A7) + RTS -> Call real function +oEnd: + NOP + + diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/misc.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/misc.e new file mode 100644 index 0000000..78d147a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/misc.e @@ -0,0 +1,16 @@ +OPT MODULE + +EXPORT DEF miscbase + +EXPORT PROC allocMiscResource(unitNum, name) + MOVE.L unitNum, D0 + MOVE.L name, A1 + MOVE.L miscbase, A6 + JSR -6(A6) -> Offset of real AllocMiscResource +ENDPROC D0 + +EXPORT PROC freeMiscResource(unitNum) + MOVE.L unitNum, D0 + MOVE.L miscbase, A6 + JSR -12(A6) -> Offset of real FreeMiscResource +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/potgo.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/potgo.e new file mode 100644 index 0000000..02d16d7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/potgo.e @@ -0,0 +1,22 @@ +OPT MODULE + +EXPORT DEF potgobase + +EXPORT PROC allocPotBits(bits) + MOVE.L bits, D0 + MOVE.L potgobase, A6 + JSR -6(A6) -> Offset of real AllocPotBits +ENDPROC D0 + +EXPORT PROC freePotBits(bits) + MOVE.L bits, D0 + MOVE.L potgobase, A6 + JSR -12(A6) -> Offset of real FreePotBits +ENDPROC + +EXPORT PROC writePotgo(word, mask) + MOVE.L word, D0 + MOVE.L mask, D1 + MOVE.L potgobase, A6 + JSR -18(A6) -> Offset of real WritePotgo +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendexplorer.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendexplorer.e new file mode 100644 index 0000000..08c836d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendexplorer.e @@ -0,0 +1,16 @@ +OPT MODULE + +MODULE 'other/sendrexx' + +CONST MAXLINE=512 + +EXPORT PROC sendExplorer(addr,obj=NIL,repPort=NIL,message=NIL,quiet=FALSE) + DEF s[MAXLINE]:STRING + StringF(s, '''DISPLAY \s$\h OBJECT "\s" MESSAGE "\s"''', + IF quiet THEN 'QUIET ' ELSE '', addr, + IF obj THEN obj ELSE '', IF message THEN message ELSE '') +ENDPROC rx_SendMsg('EXPLORER',s,repPort) + +EXPORT PROC quitExplorer(repPort=NIL) IS rx_SendMsg('EXPLORER','''QUIT''',repPort) + +EXPORT PROC isExplorerRunning() IS FindPort('EXPLORER')<>NIL diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendrexx.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendrexx.e new file mode 100644 index 0000000..dbf4f81 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/sendrexx.e @@ -0,0 +1,46 @@ +OPT MODULE, PREPROCESS + +MODULE 'exec/ports', + 'exec/nodes', + 'rexx/rxslib', + 'rexx/storage', + 'rexxsyslib', + 'amigalib/ports' + +ENUM ERR_NONE, ERR_LIB, ERR_RMSG, ERR_RSTR + +RAISE ERR_LIB IF OpenLibrary()=NIL, + ERR_RMSG IF CreateRexxMsg()=NIL, + ERR_RSTR IF CreateArgstring()=NIL + +EXPORT PROC rx_SendMsg(portname, s, repPort=NIL) HANDLE + DEF port=NIL, msg=NIL:PTR TO rexxmsg, myrep=NIL, lib=NIL, success=FALSE + IF rexxsysbase=NIL + rexxsysbase:=lib:=OpenLibrary(RXSNAME, 0) + ENDIF + IF repPort=NIL + IF NIL=(repPort:=myrep:=createPort(NIL,0)) THEN Raise("PORT") + ENDIF + msg:=CreateRexxMsg(repPort, NIL, portname) + msg.action:=RXCOMM + msg.args[]:=CreateArgstring(s, StrLen(s)) + msg.mn.ln.name:=RXSDIR + Forbid() + IF port:=FindPort(RXSDIR) THEN PutMsg(port, msg) + Permit() + IF port + WaitPort(repPort) + msg:=GetMsg(repPort) + success:=(msg.result1=0) + ENDIF +EXCEPT DO + IF msg + IF msg.args[] THEN DeleteArgstring(msg.args[]) + DeleteRexxMsg(msg) + ENDIF + IF myrep THEN deletePort(myrep) + IF lib + CloseLibrary(lib) + rexxsysbase:=NIL + ENDIF +ENDPROC success diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/setprogname.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/setprogname.e new file mode 100644 index 0000000..f1498db --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/setprogname.e @@ -0,0 +1,16 @@ +OPT MODULE, PREPROCESS +OPT EXPORT + +MODULE 'dos/dos', + 'dos/dosextens' + +PROC setprogname(p:PTR TO LONG) + DEF cli:PTR TO commandlineinterface, bstr + IF p[]=NIL + IF cli:=Cli() + bstr:=BADDR(cli.commandname) + p[]:=String(bstr[]) + IF p[] THEN StrCopy(p[],bstr+1,bstr[]) + ENDIF + ENDIF +ENDPROC \ No newline at end of file diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Useful/split.e b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/split.e new file mode 100644 index 0000000..0b40d82 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Useful/split.e @@ -0,0 +1,62 @@ +OPT MODULE + +ENUM A_BEGIN, A_SPACE, A_QUOTE, A_QUOTE2, A_END + +CONST NUM="\a"+1 + +-> Split the string "str" (which defaults to the arguments string "arg") +EXPORT PROC argSplit(str=NIL) IS splitStr_(IF str THEN str ELSE arg) + +-> A small function to split an argument string like "arg" into a C-like array +-> of arguments, handling quoted arguments properly. Uses recursion to collect +-> list contents, then allocate list and set contents. Result is NIL if out of +-> memory, or an E-list of pointers to (normal) strings (this list is also NIL +-> terminated so you have a choice of how to use it). The original string is +-> effectively destroyed and should not be used after calling this function. +PROC splitStr_(str, len=0) + DEF tmp=A_BEGIN:PTR TO LONG, s -> Reuse tmp to save stack space + s:=str + WHILE tmp<>A_END + SELECT NUM OF str[] + CASE 0, "\n", "\b" + IF tmp=A_BEGIN THEN s:=NIL + str[]:=0 + tmp:=A_END + CASE "\q" + SELECT A_END OF tmp + CASE A_BEGIN; tmp:=A_QUOTE; s++ + CASE A_QUOTE; tmp:=A_END; str[]:=0 + ENDSELECT + str++ + CASE "\a" + SELECT A_END OF tmp + CASE A_BEGIN; tmp:=A_QUOTE2; s++ + CASE A_QUOTE2; tmp:=A_END; str[]:=0 + ENDSELECT + str++ + CASE " ", "\t" + SELECT A_END OF tmp + CASE A_BEGIN; s++ + CASE A_SPACE; tmp:=A_END; str[]:=0 + ENDSELECT + str++ + DEFAULT + IF tmp=A_BEGIN THEN tmp:=A_SPACE + str++ + ENDSELECT + ENDWHILE + IF s -> If not the last one... + IF FreeStack()>=1000 -> (Check stack since recursing...) + tmp:=splitStr_(str, len+1) -> ... split the rest, + IF tmp THEN tmp[len]:=s -> and add this one in + ELSE + tmp:=NIL + ENDIF + ELSE -> Else reached the end of arg... + tmp:=List(len+1) -> ... allocate list and set length + IF tmp -> (Extra element is for NIL termination) + tmp[len]:=NIL + SetList(tmp, len) + ENDIF + ENDIF +ENDPROC tmp -> Returns NIL if List() fails diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Vector/Vector.e b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/Vector.e new file mode 100644 index 0000000..d016d28 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/Vector.e @@ -0,0 +1,173 @@ +OPT MODULE + +EXPORT PROC polygon3d(list:PTR TO LONG,col=1) + DEF n,i,sx,sy,ox,oy,f=FALSE + n:=ListLen(list)/3 + FOR i:=1 TO n + sx,sy:=vec3d(list[]++,list[]++,list[]++) + IF f THEN Line(ox,oy,sx,sy,col) ELSE f:=TRUE + ox:=sx; oy:=sy; + ENDFOR +ENDPROC + +EXPORT PROC init3d(phi=75,theta=40) + LEA sintab(PC),A0 /* uses A0,A1,D0 */ + LEA c1(PC),A1 + MOVE.L phi,D0 + LSL.W #1,D0 + MOVE.W 0(A0,D0.W),6(A1) + ADD.W #180,D0 + MOVE.W 0(A0,D0.W),2(A1) + MOVE.L theta,D0 + LSL.W #1,D0 + MOVE.W 0(A0,D0.W),4(A1) + ADD.W #180,D0 + MOVE.W 0(A0,D0.W),(A1) +ENDPROC + +EXPORT PROC setpers3d(irho=1000,id=400) /* for average size rho:d = 5:2 */ + LEA rho(PC),A0 + MOVE.W irho.W,(A0) + MOVE.W id.W,2(A0) +ENDPROC + +EXPORT PROC setmiddle3d(x=160,y=128) + LEA midx(PC),A0 + MOVE.W x.W,(A0) + MOVE.W y.W,2(A0) +ENDPROC + +c1: INT $00c2 +c2: INT $0045 +s1: INT $00a3 +s2: INT $00f5 +rho: INT 2000 +d: INT 900 +midx: INT 160 +midy: INT 128 + +EXPORT PROC vec3d(x,y,z) + MOVE.L x,D0 + MOVE.L y,D1 + MOVE.L z,D2 + MOVE.L A4,-(A7) + MOVE.W c1(PC),D3 + MOVE.W c2(PC),D4 + MOVE.W s1(PC),D5 + MOVE.W s2(PC),D6 + MOVE D0,D7 /* EXPECTS X,Y,Z IN D0-D2 */ + MULS D5,D7 /* TRASHES ALL REGS BUT A5-A7 */ + ASR.L #8,D7 + MOVE D7,A0 /* TEMP1 = X*S1 */ + MOVE D1,D7 + MULS D3,D7 + ASR.L #8,D7 + SUB A0,D7 + MOVE D7,A2 /* XE = Y*C1-TEMP1 */ + MOVE D1,D7 + MULS D5,D7 + ASR.L #8,D7 + MULS D4,D7 + ASR.L #8,D7 + MOVE D7,A0 /* TEMP1 = Y*S1*C2 */ + MOVE D0,D7 + MULS D3,D7 + ASR.L #8,D7 + MULS D4,D7 + ASR.L #8,D7 + MOVE D7,A1 /* TEMP2 = X*C1*C2 */ + MOVE D2,D7 + MULS D6,D7 + ASR.L #8,D7 + SUB A0,D7 + SUB A1,D7 + MOVE D7,A3 /* YE = Z*S2-TEMP1-TEMP2 */ + MULS D6,D0 + ASR.L #8,D0 + MULS D3,D0 + ASR.L #8,D0 + MOVE D0,A0 /* TEMP1 = X*S2*C1 */ + MULS D6,D1 + ASR.L #8,D1 + MULS D5,D1 + ASR.L #8,D1 + MOVE D1,A1 /* TEMP2 = Y*S2*S1 */ + NEG D2 + MULS D4,D2 + ASR.L #8,D2 + ADD rho(PC),D2 + SUB A0,D2 + SUB A1,D2 /* ZE(D2) = -Z*C2+RHO-TEMP1-TEMP2 */ + MOVE A2,D3 + MOVE A3,D4 + MOVE d(PC),D0 + MOVE D0,D1 + MULS D3,D0 + DIVS D2,D0 + ADD midx(PC),D0 /* SX(D0) = D*XE/ZE+160 */ + NEG D1 + MULS D4,D1 + DIVS D2,D1 + ADD midy(PC),D1 /* SY(D1) = -D*YE/ZE+128 */ + MOVE.L (A7)+,A4 + EXT.L D0 + EXT.L D1 +ENDPROC D0 + +sintab: INT $0000,$0004,$0008,$000D,$0011,$0016,$001A,$001F + INT $0023,$0027,$002C,$0030,$0035,$0039,$003D,$0041 + INT $0046,$004A,$004E,$0053,$0057,$005B,$005F,$0063 + INT $0067,$006B,$006F,$0073,$0077,$007B,$007F,$0083 + INT $0087,$008A,$008E,$0092,$0095,$0099,$009C,$00A0 + INT $00A3,$00A7,$00AA,$00AD,$00B1,$00B4,$00B7,$00BA + INT $00BD,$00C0,$00C3,$00C6,$00C8,$00CB,$00CE,$00D0 + INT $00D3,$00D5,$00D8,$00DA,$00DC,$00DF,$00E1,$00E3 + INT $00E5,$00E7,$00E8,$00EA,$00EC,$00EE,$00EF,$00F1 + INT $00F2,$00F3,$00F5,$00F6,$00F7,$00F8,$00F9,$00FA + INT $00FB,$00FB,$00FC,$00FD,$00FD,$00FE,$00FE,$00FE + INT $00FE,$00FE,$00FF,$00FE,$00FE,$00FE,$00FE,$00FE + INT $00FD,$00FD,$00FC,$00FB,$00FB,$00FA,$00F9,$00F8 + INT $00F7,$00F6,$00F5,$00F3,$00F2,$00F1,$00EF,$00EE + INT $00EC,$00EA,$00E8,$00E7,$00E5,$00E3,$00E1,$00DF + INT $00DC,$00DA,$00D8,$00D5,$00D3,$00D0,$00CE,$00CB + INT $00C8,$00C6,$00C3,$00C0,$00BD,$00BA,$00B7,$00B4 + INT $00B1,$00AD,$00AA,$00A7,$00A3,$00A0,$009C,$0099 + INT $0095,$0092,$008E,$008A,$0087,$0083,$007F,$007B + INT $0077,$0073,$006F,$006B,$0067,$0063,$005F,$005B + INT $0057,$0053,$004E,$004A,$0046,$0041,$003D,$0039 + INT $0035,$0030,$002C,$0027,$0023,$001F,$001A,$0016 + INT $0011,$000D,$0008,$0004,$0000,$FFFC,$FFF8,$FFF3 + INT $FFEF,$FFEA,$FFE6,$FFE1,$FFDD,$FFD9,$FFD4,$FFD0 + INT $FFCB,$FFC7,$FFC3,$FFBF,$FFBA,$FFB6,$FFB2,$FFAD + INT $FFA9,$FFA5,$FFA1,$FF9D,$FF99,$FF95,$FF91,$FF8D + INT $FF89,$FF85,$FF81,$FF7D,$FF79,$FF76,$FF72,$FF6E + INT $FF6B,$FF67,$FF64,$FF60,$FF5D,$FF59,$FF56,$FF53 + INT $FF4F,$FF4C,$FF49,$FF46,$FF43,$FF40,$FF3D,$FF3A + INT $FF38,$FF35,$FF32,$FF30,$FF2D,$FF2B,$FF28,$FF26 + INT $FF24,$FF21,$FF1F,$FF1D,$FF1B,$FF19,$FF18,$FF16 + INT $FF14,$FF12,$FF11,$FF0F,$FF0E,$FF0D,$FF0B,$FF0A + INT $FF09,$FF08,$FF07,$FF06,$FF05,$FF05,$FF04,$FF03 + INT $FF03,$FF02,$FF02,$FF02,$FF02,$FF02,$FF01,$FF02 + INT $FF02,$FF02,$FF02,$FF02,$FF03,$FF03,$FF04,$FF05 + INT $FF05,$FF06,$FF07,$FF08,$FF09,$FF0A,$FF0B,$FF0D + INT $FF0E,$FF0F,$FF11,$FF12,$FF14,$FF16,$FF18,$FF19 + INT $FF1B,$FF1D,$FF1F,$FF21,$FF24,$FF26,$FF28,$FF2B + INT $FF2D,$FF30,$FF32,$FF35,$FF38,$FF3A,$FF3D,$FF40 + INT $FF43,$FF46,$FF49,$FF4C,$FF4F,$FF53,$FF56,$FF59 + INT $FF5D,$FF60,$FF64,$FF67,$FF6B,$FF6E,$FF72,$FF76 + INT $FF79,$FF7D,$FF81,$FF85,$FF89,$FF8D,$FF91,$FF95 + INT $FF99,$FF9D,$FFA1,$FFA5,$FFA9,$FFAD,$FFB2,$FFB6 + INT $FFBA,$FFBE,$FFC3,$FFC7,$FFCB,$FFD0,$FFD4,$FFD9 + INT $FFDD,$FFE1,$FFE6,$FFEA,$FFEF,$FFF3,$FFF8,$FFFC + INT $0000,$0004,$0008,$000D,$0011,$0016,$001A,$001F + INT $0023,$0027,$002C,$0030,$0035,$0039,$003D,$0041 + INT $0046,$004A,$004E,$0053,$0057,$005B,$005F,$0063 + INT $0067,$006B,$006F,$0073,$0077,$007B,$007F,$0083 + INT $0087,$008A,$008E,$0092,$0095,$0099,$009C,$00A0 + INT $00A3,$00A7,$00AA,$00AD,$00B1,$00B4,$00B7,$00BA + INT $00BD,$00C0,$00C3,$00C6,$00C8,$00CB,$00CE,$00D0 + INT $00D3,$00D5,$00D8,$00DA,$00DC,$00DF,$00E1,$00E3 + INT $00E5,$00E7,$00E8,$00EA,$00EC,$00EE,$00EF,$00F1 + INT $00F2,$00F3,$00F5,$00F6,$00F7,$00F8,$00F9,$00FA + INT $00FB,$00FB,$00FC,$00FD,$00FD,$00FE,$00FE,$00FE + INT $00FE,$00FE diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest1.e b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest1.e new file mode 100644 index 0000000..84a5f1f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest1.e @@ -0,0 +1,16 @@ +MODULE 'tools/vector' + +CONST R=100 + +PROC main() + DEF w + IF w:=OpenW(0,11,400,160,$200,$F,'testing the vector3d module!',NIL,1,NIL) + init3d(75,60) + setmiddle3d(200,80) + setpers3d(500,200) + polygon3d([R,R,R, R,R,-R, R,-R,-R, R,-R,R, R,R,R, R,-R,R, -R,-R,R, -R,R,R, R,R,R],3) + polygon3d([-R,-R,-R, -R,-R,R, -R,R,R, -R,R,-R, -R,-R,-R, -R,R,-R, R,R,-R, R,-R,-R, -R,-R,-R],3) + WaitIMessage(w) + CloseW(w) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest2.e b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest2.e new file mode 100644 index 0000000..09b3aeb --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest2.e @@ -0,0 +1,46 @@ +MODULE 'tools/vector' + +CONST R=100,MAXD=24,N=3 /* set N=1..7 (number of shades) */ + +OBJECT status + phi,theta,depth,x,y +ENDOBJECT + +DEF depth:PTR TO LONG,stats[N]:ARRAY OF status + +PROC main() + DEF w,curphi=75,curtheta=40,curd=0,curs=0,a,fact=1,curx=100,cury=100 + IF w:=OpenW(0,11,220,189,$200,$E,'3d VectorZ in E!',NIL,1,NIL) + SetRast(stdrast,1) + RefreshWindowFrame(w) + FOR a:=0 TO N-1 DO stats[a].phi:=-1 + depth:=[200,201,202,205,208,211,215,220,224,230,238,246,254,262,270,276,280,285,289,292,295,298,299,300] + REPEAT + stats[curs].phi:=curphi + stats[curs].theta:=curtheta + stats[curs].depth:=curd + stats[curs].x:=curx + stats[curs].y:=cury + drawshape(stats[curs],2) + curs++ + IF curs>=N THEN curs:=0 + curd:=curd+fact + IF curd>=(MAXD-1) THEN (curd:=MAXD-1) BUT fact:=-fact + IF curd<=0 THEN (curd:=0) BUT fact:=-fact + curphi:=curphi+2 + IF curphi>=360 THEN curphi:=0 + curtheta:=curtheta+2 + IF curtheta>=360 THEN curtheta:=0 + IF stats[curs].phi>=0 THEN drawshape(stats[curs],1) + UNTIL GetMsg(Long(w+$56)) + CloseW(w) + ENDIF +ENDPROC + +PROC drawshape(s:PTR TO status,col) + setmiddle3d(s.x,s.y) + setpers3d(750,depth[s.depth]) + init3d(s.phi,s.theta) + polygon3d([R,R,R,R,R,-R,R,-R,-R,R,-R,R,R,R,R,R,-R,R,-R,-R,R,-R,R,R,R,R,R],col) + polygon3d([-R,-R,-R,-R,-R,R,-R,R,R,-R,R,-R,-R,-R,-R,-R,R,-R,R,R,-R,R,-R,-R,-R,-R,-R],col) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest3.e b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest3.e new file mode 100644 index 0000000..4d8a22d --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest3.e @@ -0,0 +1,44 @@ +MODULE 'tools/vector' + +CONST R=100,S=40 + +DEF r1=R,n1=-R,r2=R,n2=-R,fac1=-1,fac2=1,fac3=1,fac4=-1 +DEF o1,o2,l1,l2 + +PROC main() + DEF w,sx1,sx2,sy1,sy2,phi,theta + o1:=List(S) + o2:=List(S) + IF w:=OpenW(0,11,200,189,$200,$E,'3d VectorZ in E!',NIL,1,NIL) + SetRast(stdrast,1) + RefreshWindowFrame(w) + phi:=74 + theta:=60 + setmiddle3d(100,100) + setpers3d(750,300) + REPEAT + dofac({r1},{fac1}) + dofac({r2},{fac2}) + dofac({n1},{fac3}) + dofac({n2},{fac4}) + WaitTOF() + polygon3d(o1,1) + polygon3d(o2,1) + phi:=phi+2; IF phi>=360 THEN phi:=phi-360 + theta:=theta+2; IF theta>=360 THEN theta:=theta-360 + init3d(phi,theta) + polygon3d(l1:=[r1,r1,r1,r1,r1,n1,r1,n1,n1,r1,n1,r1,r1,r1,r1,r1,n1,r1,n1,n1,r1,n1,r1,r1,r1,r1,r1],2) + polygon3d(l2:=[n2,n2,n2,n2,n2,r2,n2,r2,r2,n2,r2,n2,n2,n2,n2,n2,r2,n2,r2,r2,n2,r2,n2,n2,n2,n2,n2],3) + ListCopy(o1,l1,ALL) + ListCopy(o2,l2,ALL) + Delay(1) + UNTIL GetMsg(Long(w+$56)) + CloseW(w) + ENDIF +ENDPROC + +PROC dofac(var,f) + ^var:=^var+^f + IF ^var>0 THEN IF (^var>120) OR (^var<80) THEN ^f:=-^f + IF ^var<0 THEN IF (^var<-120) OR (^var>-80) THEN ^f:=-^f +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest4.e b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest4.e new file mode 100644 index 0000000..fbf8c81 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/Vector/vectest4.e @@ -0,0 +1,92 @@ +/* this is supposed to be one of them magnifying class vectors, + but it works a little bumpy right now (implementation=experimental). + change WINX and WINY below. +*/ + +MODULE 'tools/vector' + +CONST R=100,S=-100,MAXD=24,N=3 /* set N=1..7 (number of shades) */ +CONST DISTANCE=80,WINX=639,WINY=282 + +OBJECT status + phi,theta,depth,x,y +ENDOBJECT + +DEF depth:PTR TO LONG,stats[N]:ARRAY OF status, translist:PTR TO LONG + +PROC main() + DEF w,curphi=75,curtheta=40,curd=0,curs=0,a,fact=1,x,y,nx,ny,ox,oy + IF w:=OpenW(0,0,WINX,WINY,$200,$E,'3d VectorZ in E! (move mouse!)',NIL,1,NIL) + SetRast(stdrast,1) + translist:=[0,-16,-28,-36,-40,-40,-36,-28,-16,0,16,28,36,40,40,36,28,16,0] + FOR x:=0 TO WINX STEP 16 + FOR y:=0 TO WINY STEP 16 + nx,ny:=posttrans(x,y) + ox,oy:=posttrans(x,y+16) + Line(nx,ny,ox,oy,4) + ox,oy:=posttrans(x+16,y) + Line(nx,ny,ox,oy,4) + ENDFOR + ENDFOR + RefreshWindowFrame(w) + SetDrMd(stdrast,2) + PutChar(stdrast+24,3) + FOR a:=0 TO N-1 DO stats[a].phi:=-1 + depth:=[200,201,202,205,208,211,215,220,224,230,238,246,254,262,270,276,280,285,289,292,295,298,299,300] + REPEAT + stats[curs].phi:=curphi + stats[curs].theta:=curtheta + stats[curs].depth:=curd + stats[curs].x:=Bounds(MouseX(w),DISTANCE,WINX-DISTANCE) + stats[curs].y:=Bounds(MouseY(w),DISTANCE,WINY-DISTANCE) + drawshape(stats[curs],2) + curs++ + IF curs>=N THEN curs:=0 + curd:=curd+fact + IF curd>=(MAXD-1) THEN (curd:=MAXD-1) BUT fact:=-fact + IF curd<=0 THEN (curd:=0) BUT fact:=-fact + curphi:=curphi+2 + IF curphi>=360 THEN curphi:=0 + curtheta:=curtheta+2 + IF curtheta>=360 THEN curtheta:=0 + IF stats[curs].phi>=0 THEN drawshape(stats[curs],1) + UNTIL GetMsg(Long(w+$56)) + CloseW(w) + ELSE + WriteF('um,...\n') + ENDIF +ENDPROC + +PROC drawshape(s:PTR TO status,col) + setmiddle3d(s.x,s.y) + setpers3d(750,depth[s.depth]) + init3d(s.phi,s.theta) + polygon([R,R,S, R,R,R, R,S,R, R,S,S, R,R,S, S,R,S, S,R,R, S,S,R, S,S,S, S,R,S],col) + polygon([R,S,R, S,S,R],col) + polygon([R,R,R, S,R,R],col) + polygon([R,S,S, S,S,S],col) +ENDPROC + +PROC posttrans(x,y) + IF x>DISTANCE + IF y>DISTANCE + IF DISTANCE+288>x + IF DISTANCE+288>y + x:=ListItem(translist,Shr(x-DISTANCE,4))+x + y:=ListItem(translist,Shr(y-DISTANCE,4))+y + ENDIF + ENDIF + ENDIF + ENDIF +ENDPROC x,y + +PROC polygon(list:PTR TO LONG,col=1) + DEF n,i,sx,sy,ox,oy,f=FALSE + n:=ListLen(list)/3 + FOR i:=1 TO n + sx,sy:=vec3d(list[]++,list[]++,list[]++) + sx,sy:=posttrans(sx,sy) + IF f THEN Line(ox,oy,sx,sy,col) ELSE f:=TRUE + ox:=sx; oy:=sy; + ENDFOR +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/README b/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/README new file mode 100644 index 0000000..176deef --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/README @@ -0,0 +1,18 @@ +Short: E module; case-sensitive menu hotkeys +Dest: dev/e +Uploader: el269@cleveland.freenet.edu +Long: +CONTENTS: + qualifiedItemAddress.e - E source for module qualifiedItemAddress.m + test.e - test/demo source + +The function in this module works identically to the Intuition +function ItemAddress(), except that it uses an additional argument +(keycode qualifier) to return the address of a menu item based on +the case (upper- or lowercase) of it's Intuition hotkey. + +Author: Barry Wills +Email: el269@cleveland.freenet.edu +Address: 5528D Pryor Dr. + SAFB, IL 62225, USA +Status: Public Domain diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/qualifiedItemAddress.e b/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/qualifiedItemAddress.e new file mode 100644 index 0000000..336910b --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/qualifiedItemAddress.e @@ -0,0 +1,96 @@ +/*----------------------------------------------------------------------------* + + EMODULES:other/qualifiedItemAddress + + NAME + qualifiedItemAddress -- processes case-sensitive menu command hotkeys + for either shift key + + SYNOPSIS + itemAddress:=qualifiedItemAddress(menuStrip, menuNumber, qualifier) + + PROC qualifiedItemAddress(menuStrip:PTR TO menu, menuNumber, qualifier=0) + DEF itemAddress:PTR TO menuitem + ENDPROC itemAddress + + FUNCTION + Use of this function is similar to the Intuition routine ItemAddress(), + with the addition of the qualifier argument. Both menuNumber and + qualifier can be obtained from the Intuition IDCMP_MENUPICK message + received by your program. menuStrip is searched for the upper- or + lowercase equivalent menu command hotkey, depending on whether + qualifier contains IEQUALIFIER_RSHIFT and/or IEQUALIFIER_LSHIFT. If + qualifier is 0, the function will return the item identified by + Intuition (if indeed menuNumber corresponds to a valid menu item). A + value of NIL will be returned if no valid menu item can be identified. + + INPUTS + menuStrip = a pointer to the first menu in your menu strip + menuNumber = the value which contains the packed data that selects the + the menu and item (and sub-item). Very simply, the rawkey code + gotten from an IDCMP_MENUPICK intuimessage + qualifier = the rawkey qualifier gotten from and IDCMP_MENUPICK + intuimessage + + RESULT + If menuNumber = MENUNULL or does not correspond to a valid menu item on + menuStrip, this function returns NIL; else this function returns the + address of the menu item specified by menuNumber and qualifier. + + *----------------------------------------------------------------------------*/ + +OPT MODULE +OPT REG=5 + +MODULE 'intuition/intuition', + 'devices/inputevent', + 'other/lowerChar', + 'other/upperChar' + +EXPORT PROC qualifiedItemAddress(menuStrip:PTR TO menu, menuNumber, qualifier=0) + DEF item:PTR TO menuitem, origItem:PTR TO menuitem, subitem:PTR TO menuitem, + correctItem=NIL:PTR TO menuitem, commandChar, tChar=0 + /*-- Get the vanilla item address: --*/ + IF (origItem:=ItemAddress(menuStrip, menuNumber))=NIL THEN RETURN NIL + /*-------------------------------------------------------------------* + Qualifier will be: + - 0 if selected with the mouse; + - LCOMMAND unshifted, or RCOMMAND shifted if selected with hotkey + If Qualifier is 0, just return the one Intuition sent us. + *-------------------------------------------------------------------*/ + IF qualifier=0 THEN RETURN origItem + /*-- Determine if we're looking for a shifted char or not: --*/ + commandChar:=IF qualifier AND (IEQUALIFIER_RSHIFT OR IEQUALIFIER_LSHIFT) THEN + upperChar(origItem.command) ELSE lowerChar(origItem.command) + /*-- Loop through menus, looking for our char: --*/ + IF commandChar=origItem.command + correctItem:=origItem + ELSE + REPEAT ->cycle thru menus + item:=menuStrip.firstitem + REPEAT ->cycle thru items + subitem:=item.subitem + WHILE subitem<>NIL ->cycle thru subitems + IF (tChar:=subitem.command)=commandChar + correctItem:=subitem + subitem:=NIL + ELSE + subitem:=subitem.nextitem + ENDIF + ENDWHILE + IF tChar=commandChar + item:=NIL + ELSEIF (tChar:=item.command)=commandChar + correctItem:=item + item:=NIL + ELSE + item:=item.nextitem + ENDIF + UNTIL item=NIL + menuStrip:=IF tChar=commandChar THEN NIL ELSE menuStrip.nextmenu + UNTIL menuStrip=NIL + ENDIF + /*-- Preserve multiple selections for a single menu event. -*/ + IF correctItem THEN correctItem.nextselect:=origItem.nextselect +ENDPROC correctItem + /* qualifiedItemAddress */ diff --git a/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/test.e b/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/test.e new file mode 100644 index 0000000..8ddc5a1 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Tools/qItemAddress/test.e @@ -0,0 +1,168 @@ +/*----------------------------------------------------------* + Demo of qualifiedItemAddress module. + + E Source generated by SRCGEN v0.1 + + CHANGES TO ORIGINAL GEN'ED CODE: + - inclusion of module 'other/qualifiedItemAddress' + - localization of some global variables to the functions + wait4message() and main() + - restructured wait4message() to return multiple values + when a IDCMP_MENUPICK message is received + - restructured main() to process (correctly) multiply + selected menu items in a single event + - minor changes to the CreateMenusA() arguments + + Source modified by B. Wills, Dec 12, 1994. + Placed in public domain. + *----------------------------------------------------------*/ + +OPT OSVERSION=37 +OPT REG=5 + +MODULE 'gadtools', + 'libraries/gadtools', + 'intuition/intuition', + 'intuition/screens', + 'intuition/gadgetclass', + 'graphics/text' + +MODULE 'other/qualifiedItemAddress' + +ENUM NONE,NOCONTEXT,NOGADGET,NOWB,NOVISUAL,OPENGT,NOWINDOW,NOMENUS + +DEF project0wnd:PTR TO window, + project0menus, + project0glist, + scr:PTR TO screen, + visual=NIL, + offx,offy,tattr + +PROC setupscreen() + IF (gadtoolsbase:=OpenLibrary('gadtools.library',37))=NIL THEN RETURN OPENGT + IF (scr:=LockPubScreen('Workbench'))=NIL THEN RETURN NOWB + IF (visual:=GetVisualInfoA(scr,NIL))=NIL THEN RETURN NOVISUAL + offy:=scr.wbortop+Int(scr.rastport+58)-10 + tattr:=['topaz.font',8,0,0]:textattr +ENDPROC + +PROC closedownscreen() + IF visual THEN FreeVisualInfo(visual) + IF scr THEN UnlockPubScreen(NIL,scr) + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) +ENDPROC + +PROC openproject0window() + DEF g:PTR TO gadget + IF (g:=CreateContext({project0glist}))=NIL THEN RETURN NOCONTEXT + IF (project0menus:= + CreateMenusA([1,0,'M1',0,$0,0,0, + 2,0,'I1', 'a',$0,0,0, + 2,0,'I2', 'A',$0,0,0, + 2,0,'I3', NIL,$0,0,0, + 3,0,'I3.1', 'b',$0,0,0, + 3,0,'I3.2', 'B',$0,0,0, + 2,0,'I4', NIL,$0,0,0, + 3,0,'I4.1', 'C',$0,0,0, + 3,0,'I4.2', 'c',$0,0,0, + 1,0,'M2', NIL,$0,0,0, + 2,0,'I1', 'd',$0,0,0, + 2,0,'I2', 'E',$0,0,0, + 2,0,'I3', NIL,$0,0,0, + 3,0,'I3.1', 'D',$0,0,0, + 3,0,'I3.2', 'e',$0,0,0, + 2,0,'I4', 'f',$0,0,0, + 2,0,'I5', 'G',$0,0,0, + 0,0,0,0,0,0,0]:newmenu,NIL))=NIL THEN RETURN NOMENUS + IF LayoutMenusA(project0menus,visual,NIL)=FALSE THEN RETURN NOMENUS + IF (project0wnd:=OpenWindowTagList(NIL, + [WA_LEFT,10, + WA_TOP,15, + WA_WIDTH,offx+400, + WA_HEIGHT,offy+89, + WA_IDCMP,$24C077E, + WA_FLAGS,$100F, + WA_TITLE,'Try Hotkeys AND Mouse', + WA_CUSTOMSCREEN,scr, + WA_MINWIDTH,67, + WA_MINHEIGHT,21, + WA_MAXWIDTH,$2C0, + WA_MAXHEIGHT,$226, + WA_AUTOADJUST,1, + WA_AUTOADJUST,1, + NIL]))=NIL THEN RETURN NOWINDOW + IF SetMenuStrip(project0wnd,project0menus)=FALSE THEN RETURN NOMENUS + Gt_RefreshWindow(project0wnd,NIL) + SetStdRast(project0wnd.rport) + Colour(1) +ENDPROC + +PROC closeproject0window() + IF project0wnd THEN ClearMenuStrip(project0wnd) + IF project0menus THEN FreeMenus(project0menus) + IF project0wnd THEN CloseWindow(project0wnd) + IF project0glist THEN FreeGadgets(project0glist) +ENDPROC + +PROC reporterr(er) + DEF erlist:PTR TO LONG + IF er + erlist:=['get context','create gadget','lock wb','get visual infos', + 'open "gadtools.library" v37+','open window','create menus'] + EasyRequestArgs(0,[20,0,0,'Could not \s!','ok'],0,[erlist[er-1]]) + ENDIF +ENDPROC er + +PROC wait4message(win:PTR TO window) + DEF mes:PTR TO intuimessage, class, code, qualifier + REPEAT + class:=0 + IF mes:=Gt_GetIMsg(win.userport) + class:=mes.class + IF class=IDCMP_MENUPICK + code:=mes.code + qualifier:=mes.qualifier + ELSEIF (class=IDCMP_GADGETDOWN) OR (class=IDCMP_GADGETUP) + code:=mes.iaddress + ELSEIF class=IDCMP_REFRESHWINDOW + Gt_BeginRefresh(win) + Gt_EndRefresh(win,TRUE) + class:=0 + ELSEIF class<>IDCMP_CLOSEWINDOW /* remove these if you like */ + class:=0 + ENDIF + Gt_ReplyIMsg(mes) + ELSE + WaitPort(win.userport) + ENDIF + UNTIL class +ENDPROC class,code,qualifier + +PROC main() + DEF done=FALSE, class, code, qualifier, iaddress=NIL:PTR TO menuitem + IF reporterr(setupscreen())=0 + reporterr(openproject0window()) + REPEAT + class,code,qualifier:=wait4message(project0wnd) + SELECT class + CASE IDCMP_CLOSEWINDOW + done:=TRUE + CASE IDCMP_MENUPICK + WHILE code<>-1 ->MENUNULL doesn't work since + -> terminal nextselect is -1 in E, vice 65535 in C. + IF iaddress:=qualifiedItemAddress(project0menus, code, qualifier) + TextF(4, 30, 'MenuId=\d Char=\c Qual=$\h ', + code, iaddress.command, qualifier) + code:=iaddress.nextselect + Delay(50) ->allow time to read the menu info + ELSE + code:=-1 + ENDIF + IF CtrlC() THEN code:=-1 + ENDWHILE + ENDSELECT + UNTIL done + closeproject0window() + ENDIF + closedownscreen() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt.c b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt.c new file mode 100644 index 0000000..32b9f88 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt.c @@ -0,0 +1,367 @@ +/* AmigaGuide to Text converter (v2). Copyright (c) 1994, Jason R. Hulance */ +/* C version. Restricted use of ANSI codes, so they work on Xterms etc. */ +/* Should compile easily (using gcc, say): */ +/* gcc -O2 -o ag2txt ag2txt.c */ + +#include +#include + +typedef enum { N_INIT, N_OUT, N_IN, NODE_STATES } NODE; +typedef enum { L_INIT, L_QUOTED, L_SPACED, LINE_STATES } LINE; +typedef enum { A_INIT, A_AT, A_BRAC, A_IGNORE, A_END, AT_STATES } AT; + +#define MAX_LINE_LEN (1024) +#define MAX_WIDTH (120) +#define CMP_EQUAL (0) +#define CMP_UNEQUAL (1) + +#define TRUE (0==0) +#define FALSE (1==0) + +char in[MAX_LINE_LEN]; +FILE *outh=NULL; + +typedef enum {BOLD, ITALIC, F_LINK, TITLE, HIGHLIGHT, OTHER} FONT; + +void write_ansi(FONT type, int on) +{ + /* BOLD ITALIC F_LINK TITLE HIGHLIGHT OTHER */ + if(on) { + static char *ansi[] = { + "\033[1m", "\033[1m", "\033[1m", "\033[7m", "\033[1m", "\033[1m" }; + fputs(ansi[type], outh); + } + else { + static char *ansi[] = { + "\033[0m", "\033[0m", "\033[0m", "\033[0m", "\033[0m", "\033[0m" }; + fputs(ansi[type], outh); + } +} + +int Stricmp(char *s, char *t) +{ + while(*s && *t) { + if(toupper(*s) != *t) + return CMP_UNEQUAL; + s++, t++; + } + return (*s || *t) ? CMP_UNEQUAL : CMP_EQUAL; +} + +int Strnicmp(char *s, char *t) +{ + while(*s && *t) { + if(toupper(*s) != *t) + return CMP_UNEQUAL; + s++, t++; + } + return (*t) ? CMP_UNEQUAL : CMP_EQUAL; +} + +void error(char *msg, int err) +{ + fputs(msg, stderr); + exit(err); +} + +char *get_word(char **line, int *chkbrac) +{ + LINE status=L_INIT; + char *t=NULL, *to; + int noword=TRUE, special=FALSE; + + if(line==NULL || *line==NULL) + return NULL; + to=*line; + while(**line && noword) { + if(to != *line) *to = **line; + switch(**line) { + case '"': + if(special) + to++; + else { + switch(status) { + case L_INIT: + status=L_QUOTED; + t=(*line)+1; + to++; + break; + case L_QUOTED: + *to='\0'; + noword=FALSE; + break; + default: + to++; + break; + } + } + break; + case '\n': case '\t': case ' ': + if(status==L_SPACED) { + *to='\0'; + noword=FALSE; + } + else + to++; + break; + default: + if(chkbrac && **line=='}') { + *to='\0'; + noword=FALSE; + *chkbrac=TRUE; + } + else { + if(status==L_INIT) { + t=*line; + status=L_SPACED; + } + to++; + } + break; + } + if(special) + special=FALSE; + else if(**line=='\\') { + special=TRUE; + to--; + } + (*line)++; + } + return t; +} + +int parse_at_line(char **line) +{ + char *first, *second, *third; + int gotbrac=FALSE, i=0, on=TRUE; + char c; + + first=get_word(line, &gotbrac); + if(first && *first) { + i=1; + if(gotbrac==FALSE) { + second=get_word(line, &gotbrac); + if(second && *second) { + i=2; + if(gotbrac==FALSE) { + third=get_word(line, &gotbrac); + if(third && *third) + i=3; + } + } + } + } + switch(i) { + case 1: + if(toupper(*first)=='U') { + on=FALSE; + first++; + } + c=toupper(*first); + switch(c) { + case 'B': + write_ansi(BOLD, on); + break; + case 'I': + write_ansi(ITALIC, on); + break; + } + break; + case 2: + if(Stricmp(first, "FG")==CMP_EQUAL) { + if(Stricmp(second, "HIGHLIGHT")==CMP_EQUAL) + write_ansi(HIGHLIGHT, TRUE); + else if(Stricmp(second, "TEXT")==CMP_EQUAL) + write_ansi(HIGHLIGHT, FALSE); + } + else if(Stricmp(second, "CLOSE")==CMP_EQUAL || + Stricmp(second, "QUIT")==CMP_EQUAL) { + write_ansi(OTHER, TRUE); + fputs(first, outh); + write_ansi(OTHER, FALSE); + } + break; + case 3: + if(Stricmp(second, "LINK")==CMP_EQUAL || + Stricmp(second, "ALINK")==CMP_EQUAL) { + write_ansi(F_LINK, TRUE); + fputs(first, outh); + write_ansi(F_LINK, FALSE); + } + else { + write_ansi(OTHER, TRUE); + fputs(first, outh); + write_ansi(OTHER, FALSE); + } + break; + } + return gotbrac; +} + +void parse_node_line(char *line, char *title) +{ + char *first, *second; + first=get_word(&line, NULL); + second=get_word(&line, NULL); + if(first && *first) { + if(second && *second) + strcpy(title, second); + else + strcpy(title, first); + } +} + +void parse_title_line(char *line, char *title) +{ + char *first; + first=get_word(&line, NULL); + if(first && *first) + strcpy(title, first); +} + +void statecopy(AT state) +{ + switch(state) { + case A_IGNORE: + fputc('\\', outh); + break; + case A_AT: + fputc('@', outh); + break; + case A_BRAC: + fputs("@{", outh); + break; + } +} + +void output(char *line) +{ + AT status=A_INIT; + int gotbrac; + char c; + + if(line[0]=='@' && line[1]!='{') + return; + while(c=*line) { + switch(c) { + case '\\': + if(status==A_INIT) + status=A_IGNORE; + else { + statecopy(status); + fputc(c, outh); + status=A_INIT; + } + line++; + break; + case '@': + if(status==A_INIT) + status=A_AT; + else { + if(status!=A_IGNORE) statecopy(status); + fputc(c, outh); + status=A_INIT; + } + line++; + break; + case '{': + if(status==A_AT) + status=A_BRAC; + else { + statecopy(status); + fputc(c, outh); + status=A_INIT; + } + line++; + break; + case '}': + switch(status) { + case A_BRAC: case A_END: + break; + default: + statecopy(status); + fputc(c, outh); + break; + } + status=A_INIT; + line++; + break; + default: + switch(status) { + case A_BRAC: + gotbrac=parse_at_line(&line); + status=(gotbrac ? A_INIT : A_END); + break; + case A_END: + line++; + break; + default: + statecopy(status); + fputc(c, outh); + status=A_INIT; + line++; + } + } + } +} + +void main(int argc, char *argv[]) +{ + FILE *fh; + NODE status=N_INIT; + char *s, title[MAX_WIDTH]; + int empty=TRUE; + char *top="\n--------------------------------------" \ + "--------------------------------------\n"; + char *bot="======================================" \ + "======================================\n"; + if(argc<2) + error("Usage: ag2txt []\n", 1); + if((fh=fopen(argv[1], "r"))==NULL) { + fprintf(stderr, "\"%s\" ", argv[1]); + error("could not be opened\n", 2); + } + if(argc>2) + outh=fopen(argv[2], "w"); + if(outh==NULL) + outh=stdout; + while(fgets(in, MAX_LINE_LEN, fh)) { + switch(status) { + case N_INIT: + if(Strnicmp(in, "@DATABASE")!=CMP_EQUAL) + error("Bad AmigaGuide input file\n", 3); + else + status=N_OUT; + break; + case N_OUT: + if(Strnicmp(in, "@NODE ")==CMP_EQUAL) { + status=N_IN; + parse_node_line(in+6, title); + empty=TRUE; + } + break; + case N_IN: + if(empty && Strnicmp(in, "@TITLE")==CMP_EQUAL) + parse_title_line(in+6, title); + else if(Strnicmp(in, "@ENDNODE")==CMP_EQUAL) { + fputs(bot, outh); + status=N_OUT; + } + else { + s=in; + while(*s == ' ' || *s == '\t' || *s == '\n') s++; + if(!(empty && *s=='\0')) { + if(empty) { + write_ansi(TITLE, TRUE); + fputs(title, outh); + write_ansi(TITLE, FALSE); + fputs(top, outh); + empty=FALSE; + } + output(in); + } + } + break; + } + } +} diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS1.3.e b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS1.3.e new file mode 100644 index 0000000..da62cd6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS1.3.e @@ -0,0 +1,313 @@ +/* AmigaGuide to Text converter (v2). Copyright (c) 1994, Jason R. Hulance */ +/* E version. For AmigaDos 1.3 or before (?). Very slow because it lacks */ +/* buffering on the I/O, and it's not likely to be added by me, either :-) */ + +ENUM N_INIT, N_OUT, N_IN, NODE_STATES +ENUM L_INIT, L_QUOTED, L_SPACED, LINE_STATES +ENUM A_INIT, A_AT, A_BRAC, A_IGNORE, A_END, AT_STATES +ENUM NO_ERR, ERR_FILE, ERR_DATA, ERR_BRK, NUM_ERRS + +CONST MAX_LINE_LEN=1024, MAX_WIDTH=120, CMP_EQUAL=0, CMP_UNEQUAL=1 + +DEF in[MAX_LINE_LEN]:STRING, outh=NIL + +ENUM BOLD, ITALIC, F_LINK, TITLE, HIGHLIGHT, OTHER + +PROC write_ansi(type, on=TRUE) + DEF ansi:PTR TO LONG + /* BOLD ITALIC F_LINK TITLE HIGHLIGHT OTHER */ + IF on + ansi:=['\e[1m', '\e[3m', '\e[1m\e[3m', '\e[7m', '\e[1m', '\e[1m'] + ELSE + ansi:=['\e[22m', '\e[23m', '\e[23m\e[22m', '\e[0m', '\e[22m', '\e[22m'] + ENDIF + fputs(outh, ansi[type]) +ENDPROC + +PROC fputc(fh, c) IS Out(fh, c) +PROC fputs(fh, s) IS Write(fh, s, StrLen(s)) + +PROC toupper(c) IS IF (c<"a") OR (c>"z") THEN c ELSE c-32 + +PROC stricmp(s1, s2, all=TRUE) + WHILE (s2[]<>0) AND (s1[]<>0) + IF toupper(s1[]++)<>s2[]++ THEN RETURN CMP_UNEQUAL + ENDWHILE + IF all + RETURN IF (s1[] OR s2[]) THEN CMP_UNEQUAL ELSE CMP_EQUAL + ELSE + RETURN IF s2[] THEN CMP_UNEQUAL ELSE CMP_EQUAL + ENDIF +ENDPROC + +PROC main() HANDLE + DEF fh, status=N_INIT, s, title[MAX_WIDTH]:STRING, + empty=TRUE, top, bot, ownout=TRUE, err + s, arg:=get_word(arg) + IF (fh:=Open(s, OLDFILE))=NIL THEN Raise(ERR_FILE) + IF arg[] + s:=get_word(arg) + IF s[] + outh:=Open(s, NEWFILE) + ENDIF + ENDIF + IF outh=NIL + WriteF('') + outh:=stdout + ownout:=FALSE + ENDIF + top:='\n--------------------------------------' + + '--------------------------------------\n' + bot:='======================================' + + '======================================\n' + REPEAT + err:=ReadStr(fh, in) + SELECT NODE_STATES OF status + CASE N_INIT + IF stricmp(in, '@DATABASE', FALSE)<>CMP_EQUAL + Raise(ERR_DATA) + ELSE + status:=N_OUT + ENDIF + CASE N_OUT + IF stricmp(in, '@NODE ', FALSE)=CMP_EQUAL + status:=N_IN + parse_node_line(in+STRLEN, title) + empty:=TRUE + ENDIF + CASE N_IN + IF empty AND (stricmp(in, '@TITLE', FALSE)=CMP_EQUAL) + parse_title_line(in+STRLEN, title) + ELSEIF stricmp(in, '@ENDNODE', FALSE)=CMP_EQUAL + fputs(outh, bot) + status:=N_OUT + ELSE + IF CtrlC() THEN Raise(ERR_BRK) + s:=TrimStr(in) + IF Not(empty AND (s[]=0)) + IF empty + write_ansi(TITLE) + fputs(outh, title) + write_ansi(TITLE, FALSE) + fputs(outh, top) + empty:=FALSE + ENDIF + output(in) + ENDIF + ENDIF + ENDSELECT + UNTIL err=-1 +EXCEPT DO + SELECT NUM_ERRS OF exception + CASE ERR_FILE + WriteF('Could not open file "\s"\n', s) + CASE ERR_DATA + WriteF('"\s" is not an AmigaGuide file\n') + CASE ERR_BRK + WriteF('User aborted\n') + ENDSELECT + IF ownout AND outh THEN Close(outh) + IF fh THEN Close(fh) +ENDPROC + +PROC output(line) + DEF status=A_INIT, gotbrac, c + IF line[]="@" THEN IF line[1]<>"{" THEN RETURN + WHILE c:=line[] + SELECT c + CASE "\\" + IF status=A_INIT + status:=A_IGNORE + ELSE + statecopy(status) + fputc(outh, c) + status:=A_INIT + ENDIF + line++ + CASE "@" + IF status=A_INIT + status:=A_AT + ELSE + IF status<>A_IGNORE THEN statecopy(status) + fputc(outh, c) + status:=A_INIT + ENDIF + line++ + CASE "{" + IF status=A_AT + status:=A_BRAC + ELSE + statecopy(status) + fputc(outh, c) + status:=A_INIT + ENDIF + line++ + CASE "}" + SELECT AT_STATES OF status + CASE A_BRAC, A_END + DEFAULT + statecopy(status) + fputc(outh, c) + ENDSELECT + status:=A_INIT + line++ + DEFAULT + SELECT AT_STATES OF status + CASE A_BRAC + line,gotbrac:=parse_at_line(line) + status:=IF gotbrac THEN A_INIT ELSE A_END + CASE A_END + line++ + DEFAULT + statecopy(status) + fputc(outh, c) + status:=A_INIT + line++ + ENDSELECT + ENDSELECT + ENDWHILE + fputc(outh, "\n") +ENDPROC + +PROC statecopy(state) + SELECT AT_STATES OF state + CASE A_IGNORE + fputc(outh, "\\") + CASE A_AT + fputc(outh, "@") + CASE A_BRAC + fputs(outh, '@{') + ENDSELECT +ENDPROC + +PROC parse_at_line(line) + DEF first, second, third, gotbrac, i=0, on=TRUE, c + first,line,gotbrac:=get_word(line, TRUE) + IF first[] + i:=1 + IF gotbrac=FALSE + second,line,gotbrac:=get_word(line, TRUE) + IF second[] + i:=2 + IF gotbrac=FALSE + third,line,gotbrac:=get_word(line, TRUE) + IF third[] THEN i:=3 + ENDIF + ENDIF + ENDIF + ENDIF + SELECT 4 OF i + CASE 1 + IF toupper(first[])="U" + on:=FALSE + first++ + ENDIF + c:=toupper(first[]) + SELECT c + CASE "B" + write_ansi(BOLD, on) + CASE "I" + write_ansi(ITALIC, on) + ENDSELECT + CASE 2 + IF stricmp(first, 'FG')=CMP_EQUAL + IF stricmp(second, 'HIGHLIGHT')=CMP_EQUAL + write_ansi(HIGHLIGHT) + ELSEIF stricmp(second, 'TEXT')=CMP_EQUAL + write_ansi(HIGHLIGHT, FALSE) + ENDIF + ELSEIF (stricmp(second, 'CLOSE')=CMP_EQUAL) OR + (stricmp(second, 'QUIT')=CMP_EQUAL) + write_ansi(OTHER) + fputs(outh, first) + write_ansi(OTHER, FALSE) + ENDIF + CASE 3 + IF (stricmp(second, 'LINK')=CMP_EQUAL) OR + (stricmp(second, 'ALINK')=CMP_EQUAL) + write_ansi(F_LINK) + fputs(outh, first) + write_ansi(F_LINK, FALSE) + ELSE + write_ansi(OTHER) + fputs(outh, first) + write_ansi(OTHER, FALSE) + ENDIF + ENDSELECT +ENDPROC line,gotbrac + +PROC parse_node_line(line, title) + DEF first, second + first,line:=get_word(line) + second,line:=get_word(line) + IF first[] + IF second[] + StrCopy(title, second) + ELSE + StrCopy(title, first) + ENDIF + ENDIF +ENDPROC + +PROC parse_title_line(line, title) + DEF first + first,line:=get_word(line) + IF first[] + StrCopy(title, first) + ENDIF +ENDPROC + +CONST L_SIZE=35 + +PROC get_word(line, chkbrac=FALSE) + DEF status=L_INIT, noword=TRUE, foundbrac=FALSE, + t=NIL, to, special=FALSE + to:=line + WHILE line[] AND noword + IF to<>line THEN to[]:=line[] + SELECT L_SIZE OF line[] + CASE "\q" + IF special + to++ + ELSE + SELECT LINE_STATES OF status + CASE L_INIT + status:=L_QUOTED + t:=line+1 + to++ + CASE L_QUOTED + to[]:=0 + noword:=FALSE + DEFAULT + to++ + ENDSELECT + ENDIF + CASE "\n", "\t", " " + IF status=L_SPACED + to[]:=0 + noword:=FALSE + ELSE + to++ + ENDIF + DEFAULT + IF chkbrac AND (line[]="}") + to[]:=0 + noword:=FALSE + foundbrac:=TRUE + ELSE + IF status=L_INIT + t:=line + status:=L_SPACED + ENDIF + to++ + ENDIF + ENDSELECT + IF special + special:=FALSE + ELSEIF line[]="\\" + special:=TRUE + to-- + ENDIF + line++ + ENDWHILE +ENDPROC t,line,foundbrac diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS2.0.e b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS2.0.e new file mode 100644 index 0000000..130f9bc --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_OS2.0.e @@ -0,0 +1,306 @@ +/* AmigaGuide to Text converter (v2). Copyright (c) 1994, Jason R. Hulance */ +/* E version. For AmigaDos 2.0+. Uses Michael Zucchi's excellent 'async' */ +/* module that comes with E v3.0 to get a 1/3 speed up over the AmigaDOS */ +/* buffered I/O functions. (Would be good if 'async' handled output, too.) */ + +OPT OSVERSION=37 + +MODULE 'utility', 'tools/async', 'dos/stdio' + +ENUM N_INIT, N_OUT, N_IN, NODE_STATES +ENUM L_INIT, L_QUOTED, L_SPACED, LINE_STATES +ENUM A_INIT, A_AT, A_BRAC, A_IGNORE, A_END, AT_STATES +ENUM NO_ERR, ERR_FILE, ERR_LIB, ERR_DATA, ERR_BRK, NUM_ERRS + +CONST MAX_LINE_LEN=1024, MAX_WIDTH=120, CMP_EQUAL=0 + +RAISE ERR_LIB IF OpenLibrary()=NIL + +DEF in[MAX_LINE_LEN]:ARRAY, outh=NIL + +ENUM BOLD, ITALIC, F_LINK, TITLE, HIGHLIGHT, OTHER + +PROC write_ansi(type, on=TRUE) + DEF ansi:PTR TO LONG + /* BOLD ITALIC F_LINK TITLE HIGHLIGHT OTHER */ + IF on + ansi:=['\e[1m', '\e[3m', '\e[1m\e[3m', '\e[7m', '\e[1m', '\e[1m'] + ELSE + ansi:=['\e[22m', '\e[23m', '\e[23m\e[22m', '\e[0m', '\e[22m', '\e[22m'] + ENDIF + Fputs(outh, ansi[type]) +ENDPROC + +PROC main() HANDLE + DEF fh, status=N_INIT, s, title[MAX_WIDTH]:STRING, + empty=TRUE, top, bot, ownout=TRUE + utilitybase:=OpenLibrary('utility.library', 37) + s, arg:=get_word(arg) + IF (fh:=as_Open(s, OLDFILE, 3, 8*1024))=NIL THEN Raise(ERR_FILE) + IF arg[] + s:=get_word(arg) + IF s[] + outh:=Open(s, NEWFILE) + ENDIF + ENDIF + IF outh=NIL + WriteF('') + outh:=stdout + ownout:=FALSE + ENDIF + top:='\n--------------------------------------' + + '--------------------------------------\n' + bot:='======================================' + + '======================================\n' + WHILE as_FGetS(fh, in, MAX_LINE_LEN) + SELECT NODE_STATES OF status + CASE N_INIT + IF Strnicmp(in, '@DATABASE', STRLEN)<>CMP_EQUAL + Raise(ERR_DATA) + ELSE + status:=N_OUT + ENDIF + CASE N_OUT + IF Strnicmp(in, '@NODE ', STRLEN)=CMP_EQUAL + status:=N_IN + parse_node_line(in+STRLEN, title) + empty:=TRUE + ENDIF + CASE N_IN + IF empty AND (Strnicmp(in, '@TITLE', STRLEN)=CMP_EQUAL) + parse_title_line(in+STRLEN, title) + ELSEIF Strnicmp(in, '@ENDNODE', STRLEN)=CMP_EQUAL + Fputs(outh, bot) + status:=N_OUT + ELSE + IF CtrlC() THEN Raise(ERR_BRK) + s:=TrimStr(in) + IF Not(empty AND (s[]=0)) + IF empty + write_ansi(TITLE) + Fputs(outh, title) + write_ansi(TITLE, FALSE) + Fputs(outh, top) + empty:=FALSE + ENDIF + output(in) + ENDIF + ENDIF + ENDSELECT + ENDWHILE +EXCEPT DO + SELECT NUM_ERRS OF exception + CASE ERR_LIB + WriteF('Could not open utility.library\n') + CASE ERR_FILE + WriteF('Could not open file "\s"\n', s) + CASE ERR_DATA + WriteF('"\s" is not an AmigaGuide file\n') + CASE ERR_BRK + WriteF('User aborted\n') + ENDSELECT + IF ownout AND outh THEN Close(outh) + IF fh THEN as_Close(fh) + IF utilitybase THEN CloseLibrary(utilitybase) +ENDPROC + +PROC output(line) + DEF status=A_INIT, gotbrac, c + IF line[]="@" THEN IF line[1]<>"{" THEN RETURN + WHILE c:=line[] + SELECT c + CASE "\\" + IF status=A_INIT + status:=A_IGNORE + ELSE + statecopy(status) + FputC(outh, c) + status:=A_INIT + ENDIF + line++ + CASE "@" + IF status=A_INIT + status:=A_AT + ELSE + IF status<>A_IGNORE THEN statecopy(status) + FputC(outh, c) + status:=A_INIT + ENDIF + line++ + CASE "{" + IF status=A_AT + status:=A_BRAC + ELSE + statecopy(status) + FputC(outh, c) + status:=A_INIT + ENDIF + line++ + CASE "}" + SELECT AT_STATES OF status + CASE A_BRAC, A_END + DEFAULT + statecopy(status) + FputC(outh, c) + ENDSELECT + status:=A_INIT + line++ + DEFAULT + SELECT AT_STATES OF status + CASE A_BRAC + line,gotbrac:=parse_at_line(line) + status:=IF gotbrac THEN A_INIT ELSE A_END + CASE A_END + line++ + DEFAULT + statecopy(status) + FputC(outh, c) + status:=A_INIT + line++ + ENDSELECT + ENDSELECT + ENDWHILE +ENDPROC + +PROC statecopy(state) + SELECT AT_STATES OF state + CASE A_IGNORE + FputC(outh, "\\") + CASE A_AT + FputC(outh, "@") + CASE A_BRAC + Fputs(outh, '@{') + ENDSELECT +ENDPROC + +PROC parse_at_line(line) + DEF first, second, third, gotbrac, i=0, on=TRUE, c + first,line,gotbrac:=get_word(line, TRUE) + IF first[] + i:=1 + IF gotbrac=FALSE + second,line,gotbrac:=get_word(line, TRUE) + IF second[] + i:=2 + IF gotbrac=FALSE + third,line,gotbrac:=get_word(line, TRUE) + IF third[] THEN i:=3 + ENDIF + ENDIF + ENDIF + ENDIF + SELECT 4 OF i + CASE 1 + IF ToUpper(first[])="U" + on:=FALSE + first++ + ENDIF + c:=ToUpper(first[]) + SELECT c + CASE "B" + write_ansi(BOLD, on) + CASE "I" + write_ansi(ITALIC, on) + ENDSELECT + CASE 2 + IF Stricmp(first, 'FG')=CMP_EQUAL + IF Stricmp(second, 'HIGHLIGHT')=CMP_EQUAL + write_ansi(HIGHLIGHT) + ELSEIF Stricmp(second, 'TEXT')=CMP_EQUAL + write_ansi(HIGHLIGHT, FALSE) + ENDIF + ELSEIF (Stricmp(second, 'CLOSE')=CMP_EQUAL) OR + (Stricmp(second, 'QUIT')=CMP_EQUAL) + write_ansi(OTHER) + Fputs(outh, first) + write_ansi(OTHER, FALSE) + ENDIF + CASE 3 + IF (Stricmp(second, 'LINK')=CMP_EQUAL) OR + (Stricmp(second, 'ALINK')=CMP_EQUAL) + write_ansi(F_LINK) + Fputs(outh, first) + write_ansi(F_LINK, FALSE) + ELSE + write_ansi(OTHER) + Fputs(outh, first) + write_ansi(OTHER, FALSE) + ENDIF + ENDSELECT +ENDPROC line,gotbrac + +PROC parse_node_line(line, title) + DEF first, second + first,line:=get_word(line) + second,line:=get_word(line) + IF first[] + IF second[] + StrCopy(title, second) + ELSE + StrCopy(title, first) + ENDIF + ENDIF +ENDPROC + +PROC parse_title_line(line, title) + DEF first + first,line:=get_word(line) + IF first[] + StrCopy(title, first) + ENDIF +ENDPROC + +CONST L_SIZE=35 + +PROC get_word(line, chkbrac=FALSE) + DEF status=L_INIT, noword=TRUE, foundbrac=FALSE, + t=NIL, to, special=FALSE + to:=line + WHILE line[] AND noword + IF to<>line THEN to[]:=line[] + SELECT L_SIZE OF line[] + CASE "\q" + IF special + to++ + ELSE + SELECT LINE_STATES OF status + CASE L_INIT + status:=L_QUOTED + t:=line+1 + to++ + CASE L_QUOTED + to[]:=0 + noword:=FALSE + DEFAULT + to++ + ENDSELECT + ENDIF + CASE "\n", "\t", " " + IF status=L_SPACED + to[]:=0 + noword:=FALSE + ELSE + to++ + ENDIF + DEFAULT + IF chkbrac AND (line[]="}") + to[]:=0 + noword:=FALSE + foundbrac:=TRUE + ELSE + IF status=L_INIT + t:=line + status:=L_SPACED + ENDIF + to++ + ENDIF + ENDSELECT + IF special + special:=FALSE + ELSEIF line[]="\\" + special:=TRUE + to-- + ENDIF + line++ + ENDWHILE +ENDPROC t,line,foundbrac diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_v2.readme b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_v2.readme new file mode 100644 index 0000000..a7e449f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Ag2Txt/Ag2Txt_v2.readme @@ -0,0 +1,40 @@ +Short: AmigaGuide to text (v2). E & C source. +Type: text/hyper +Uploader: m88jrh@uk.ac.ox.ecs (Jason R. Hulance) +Author: m88jrh@uk.ac.ox.ecs (Jason R. Hulance) + +Ag2Txt (v2) +=========== +Ag2Txt converts AmigaGuide files to highlighted text. This text may be +read using a standard text reader, or may be sent to a suitable printer. +(The Amiga printer drivers handle the ANSI codes produced.) + +There are three different versions of this program in the archive: two +written in E (one for AmigaDOS 1.3 and one for 2.0+), and one in C. All +three versions have the following syntax: + + ag2txt [ ] + +The is an optional output file. If it is not specified or +cannot be opened then the output is written to the terminal (stdout). + +Version 2 of Ag2Txt knows a lot more AmigaGuide codes and handles them a +lot better than version 1. Also, version 1 omitted the C version, which +was subsequently requested by a number of people. + +You can customise the output by fiddling with the source. The ansi codes +used are confined to the function 'write_ansi' near the top of the source. +One list is for turning on the appropriate attribute, and the second is +for turning it off. The C version is particularly dumb because the Xterms +I use at work don't understand the 'turn off' codes so I took them out +(and used just the 'set to plain' code, '\e[0m'). + +The AmigaDOS 2.0+ version uses the buffered I/O functions to gain a huge +performance increase compared to the unbuffered I/O used in the AmigaDOS +1.3 version. Also, the 2.0+ version uses Michael Zucchi's excellent +'async' module that comes with E v3.0 to get an extra 1/3 speed up (for +reading, since 'async' doesn't do writes... yet??). + +Legal stuff: +The programs in this archive are Copyright (C) 1994, Jason R. Hulance. +Apart from that the GNU Public License (Version 2) holds. diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit.readme b/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit.readme new file mode 100644 index 0000000..60450ed --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit.readme @@ -0,0 +1,80 @@ +Short: Intelligent AmigaGuide splitter +Type: text/hyper +Uploader: jason@fsel.com (Jason R. Hulance) +Author: jason@fsel.com (Jason R. Hulance) + +AGSplit +======= +AGSPlit is an intelligent AmigaGuide file splitter. By "intelligent" +I mean that each of the resulting pieces is a complete, stand-alone +AmigaGuide file. Needless to say, the pieces are all interlinked and +behave as if they were in one big AmigaGuide file. + +Why would you want to split an AmigaGuide file? Well, the smaller the +file is the faster it loads into AmigaGuide/Multiview. The trade-off +is that it is marginally slower to go between links that are not in +the same AmigaGuide file (but this is hardly noticeable if the pieces +are small!). + +In particular, I wrote this program to split up my "Beginner's Guide +to Amiga E" which I write in TeXinfo format and so produce using the +excellent MakeGuide utility (and the version of MakeGuide I use can +only make one large file). + +Usage +----- +The template is: + + GUIDEFILE/A,SPLITFILE/A,DESTDIR + +"GUIDEFILE" is the file to split. +"SPLITFILE" is a short file to show the split positions (see below). +"DESTDIR" is an optional directory name to store the pieces (default + is the current directory). + +Split Files +----------- +A split file consists of node/filename pairs which describe the +positions where the AmigaGuide file is to be split. The nodes must be +specified in the order in which they appear in the AmigaGuide file. +For example: + +Main +Contents.guide +FirstNode +Chapter1.guide +AnotherNode +Appendix.guide + +This split file specifies that *all* nodes from "Main" up to +"FirstNode" (but not including "FirstNode") will be split into the +file "Contents.guide". + +All nodes from "FirstNode" up to "AnotherNode" (but not including +"AnotherNode") will be split into "Chapter1.guide". + +All nodes from "AnotherNode" to the end of the original AmigaGuide +file will be split into "Appendix.guide". + +If this split file were called "mysplitfile" and the AmigaGuide file +to be split were called "myagfile.guide", then: + + AGSplit myagfile.guide mysplitfile ram: + +would split "myagfile.guide" into the specified pieces +("Contents.guide", "Chapter1.guide" and "Appendix.guide") and put the +pieces into the "ram:" directory. + +Examples +-------- +Two supplied example split files can be used to split my "Beginner's +Guide to Amiga E" and the "E Reference Guide" (both available in the +current Amiga E distribution in dev/e). + +To Do +----- +I might make a better interface than "split files", but they are +simple enough to use... + +It's a bit slow at the moment (I'm using a quite general engine), but +it's not something you'd do very often... diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EBeginnersGuide b/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EBeginnersGuide new file mode 100644 index 0000000..5ee7a40 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EBeginnersGuide @@ -0,0 +1,36 @@ +main +Contents.guide +Introduction to Amiga E +Introduction.guide +Format and Layout +Format.guide +Procedures and Functions +Procedures.guide +Constants +Constants.guide +Types +Types.guide +More About Statements and Expressions +MoreExpressions.guide +E Built-In Constants Variables and Functions +BuiltIns.guide +Modules +Modules.guide +Exception Handling +Exceptions.guide +Memory Allocation +Memory.guide +Floating-Point Numbers +FloatingPoint.guide +Recursion +Recursion.guide +Object Oriented E +OOE.guide +Introduction to the Examples +Examples.guide +Common Problems +Appendices.guide +E Language Index +EIndex.guide +Main Index +Index.guide diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EGuide b/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EGuide new file mode 100644 index 0000000..5a1b520 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/AgSplit/AGSplit_EGuide @@ -0,0 +1,28 @@ +MAIN +E-Contents.guide +CH_0A +E-Intro.guide +CH_1A +E-Basics.guide +CH_5A +E-Statements.guide +CH_6A +E-Functions.guide +CH_7A +E-Types.guide +CH_9A +E-Built-Ins.guide +CH_10A +E-Modules.guide +CH_11A +E-OtherExprs.guide +CH_13A +E-Exceptions.guide +CH_14A +E-OOP.guide +CH_15A +E-Technical.guide +CH_17A +E-Utilities.guide +CH_18A +E-Appendices.guide diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 1 b/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 1 new file mode 100644 index 0000000..eac2e0c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 1 @@ -0,0 +1,12 @@ +testfile=build +bla=build +target=blo + +all:$(testfile) + echo 1 + echo $target + echo 2 + +build:$(bla).e + echo $target + echo YeP! diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 2 b/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 2 new file mode 100644 index 0000000..1b35543 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 2 @@ -0,0 +1,8 @@ +testfile=.build +bla=build + +blak:$(testfile) + echo 1 + cat $(testfile) + echo 2 + diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 3 b/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 3 new file mode 100644 index 0000000..c445622 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Build/.build example 3 @@ -0,0 +1,108 @@ +#programs and dirs +ec=EMODULES:oomodules/oodoc/scripts/compile +docs=EMODULES:oomodules/oodoc/scripts/gendoc + +# objects to compile +OBJECTX=char +OBJECT2=int +OBJECT3=long +OBJECT4=list +OBJECT5=string +OBJECT6=pchar +OBJECT7=pint +OBJECT8=plong +OBJECT9=plist +OBJECT10=pstring +OBJECT11=float +OBJECT12=pfloat +OBJECT13=association + + +ALLOBJECTS=char.m int.m float.m long.m list.m string.m pchar.m pint.m plist.m plong.m pstring.m pfloat.m association.m + +TESTS=testpint testpfloat testpstring testfloat testlist teststring + +#dependencies +DEPS=/object.m /primitive.m + +#compiler options: don't use cache and BE QUIET! +OPTS=IGNORECACHE QUIET + +objects: $(ALLOBJECTS) + +all: + build binaries NOHEAD + build doc NOHEAD + +binaries: + build objects NOHEAD + build test NOHEAD + +#build the documentation +doc: + $(docs) + + +$(OBJECTX).m: $(OBJECTX).e $(DEPS) + $(ec) $(OBJECTX).e $(target) $(OPTS) + +$(OBJECT2).m: $(OBJECT2).e $(DEPS) + $(ec) $(OBJECT2).e $(target) $(OPTS) + +$(OBJECT3).m: $(OBJECT3).e $(DEPS) + $(ec) $(OBJECT3).e $(target) $(OPTS) + +$(OBJECT4).m: $(OBJECT4).e $(DEPS) + $(ec) $(OBJECT4).e $(target) $(OPTS) + +$(OBJECT5).m: $(OBJECT5).e $(DEPS) + $(ec) $(OBJECT5).e $(target) $(OPTS) + +$(OBJECT6).m: $(OBJECT6).e $(DEPS) + $(ec) $(OBJECT6).e $(target) $(OPTS) + +$(OBJECT7).m: $(OBJECT7).e $(DEPS) + $(ec) $(OBJECT7).e $(target) $(OPTS) + +$(OBJECT8).m: $(OBJECT8).e $(DEPS) + $(ec) $(OBJECT8).e $(target) $(OPTS) + +$(OBJECT9).m: $(OBJECT9).e $(DEPS) + $(ec) $(OBJECT9).e $(target) $(OPTS) + +$(OBJECT10).m: $(OBJECT10).e $(DEPS) + $(ec) $(OBJECT10).e $(target) $(OPTS) + +$(OBJECT11).m: $(OBJECT11).e $(DEPS) + $(ec) $(OBJECT11).e $(target) $(OPTS) + +$(OBJECT12).m: $(OBJECT12).e $(DEPS) + $(ec) $(OBJECT12).e $(target) $(OPTS) + +$(OBJECT13).m: $(OBJECT13).e $(DEPS) + $(ec) $(OBJECT13).e $(target) $(OPTS) + + +#build the test programs +test: $(TESTS) + Echo "Compiled test programs." + +test$(OBJECT7): test$(OBJECT7).e $(OBJECT7).m + $(ec) test$(OBJECT7).e $(target) $(OPTS) + +test$(OBJECT11): test$(OBJECT11).e $(OBJECT11).m + $(ec) test$(OBJECT11).e $(target) $(OPTS) + +test$(OBJECT12): test$(OBJECT12).e $(OBJECT12).m + $(ec) test$(OBJECT12).e $(target) $(OPTS) + +test$(OBJECT10): test$(OBJECT10).e $(OBJECT10).m + $(ec) test$(OBJECT10).e $(target) $(OPTS) + +test$(OBJECT4): test$(OBJECT4).e $(OBJECT4).m + $(ec) test$(OBJECT4).e $(target) $(OPTS) + +test$(OBJECT5): test$(OBJECT5).e $(OBJECT5).m + $(ec) test$(OBJECT5).e $(target) $(OPTS) + + diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Build/EBuild.guide b/amigae33a/E_v3.3a/Src/Src/Utils/Build/EBuild.guide new file mode 100644 index 0000000..9f64305 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Build/EBuild.guide @@ -0,0 +1,290 @@ +@database EBuild.guide + +@Master ebuild.texi + +@Width 72 + + +This is the AmigaGuide® file EBuild.guide, produced by Makeinfo-1.64 from +the input file ebuild.texi. + + EBuild Copyright 1997 Glauschwuffel, Wouter, Rob + + +@Node Main "EBuild.guide" +@Prev "(dir)" +@Toc "(dir)" + +EBuild +The Make clone +Copyright 1997 Glauschwuffel, Wouter, Rob + + @{" Introduction " Link "Introduction"} + @{" Invoking EBuild " Link "Invoking EBuild"} + @{" Build Files " Link "Build Files"} + @{" Misc " Link "Misc"} + @{" History " Link "History"} + @{" The Authors " Link "The Authors"} + + +@EndNode + +@Node "Introduction" "EBuild.guide/Introduction" +@Next "Invoking EBuild" +@Toc "Main" + +1 Introduction +************** + + EBuild is a "Make" clone, and it functions likewise. It is a tool +that helps you in recompiling necessary parts of a large application +after modification. + + You write a file `.build' in the directory that contains the sources +of your project. The file contains info about which sources depend on +which, and what actions need to be performed if a module or exe needs +to be rebuilt. + + EBuild checks the dates of the files to see if a source has been +modified after the last compilation, and if the source uses modules +that also have been modified, it will compile these first. + + +@EndNode + +@Node "Invoking EBuild" "EBuild.guide/Invoking EBuild" +@Next "Build Files" +@Prev "Introduction" +@Toc "Main" + +2 Invoking EBuild +***************** + + EBuild can be run from any shell. It's arguments are: + + TARGET,FROM/K,FORCE/S,VERBOSE/S,NOHEAD/S,CONSTANTS/S: + + If you supply a `TARGET', this way build will start with another +target. `FROM' allows you to use another file than `.build', and +`FORCE' will rebuild everything, regardless of whether it was really +necessary. + + `VERBOSE' makes the program print each action it executes. `NOHEAD' +doesn't print the heading line and the `CONSTANTS' switch forces EBuild +to tell you what symbolic constants are there. + + +@EndNode + +@Node "Build Files" "EBuild.guide/Build Files" +@Next "Misc" +@Prev "Invoking EBuild" +@Toc "Main" + +3 Build Files +************* + + + @{" Symbolic Constants " Link "Symbolic Constants"} + + Build files are normally named `.build'. This is the file EBuild +looks for when it is run. + + The syntax of build files equals that of unix-make. In general, `#' +precedes lines with comments, and: + + target: dep1 dep2 ... + action1 + action2 + ... + + `target' is the resulting file we're talking about, in most cases an +exe or module, but may be anything. Following the `:' you write all +files that it depends upon, most notably its source, and other modules. + + The actions on the following lines are normal AmigaDos commands, and +need to be preceded by at least one space or tab to distinquish them +from targets. + + bla: bla.e defs.m + ec bla quiet + + This simple example will only recompile `bla.e' if it was modified, +or if the `defs.m' which it uses was modified. + + If you type `build' with no args, build will ensure the first target +in the file to be up to date. + + A longer example: + + # test build file + + all: bla burp + + defs.m: defs.e + ec defs quiet + + bla: bla.e defs.m + ec bla quiet + + burp: burp.e + ec burp quiet + + clean: + delete defs.m bla burp + + This build file is about two programs, `bla' and `burp', of which +`bla' also depends on a module `defs.m'. An extra fake target `clean' +has been added so you can type `build clean' to delete all results. + + It's okay to have fake targets, however, these cannot be used as +module dependencies. + + Other dependencies and actions are easily added. For example, if +your project uses a parser generated by E-Yacc: + + yyparse.m: parser.y + eyacc parser.y + ec yyparse quiet + + Or incorporates macro-assembly code as often used tool module: + + blerk.m: blerk.s + a68k blerk.s + o2m blerk + copy blerk.m emodules:tools + flushcache tools/blerk + + +@EndNode + +@Node "Symbolic Constants" "EBuild.guide/Symbolic Constants" +@Toc "Build Files" + +3.1 Symbolic Constants +====================== + + EBuild v3.3 has symbolic constants. Before writing the rules you can +set a symbol to any value. Those symbols can be used in rules and +actions. The text of a symbol will be inserted wherever the symbol is +found. + + Example: + + options=IGNORECACHE LINEDEBUG DEBUG + test: test.e + ec test.e $(options) + + or even + + testfile=bla + $(testfile):$(testfile).e + ec $(testfile).e + + There is one special symbol in EBuild: `target'. It holds the name of +the target the current action belongs to. In the example above we can +tell EC to compile the target instead of writing the actual name: + + options=IGNORECACHE LINEDEBUG DEBUG + test: test.e + ec $(target).e $(options) + + This may seem to be not too useful, but take a look at this example: + + options=IGNORECACHE LINEDEBUG DEBUG + test: test.e + ec $(target) $(options) + if warn + echo "Error: compile failed" + else + echo "Compiled OK... running" + $(target) + endif + + It's largely equivalent to the old code below, but allows more. + + options=IGNORECACHE LINEDEBUG DEBUG + all: test + echo "ok, running:" + test + + test: test.e + ec -q test $(options) + + All symbols except `$(target)' may be used in rules as well as in +actions. `$(target)', however, may only be used in actions. It's safe +to have it in rules, EBuild just aborts with a message that tells you +that it doesn't know this symbol. + + +@EndNode + +@Node "Misc" "EBuild.guide/Misc" +@Next "History" +@Prev "Build Files" +@Toc "Main" + +4 Misc +****** + + Once you get to know build, you'll discover you can use it for more +purposes than just this. See it as an intelligent script tool. + + If you want to find out the details of what build can do, read the +documentation of some unix-make, as build should be somewhat compatible +with this. What it doesn't do for now, is: + + - allow "\" at the end of a line for longer rules + + When EBuild discovers a cyclic dependancy it just aborts, i.e. this +won't be executed: + + bla: defs.m blurp.m bla + ec $(target).e + + since the target `bla.e' has the dependancy `bla.e'. EBuild used to +crash with an infinite loop on this one. + + +@EndNode + +@Node "History" "EBuild.guide/History" +@Next "The Authors" +@Prev "Misc" +@Toc "Main" + +5 History +********* + + For v3.1 it was updated by Jason Hulance, to fix the bug that +executed actions in reverse order. Also he introduced the local variable +$target in actions. + + EBuild was updated for v3.3 by Gregor Goldbach to support symbolic +constants and to stop on cyclic dependancies. The $target behaviour was +expanded to match other symbols: $(target) is legal, too. + + +@EndNode + +@Node "The Authors" "EBuild.guide/The Authors" +@Prev "History" +@Toc "Main" + +6 The Authors +************* + + Wouter van Oortmerssen is the creator of E. He has studied computer +sciences and lives in England where he occasionally destroys monitors. + + Gregor Goldbach loves E, starts studying computer sciences very soon +and lives in Germany. He met Wouter but his monitor is still running. + + Jason R Hulance is an Englishman and they say he has met Wouter +several times. He coded some tools for E of which one will work +together with EDBG in the next E release. + + Rob is just Rob. + +@EndNode + diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Build/build.e b/amigae33a/E_v3.3a/Src/Src/Utils/Build/build.e new file mode 100644 index 0000000..4b3f261 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Build/build.e @@ -0,0 +1,437 @@ +/* build in E. + +TODO: - cyclic structure check (part) + - (amigados?) constants (part) + +*/ + +OPT OSVERSION=37 + +MODULE 'tools/file', 'dos/dosextens', 'dos/dos' + +/* + symbol=object + object: dep1 dep2 .... + act1 + act2 + + $(symbol): $(symbol)bla .... + act1 + ... +*/ + +/* +history: + +(Version 0.8 by Rob and Wouter) + +When Who What +23.07.97 Glauschwuffel - Added symbolic constants. Constants are allowed everywhere +26.07.97 Glauschwuffel - Removed bug in constants: The part after the last constant + wouldn't be copied. $(test): $(test).e crashed in cyclic + dependancy. :( + - Used source that Jason mailed me to get right order of actions. + - Minor modification in traverse(): "circ" is raised when object + and a dependancy have the same name. + - Added version facility :) + - local constant $(target) is now available in actions + - Added QUIET arg +27.07.97 Glauschwuffel - Changed QUIET to VERBOSE since quiet was default for v3.1 +(between Glauschwuffel - Used EBuild with new oomodules/ objects. *Very* stable, no errrors + at all. I tend to say it's error-free ) +09.08.97 Glauschwuffel - Actions of a target are now collected in a script again. + EBuild now acts as described in the Ev3.2 doc (except of the + modified $target). Bumped version to 0.9. +10.08.97 Glauschwuffel - Added script variable $target for reasons of consistency. Now + $(target) and $target are possible. + Discovered a potential bug: if build is called without a target and + the first target in the buildfile is not a filename (e.g. a symbolic + target like `all' or `clean') the actions for this target are + executed anyway (0.8 does this, too). +05.09.97 Glauschwuffel - BUG: the temporary script in T: won't be closed on exceptions + Fixed. +13.09.97 Glauschwuffel - ADD: commandline option CONSTANTS. Lists the constants before executing + anything. Modified `dumpC()' for this. +12.10.97 Glauschwuffel - BUG: EBuild would cause an enforcer hit when no dependent objects are + specified (as with symbolic targets like 'clean'). target was only set + when there were dependencies, moved the statement two lines higher. + Fixed. Bumped version. Thanks to Nuno for the report. +*/ + +OBJECT object + next:PTR TO object + name:PTR TO CHAR + firstdep:PTR TO dependancy + firstaction:PTR TO action + child + lastaction:PTR TO action +ENDOBJECT + +OBJECT dependancy + next:PTR TO dependancy + object:PTR TO object +ENDOBJECT + +OBJECT action + next:PTR TO action + comstring:PTR TO CHAR +ENDOBJECT + +OBJECT arg + target,buildfile,force,verbose,nohead,constants +ENDOBJECT + +OBJECT constant + next:PTR TO constant + name:PTR TO CHAR + subst:PTR TO CHAR +ENDOBJECT + +DEF curline=0, curstring, uptodate=TRUE, args:PTR TO arg, + constants:PTR TO constant, -> global list of constants in reverse order + target:PTR TO CHAR -> holds name of current target + +PROC main() HANDLE + DEF m,l,buildfile[200]:STRING,rdargs=NIL + NEW args + IF (rdargs:=ReadArgs('TARGET,FROM/K,FORCE/S,VERBOSE/S,NOHEAD/S,CONSTANTS/S',args,NIL))=NIL THEN Raise("barg") + IF args.buildfile THEN StrCopy(buildfile,args.buildfile) + StrAdd(buildfile,'.build') + IF (args.nohead = 0) -> be VERY quiet + PrintF({versionString}) + PrintF(' (processing "\s")\n', buildfile) + ENDIF + m,l:=readfile(buildfile) + buildtree(parse(stringsinfile(m,l,countstrings(m,l)))) + IF uptodate THEN PrintF('All files are up to date.\n') + Raise() +EXCEPT + IF rdargs THEN FreeArgs(rdargs) + IF exception=0 THEN RETURN + PrintF('Error: ') + SELECT exception + CASE "OPEN" + PrintF('couldn''t open "\s".\n',exceptioninfo) + CASE "MEM" + PrintF('not enough memory.\n') + CASE "IN" + PrintF('couldn''t read file.\n') + CASE "nobj" + PrintF('action without object.\n') + CASE "fexp" + PrintF('filename expected.\n') + CASE "dexp" + PrintF('":" or "=" expected.\n') + CASE "empt" + PrintF('nothing to build.\n') + CASE "circ" + PrintF('circular dependancies at file "\s".\n', exceptioninfo) + CASE "bada" + PrintF('action failed to build "\s".\n',exceptioninfo) + CASE "badd" + PrintF('dependancy "\s" not available.\n',exceptioninfo) + CASE "derr" + PrintF('child process failed.\n') + CASE "ntar" + PrintF('no such target: "\s".\n',args.target) + CASE "ndep" + PrintF('no dependancies for object "\s".\n',exceptioninfo) + CASE "clos" + PrintF('missing closing brace: "\s".\n',exceptioninfo) + CASE "cons" + PrintF('unknown constant: "\s".\n',exceptioninfo) + CASE "barg" + PrintFault(IoErr(),NIL) + CASE "scrp" + PrintF ('unable to create temporary script.\n') + DEFAULT + PrintF('burp.\n') + ENDSELECT + IF curline THEN PrintF('at line: (\d) "\s"\n',curline,curstring) + IF exception THEN PrintF('Build terminated\n') + RETURN 10 +ENDPROC + +PROC parse(list:PTR TO LONG) + DEF l=NIL:PTR TO object, s, c, i, t, const=NIL:PTR TO constant,str:PTR TO CHAR + FOR curline:=0 TO ListLen(list)-1 + s:=list[curline] + curstring:=s + c:=s[] + IF (c<>"#") AND (c<>"\0") -> ignore? + IF (c=" ") OR (c="\t") -> action + s:=eatwhite(s) + IF s[] + IF l=NIL THEN Raise("nobj") + -> was: l.firstaction:=NEW [l.firstaction,s]:action + -> replaced by the following IF (Rob through Glauschwuffel) + IF l.lastaction + l.lastaction.next:=NEW [NIL,s]:action + l.lastaction:=l.lastaction.next + ELSE + l.firstaction:=NEW [NIL,s]:action + l.lastaction:=l.firstaction + ENDIF + ENDIF + ELSE -> object rule or constant + i:=s + s:=eatname(s) + IF s=i THEN Raise("fexp") + t:=s + + IF (s[]<>":") AND (s[]<>"=") THEN Raise("dexp") + IF s[]=":" + + -> check object rule for use of constants + str:=String(1024) -> dyn. alloc., free if no constants + IF str=NIL THEN Raise("MEM") +/* IF (substituteConstants (i, str)<>0) ->update vars if there were constants + i := str; s:=eatname(str) -> these were copied from above + IF s=i THEN Raise("fexp") + t:=s + ELSE + Dispose(str) + ENDIF +*/ + substituteConstants (i, str) + i := str; s:=eatname(str) + IF s=i THEN Raise("fexp") + t:=s + + + t[]:="\0" + s++ + s:=eatwhite(s) + l:=NEW [l,i,NIL,NIL,0]:object + s:=eatwhite(s) + IF s[]<>"\0" + REPEAT + i:=s + s:=eatname(s) + t:=s + IF t=i THEN Raise("fexp") + s:=eatwhite(s) + t[]:="\0" + l.firstdep:=NEW [l.firstdep,i]:dependancy + UNTIL s[]="\0" + ENDIF + ELSE -> we have a constant + s++ + s:=eatwhite(s) + t[]:="\0" -> terminate name + const:=NEW[const,i,s]:constant + constants:=const -> have to do it here so consts in rules are recognized + ENDIF + ENDIF + ENDIF + ENDFOR + curline:=0 + IF args.constants THEN dumpC() + IF l=NIL THEN Raise("empt") +ENDPROC l + + +PROC eatwhite(s) + WHILE (s[]=" ") OR (s[]="\t") DO s++ +ENDPROC s + +PROC eatname(s) + WHILE (s[]<>" ") AND (s[]<>"\t") AND (s[]<>"\0") AND (s[]<>":") AND (s[]<>"=") DO s++ +ENDPROC s + +/* obsolete +PROC execute(c) +DEF s[1024]:STRING + uptodate:=FALSE + substituteConstants (c, s) + IF args.verbose THEN PrintF('\t\s\n', s) +-> PrintF('\t\s\n',IF substituteConstants (c, s) THEN s ELSE c) + IF Execute(s,NIL,stdout)=NIL THEN Raise("derr") +ENDPROC */ + +PROC filetime(name:PTR TO CHAR) + DEF l:PTR TO filelock, fib:fileinfoblock, date:PTR TO datestamp + IF l:=Lock(name,ACTION_READ) + IF Examine(l,fib) + date:=fib.datestamp + IF fib.direntrytype<0 + UnLock(l) + RETURN date.days, Shl(date.minute,12)+date.tick + ENDIF + ENDIF + UnLock(l) + ENDIF +ENDPROC -1 + +PROC timelater(day1,tick1,day2,tick2) + IF day1>day2 + RETURN TRUE + ELSEIF day1=day2 + RETURN tick1>tick2 + ENDIF +ENDPROC FALSE + +/*----------------rob's-stuff-------------------*/ + +PROC buildtree(list:PTR TO object) -> returns root of tree + DEF dep:PTR TO dependancy, + obj:PTR TO object + + obj:=list + WHILE obj -> traverse objects + dep:=obj.firstdep + WHILE dep -> traverse dependencies + dep.object:=findobject(dep.object,list) + dep:=dep.next + ENDWHILE + obj:=obj.next + ENDWHILE + + -> CHECK CYCLES!!! + + obj:=list + IF args.target + WHILE obj + IF StrCmp(args.target,obj.name) THEN JUMP out + obj:=obj.next + ENDWHILE + Raise("ntar") + out: + ELSE + IF obj THEN WHILE obj.next DO obj:=obj.next + ENDIF + traverse(obj) +ENDPROC + + +-> find object in list of objects by name +PROC findobject(name:PTR TO CHAR,list:PTR TO object) + WHILE list + IF StrCmp(name,list.name) + -> remove object from root list + list.child:=TRUE; + RETURN list + ENDIF + list:=list.next + ENDWHILE +ENDPROC NEW [NIL,name,NIL,NIL]:object + +-> child-first traversal of dependancy tree +PROC traverse(obj:PTR TO object) -> executes actions in tree + DEF dep:PTR TO dependancy,maxtime1=0,maxtime2=0,time1,time2,action:PTR TO action + + IF obj.firstdep OR obj.firstaction -> object with dependancies/actions + -> traverse children and get maximum timestamp + dep:=obj.firstdep + WHILE dep + IF OstrCmp (dep.object.name, obj.name) = 0 THEN Throw("circ",obj.name) -> cyclic check by Glauschwuffel + target := obj.name + time1,time2:=traverse(dep.object) + IF timelater(time1,time2,maxtime1,maxtime2) + maxtime1:=time1 + maxtime2:=time2 + ENDIF + dep:=dep.next + ENDWHILE + time1,time2:=filetime (obj.name) + IF time1<0 OR timelater(maxtime1,maxtime2,time1,time2) OR args.force + -> dependancy file(s) more recent: build object + -> execute actions + action:=obj.firstaction + + buildAndExecuteScript (action) + + time1,time2:=filetime(obj.name) + IF (time1<0) AND (obj.child=TRUE) THEN Throw("bada",obj.name) + ENDIF + RETURN time1,time2 + ENDIF + -> object requires no action: return timestamp + time1,time2:=filetime(obj.name); + IF time1<0 THEN Throw("badd",obj.name) +ENDPROC time1,time2 + +/* - glauschwuffel's stuff --- */ + + +PROC dumpC() +DEF co:PTR TO constant + co:=constants + WriteF ('Constants are:\n') + WHILE co + WriteF('\t<\s> with <\s>.\n', co.name, co.subst) + co:=co.next + ENDWHILE +ENDPROC + +PROC substituteConstants(c:PTR TO CHAR, s:PTR TO CHAR) +-> search c for constants and substitute them +DEF dollar, bclose=-1,sub=NIL + REPEAT + bclose++ + dollar := InStr (c,'$(',bclose) + IF (dollar<>-1) -> found it? + StrAdd (s, c+bclose, dollar-bclose) + bclose := InStr (c,')',dollar+2) + IF bclose=-1 THEN Throw("clos",c) + sub := findConstant(c,dollar+2,bclose-1) + IF sub=NIL THEN Throw("cons",c+dollar) + StrAdd (s,sub) + ELSE -> copy rest of the line to buffer + StrAdd (s, c+bclose) + ENDIF + UNTIL (dollar=-1) OR (bclose=-1) + RETURN sub -> did we substitute something at all? +ENDPROC + +PROC findConstant(c,start,end) +-> find constant of given position in list +-> add 27.07.97: returns global target on target +DEF co:PTR TO constant + IF OstrCmp('target',c+start,end-start+1)=0 THEN RETURN target + co:=constants + WHILE co + EXIT (OstrCmp(co.name,c+start,end-start+1)=0) + co:=co.next + ENDWHILE + RETURN IF co THEN co.subst ELSE NIL +ENDPROC + +PROC buildAndExecuteScript (action:PTR TO action) HANDLE +DEF s[1024]:STRING, + handle + + handle := Open ('T:Ebuild_actions', MODE_NEWFILE) -> open script file + IF (handle = NIL) THEN Raise ("scrp") + + /* create script variable TARGET */ + StrCopy (s, 'Set target ') + StrAdd (s, target) + StrAdd (s, '\n') -> add newline + + Write (handle, s, StrLen (s)) + IF args.verbose THEN PrintF('\t\s', s) + + WHILE action + uptodate:=FALSE + SetStr (s, 0) -> "delete" the string of the last action + substituteConstants (action.comstring, s) -> expand action + StrAdd (s, '\n') -> add newline + IF args.verbose THEN PrintF('\t\s', s) + Write (handle, s, StrLen (s)) + action:=action.next + ENDWHILE + + Close (handle) + IF Execute('Execute T:Ebuild_actions', NIL, stdout)=NIL THEN Raise("derr") + DeleteFile ('T:EBuild_actions') + +EXCEPT + IF handle THEN Close(handle) + ReThrow() +ENDPROC + + +versionTag: CHAR 0,'$VER:' +versionString: CHAR 'EBuild 0.92 (12.10.97) ©1997 Rob, Wouter and Glauschwuffel',0 + diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/D.e b/amigae33a/E_v3.3a/Src/Src/Utils/D.e new file mode 100644 index 0000000..5b43a76 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/D.e @@ -0,0 +1,297 @@ +/* recursive directory tool + +needs v37. + +Universal directory lister. called with no arguments, by just typing +"d", it lists the current directory. template: + +DIR,REC/S,WIDTH/K/N,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,FULL/S,NOANSI/S, +TARGET/K,DO/K/F + +DIR specifies an optional path to the dir you wish to list. + may contain standard wildcard patterns like #?~[]%() etc. +REC specifies that subdirectories should be listed recursively. +WIDTH max width of one line of output. if not present, D will + infer this from the current width of the console. + NOTE: currently it just takes WIDTH=77 as default. does anyone + have code that gets the width from the console? +COL where n=1..10, by default, D will try and fit as many + columns as allowed by WIDTH. +SIZE reports the size of each dir as it is being listed. note that + combined with REC gives sizes of whole dir (sub-)trees. +NOSORT by default, dirs are sorted before display. disable this with + the NOSORT switch. +NOFILES displays just dirs +NODIRS displays just files +FULL lists full path instead of just filename +NOANSI doesn't use ansi display codes while printing +TARGET

specifies a target directory for use with DO. should + end in either "/" or ":" +DO specifies a commandline for automatic script generation. + note that this uses up the rest of D's commandline. + +something should be said on the script feature: it enables you +to perform repetitive tasks on whole dirs, or dir-trees. existing +utilities that enabled you to do such tasks where mostly not +flexible enough; d enables you to use the REC keyword in combination +with scripts, allows for variable extensions: use .o if +the original name was .s, and the spec. of a target: +resulting files from the operation are placed in another dir, which +can be a complete mirror image of another dir-tree. makedir +statements are inserted if target: is empty. + +following format codes may be used in : + +%s is file (filename+path) +%f is file WITHOUT extension +%r is file without extension, but with leading replaced by + (usefull if allows for an outputfile) +%> or %< %>> etc. prevents the shell from thinking ">" is a redirection + for D, instead of + +a complex example: +you wish to have a complete ascii reference of the emodules: +directory, recursively, and with the resulting .txt files +as a mirror-image directory structure somewhere else. + +1> D >ram:script emodules: REC TARGET=t:mods/ DO showmodule %>%r.txt %s +1> execute ram:script + +will do that for you. +for any file like "emodules:exec/io.m" D will make a line like: +"showmodule >t:mods/exec/io.txt emodules:exec/io.m" + +other examples: D >mydirlist dh0: WIDTH=100 SIZE REC NOANSI + D docs: DO type >prt: %s + D asm: TARGET=obj: DO genam %s -o%r.o + D emodules: REC TARGET=ram: DO showmodule %>%r.txt %s + +*/ + +OPT OSVERSION=37 + +CONST MAXPATH=250 + +ENUM ER_NONE,ER_BADARGS,ER_MEM,ER_UTIL,ER_ITARG,ER_COML +ENUM ARG_DIR,ARG_REC,ARG_WIDTH,ARG_COL,ARG_SIZE,ARG_NOSORT,ARG_NOFILES, + ARG_NODIRS,ARG_FULL,ARG_NOANSI,ARG_TARGET,ARG_COMMAND,NUMARGS + +MODULE 'dos/dosasl', 'dos/dos', 'utility', 'intuition/intuitionbase', + 'intuition/intuition', 'graphics/gfxbase', 'graphics/text' + +RAISE ER_MEM IF New()=NIL, /* set common exceptions: */ + ER_MEM IF String()=NIL, /* every call to these functions will be */ + ERROR_BREAK IF CtrlC()=TRUE /* automatically checked against NIL, */ + /* and the exception ER_MEM is raised */ + +DEF dir,command,target, + recf=FALSE,col=3,calccolf=TRUE,comf=FALSE,sizef=FALSE,sortf=TRUE,filesf=TRUE, + fullf=FALSE,ansif=TRUE,dirsf=TRUE,dirw[100]:STRING, + rdargs=NIL,work[250]:STRING,work2[250]:STRING,dirno=0, + prtab[25]:LIST,prcopy[25]:LIST,workdir[250]:STRING, + consolewidth=0 + +PROC main() HANDLE + DEF args[NUMARGS]:LIST,templ,x,lock,fib:fileinfoblock,s + IF (utilitybase:=OpenLibrary('utility.library',37))=NIL THEN Raise(ER_UTIL) + FOR x:=0 TO NUMARGS-1 DO args[x]:=0 + templ:='DIR,REC/S,WIDTH/K/N,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,' + + 'FULL/S,NOANSI/S,TARGET/K,DO/K/F' + rdargs:=ReadArgs(templ,args,NIL) + IF rdargs=NIL THEN Raise(ER_BADARGS) /* initialise flags */ + IF args[ARG_SIZE] THEN sizef:=TRUE /* from command line args */ + consolewidth:=Bounds(IF args[ARG_WIDTH] THEN Long(args[ARG_WIDTH]) ELSE findconsolewidth(),1,1000) + IF args[ARG_COL] THEN (calccolf:=FALSE) BUT col:=Long(args[ARG_COL]) + col:=Bounds(col,1,100) + IF args[ARG_NOSORT] THEN sortf:=FALSE + IF args[ARG_NOANSI] THEN ansif:=FALSE + IF args[ARG_NOFILES] THEN filesf:=FALSE + IF args[ARG_NODIRS] THEN dirsf:=FALSE + IF args[ARG_REC] THEN recf:=TRUE + IF args[ARG_FULL] THEN fullf:=TRUE + target:=args[ARG_TARGET] + command:=args[ARG_COMMAND] + IF command THEN comf:=TRUE + IF target + x:=target+StrLen(target)-1 + IF (x":") AND (x[]<>"/")) THEN Raise(ER_ITARG) + ENDIF + IF comf + sortf:=FALSE /* read and convert commandline for scripts */ + col:=1 + filesf:=FALSE + dirsf:=FALSE + IF command[]=0 THEN Raise(ER_COML) + s:=command + WHILE x:=s[]++ + IF x="%" + x:=s[] + SELECT x + CASE "s"; ListAdd(prtab,[1],1) /* %s = fullpath */ + CASE "f"; ListAdd(prtab,NEW [work],1); s[]:="s" /* %f = work */ + CASE "r"; ListAdd(prtab,NEW [work2],1); s[]:="s" /* %r = work2 */ + DEFAULT; s[-1]:=" " + ENDSELECT + ENDIF + ENDWHILE + ENDIF + dir:=args[ARG_DIR] + IF dir THEN StrCopy(dirw,dir,ALL) + lock:=Lock(dirw,-2) + IF lock /* if yes, the prob. dir, else wildcard */ + IF Examine(lock,fib) AND (fib.direntrytype>0) + AddPart(dirw,'#?',100) + ENDIF + UnLock(lock) + ENDIF + recdir(dirw) + Raise(ER_NONE) +EXCEPT + IF rdargs THEN FreeArgs(rdargs) + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE ER_BADARGS; PrintF('Bad Arguments for D!\n') + CASE ER_MEM; PrintF('No mem!\n') + CASE ER_COML; PrintF('No commandline specified\n') + CASE ER_ITARG; PrintF('Illegal target\n') + CASE ER_UTIL; PrintF('Could not open "utility.library" v37\n') + CASE ERROR_BREAK; PrintF('User terminated D\n') + CASE ERROR_BUFFER_OVERFLOW; PrintF('Internal error\n') + DEFAULT; PrintFault(exception,'Dos Error') + ENDSELECT +ENDPROC + +PROC recdir(dirr) HANDLE + DEF er,i:PTR TO fileinfoblock,size=0,anchor=NIL:PTR TO anchorpath,fullpath, + flist=NIL,first,entries=0,ascii,w,x,y,z,flist2=NIL, + isfirst=0,maxfilename=1,maxfilesize=-1,lcol + anchor:=New(SIZEOF anchorpath+MAXPATH) + anchor.breakbits:=4096 + anchor.strlen:=MAXPATH-1 + er:=MatchFirst(dirr,anchor) /* collect all strings */ + WHILE er=0 + fullpath:=anchor+SIZEOF anchorpath + i:=anchor.info + ascii:=IF fullf THEN fullpath ELSE i.filename + IF i.direntrytype>0 + StringF(work,'\s\l\s[30] ',IF ansif THEN '\e' ELSE '',ascii) + ELSE + StringF(work,'\l\s[30] \r\d[8]',ascii,i.size) + IF i.size>maxfilesize THEN maxfilesize:=i.size + ENDIF + x:=StrLen(ascii) + IF x>maxfilename THEN maxfilename:=x + IF IF i.direntrytype>0 THEN dirsf ELSE filesf + first:=String(EstrLen(work)) + StrCopy(first,work,ALL) + flist:=Link(first,flist) + INC entries + ENDIF + IF i.direntrytype<0 THEN size:=size+i.size + IF (i.direntrytype<0) AND comf /* execute commandline */ + ListCopy(prcopy,prtab,ALL) + IF comf THEN MapList({x},prcopy,prcopy,`IF x=1 THEN fullpath ELSE x) + StrCopy(work,fullpath,ALL) + x:=InStr(work,'.',0) + IF x<>-1 THEN SetStr(work,x) /* find f% */ + IF target + StrCopy(work2,target,ALL) + x:=work; y:=dirw /* was dirr */ + WHILE x[]++=y[]++ DO NOP + DEC x + StrAdd(work2,x,ALL) /* find r% */ + ELSE + StrCopy(work2,work,ALL) + ENDIF + IF isfirst++=0 + StrCopy(workdir,work2,ALL) /* see if makedir is needed */ + SetStr(workdir,PathPart(work2)-work2) + x:=Lock(workdir,-2) + IF x THEN UnLock(x) ELSE PrintF('makedir \s\n',workdir) + ENDIF + Flush(stdout); VfPrintf(stdout,command,prcopy); Flush(stdout) + PrintF('\n') + ENDIF + IF recf AND (i.direntrytype>0) /* do recursion(=tail) */ + x:=StrLen(fullpath) + IF x+5ERROR_NO_MORE_ENTRIES THEN Raise(er) + MatchEnd(anchor) + Dispose(anchor) + anchor:=NIL + maxfilesize:=IF maxfilesize>=0 THEN sillylog10(maxfilesize) ELSE 0 + lcol:=Bounds(IF calccolf THEN consolewidth+1/(maxfilesize+maxfilename+2) ELSE col,1,100) + flist:=Link(String(1),flist) + IF entries>2 AND sortf THEN flist:=sort(flist) + IF comf=FALSE /* display dir */ + IF dirno THEN PrintF('\n') + PrintF(IF ansif THEN '\e[1mDirectory of: "\s"\e[0m\n' ELSE 'Directory of: "\s"\n',dirr) + ENDIF + first:=flist + x:=entries/lcol /* put dirlist in columns */ + IF x*lcollcol THEN PrintF(' ') + ENDIF + ENDFOR + PrintF('\n') + CtrlC() + ENDFOR + IF sizef THEN PrintF('BYTE SIZE: \d\n',size) + DisposeLink(flist) + INC dirno +EXCEPT /* nested exception handlers! */ + IF anchor THEN MatchEnd(anchor) + Raise(exception) /* this way, we call _all_ handlers in the recursion */ +ENDPROC size /* and thus calling MatchEnd() on all hanging anchors */ + +PROC sort(flist) + DEF sortdone,prev,first,next,nnext + REPEAT + sortdone:=TRUE /* sort dirlist */ + prev:=first:=flist + WHILE first:=Next(first) + IF next:=Next(first) + IF Stricmp(first,next)>0 + nnext:=Next(next) + Link(prev,first:=Link(next,Link(first,nnext))) + sortdone:=FALSE + ENDIF + ENDIF + prev:=first + ENDWHILE + CtrlC() + UNTIL sortdone +ENDPROC flist + +PROC findconsolewidth() + DEF ib:PTR TO intuitionbase,gb:PTR TO gfxbase,w,fw + ib:=intuitionbase + gb:=gfxbase + Forbid() + w:=ib.activewindow.width + fw:=gb.defaultfont.xsize + Permit() +ENDPROC Bounds(w-24/fw,5,250) + +PROC sillylog10(n) IS IF n<10 THEN 1 ELSE sillylog10(Div(n,10))+1 diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/DirQuick.e b/amigae33a/E_v3.3a/Src/Src/Utils/DirQuick.e new file mode 100644 index 0000000..d3fdf43 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/DirQuick.e @@ -0,0 +1,26 @@ +/* nice directory command in E ! */ + +MODULE 'dos/dos' + +PROC main() + DEF info:fileinfoblock,lock,c=0 + IF lock:=Lock(arg,-2) + IF Examine(lock,info) + IF info.direntrytype>0 + WriteF('Directory of: \s\n',info.filename) + WHILE ExNext(lock,info) + WriteF(IF info.direntrytype>0 THEN + '\e[1;32m\l\s[25]\e[0;31m' ELSE '\l\s[17] \r\d[7]', + info.filename,info.size) + WriteF(IF c++=2 THEN (c:=0) BUT '\n' ELSE ' ') + ENDWHILE + IF c THEN WriteF('\n') + ELSE + WriteF('No Dir!\n') + ENDIF + ENDIF + UnLock(lock) + ELSE + WriteF('What ?!?\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/README_IMPORTANT b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/README_IMPORTANT new file mode 100644 index 0000000..2e36ff4 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/README_IMPORTANT @@ -0,0 +1,28 @@ +TERMS AND CONDITIONS FOR USING THE EDBG SOURCECODE + +* modifying or reusing part or whole of the EDBG code for your + own project is always allowed: giving credit is encouraged. +* making new versions of EDBG public is discouraged in + general. if you still feel that need, try in this order: + - suggest the extension to the maintainer of the "official" + EDBG, currently Jason Hulance. + - cooperate with other people that may be working on a + custom EDBG (try discussing this on the E mailing list). + - the EDBG core (eexe.e) has been programmed to be + used by various different programs/user-interfaces. + Try making your own debugging tool that uses eexe.e + unmodified. + - if you HAVE to start your own spin-off project, make sure + your release is heavily marked as being different from the + official version while still giving credit. e.g. + "Harry's TurboDebug v1.0a featuring runtime type analysis, + based on Wouter and Jason's original EDBG v3.3a". + After you start your own version, don't come and + bother us about making it the official version. + Doing your own commercial version or anything else related + to money won't be tolerated at all. + +The purpose of this release is first and foremost educational. + +If you intend to do something with this code which doesn't +seem to be covered by the above, ask me (Wouter) or Jason first. diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/edbg.e b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/edbg.e new file mode 100644 index 0000000..fcfb563 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/edbg.e @@ -0,0 +1,1424 @@ +-> Yes! A real E debugger! + +OPT OSVERSION=37, LARGE + +MODULE 'tools/clonescreen', 'tools/macros', 'tools/arexx', + 'tools/EasyGUI', 'tools/constructors', 'tools/exceptions', + 'tools/iterators', + '*eexe', 'class/sc', '*sctext', '*schex', '*screg', 'other/sendexplorer', + 'dos/dostags', 'exec/lists', 'exec/nodes', + 'gadtools', 'libraries/gadtools', + 'intuition/intuition', 'intuition/screens', 'intuition/gadgetclass', + 'graphics/text', 'graphics/rastport', + 'rexx/storage', 'rexxsyslib' + +OBJECT dbgwin + next:PTR TO dbgwin,type +ENDOBJECT + +OBJECT srcwin OF dbgwin + scwin:PTR TO scrolltext,src:PTR TO e_source +ENDOBJECT + +OBJECT memwin OF dbgwin + scwin:PTR TO scrollhex,addr +ENDOBJECT + +OBJECT regwin OF dbgwin + scwin:PTR TO scrollreg +ENDOBJECT + +OBJECT varwin OF dbgwin + scwin:PTR TO scrolltext +ENDOBJECT + +OBJECT wvar OF ln + v:PTR TO CHAR +ENDOBJECT + +CONST RXSTR_SIZE=250 + +DEF exe=NIL:PTR TO e_exe,frame:PTR TO stackframe, + oscr=NIL,scr=NIL:PTR TO screen,font=NIL:PTR TO textfont,depth,xsize,ysize, + title,doabout=TRUE,dorefresh=TRUE,dosavewindowpos=TRUE,dosavevars=TRUE,argstring[100]:STRING, + dwins=NIL:PTR TO dbgwin,numsrc=0,wrapsrc=FALSE,maxsrcs=0,stackwin=NIL:PTR TO memwin, + vwin=NIL:PTR TO varwin,varlist=NIL:PTR TO LONG,vars:PTR TO lh, + rwin=NIL:PTR TO regwin, + visual=NIL,menu=NIL,whatstep,evgh=NIL:PTR TO guihandle, + followgh=NIL:PTR TO guihandle,followspeed=30,repeatcount=0,repeatover=TRUE, + toolwin=NIL:PTR TO window,toolgads=NIL:PTR TO LONG, + currentwin:PTR TO srcwin, -> active intuition + activewin:PTR TO srcwin, -> where (pc) is + lastsec=0,lastmic=0,findstr[100]:STRING,offstr[12]:STRING, + ocon=NIL,reqtitle,oldi,oldo, + first_step_done=FALSE,unreachablea7, + srcport=NIL,rexxport=NIL,rexxname,startExp=FALSE,oldvy=-1, + fx=0,fy=0,fxs=0,fys=0,explorer[RXSTR_SIZE]:STRING,pubname[100]:STRING, + rxs1[RXSTR_SIZE]:STRING,rxs2[RXSTR_SIZE]:STRING,rxs3[RXSTR_SIZE]:STRING + +ENUM STEP_NONE,STEP_IN,STEP_OVER,STEP_RUN,STEP_THROW,STEP_FOLLOW + +CONST MAX_WATCH=250, MAX_WLINE=100 + +RAISE "MEM" IF String()=NIL + +PROC main() HANDLE + DEF options:PTR TO LONG,rdargs=NIL,exename[100]:STRING,e:PTR TO dbgwin, + pubconname[200]:STRING, i + title:='EDBG v3.3a, The E Debugger! © 1994-1997 Wouter (and Jason)' + reqtitle:='EDBG' + vars:=newlist() + options:=[0,0,0] + IF rdargs:=ReadArgs('EXECUTABLE/A,PUBSCREEN/K,ARG/K',options,NIL) + StrCopy(exename,options[0]) + IF options[2] THEN StrCopy(argstring,options[2]) + IF options[1] + StrCopy(pubname,options[1]) + IF scr:=LockPubScreen(pubname) THEN font:=scr.rastport::rastport.font + ENDIF + FreeArgs(rdargs) + ELSE + Raise("ARGS") + ENDIF + WriteF('\s.\nLoading "\s"...\n',title,exename) + NEW exe.load(exename) + IF scr=NIL + StrCopy(pubname,'EDBG') + IF options[1] THEN StrAdd(pubname,options[1]) + scr,font:=openclonescreen('Workbench',title,2,pubname) + oscr:=scr + PubScreenStatus(scr,0) -> TEMP!! + ENDIF + rexxname:=IF oscr THEN pubname ELSE 'EDBG' + depth,xsize,ysize:=getcloneinfo(scr) + IF (gadtoolsbase:=OpenLibrary('gadtools.library',37))=NIL THEN Raise("GT") + IF (visual:=GetVisualInfoA(scr,NIL))=NIL THEN Raise("MENU") + createmenus() + createtoolbar() + IF (srcport:=CreateMsgPort())=NIL THEN Raise("PORT") + rexxport:=rx_OpenPort(rexxname) + StrCopy(pubconname,'CON:0/900/640/50/Standard Input and Output:/SCREEN ') + StrAdd(pubconname,pubname) + IF ocon:=Open(pubconname,NEWFILE) + oldi:=SelectInput(ocon) + oldo:=SelectOutput(ocon) + ELSE + Throw("OPEN",'CON:') + ENDIF + exe.edebug({step},argstring) +EXCEPT DO + IF followgh OR repeatcount THEN Delay(6) BUT request1('Program completed execution','_OK',"o") + IF startExp + quitExplorer() + FOR i:=1 TO 20 + EXIT isExplorerRunning()=FALSE + Delay(6) + ENDFOR + ENDIF + removefollow() + WHILE dwins + e:=dwins + dwins:=dwins.next + END e + ENDWHILE + IF ocon + SelectInput(oldi) + SelectOutput(oldo) + Close(ocon) + ENDIF + rx_ClosePort(rexxport) + rexxport:=NIL + IF srcport THEN DeleteMsgPort(srcport) + deletetoolbar() -> no request()s after this + IF menu THEN FreeMenus(menu) + IF visual THEN FreeVisualInfo(visual) + IF gadtoolsbase THEN CloseLibrary(gadtoolsbase) + IF oscr + IF closeclonescreen(oscr,font)=FALSE + Delay(20) + WHILE closeclonescreen(oscr,font)=FALSE + request1('Please close other windows on this screen!','_OK',"o") + ENDWHILE + ENDIF + ELSEIF scr + UnlockPubScreen(NIL,scr) + ENDIF + END exe + SELECT exception + CASE "MEM"; WriteF('Aaargh! no mem!\n') + CASE "ARGS"; WriteF('Bad Args! (try "edbg ?")\n') + CASE "OPEN"; WriteF('Failed to open "\s".\n',exceptioninfo) + CASE "IN"; WriteF('Problems while reading file.\n') + CASE "eexe"; WriteF('Not a valid E executable\n') + CASE "eexd"; WriteF('Try compiling with "EC DEBUG" first\n') + CASE "SCR"; WriteF('no screen!\n') + CASE "GT"; WriteF('no "gadtools.library"!\n') + CASE "MENU"; WriteF('no menus!\n') + CASE "WIN"; WriteF('no window!\n') + CASE "DOUB"; WriteF('port with same name already exists! (another EDBG running?)\n') + CASE "SIG"; WriteF('could not allocate signal!\n') + DEFAULT; report_exception() + ENDSELECT +ENDPROC + +PROC createmenus() + IF (menu:=CreateMenusA([ + 1,0,'Project',0,0,0,0, + 2,0,'About...', 0 ,0,0,0, + 2,0,'Settings...', 'P',0,0,0, + 2,0,'Save Settings', 'W',0,0,0, + 2,0,'Quit', 'Q',0,0,0, + 1,0,'Windows',0,0,0,0, + 2,0,'Source', 'S',0,0,0, + 2,0,'Registers', 'D',0,0,0, + 2,0,'Memory', 'M',0,0,0, + 2,0,'Stack', 'T',0,0,0, + 2,0,'Variables', 'X',0,0,0, + 1,0,'Debug',0,0,0,0, + 2,0,'Step In (left)', 'I',0,0,0, + 2,0,'Step Over (down)', 'O',0,0,0, + 2,0,'Step Follow', 0 ,0,0,0, + 2,0,'Repeat Step', 0 ,0,0,0, + 2,0,'Watch Variable', 0 ,0,0,0, + 2,0,'Set Breakpoint', 0 ,0,0,0, + 2,0,'Memory Breakpoint', 'B',0,0,0, + 2,0,'Clear Breakpoints', 'C',0,0,0, + 2,0,'Run upto Breakpoint','R',0,0,0, + 2,0,'Raise Exception', 'E',0,0,0, + 1,0,'Tools',0,0,0,0, + 2,0,'Eval E Expression', 'K',0,0,0, + 2,0,'Modify Variable', 0 ,0,0,0, + 2,0,'Refresh Views', 'V',0,0,0, + 2,0,'Find in Source', 'F',0,0,0, + 2,0,'Locate Offset', 'L',0,0,0, + 1,0,'Rexx',0,0,0,0, + 2,0,'Execute script 1', 0 ,0,0,0, + 2,0,'Execute script 2', 0 ,0,0,0, + 2,0,'Execute script 3', 0 ,0,0,0, + 0,0,0,0,0,0,0]:newmenu,NIL))=NIL THEN Raise("MENU") + IF LayoutMenusA(menu,visual,[GTMN_NEWLOOKMENUS,TRUE,NIL])=FALSE THEN Raise("MENU") +ENDPROC + +/*-----------------------------------------------------------------------*/ + +ENUM T_SRC,T_MEM,T_STACK,T_REG,T_VAR + +PROC message() OF dbgwin + IF self.next THEN self.next.message() +ENDPROC + +PROC refresh() OF dbgwin + IF self.next THEN self.next.refresh() +ENDPROC + +PROC end() OF dbgwin + DEF x:PTR TO dbgwin + IF (x:=dwins)=self + dwins:=self.next + ELSE + WHILE x.next + EXIT x.next=self + x:=x.next + ENDWHILE + IF x.next THEN x.next:=self.next + ENDIF +ENDPROC + +/*----------------------------------------------------------------------*/ + +PROC srcwin(src:PTR TO e_source) OF srcwin + DEF x:PTR TO scrolltext,a + self.next:=dwins + dwins:=self + self.type:=T_SRC + self.src:=src + self.scwin:=NEW x.settext(src.lines(),120) + IF (fx>=xsize) OR (fy>=ysize) OR (fxs>=xsize) OR (fys>=ysize) OR (fxs<40) OR (fys<20) + a:=(numsrc+1)*(font.ysize+3)+IF wrapsrc THEN 5 ELSE 0 + IF maxsrcs=0 + IF ysize-a<(10*font.ysize) + maxsrcs:=numsrc + numsrc:=0 + wrapsrc:=TRUE + a:=font.ysize+3+5 + ENDIF + ENDIF + fx:=numsrc*10+49+IF wrapsrc THEN 5 ELSE 0 + fy:=a + fxs:=500 + fys:=Min(ysize-a,400) + ENDIF + x.open(src.name(),fx,fy,fxs,fys,scr,IDCMP_MENUPICK OR IDCMP_MOUSEBUTTONS OR IDCMP_RAWKEY,{handlesrc},srcport,self) + IF SetMenuStrip(x.window,menu)=FALSE THEN Raise("MENU") + IF (numsrc++>=maxsrcs) AND maxsrcs + numsrc:=0 + wrapsrc:=(wrapsrc=FALSE) + ENDIF + fx:=fy:=fxs:=fys:=0 +ENDPROC + +PROC end() OF srcwin + DEF sc:PTR TO scrolltext + sc:=self.scwin + IF sc.window THEN ClearMenuStrip(sc.window) + END sc + SUPER self.end() + IF 0>numsrc-- THEN numsrc:=maxsrcs +ENDPROC + +/*----------------------------------------------------------------------*/ + +PROC memwin(addr,type) OF memwin + DEF x:PTR TO scrollhex,a + self.next:=dwins + dwins:=self + self.type:=type + self.addr:=addr + IF type=T_STACK THEN stackwin:=self + self.scwin:=NEW x.setmem(addr) + a:=40*font.xsize+20 + x.open(IF type=T_MEM THEN 'Memory View' ELSE 'Stack View', + xsize-a,font.ysize+3,a,ysize/3,scr,IDCMP_MENUPICK,{handlesrc}) + IF SetMenuStrip(x.window,menu)=FALSE THEN Raise("MENU") +ENDPROC + +PROC message() OF memwin + self.scwin.setmem(self.addr) + IF self.next THEN self.next.message() + IF self.scwin.handle() THEN END self +ENDPROC + +PROC refresh() OF memwin + self.scwin.setmem(self.addr) + self.scwin.refreshwindow() + IF self.next THEN self.next.refresh() +ENDPROC + +PROC end() OF memwin + DEF sc:PTR TO scrolltext + sc:=self.scwin + IF self.type=T_STACK THEN stackwin:=NIL + IF sc.window THEN ClearMenuStrip(sc.window) + END sc + SUPER self.end() +ENDPROC + +/*----------------------------------------------------------------------*/ + +PROC regwin() OF regwin + DEF x:PTR TO scrollreg,a + self.next:=dwins + dwins:=self + self.type:=T_REG + self.scwin:=NEW x.scrollreg(frame) + a:=13*font.xsize+20 + x.open('Register View',xsize-a,font.ysize+3,a,ysize/2,scr,IDCMP_MENUPICK,{handlesrc}) + IF SetMenuStrip(x.window,menu)=FALSE THEN Raise("MENU") + rwin:=self +ENDPROC + +PROC message() OF regwin + IF self.next THEN self.next.message() + IF self.scwin.handle() THEN END self +ENDPROC + +PROC refresh() OF regwin + self.scwin.refreshreg(frame) + IF self.next THEN self.next.refresh() +ENDPROC + +PROC end() OF regwin + DEF sc:PTR TO scrolltext + rwin:=NIL + sc:=self.scwin + IF sc.window THEN ClearMenuStrip(sc.window) + END sc + SUPER self.end() +ENDPROC + +/*----------------------------------------------------------------------*/ + +PROC varwin() OF varwin + DEF x:PTR TO scrolltext + self.next:=dwins + dwins:=self + self.type:=T_VAR + IF varlist=NIL THEN IF (varlist:=List(MAX_WATCH))=NIL THEN Raise("MEM") + constructvars() + self.scwin:=NEW x.settext(varlist,MAX_WLINE) + IF (fx>=xsize) OR (fy>=ysize) OR (fxs>=xsize) OR (fys>=ysize) OR (fxs<40) OR (fys<20) + fx:=xsize/8 + fy:=ysize/2 + fxs:=xsize-(xsize/4) + fys:=ysize/4 + ENDIF + x.open('Variable View',fx,fy,fxs,fys,scr,IDCMP_MENUPICK OR IDCMP_MOUSEBUTTONS OR IDCMP_RAWKEY,{handlevar}) + IF SetMenuStrip(x.window,menu)=FALSE THEN Raise("MENU") + vwin:=self + fx:=fy:=fxs:=fys:=0 +ENDPROC + +PROC message() OF varwin + IF self.next THEN self.next.message() + IF self.scwin.handle() THEN END self +ENDPROC + +PROC refresh() OF varwin + varrefresh(self) + IF self.next THEN self.next.refresh() +ENDPROC + +PROC varrefresh(win:PTR TO varwin) + constructvars() + win.scwin.settext(varlist,MAX_WLINE) + win.scwin.refreshwindow() +ENDPROC + +PROC end() OF varwin + DEF sc:PTR TO scrolltext + vwin:=NIL + sc:=self.scwin + IF sc.window THEN ClearMenuStrip(sc.window) + END sc + SUPER self.end() +ENDPROC + +PROC actionvar(y) + DEF wv:PTR TO wvar,n=0,s[100]:STRING,v,vptr,type,r + wv:=vars.head + WHILE wv.succ + v,vptr,type:=getvarval(wv.v) + IF type + IF y=n++ + StringF(s,'Variable "\s" selected.',wv.v) + r:=request3(s,'_Remove','_Modify','_Cancel',"r","m","c") + IF r=1 + Remove(wv) + varrefresh(vwin) + ELSEIF r=2 + StringF(s, IF (v>4096) OR (v<-4096) THEN '$\h' ELSE '\d', v) + r:=easyguiA(reqtitle, + [ROWS, + [TEXT,'New contents of variable?',NIL,FALSE,3], + [STR,1,'_Value:',s,100,10,0,0,"v"], + [COLS,[TEXT,'(Examples: 0,$0,var,{var})',NIL,FALSE,3],[BUTTON,{ehelp},'_Help',0,"h"]], + [BAR], + [COLS, + [BUTTON,1,'_OK',0,"o"], + [SPACEH], + [BUTTON,0,'_Cancel',0,"c"] + ] + ], + [EG_SCRN,scr,NIL]) + IF r=1 + r,v:=extval(s) + IF r + SELECT 8 OF type + CASE 3 TO 7 + frame.regs[type]:=v + CASE 1,2 + ^vptr:=v + ENDSELECT + varrefresh(vwin) + ENDIF + ENDIF + ENDIF + RETURN + ENDIF + ENDIF + wv:=wv.succ + ENDWHILE +ENDPROC + +PROC addvar(var,shift=FALSE) + DEF wv:PTR TO wvar + IF openvarwin() + IF shift THEN getvarval(var,TRUE) + IF findtracedvar(var) + request1('You''re already watching this variable','_Indeed!',"i") + ELSE + AddTail(vars,NEW wv) + wv.v:=StrCopy(String(EstrLen(var)),var) + wv.name:=String(MAX_WLINE) + IF wv.name=NIL THEN Raise("MEM") + varrefresh(vwin) + ENDIF + ENDIF +ENDPROC + +PROC addval(s,v) + DEF vl:PTR TO LONG,a,c,t[20]:STRING + IF TypeOfMem(v) + vl:=v + StrAdd(s,' [') + FOR a:=1 TO 4 DO StrAdd(s,StringF(t,'\z\h[8] ',vl[]++)) + StrAdd(s,' \q') + FOR a:=1 TO 16 DO (c:=v[]++) BUT StrAdd(s,IF (c>32) AND (c<127) THEN [c,0]:CHAR ELSE '.') + StrAdd(s,'\q]') + ENDIF +ENDPROC + +PROC findtracedvar(n) + DEF wv:PTR TO wvar + wv:=vars.head + WHILE wv.succ + IF StrCmp(n,wv.v) THEN RETURN wv + wv:=wv.succ + ENDWHILE +ENDPROC NIL + +PROC constructvars() + DEF wv:PTR TO wvar,num=0,v,vptr,type,t[30]:STRING + wv:=vars.head + WHILE wv.succ + v,vptr,type:=getvarval(wv.v) + IF type + StrCopy(wv.name,wv.v) + StrAdd(wv.name,StringF(t,IF (v>-1000) AND (v<1000) THEN ' = \d ' ELSE ' = $\h ',v)) + SELECT 8 OF type + CASE 3 TO 7 + StrAdd(wv.name,StringF(t,'(local reg D\d)',type)) + CASE 1,2 + StrAdd(wv.name,StringF(t,'(\s at $\z\h[8])',IF type=2 THEN 'global' ELSE 'local',vptr)) + ENDSELECT + addval(wv.name,v) + varlist[num++]:=wv.name + ENDIF + EXIT num=MAX_WATCH + wv:=wv.succ + ENDWHILE + SetList(varlist,num) +ENDPROC + +/*-------------------------------------------------------------------*/ + +PROC showsrcwin(src:PTR TO e_source,i=NIL) + DEF w:PTR TO srcwin,n:PTR TO srcwin,sc:PTR TO scrolltext + w:=dwins + WHILE IF w THEN (IF w.type=T_SRC THEN w.src<>src ELSE w) ELSE w DO w:=w.next + IF w=NIL + NEW n.srcwin(src) + ELSE + n:=w + IF fxs + ChangeWindowBox(n.scwin.window,fx,fy,fxs,fys) + fx:=fy:=fxs:=fys:=0 + ENDIF + ENDIF + sc:=n.scwin + IF i + sc.active(i) + activewin:=n + ENDIF + IF w THEN WindowToFront(sc.window) +ENDPROC + +PROC quit() + DEF a + a:=request3('Sure to leave the debugged program halfway?','_Quit','_Run','_Oops!',"q","r","o") + IF a=1 + Raise() + ELSEIF a=2 + whatstep:=STEP_RUN + ENDIF +ENDPROC + +PROC newmem() + DEF w:PTR TO memwin,a + IF (a:=getmem())<>-1 THEN NEW w.memwin(a,T_MEM) +ENDPROC + +PROC newreg() IS IF rwin THEN WindowToFront(rwin.scwin.window) ELSE NEW rwin.regwin() +PROC openstackwin() IS IF stackwin=NIL THEN NEW stackwin.memwin(frame.stack,T_STACK) ELSE WindowToFront(stackwin.scwin.window) +PROC openvarwin() IS IF vwin THEN (WindowToFront(vwin.scwin.window) BUT TRUE) ELSE NEW vwin.varwin() +PROC dum(p,q) IS EMPTY +PROC modifyvar() IS request13('You can modify a variable','by clicking on it','in the variable view','_Great!',"g") +PROC watchvar() IS request13('You can watch a variable','by double-clicking on it','in a source-window','_Great!',"g") +PROC breakpoint() IS request13('You can set a breakpoint','by double-clicking on a line','in a source-window','_Great!',"g") + +PROC breakpointvar() + DEF m + IF (m:=getmem())<>-1 THEN setmembreak(m) +ENDPROC + +PROC clearbreakpoints() + setbreak(NIL) + setmembreak(NIL) +ENDPROC + +PROC raiseexception() + DEF e[20]:STRING,ei[20]:STRING,ev,eiv,n + StrCopy(e,'"HALT"') + StrCopy(ei,'0') + LOOP + IF easyguiA(reqtitle, + [EQROWS, + [TEXT,'Enter exception values:',NIL,FALSE,3], + [STR,{dum},'_exception:',e,100,5,0,0,"e"], + [STR,{dum},'e_xceptioninfo:',ei,100,5,0,0,"x"], + [COLS,[TEXT,'(Examples: 0,$0,var,{var})',NIL,FALSE,3],[BUTTON,{ehelp},'_Help',0,"h"]], + [BAR], + [COLS, + [BUTTON,1,'_OK',0,"o"], + [SPACEH], + [BUTTON,0,'_Cancel',0,"c"] + ] + ], + [EG_SCRN,scr,NIL]) + n,ev:=extval(e) + IF n + n,eiv:=extval(ei) + IF n + setthrow(ev,eiv) + whatstep:=STEP_THROW + RETURN + ENDIF + ENDIF + request1('Illegal value(s)','_Sorry',"s") + ELSE + RETURN + ENDIF + ENDLOOP +ENDPROC + +PROC repeatstep() + DEF str[20]:STRING,n + StrCopy(str,'1') + LOOP + IF easyguiA(reqtitle, + [EQROWS, + [TEXT,'Enter number and type of steps:',NIL,FALSE,3], + [COLS, + [STR,{dum},'_Steps:',str,100,5,0,0,"s"], + [CHECK,{mrepeattype},'Step _Over?',repeatover,TRUE,0,"o"] + ], + [COLS,[TEXT,'(Examples: 10,$2F,var,^var)',NIL,FALSE,3],[BUTTON,{ehelp},'_Help',0,"h"]], + [BAR], + [COLS, + [BUTTON,1,'_OK',0,"o"], + [SPACEH], + [BUTTON,0,'_Cancel',0,"c"] + ] + ], + [EG_SCRN,scr,NIL]) + n,repeatcount:=extval(str) + IF n AND (repeatcount>0) + repeatcount-- + whatstep:=STEP_OVER + RETURN + ENDIF + request1('Illegal value(s)','_Sorry',"s") + ELSE + RETURN + ENDIF + ENDLOOP +ENDPROC + +PROC mrepeattype(p,x) IS repeatover:=x + +PROC evalexps() + DEF r,s[100]:STRING + easyguiA(reqtitle, + [EQROWS, + [TEXT,'Enter E Expression:',NIL,FALSE,3], + [STR,{evexp},'_Exp:',s,100,10,0,0,"e"], + r:=[TEXT,s,'Result:',TRUE,1], + [COLS,[TEXT,'(Examples: 0,$0,var,{var})',NIL,FALSE,3],[BUTTON,{ehelp},'_Help',0,"h"]], + [BAR], + [COLS,[SPACEH],[BUTTON,0,'_OK',0,"o"],[SPACEH]] + ], + [EG_INFO,r, EG_SCRN,scr, EG_GHVAR,{evgh}, NIL]) +ENDPROC + +PROC evexp(rgad,s) + DEF v,r,f[20]:STRING + r,v:=extval(s) + IF r + StringF(f,IF v<10000 THEN '\d' ELSE '$\h',v) + ELSE + StrCopy(f,'') + ENDIF + settext(evgh,rgad,f) +ENDPROC + +PROC ehelp(p) + easyguiA(reqtitle, + [ROWS, + [TEXT,'Values: 123, $ABC, %010101, "FORM"',NIL,FALSE,3], + [TEXT,'Variables: a, {a}, ^a',NIL,FALSE,3], + [TEXT,'Operators: +, -, *, /, ()',NIL,FALSE,3], + [BAR], + [BUTTON,0,'_OK',0,"o"] + ], + [EG_SCRN,scr,NIL]) +ENDPROC + +PROC search() + DEF lines:PTR TO LONG,n,max,st:PTR TO scrolltext + max:=n:=ListLen(lines:=currentwin.src.lines()) + st:=currentwin.scwin + IF easyguiA(reqtitle, + [ROWS, + [TEXT,'Enter text to find (case sensitive)',NIL,FALSE,3], + [STR,1,'_Text:',findstr,100,10,0,0,"t"], + [BAR], + [COLS, + [BUTTON,1,'_Find',0,"f"], + [SPACEH], + [BUTTON,0,'_Cancel',0,"c"] + ] + ], + [EG_SCRN,scr,NIL]) + WHILE n>0 + EXIT InStr(lines[],findstr,0)<>-1 + lines++ + n-- + ENDWHILE +-> IF n THEN st.settop(max-n) ELSE request1('Could not find text','_Hmmm',"h") + IF n THEN st.active(max-n) ELSE request1('Could not find text','_Hmmm',"h") + ENDIF +ENDPROC + +PROC handlemenu(imsg:PTR TO intuimessage) + DEF c,menu,item,sub + c:=imsg.code + menu:=menunum(c) + item:=itemnum(c) + sub:=subnum(c) + SELECT menu + CASE 0 + SELECT item + CASE 0; about() -> About + CASE 1; setprefs() -> Settings... + CASE 2; saveprefs() -> Save Settings + CASE 3; quit() -> Quit + ENDSELECT + CASE 1 + SELECT item + CASE 0; choose_source() -> Source + CASE 1; newreg() -> Registers + CASE 2; newmem() -> Memory + CASE 3; openstackwin() -> Stack + CASE 4; openvarwin() -> Variables + ENDSELECT + CASE 2 + SELECT item + CASE 0; whatstep:=STEP_IN -> Step In + CASE 1; whatstep:=STEP_OVER -> Step Over + CASE 2; whatstep:=STEP_FOLLOW -> Step Follow + CASE 3; repeatstep() -> Repeat Step + CASE 4; watchvar() -> Watch Variable + CASE 5; breakpoint() -> Set Breakpoint on Sourceline + CASE 6; breakpointvar() -> Set Breakpoint on Memory + CASE 7; clearbreakpoints() -> Clear all Breakpoints + CASE 8; whatstep:=STEP_RUN -> Run to Breakpoint + CASE 9; raiseexception() -> Raise Exception + ENDSELECT + CASE 3 + SELECT item + CASE 0; evalexps() -> Eval E Expressions + CASE 1; modifyvar() -> Modify Variable + CASE 2; dwins.refresh() -> Refresh + CASE 3; search() -> Find in Source + CASE 4; offset() -> Locate Offset + ENDSELECT + CASE 4 + SELECT item + CASE 0; exe_arexx_cmd(rxs1) + CASE 1; exe_arexx_cmd(rxs2) + CASE 2; exe_arexx_cmd(rxs3) + ENDSELECT + ENDSELECT +ENDPROC + +PROC offset() + DEF v,r,i + IF easyguiA(reqtitle, + [ROWS, + [TEXT,'Enter offset to locate',NIL,FALSE,3], + [STR,1,'_Offset:',offstr,12,10,0,0,"o"], + [BAR], + [COLS, + [BUTTON,1,'_Locate',0,"l"], + [SPACEH], + [BUTTON,0,'_Cancel',0,"c"] + ] + ], + [EG_SCRN,scr,NIL]) + v,r:=Val(offstr) + IF r + v,r,i:=exe.findoffset(v) + IF v + showsrcwin(v,r) + IF i THEN Delay(6) BUT request13('This might actually be an', + 'E internal function, such', + 'as Char() or WriteF()','_Oh',"o") + ELSE + request1('No line for this offset','_Oh',"o") + ENDIF + ELSE + request1('Bad offset','_Oh',"o") + ENDIF + ENDIF +ENDPROC + +PROC handlekey(c) + IF c=77 THEN whatstep:=STEP_OVER ELSE IF c=78 THEN whatstep:=STEP_IN +ENDPROC + +PROC handlesrc(data,imsg:PTR TO intuimessage) + DEF cl,vx,vy + IF data THEN currentwin:=data + IF (cl:=imsg.class)=IDCMP_MENUPICK + handlemenu(imsg) + ELSEIF cl=IDCMP_RAWKEY + handlekey(imsg.code) + ELSEIF cl=IDCMP_MOUSEBUTTONS + IF imsg.code=SELECTUP + IF DoubleClick(lastsec,lastmic,imsg.seconds,imsg.micros) + vx,vy:=currentwin.scwin.where(imsg.mousex,imsg.mousey) + IF vx<>-1 THEN dovar(vx,vy,imsg.qualifier) + ELSE + lastsec:=imsg.seconds + lastmic:=imsg.micros + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC handlevar(imsg:PTR TO intuimessage) + DEF cl,vx,vy + IF (cl:=imsg.class)=IDCMP_MENUPICK + handlemenu(imsg) + ELSEIF cl=IDCMP_RAWKEY + handlekey(imsg.code) + ELSEIF cl=IDCMP_MOUSEBUTTONS + IF vwin + vx,vy:=vwin.scwin.where(imsg.mousex,imsg.mousey) + IF imsg.code=SELECTDOWN + oldvy:=vy + ELSEIF imsg.code=SELECTUP + IF (vx<>-1) AND (oldvy=vy) THEN actionvar(vy) + oldvy:=-1 + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC getvarval(var,send=FALSE) + DEF isglob,v,vptr,x,type=0,mess[256]:STRING,evar:PTR TO e_var + IF (x:=activewin.scwin.getactive())<>-1 + evar,isglob:=activewin.src.findvar(var,activewin.src.findproc(x)) + IF evar + IF type:=evar.regno + v:=frame.regs[type] + vptr:=0 + ELSEIF evar.offs + v:=Long(vptr:=frame.regs[IF isglob THEN 12 ELSE 13]+evar.offs) + type:=IF isglob THEN 2 ELSE 1 + ENDIF + IF send + x:=evar.type + StringF(mess,'[\s] \s',IF isglob THEN 'Global' ELSE 'Local', var) + IF x + StrAdd(mess,':PTR TO ') + StrAdd(mess,x) + ENDIF + SelectOutput(NIL) + IF sendExplorer(v,x,NIL,mess,TRUE)=FALSE + IF runExplorer()=0 + FOR send:=1 TO 20 + Delay(6) + EXIT isExplorerRunning() + ENDFOR + IF send<=20 + sendExplorer(v,x,NIL,mess,TRUE) + startExp:=TRUE + ENDIF + ENDIF + ENDIF + SelectOutput(ocon) + ENDIF + ENDIF + ENDIF +ENDPROC v,vptr,type + +PROC runExplorer() + DEF cmd[256]:STRING + StrCopy(cmd,IF explorer[] THEN explorer ELSE 'explorer') + IF pubname[] + StrAdd(cmd,' SCREEN="') + StrAdd(cmd,pubname) + StrAdd(cmd,'"') + ENDIF +ENDPROC SystemTagList(cmd,[SYS_ASYNCH,TRUE, SYS_INPUT,NIL, SYS_OUTPUT,NIL, NIL]) + +PROC dovar(vx,vy,qual) + DEF var[50]:STRING,v,vptr,reg=0 + vy:=currentwin.src.locate(vx,vy,var) + IF var[] THEN v,vptr,reg:=getvarval(var) + IF reg + addvar(var,qual AND 3) + ELSEIF vy>=0 + v:=request3('Put breakpoint here?','_OK','OK and _Run','_Cancel',"o","r","c") + IF v>0 + setbreak(currentwin.src.findpc(vy,exe)) + IF v>1 THEN whatstep:=STEP_RUN + ENDIF + ENDIF +ENDPROC + +PROC makefollow() + IF followgh=NIL + followgh:=guiinitA('** EDBG ** Following Execution ** Close Me to Stop! **', + [SPACEH], + [EG_LEFT,0, EG_TOP,0, EG_MAXW,TRUE, EG_SCRN,scr, + EG_WTYPE,WTYPE_NOSIZE, NIL]) + ENDIF +ENDPROC + +PROC removefollow() + IF followgh + cleangui(followgh) + followgh:=NIL + ENDIF +ENDPROC + +PROC step(fr:PTR TO stackframe) + DEF pc,src,i + IF repeatcount + repeatcount-- + IF repeatover + stepover(fr,fr.regs[13]) + ELSE + stepover() + ENDIF + ELSE + frame:=fr + IF stackwin THEN stackwin.addr:=fr.stack + pc:=fr.returnpc-2 + src,i,pc:=exe.findline(pc) + IF src=NIL + removefollow() + request13('Your program caused a guru!', + 'It may not be safe to continue running this program,', + 'you might even need to reboot!', + '_Oops!',"o") + -> Try it now with last known PC + src,i:=exe.findline(pc) + ENDIF + IF src THEN showsrcwin(src,i) + whatstep:=STEP_NONE + IF dorefresh THEN dwins.refresh() + IF followgh + WindowToFront(followgh.wnd) + ActivateWindow(followgh.wnd) + Delay(followspeed) + IF guimessage(followgh)<0 + stepover() + ELSE + removefollow() + ENDIF + ENDIF + IF followgh=NIL + IF first_step_done=FALSE + unreachablea7:=fr+100000 -> imp! beyond main stack level + first_step_done:=TRUE + exe_arexx_cmd('.edbg-startup.rexx') + IF doabout THEN Delay(6) BUT about() + ENDIF + REPEAT + Wait(-1) + srcmessage() + IF dwins THEN dwins.message() + rexxmessage() + toolmessage() + UNTIL whatstep + SELECT whatstep + CASE STEP_IN; stepover() + CASE STEP_OVER; stepover(fr,fr.regs[13]) + CASE STEP_RUN; stepover(unreachablea7,unreachablea7) + CASE STEP_THROW; stepover(); RETURN TRUE + CASE STEP_FOLLOW + makefollow() + stepover() + ENDSELECT + ENDIF + ENDIF +ENDPROC FALSE + +PROC srcmessage() + DEF s:PTR TO scrollwin, srcwin:PTR TO srcwin + WHILE s:=handleIDCMP(srcport) + srcwin:=s.data + END srcwin + ENDWHILE +ENDPROC + +/*--------------------------------------------------------------------*/ + +CONST TOOL_NUM=6,TOOL_ONEH=32,TOOL_W=37,TOOL_SP=2 +CONST TOOL_HEIGHT=TOOL_ONEH+TOOL_SP*TOOL_NUM-TOOL_SP +CONST TOOL_SIZE=TOOL_HEIGHT*12 + +PROC toolmessage() + DEF imsg:PTR TO intuimessage,cl + WHILE imsg:=GetMsg(toolwin.userport) + cl:=imsg.class + SELECT cl + CASE IDCMP_MENUPICK + handlemenu(imsg) + CASE IDCMP_GADGETUP + SELECT 7 OF imsg.iaddress::gadget.gadgetid + CASE 1; whatstep:=STEP_OVER + CASE 2; whatstep:=STEP_IN + CASE 3; newmem() + CASE 4; newreg() + CASE 5; openvarwin() + CASE 6; quit() + ENDSELECT + ENDSELECT + ReplyMsg(imsg) + ENDWHILE +ENDPROC + +PROC createtoolbar() + DEF m,i,a,b=1,gads=NIL:PTR TO gadget,aw,ah,al,at,ab,ar,wpos + wpos:=font.ysize+scr.wbortop+1 + al:=scr.wborleft+2 + at:=wpos+2 + ab:=scr.wborbottom+2 + ar:=scr.wborright+2 + aw:=al+ar+TOOL_W + ah:=at+ab+TOOL_HEIGHT + IF (toolgads:=List(TOOL_NUM))=NIL THEN Raise("MEM") + SetList(toolgads,TOOL_NUM) + CopyMem({tooldata},m:=NewM(TOOL_SIZE,2),TOOL_SIZE) + i:=[0,0,TOOL_W,TOOL_HEIGHT,2,m,%11,0,NIL]:image + MapList({a},toolgads,toolgads, + `gads:=NEW [gads,al,b-1*(TOOL_ONEH+TOOL_SP)+at,TOOL_W,TOOL_ONEH, + GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET, + NIL,NIL,NIL,0,NIL,b++,0]:gadget) + IF ForAll({a},toolgads,`a)=FALSE THEN Raise("MEM") + IF (toolwin:=OpenW(0,wpos,aw,Min(ah,ysize-wpos), + IDCMP_GADGETUP OR IDCMP_MENUPICK, + 6 OR WFLG_NEWLOOKMENUS,' Toolbar',scr,15,gads))=NIL THEN Raise("WIN") + DrawImage(toolwin.rport,i,al,at) + IF SetMenuStrip(toolwin,menu)=FALSE THEN Raise("MENU") + RefreshWindowFrame(toolwin) + Dispose(m) +ENDPROC + +PROC deletetoolbar() + IF toolwin THEN ClearMenuStrip(toolwin) + CloseW(toolwin) + toolwin:=NIL +ENDPROC + +tooldata: INCBIN 'pix/toolbar.raw' + +/*-----------------------------------------------------------------*/ + +aboutdata: INCBIN 'pix/about.raw' + +CONST ABOUT_SIZE=7872,ABOUT_HEIGHT=164,ABOUT_WIDTH=182 + +PROC about() + DEF m,i,win=NIL:PTR TO window,aw,ah,al,at,ab,ar + al:=scr.wborleft+2 + at:=font.ysize+scr.wbortop+1+2 + ab:=scr.wborbottom+2 + ar:=scr.wborright+2 + aw:=al+ar+ABOUT_WIDTH + ah:=at+ab+ABOUT_HEIGHT + CopyMem({aboutdata},m:=NewM(ABOUT_SIZE,2),ABOUT_SIZE) + i:=[0,0,ABOUT_WIDTH,ABOUT_HEIGHT,2,m,%11,0,NIL]:image + IF win:=OpenW(xsize-ABOUT_WIDTH/2,ysize-ABOUT_HEIGHT/2,aw,ah, + IDCMP_CLOSEWINDOW OR IDCMP_RAWKEY OR IDCMP_MOUSEBUTTONS,$100E,'About...',scr,15,NIL) + DrawImage(win.rport,i,al,at) + WaitIMessage(win) + CloseW(win) + ENDIF + Dispose(m) +ENDPROC + +/*-----------------------------------------------------------------*/ + +PROC request1(body,gadget,key) IS easyguiA(reqtitle,[ROWS,[TEXT,body,NIL,FALSE,3],[BAR],[BUTTON,0,gadget,0,key]],[EG_SCRN,scr,NIL]) +PROC request13(b1,b2,b3,gadget,key) IS easyguiA(reqtitle,[ROWS,[TEXT,b1,NIL,FALSE,3],[TEXT,b2,NIL,FALSE,3],[TEXT,b3,NIL,FALSE,3],[BAR],[BUTTON,0,gadget,0,key]],[EG_SCRN,scr,NIL]) +PROC request3(body,g1,g2,g3,k1,k2,k3) IS easyguiA(reqtitle,[ROWS,[TEXT,body,NIL,FALSE,3],[BAR],[COLS,[BUTTON,1,g1,0,k1],[SPACEH],[BUTTON,2,g2,0,k2],[SPACEH],[BUTTON,0,g3,0,k3]]],[EG_SCRN,scr,NIL]) + +PROC getmem() + DEF ok,s[100]:STRING,r,v,p + REPEAT + ok:=1 + r:=easyguiA(reqtitle, + [ROWS, + [TEXT,'Which memory location?',NIL,FALSE,3], + [STR,1,'_Addr:',s,100,10,0,0,"a"], + [COLS,[TEXT,'(Examples: 0,$0,var,{var})',NIL,FALSE,3],[BUTTON,{ehelp},'_Help',0,"h"]], + [BAR], + [COLS, + [BUTTON,1,'_OK',0,"o"], + [SPACEH], + [BUTTON,0,'_Cancel',0,"c"] + ] + ], + [EG_SCRN,scr,NIL]) + IF r + r,v:=extval(s) + IF r + IF TypeOfMem(v)=FALSE + ok:=request3('Not a valid ram-address','_Do it anyway','_Oops','_Cancel',"d","o","c") + ENDIF + ELSE + ok:=2 + ENDIF + ELSE + ok:=0 + ENDIF + UNTIL ok<2 +ENDPROC IF ok THEN v AND -2 ELSE -1 + +PROC extval(s) + DEF v + s,v:=exp(s) + IF s=0 THEN request1('Syntax Error in Expression','_Um',"u") +ENDPROC s,v + +PROC exp(s) + DEF v=0,o,v2 + s,v:=factor(s) + IF s + s:=whitesp(s) + WHILE o:=s[]++ + IF o=")" THEN RETURN s-1,v + s,v2:=factor(s) + IF s=0 THEN RETURN 0 + SELECT o + CASE "+"; v:=v+v2 + CASE "-"; v:=v-v2 + CASE "*"; v:=Mul(v,v2) + CASE "/"; v:=Div(v,v2) + DEFAULT; RETURN request1('Missing operator','_Oh',"o") + ENDSELECT + s:=whitesp(s) + ENDWHILE + ENDIF +ENDPROC s,v + +PROC factor(s) + DEF v,r,c,a,neg=FALSE + v,r:=Val(s) + IF r + s:=s+r + ELSE + s:=whitesp(s) + IF s[]="-" + s:=whitesp(s+1) + neg:=TRUE + ENDIF + IF s[]="\q" + s++ + a:=v:=0 + WHILE (c:=s[]++)<>"\q" + EXIT a++=4 + v:=Shl(v,8)+c + ENDWHILE + IF c<>"\q" THEN RETURN request1('Missing "','_Oh',"o") + ELSEIF s[]="{" + s++ + s:=whitesp(s) + s,r,v:=id(s,TRUE) + IF s + s:=whitesp(s) + IF s[]++<>"}" THEN RETURN request1('Missing "}"','_Oh',"o") + ENDIF + ELSEIF s[]="^" + s++ + s:=whitesp(s) + s,v:=id(s) + v:=^v + ELSEIF s[]="(" + s++ + s,v:=exp(s) + IF s THEN IF s[]++<>")" THEN RETURN request1('Missing ")"','_Oh',"o") + ELSE + s,v:=id(s) + ENDIF + ENDIF +ENDPROC s,IF neg THEN -v ELSE v + +PROC id(s,isaddr=FALSE) + DEF r,v,t,str[50]:STRING,c + WHILE (((c:=s[]++)>="a") AND (c<="z")) OR ((c>="A") AND (c<="Z")) OR (c="_") DO StrAdd(str,[c,0]:CHAR) + s-- + IF str[]=0 THEN RETURN 0 + v,r,t:=getvarval(str) + IF t=0 THEN RETURN request1('Unknown var','_Oops',"o") + IF isaddr THEN IF t>=3 THEN RETURN request13('You can''t take the address','of a register variable.','Recompile without OPTI/S or REG/K','_Sure',"s") +ENDPROC s,v,r + +PROC whitesp(s) + WHILE s[]=" " DO s++ +ENDPROC s + +PROC setprefs() + easyguiA('EDBG Preferences', + [ROWS, + [EQROWS, + [CHECK,{mdoabout},'_Show "About..." on startup',doabout,TRUE,0,"s"], + [CHECK,{mdorefresh},'_Refresh views each step',dorefresh,TRUE,0,"r"], + [CHECK,{mdowins},'Save _current window positions',dosavewindowpos,TRUE,0,"c"], + [CHECK,{mdovars},'Save _watched variable names',dosavevars,TRUE,0,"w"] + ], + [SLIDE,{mspeed},'Follow Delay (0.1sec): ',FALSE,0,30,followspeed/5,2,'%3ld'], + [BAR], + [EQROWS, + [STR,{dstr},'_Arexx script 1',rxs1,RXSTR_SIZE,4,0,0,"a"], + [STR,{dstr},'Arexx script 2',rxs2,RXSTR_SIZE,4], + [STR,{dstr},'Arexx script 3',rxs3,RXSTR_SIZE,4] + ], + [BAR], + [STR,{dstr},'_Explorer',explorer,RXSTR_SIZE,4,0,0,"e"], + [BAR], + [BUTTON,0,'_OK',0,"o"] + ], + [EG_SCRN,scr,NIL]) +ENDPROC + +PROC mdoabout(p,x) IS doabout:=x +PROC mdorefresh(p,x) IS dorefresh:=x +PROC mdowins(p,x) IS dosavewindowpos:=x +PROC mdovars(p,x) IS dosavevars:=x +PROC dstr(p,q) IS EMPTY +PROC mspeed(p,x) IS followspeed:=x*5 + +PROC saveprefs() + DEF fh,ofh,dw:PTR TO dbgwin,wv:PTR TO wvar,win:PTR TO window + IF fh:=Open('.edbg-startup.rexx',NEWFILE) + ofh:=SetStdOut(fh) + WriteF('/* generated by EDBG */\n\n/* address EDBG */\n\n') + IF doabout=FALSE THEN WriteF('''noabout''\n') + IF dorefresh=FALSE THEN WriteF('''norefresh''\n') + IF dosavewindowpos + dw:=dwins + WHILE dw + IF dw.type=T_VAR + win:=dw::varwin.scwin.window + WriteF('''variables \d \d \d \d''\n',win.leftedge,win.topedge,win.width,win.height) + ELSEIF dw.type=T_MEM + WriteF('''memory \d''\n',dw::memwin.addr) + ELSEIF dw.type=T_SRC + win:=dw::srcwin.scwin.window + WriteF('''srcwindow \s \d \d \d \d''\n',dw::srcwin.src.name(),win.leftedge,win.topedge,win.width,win.height) + ENDIF + dw:=dw.next + ENDWHILE + ENDIF + IF dosavevars + IF vars.tailpred<>vars + WriteF('''watch') + iterate_exec_list({wv},vars,`WriteF(' \s',wv.v)) + WriteF('''\n') + ENDIF + ENDIF + IF explorer[] THEN WriteF('''explorer \s''\n',explorer) + IF rxs1[] THEN WriteF('''rexx 1 \s''\n',rxs1) + IF rxs2[] THEN WriteF('''rexx 2 \s''\n',rxs2) + IF rxs3[] THEN WriteF('''rexx 3 \s''\n',rxs3) + SetStdOut(ofh) + Close(fh) + ELSE + request1('Unable to write prefs','_Hmmm...',"h") + ENDIF +ENDPROC + +PROC choose_source() HANDLE + DEF l,s:PTR TO e_source,a=0,num=-1 + s:=exe.sources() + l:=newlist() + WHILE s + AddTail(l,newnode(NIL,s.name())) + s:=s.next() + ENDWHILE + easyguiA(reqtitle, + [EQROWS, + [LISTV,{sourcenum},'Select Source:',12,5,l,FALSE,0,0], + [BAR], + [COLS,[SPACEH],[BUTTON,0,'_Cancel',0,"c"],[SPACEH]] + ], + [EG_INFO,{num}, EG_SCRN,scr, NIL]) +EXCEPT DO + IF num>=0 + s:=exe.sources() + WHILE s + EXIT a++=num + s:=s.next() + ENDWHILE + IF s THEN showsrcwin(s) + ENDIF +ENDPROC + +PROC sourcenum(i,n) + ^i:=n + Raise() +ENDPROC + +PROC rexxmessage() + DEF mes,rexxstr + IF rexxport + WHILE TRUE + mes,rexxstr:=rx_GetMsg(rexxport) + EXIT mes=NIL + rexxcontinue(rexxstr,mes) + ENDWHILE + ENDIF +ENDPROC + +PROC rexxcontinue(rexxstr,mes) HANDLE -> called from other spots too + DEF rc=0,rstr=NIL + rc,rstr:=processcmd(rexxstr) +EXCEPT DO + rx_ReplyMsg(mes,rc,rstr) + ReThrow() +ENDPROC + +PROC getword(s,dest) + DEF b,c + LOOP + SELECT 256 OF c:=s[]++ + CASE 0; request1('Argument to Arexx command expected','_Oh',"o"); Raise() + CASE " ", "\t" + CASE 33 TO 255 + b:=s-1 + WHILE (s[]>" ") AND (s[]<=255) DO s++ + StrCopy(dest,b,s-b) + WHILE (s[]=" ") OR (s[]="\t") DO s++ + RETURN s + DEFAULT + request1('Garbage in Arexx command','_Oh',"o"); Raise() + ENDSELECT + ENDLOOP +ENDPROC + +PROC getexp(s) + DEF v,dest[250]:STRING,sr + s:=getword(s,dest) + sr,v:=extval(dest) + IF sr=NIL THEN Raise() +ENDPROC s,v + +PROC processcmd(s) + DEF rc=0,rstr=NIL,ts[250]:STRING,a,b,esrc=NIL:PTR TO e_source,w:PTR TO memwin,vptr,type + s:=getword(s,ts) + UpperStr(ts) + IF StrCmp(ts,'QUIT') + quit() + ELSEIF StrCmp(ts,'RUN') + whatstep:=STEP_RUN + ELSEIF StrCmp(ts,'MEMORY') + s,a:=getexp(s) + NEW w.memwin(a,T_MEM) + ELSEIF StrCmp(ts,'EXPLORER') + s:=getword(s,explorer) + ELSEIF StrCmp(ts,'REXX') + s,a:=getexp(s) + IF a=1 + s:=getword(s,rxs1) + ELSEIF a=2 + s:=getword(s,rxs2) + ELSEIF a=3 + s:=getword(s,rxs3) + ENDIF + ELSEIF StrCmp(ts,'VARIABLES') + s,fx:=getexp(s) + s,fy:=getexp(s) + s,fxs:=getexp(s) + s,fys:=getexp(s) + openvarwin() + ELSEIF StrCmp(ts,'STEPIN') + whatstep:=STEP_IN + ELSEIF StrCmp(ts,'STEPOVER') + whatstep:=STEP_OVER + ELSEIF StrCmp(ts,'WATCH') + WHILE s[] + s:=getword(s,ts) + addvar(ts) + ENDWHILE + ELSEIF StrCmp(ts,'BREAKPOINT') + s,a:=getexp(s) + setbreak(currentwin.src.findpc(a,exe)) + ELSEIF StrCmp(ts,'EVAL') + s,rc:=getexp(s) + ELSEIF StrCmp(ts,'MEMORYBREAKPOINT') + s,a:=getexp(s) + setmembreak(a) + ELSEIF StrCmp(ts,'RAISE') + s,a:=getexp(s) + s,b:=getexp(s) + setthrow(a,b) + whatstep:=STEP_THROW + ELSEIF StrCmp(ts,'SRCWINDOW') + s:=getword(s,ts) + s,fx:=getexp(s) + s,fy:=getexp(s) + s,fxs:=getexp(s) + s,fys:=getexp(s) + IF esrc:=exe.sources() THEN esrc:=esrc.findsrc(ts) + IF esrc THEN showsrcwin(esrc) + ELSEIF StrCmp(ts,'NOABOUT') + doabout:=FALSE + ELSEIF StrCmp(ts,'NOREFRESH') + dorefresh:=FALSE + ELSEIF StrCmp(ts,'ASSIGN') + s:=getword(s,ts) + s,a:=getexp(s) + b,vptr,type:=getvarval(ts) + SELECT 8 OF type + CASE 3 TO 7 + frame.regs[type]:=a + CASE 1,2 + ^vptr:=a + ENDSELECT + ELSE + request13('Unknown Arexx command:',ts,'received','_Really?',"r") + s:='' + ENDIF + IF s[] THEN request13('Superfluous arguments:',ts,'in Arexx command','_Really?',"r") +ENDPROC rc,rstr + +PROC exe_arexx_cmd(cmdstr) HANDLE -> either a file name or a quoted string + DEF rexx,rmsg=NIL:PTR TO rexxmsg,rarg=NIL,forb,noreply=TRUE,rrmsg:PTR TO rexxmsg,cstr + rexxsysbase:=NIL + Forbid(); forb:=TRUE + IF (rexx:=FindPort('REXX'))=NIL THEN Raise() + IF (rexxsysbase:=OpenLibrary('rexxsyslib.library',0))=NIL THEN Raise() + IF (rmsg:=CreateRexxMsg(rexxport,'rexx',rexxname))=NIL THEN Raise() + IF (rarg:=CreateArgstring(cmdstr,StrLen(cmdstr)))=NIL THEN Raise() + rmsg.args[0]:=rarg + rmsg.action:=RXCOMM + PutMsg(rexx,rmsg) + Permit(); forb:=FALSE + WriteF('executing script \s\n',cmdstr) + WHILE noreply + Wait(-1) + WHILE TRUE + rrmsg,cstr:=rx_GetMsg(rexxport) + EXIT rrmsg=NIL + IF rrmsg::ln.type=NT_REPLYMSG + WriteF('done with script \s\n',cmdstr) + noreply:=FALSE + ELSE + rexxcontinue(cstr,rrmsg) + ENDIF + ENDWHILE + ENDWHILE +EXCEPT DO + IF forb THEN Permit() + IF rarg THEN DeleteArgstring(rarg) + IF rmsg THEN DeleteRexxMsg(rmsg) + IF rexxsysbase THEN CloseLibrary(rexxsysbase) +ENDPROC + +CHAR 0, '$VER: EDBG 3.3a', 0, 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/eexe.e b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/eexe.e new file mode 100644 index 0000000..906c464 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/eexe.e @@ -0,0 +1,498 @@ +/* E executable load and debug objects + +probs: all that uses task-structure +- Forbid(): broken by debugger? +etc. + +*/ + +OPT MODULE + +MODULE 'exec/tasks', 'dos/doshunks' +MODULE 'tools/file' + +/*---------------load-e-exe-functions------------------*/ + +EXPORT OBJECT e_exe PRIVATE + file,code,codelen,sources:PTR TO e_source +ENDOBJECT + +EXPORT OBJECT e_source PRIVATE + next:PTR TO e_source + lines:PTR TO LONG,numlines -> of LINEDEBUG info + sourcename,source + procs:PTR TO e_proc + globs:PTR TO e_var + sourcelines:PTR TO LONG +ENDOBJECT + +PROC sources() OF e_exe IS self.sources +PROC next() OF e_source IS self.next +PROC name() OF e_source IS self.sourcename +PROC lines() OF e_source IS self.sourcelines + +OBJECT e_proc PRIVATE + next:PTR TO e_proc + name:PTR TO CHAR + firstvarline + vars:PTR TO e_var +ENDOBJECT + +EXPORT OBJECT e_var PRIVATE + next:PTR TO e_var + name:PTR TO CHAR +PUBLIC + regno:INT,offs:INT -> if 0 then other + type:PTR TO CHAR +ENDOBJECT + +PROC findsrc(name) OF e_source + WHILE self + IF StrCmp(self.sourcename,name) THEN RETURN self + self:=self.next + ENDWHILE +ENDPROC NIL + +PROC locate(vx,vy,var) OF e_source + DEF l,l2,c + IF (vy<0) OR (vy>=ListLen(self.sourcelines)) + vy:=-1 + ELSE + l:=self.sourcelines[vy] + vx:=Bounds(vx,0,StrLen(l)) + l:=l+vx + IF isalnum(l[]) + l2:=l + WHILE isalnum(l[-1]) DO l-- + WHILE isalnum(l2[]) DO l2++ + IF ((c:=l[])>="_") AND (c<="z") THEN StrCopy(var,l,l2-l) + ENDIF + ENDIF +ENDPROC vy + +PROC isalnum(c) IS ((c>="A") AND (c<="Z")) OR ((c>="_") AND (c<="z")) OR ((c>="0") AND (c<="9")) + +PROC findproc(linenum) OF e_source + DEF pr:PTR TO e_proc + pr:=self.procs + WHILE pr + EXIT IF pr.vars THEN pr.firstvarline<=linenum ELSE FALSE + pr:=pr.next + ENDWHILE +ENDPROC pr + +PROC findvar(name,pr=NIL:PTR TO e_proc) OF e_source + DEF var=NIL:PTR TO e_var,isglob=FALSE + IF pr THEN var:=lookupvar(pr.vars,name) + IF var=NIL THEN (isglob:=TRUE) BUT var:=lookupvar(self.globs,name) +ENDPROC var,isglob + +PROC lookupvar(v:PTR TO e_var,name) + WHILE v + IF StrCmp(v.name,name) THEN RETURN v + v:=v.next + ENDWHILE +ENDPROC NIL + +PROC grabvarinfo(src:PTR TO e_source,o:PTR TO INT,end) + DEF pr=NIL:PTR TO e_proc,job,v + WHILE (job:=o[]++) BUT oWriteF('\nPROC \s:',o) + pr.name:=o + pr.firstvarline:=-1 + pr.next:=src.procs -> in reverse order, for line-search + src.procs:=pr + o:=o+v + CASE 5 + v:=o[]++ + newself(pr,o[],o[1]) + o:=o+v + DEFAULT + Raise("eexe") + ENDSELECT + ENDWHILE +->WriteF('\n') +ENDPROC + +CONST REGVARLIM=30000 + +PROC newself(pr:PTR TO e_proc,linenum,b) + DEF i,t + IF (i:=InStr(pr.name,':'))=-1 THEN Raise("eexe") + i++ + NEW t[i] + AstrCopy(t,pr.name,i) + pr.vars:=NEW [pr.vars,'self',IF b>=REGVARLIM THEN b-REGVARLIM ELSE 0, + IF b>=REGVARLIM THEN 0 ELSE b,t]:e_var + pr.firstvarline:=linenum +->WriteF('new self "\s"\n',t) +ENDPROC + +PROC collectvars(o:PTR TO INT,varlist,src:PTR TO e_source,pr:PTR TO e_proc,job) + DEF line,v:PTR TO e_var,num,a,b,s:PTR TO CHAR,st,t + v:=varlist + line:=o[]++ + s:=src.sourcelines[line] + num:=o[]++ + IF pr THEN IF pr.firstvarline<0 THEN pr.firstvarline:=line + FOR a:=1 TO num + b:=o[]++ + v:=NEW [v,NIL,IF b>=REGVARLIM THEN b-REGVARLIM ELSE 0,IF b>=REGVARLIM THEN 0 ELSE b,NIL]:e_var +->WriteF(' $\h ',b) + IF (a=1) AND (job=1) THEN WHILE s[]++<>"(" DO NOP + IF a>1 THEN WHILE s[]++<>"," DO NOP + WHILE ((b:=s[])<"_") OR (b>"z") DO s++ + st:=s + REPEAT + s++ + UNTIL isalnum(s[])=FALSE + b:=s-st+1 + NEW t[b] + AstrCopy(t,st,b) +->WriteF('(\s)',t) + v.name:=t + t:=FALSE + WHILE (b:=s[]) AND (b<>",") + EXIT t:=((b>="_") AND (b<="z")) + s++ + ENDWHILE + IF t + st:=s + REPEAT + s++ + UNTIL isalnum(s[])=FALSE + b:=s-st+1 + NEW t[b] + AstrCopy(t,st,b) + v.type:=t + ENDIF + ENDFOR +ENDPROC o,v + +PROC load(name) OF e_exe + DEF o:PTR TO LONG,l,cl,c,dbl,numrel,a,b:PTR TO LONG,src=NIL:PTR TO e_source,add + + -> read exe + + o,l:=readfile(name,0) + self.file:=o + + -> eat header + + IF (o[]++<>HUNK_HEADER) OR (o[]++<>0) OR (o[]++<>1) OR (o[]++<>0) OR (o[]++<>0) THEN Raise("eexe") + o++ + + -> eat code hunk + + IF o[]++<>HUNK_CODE THEN Raise("eexe") + self.codelen:=cl:=o[]++*4 + self.code:=c:=o + o:=o+cl + + -> eat and digest reloc + + IF o[]++<>HUNK_RELOC32 THEN Raise("eexe") + numrel:=o[]++ + IF o[]++<>0 THEN Raise("eexe") + IF numrel + FOR a:=1 TO numrel -> do own reloc! + b:=c+o[]++ + b[]:=b[]+c + ENDFOR + ENDIF + IF o[]++<>0 THEN Raise("eexe") + + -> skip symbol hunk if necessary + + IF o[]=HUNK_SYMBOL + o++ + WHILE a:=o[]++ DO o:=a*4+o+4 + ENDIF + + -> eat debug hunks + + IF o[]<>HUNK_DEBUG THEN Raise("eexd") + + WHILE (a:=o[]++)<>HUNK_END + IF a=HUNK_DEBUG + IF o[2]="EVAR" + IF src=NIL THEN Raise("eexe") + dbl:=o[]++ + grabvarinfo(src,o+8,o:=dbl*4+o) + ELSE + NEW src + dbl:=o[]++ + IF (o[]++<>0) THEN Raise("eexe") + IF o[]="LINE" + add:=0 + ELSEIF Char(o)="L" + add:=o[] AND $FFFFFF + ELSE + Raise("eexe") + ENDIF + o++ + src.numlines:=dbl:=dbl-(a:=o[]++)-3 + src.sourcename:=o + o:=a*4+o + src.lines:=o + make_illegal(c,o,dbl,add) + o:=dbl*4+o + src.next:=self.sources + self.sources:=src + src.load() + src.globs:=add_globs(src.globs) + ENDIF + ELSE + Raise("eexe") + ENDIF + ENDWHILE + + CacheClearU() -> important! + +ENDPROC + +PROC new_var(v,s,off,type=NIL) IS NEW [v,s,0,off,type]:e_var + +PROC add_globs(v) + v:=new_var(v,'stdout', -$8) + v:=new_var(v,'conout', -$C) + v:=new_var(v,'stdrast', -$10, 'rastport') + v:=new_var(v,'arg', -$20) + v:=new_var(v,'wbmessage', -$24, 'wbstartup') + v:=new_var(v,'execbase', -$28, 'execbase') + v:=new_var(v,'dosbase', -$2C, 'doslibrary') + v:=new_var(v,'intuitionbase',-$30, 'intuitionbase') + v:=new_var(v,'gfxbase', -$34, 'gfxbase') + v:=new_var(v,'exception', -$54) + v:=new_var(v,'stdin', -$5C) + v:=new_var(v,'exceptioninfo',-$60) +ENDPROC v + +CONST OPCODE_NOP=$4E71, OPCODE_ILLEGAL=$4AFC + +PROC make_illegal(code,dbg:PTR TO LONG,len,add) + DEF a,b:PTR TO INT + IF len + FOR a:=1 TO len STEP 2 + dbg++ + dbg[]++:=b:=dbg[]+add + b:=b+code + IF b[]<>OPCODE_NOP THEN Raise("eexd") + b[]:=OPCODE_ILLEGAL + ENDFOR + ENDIF +ENDPROC + +PROC end() OF e_exe + DEF p:PTR TO e_source + IF self.file THEN freefile(self.file) + p:=self.sources + END p +ENDPROC + +PROC load() OF e_source + DEF m,l,a,p + m,l:=readfile(self.sourcename) + self.source:=m + self.sourcelines:=stringsinfile(m,l,countstrings(m,l)) + p:=m + FOR a:=1 TO l DO IF p[]++="\t" THEN p[-1]:=" " +ENDPROC + +PROC end() OF e_source + DEF n:PTR TO e_source + n:=self.next + IF self.source THEN freefile(self.source) + END n +ENDPROC + +PROC findline(pc) OF e_exe + DEF l:PTR TO e_source,a,b,dbg:PTR TO LONG,num,c + l:=self.sources + c:=self.code + WHILE l + dbg:=l.lines + num:=l.numlines-1 + FOR a:=0 TO num STEP 2 + b:=dbg[]++-1 + IF dbg[]+++c=pc THEN RETURN l,b + ENDFOR + l:=l.next + ENDWHILE + MOVE.L lastpc(PC),a +ENDPROC NIL,NIL,a + +CONST STARTUP_SIZE=$196 + +PROC findoffset(off) OF e_exe + DEF l:PTR TO e_source,a,b,dbg:PTR TO LONG,num,best=0,src=NIL,line,start=0,largest=0 + IF (off<0) OR (off>=self.codelen) THEN RETURN NIL + l:=self.sources + WHILE l + dbg:=l.lines + num:=l.numlines-1 + IF largestbest + best:=dbg[] + line:=b + src:=l + ENDIF + dbg++ + ENDFOR + l:=l.next + ENDWHILE + IF (off(largest+8) + best:=TRUE + ELSE + best:=FALSE + ENDIF +ENDPROC src,line,best + +PROC findpc(line,exe:PTR TO e_exe) OF e_source + DEF a,dbg:PTR TO LONG,num,c + c:=exe.code + dbg:=self.lines + num:=self.numlines-1 + FOR a:=0 TO num STEP 2 DO IF dbg[]++-1=line THEN RETURN dbg[]+c ELSE dbg++ +ENDPROC NIL + +PROC edebug(do_at_break,cli_arg) OF e_exe + DEF mytask:PTR TO tc,code,alen + alen:=StrLen(cli_arg)+1 + mytask:=FindTask(NIL) + mytask.trapcode:={tcode} + LEA codejmp(PC),A0 + MOVE.L do_at_break,(A0) + LEA debuga4(PC),A0 + MOVE.L A4,(A0) + code:=self.code + MOVEM.L D0-D7/A0-A6,-(A7) + MOVE.L cli_arg,A0 + MOVE.L alen,D0 + MOVE.L code,A1 + JSR (A1) + MOVEM.L (A7)+,D0-D7/A0-A6 +ENDPROC + +EXPORT OBJECT stackframe PUBLIC + status:LONG + regs[15]:ARRAY OF LONG + returnpc:LONG + stack[1]:ARRAY OF LONG -> from here on +ENDOBJECT + +tcode: + CMP.L #3,(A7) + MOVEM.L A0,(A7) -> yeah! keep flags! + BGT.S noadjust + MOVE.L $4.W,A0 + BTST #0,297(A0) + BNE.S noadjust + MOVE.L (A7),8(A7) -> for 68000 long-format frames + ADDQ.L #8,A7 +noadjust: + LEA continue(PC),A0 -> finish superstate + MOVE.L 6(A7),-4(A0) + MOVE.W 4(A7),-6(A0) + MOVE.L A0,6(A7) + MOVE.L (A7)+,A0 + RTE + + LONG 0 +pcstore: + LONG 0 +continue: + SUBQ.L #4,A7 -> make space for return + MOVEM.L D0-D7/A0-A6,-(A7) + LEA continue(PC),A0 -> pc,sr on the stack + MOVE.L -(A0),D0 + MOVE.L -(A0),-(A7) + ADDQ.L #2,D0 + MOVE.L D0,64(A7) -> prepare return pc + + MOVE.L breakpoint(PC),D0 -> check for breakpoint + BEQ.S nobreak + CMP.L pcstore(PC),D0 + BEQ.S stophere + +nobreak: + MOVE.L breakpointmem(PC),D0 -> check for breakpoint on mem + BEQ.S nomembreak + MOVE.L D0,A0 + MOVE.L (A0),D0 + CMP.L memval(PC),D0 + BNE.S stophere + +nomembreak: + MOVE.L stepovera7(PC),D0 -> check for step over + BEQ.S stophere + CMPA.L stepovera5(PC),A5 + BEQ.S stophere + CMPA.L D0,A7 -> we compare TOP of frame, not actual A7 + BMI.S dontstop + +stophere: + MOVE.L debuga4(PC),A4 -> restore A4 + MOVE.L A7,-(A7) + MOVE.L codejmp(PC),A0 + JSR (A0) -> call E func with frame + ADDQ.L #4,A7 + TST.L D0 -> see if we need to raise an exception + BNE.S raise + +dontstop: + MOVE.L pcstore(PC), D0 + LEA lastpc(PC), A0 + MOVE.L D0, (A0) + MOVE.L (A7)+,D0 + MOVEQ #-1,D1 + MOVE.L $4.W,A6 + JSR -144(A6) -> SetSr(orig_sr,$FF) + MOVEM.L (A7)+,D0-D7/A0-A6 -> hold SR! + RTS -> retpc is on top! + +raise: + ADDQ.L #4,A7 -> remove sr + MOVEM.L (A7)+,D0-D7/A0-A6 -> registers back + MOVE.L exc(PC),-84(A4) -> fill programs' exception(-info) + MOVE.L excinfo(PC),-96(A4) + ReThrow() + +codejmp: LONG 0 +debuga4: LONG 0 + +stepovera7: LONG 0 +stepovera5: LONG 0 + +breakpoint: LONG 0 -> 0=no break, -1=run, other=break +breakpointmem: LONG 0 -> 0=no break, other=memaddress +memval: LONG 0 -> value for breakpointmem + +exc: LONG 0 +excinfo: LONG 0 + +-> Last known PC +lastpc: LONG 0 + +EXPORT PROC stepover(a7=NIL,a5=NIL) IS PutLong({stepovera7},a7) BUT PutLong({stepovera5},a5) +EXPORT PROC setbreak(a) IS PutLong({breakpoint},a) +EXPORT PROC setmembreak(a) IS PutLong({breakpointmem},a) BUT PutLong({memval},IF a THEN Long(a) ELSE NIL) +EXPORT PROC setthrow(e,ei) IS PutLong({exc},e) BUT PutLong({excinfo},ei) diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/about.iff2 b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/about.iff2 new file mode 100644 index 0000000000000000000000000000000000000000..6750821b4b78f6619a9b2d6194cffac96547c45f GIT binary patch literal 4500 zcmd6rU2Ggz701tf*t06z%-T3{0pp2RMp>jhY;lntVLaaLh7<`mA5TTpYIy*G5XM#- z*I}LA*?5WTG_q?RK=42-7pV^wZp#CpIBSmyiX$4Dhe)i2u`|IyQyF>3b=qBLJ}&3Z z%zh>{g@T0S{qViN|2gO0d+s@7f9dFnK7fV`U;aw8FWUE53;>$oSMYQE1eRqKfPMQ| zg@s4^BFAvZKl|#d_(2Hy&gAVQCn8b&g@>=fiAN)SN1X2uyue3~#=eR+J2wbp!aMMP z|FJ{r6p0XBunD6|_-4Wm)Fm|lv0wuuYbMx4Q~-nmaD)IPi4B~?*&rqfDG0=*o1y?i z%o42PPys-qZ`bOae$93bRv1MAn#CGqqLqhX)f9DprF=M zR-&w^+{I(81jp_Rj{cjVzaVc>*E+i9bi?)R7t}q}vxuHeaR(ijumt9hR*R)Dc_a^8 zbgU)Bf>?p|IM!0SpnDjmJawADL@#4_Kd93bW;w;cFVu`+82>_845N%yMq3PnGi#$Y zxpElZ+EY5%MaXv!1S(R3Dq>b z|5!%6OY0iNS zdue)A?q{1`Lvg$|5_)O%k?Kh5ag{EuR>Zx7t8{6(DsD>Cf*_68(zMuUBOgGIX*IST zdQ`f{HZ5clmZox%q><3Fr(q$hEU6fYQzT_nRMAdJRZ&q%?-8*8BbmUGTBf(K8c0Z{ zumIQ4qKdSQCAeJNk=A9T87$b9tpLkR5@X>^Yz0!ONMcD+u)LcbHV(}zlC*)@_=Am# z6z~!!F)^KP#{k|v4X{mVl2XyY5JnEKHqOv2F2cxR5x_Yda>|}(S*0+wRceiBS*9@c z>h@9W612_gr3U=r9~<((%98Rv4$pUqq2Zm+d!x6@^@y(+b-p3Bf<>S`6 zL(#zt^+9*=W3!hgM| zBOLCo9CoAV=;-VW|L=qQ=!+J@-fr5hOlcjv9e_8tiCJsGCgCyVO~9%xzXbI*0A~Tq z=)L$&u`!7`^(nGr6EH2p+TwyuxTK5o`@x40PjM*Y#!Zq(+@Lrq5u=GY6#hD+*n$ld?fL(IdJ9qd2;R_UnC2T{YL(CG2i)vY&(Daa5@5qn|h0a zKg{J%-LO`S*^BXca&cp!BnZZQ6So}!AJI@S>Umh5%MUj@0%Kl6!C28laMX7<#I_5+ zKf_mfSRKpPWv!LM=g%579(sLeQNTYCsSzyX&!E6~Z@yN5YoLPIVJdhe>h9@Y14BAR z1#=gv;LQwiH?@%ucKL>GGr!}~hqy(3BV#0 zCV-n=hcDc{J5a~>;?eZtS5jvz5Mtm2mI|EU6g*X`En|sCpm&a<}9>-2^z(7>9n7VM%h}0 zemWlCHZvKkM$sIIrqfMKG|KxXuKwn4i+i5X*`cL_`=L3PiN`nWOvcC$cOLm<&(g)^ggEH8v*uw=$EKiUX90BsKWSecHkX*^QSrMRJIQlp_z0# zwiAu|>Q02Fn;7wMfc?I21{K-8t++JLC6d$uUQ8C=_}B21C<4RYac)xjqbou`MfSt!4)ds>nQ> zrHTVVpO0sF9u=RRZh~o4oDa?P(sktXhHV(A_~XC^89>FUZ2u*|y&4?knXaw?+jix` zUtubycb{Ggq9T`>nlkLArJS{P=;Wu!;GB5*T-WL)U_|9k@mLu>d8c@?yX8Uk95%i1 z7BGxLZ!uio!aCyR@BtNQcg2TonuE~h6_UNnGQsS`hXsKqBw3^BK?@JlzTW~rN&;#n z&#c_Eh=_`uT!lBbA8394$@LV(_CL=3SeQIH`J@xW-j(HB&%E4{Aagh0Fuzq8x-j&z z7f^d>X5#Bj5r{o~oPUBp-q!H6C&=~>|7>HP%)K~kykg9*ZN6As!PS|GNE4&Q0!R5{ zRM6`RmOJ~0=QnI=F88|e8Wk*fg3pL3*iJ#ncN_&zwMm}fPdWh;5nMw4Co- Qn_v;J@B!u{|H}jZ3D(`p@&Et; literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/about.raw b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/about.raw new file mode 100644 index 0000000000000000000000000000000000000000..8907b19b2fd2284ffecc4677b9fbd025c4d2b4f3 GIT binary patch literal 7872 zcmeI0Pi!1l9mn77OuQ?IGHYSc0>*2vjJ!xWY)O$FVRqIlM{uESIQ3Agz6f`Jwpc_%7p*O}RQ{C@Li zJu{gNDYP_5{>d}*_Va%GeZTq5d+Yf(lBy33?E0fs>j-L>hoVke;o84IE8UXo?qhs+r2oH~!2tPyN zslaE)T)g4oa?0{oS>4MI*_;?{c;3r99Dkt=j{%39wJa=K{)|d|oS;q&`J%_a#rZ{v zgyojbU3m}a1o@|s&v|t^U|fsK9)09FjAyP5pH=SgZ=gSW2WM2^0vzu65AhPK0Lznx zpYt+sgX9SBy5AHpi4p_PiwGp9Dvc?kogP@s$N|B8fXP99((e;sf{FMazS7nwQym|yId9_6e`N(-P>DAXEo`cs?N0Q0mz;Oo$lb=YO z|8*X$JoiAJ-S_26?I+l@*N5;D>3}F$jD%6saF*a8gzF^{ykMIlX*f%80609!poIQOX$9|wKpqsNdxoN?lb4@D;5XMWEXjS%3eOu^THEbGi0>)5%y={g%b-;Na#rV6U+18=^7!UPaWqT=Z^PvK4tNN zE6ejEU5qjseUy6)dD`M%;(>oKLlTkWz@O}k*}VVx`1}YNvH4?tQHOtX`R5~`-x)>! zJ)Qo6o*$&QX4L4P9%X+VUU={=+doNghPlkXUzmz6xZm8*z*5c>&oS01Slci@jx5D0Z8`DzW8IX(LGOX%zX7bv zQenyMZ`OlY_d$I_T4vXY$aD9`t-2Nbb-txSAR$gY%e1L~!z$FLEpye&dv!F$N-Ci4 z_VPCMyUw=ibo3XTdY>|F_>7mE`wVKHr*a#v0LP6R_r3(~Gx#`c{fOp1hBD#tZ*g@( zH0PwPb61Z0BtibT-=a=?b#`G~iwhoog+qJh}I&V1GvfC7p%+E5*^5%>V8TEK*piN=$-BXpU=fKm(BPm3EyLO7*Vncd9?n0ck6(VFM9=>H>(GZf+8!*Qh|19}9=p$dbi2Ti>6Hj%mzVLwYH9dP- zPw{hy1)F2sj+LQNw(r+raMgh0;a^|62nY^82V&XBHs8vYevZ)Q+?-}yx-?U-(;B9} z)`YG%hkSb+K^+zW`k|!OPcgKKpWa zp03<@UH^V#^8Dn>md-|HZ0eWWCA#wB1??5>!sgD4w*KJQRB79Yt<+xAUPWHE_&X}_ zgLzu1UjY8nregDr=c-dBTC(}8n>C03X6$<<(BG+{|DMjq`put~yYqbQi?8X=G$!AB c$o9WRafZ3fzF+F+;BvRTxfEK>{~!N<0bxS*rT_o{ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/toolbar.iff b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/toolbar.iff new file mode 100644 index 0000000000000000000000000000000000000000..f3e4a2fada5eaa6e469bf6b67d926b6a47bad616 GIT binary patch literal 2540 zcmd7TPlyv&90%~mQogA{0E?(wm2!tc(BHup$kmhhha;XiIw&_aJ7( z9K?gHg$j$%uAU@fDF~%_a3gr=LG02)p)K7_>%x{EvMWMOs+;Hc_f2LpuB)eoI+uL% z&F}r*oA;8*zR@EEk@fQjM}`VRg#*JPvRU4id-ADFIgSJ(eSJ>g$lgN!Fg{Cvd;L0I zthJwA_KQ3v_ z%N(yya%_`hx1T9v?EL9*j6FW4eJ)RGpB??`2Mg+rtbfS*^_=Tp&Xr-l$UJV3`5g1z z^iT8%eG^W|S@@Ja1v_`7>WYtfM4WfU3oYrGMKV!tEM3t7Df=VxbwwZUwRLzyWs0sv zdCF>krxGAHR$x;E^@8~t_aJurX_USS;aO;(|G~can0MMv}p^CtagL;5aFd_rG>f3X+U)i2aDURmdw8%O`57(-S)i+DbW8Q1>z5@6nv#S;!w#qHNLpU!EX$8(@$ zZ!f9`=vn$5`aYdz{Ug>Ve64>vt@ZlM!Cnonu#qX`EqfHXbH;<0PtUchyTrHdWV+a!eLFfxTMQpMU?mD*0eS-cu+y?`^|sI7g~qlzSNDf?%@?}Ir#zoJ}k%36ZtN+peMYA#=XN1jXi-4jlF_9m%EBz Hb}r8V=qjtp literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/toolbar.raw b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/pix/toolbar.raw new file mode 100644 index 0000000000000000000000000000000000000000..e8fd0bec684756b409f54d17e4bad34712fde65f GIT binary patch literal 2424 zcmb`{PiP!v7zXfnW_GuOq-IN7h)~FO8$pVJ{vnNmvSaL_-aIrXFF^#o2wv)`?M`#b zu`M3jLuoF8M2ZK|OO08qXb!Cf!IO=N6!f5&+ECh<-TC@F&$pY-vRg@MC*;SIcfWt{ z%w)|vSB&ty(H%Yd`he==5yvcEr>`8KdsN>kD>)P8DR}{wf)XrF2Wf1D_bkEOA!$}Y zjxsvv&cb1LOEy$VVU!uf)v@lJd!R}$oiX|GTgs_%uQLrgv6p*!t5xQMKhOd8V$ljU z-=nvpiVPg{HrIfIZe>$n@t^&ZVUE)R#uSZ)_`$v@4U+&y4H_nVlfy*28}GoDdcn@v3-7EPlYh}@l7?4vc{P`P z{e&tTbXd9iIrBcvozOaO{=&*M>j$EH@a4gG;J!m&uzpP=O(SiLmG(*esn7+lPA?AE z9qah7@;^QL`kLyCO^zQwOn#>dT+X?md|AE^*Ryq)YX3e4$MH$}+#EhicTXmp zxj4ysI7ji@QL&3o7x|8!FxOoj9i6Vx`QLEbwo6OQKfOxV*o$ip!&LkCQ>QJqyO_n9 zeGb)KppJ5L6}x!KUT))r&Mo!m>uaiClcO~CBfn){Ijy?;h%3Mae2>{g#pZvq!eF1yufP(fgXUdUg5#o(PYW>RcB`&cBt~xsmh7 z`sv4bHN1;Hz0|VW9m`w`ySH6scH^wOjb a memory-display window based on scrollwin + +OPT MODULE + +MODULE 'class/sc','intuition/intuition','graphics/rastport', + 'graphics/gfxbase','graphics/text' + +EXPORT OBJECT scrollhex OF scrollwin PRIVATE + addr,font:PTR TO textfont,osx,osy +ENDOBJECT + +CONST ONELINE=50 + +PROC setmem(addr) OF scrollhex + self.addr:=addr +ENDPROC + +PROC extra_refresh(x,y,xs,ys,xoff,yoff,win:PTR TO window) OF scrollhex + DEF fx,fy,a,b,c,d,e,ad,base,r:PTR TO rastport,bot,rnum,addr:PTR TO LONG,s[200]:ARRAY,t[10]:STRING + r:=stdrast:=win.rport + fx:=self.font.xsize + fy:=self.font.ysize + SetFont(r,self.font) + base:=self.font.baseline + bot:=win.height-win.borderbottom-1 + r.mask:=1 + IF (self.osx<>xs) OR (self.osy<>ys) THEN Box(xoff,yoff,win.width-win.borderright-1,bot,0) + Colour(1) + rnum:=Bounds(Abs(xs-13)/13,1,12) + addr:=rnum*4*y+self.addr AND -2 + FOR a:=1 TO ys + StringF(s,'\z\h[8]: ',addr) + ad:=addr + FOR b:=1 TO rnum DO StrAdd(s,StringF(t,'\z\h[8] ',addr[]++)) + StrAdd(s,' "') + c:=EstrLen(s) + e:=rnum*4+c-1 + FOR b:=c TO e DO s[b]:=IF ((d:=ad[]++)>31) AND (d<127) THEN d ELSE "." + SetStr(s,e+1) + StrAdd(s,'"') + Move(r,xoff,a-1*fy+yoff+base) + Text(r,s,Min(xs,StrLen(s))) + ENDFOR + self.osx:=xs + self.osy:=ys +ENDPROC + +PROC extra_init(screen) OF scrollhex + DEF gb:PTR TO gfxbase + gb:=gfxbase + self.font:=gb.defaultfont -> needs openfont? +ENDPROC + +PROC extra_unit() OF scrollhex IS self.font.xsize, self.font.ysize +PROC extra_max() OF scrollhex IS 1,1000 diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/screg.e b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/screg.e new file mode 100644 index 0000000..86226ad --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/screg.e @@ -0,0 +1,59 @@ +-> screg.e + +OPT MODULE + +MODULE '*sctext', '*eexe' + +EXPORT OBJECT scrollreg OF scrolltext PRIVATE + txt:PTR TO LONG, frame:stackframe +ENDOBJECT + +CONST LIST_SIZE=20 + +PROC scrollreg(stackframe:PTR TO stackframe) OF scrollreg + DEF m:PTR TO LONG,x + IF (m:=List(LIST_SIZE))=NIL THEN Raise("MEM") + SetList(m,LIST_SIZE) + self.txt:=m + MapList({x},m,m,`String(13)) + IF ForAll({x},m,`x)=FALSE THEN Raise("MEM") + copyframe(stackframe,self.frame) + pokeregs(m,stackframe,self.frame) + self.settext(m,13) +ENDPROC + +PROC copyframe(st:PTR TO stackframe,old:PTR TO stackframe) + CopyMem(st,old,SIZEOF stackframe-4) + old.stack[]:=st.stack +ENDPROC + +SET C, V, Z, N, X + +CONST S=$2000, T=$8000, I=$0E00 + +PROC pokeregs(t:PTR TO LONG,st:PTR TO stackframe,old:PTR TO stackframe) + DEF a, b, regs:PTR TO LONG + regs:=old.regs + FOR a:=0 TO 7 DO StringF(t[a],'D\d=$\z\h[8]\c',a,b:=st.regs[a],IF b=regs[a] THEN " " ELSE "*") + FOR a:=0 TO 6 DO StringF(t[a+9],'A\d=$\z\h[8]\c',a,b:=st.regs[a+8],IF b=regs[a+8] THEN " " ELSE "*") + StringF(t[16],'A7=$\z\h[8]\c',b:=st.stack,IF b=old.stack[] THEN " " ELSE "*") + StringF(t[18],'PC=$\z\h[8]\c',b:=st.returnpc,IF b=old.returnpc THEN " " ELSE "*") + b:=st.status + StringF(t[19],'ST=\c\c\c\c\c\c\c\c\c\c', + IF b AND T THEN "T" ELSE " ", + IF b AND S THEN "S" ELSE " ", + IF a:=Shr(b AND I,9) THEN "I" ELSE " ", + IF a THEN "0"+a ELSE " ", + IF b AND X THEN "X" ELSE " ", + IF b AND N THEN "N" ELSE " ", + IF b AND Z THEN "Z" ELSE " ", + IF b AND V THEN "V" ELSE " ", + IF b AND C THEN "C" ELSE " ", + IF b=old.status THEN " " ELSE "*") + copyframe(st,old) +ENDPROC + +PROC refreshreg(stackframe:PTR TO stackframe) OF scrollreg + pokeregs(self.txt,stackframe,self.frame) + self.refreshwindow() +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/sctext.e b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/sctext.e new file mode 100644 index 0000000..15af3ae --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/EDBG/sctext.e @@ -0,0 +1,107 @@ +-> implementation of textscrollerwindow class, subclass of scrollwin + +OPT MODULE + +MODULE 'class/sc' +MODULE 'intuition/intuition', 'intuition/screens', + 'graphics/rastport', 'graphics/gfxbase', 'graphics/text' + +EXPORT OBJECT scrolltext OF scrollwin PRIVATE + font:PTR TO textfont + lines, cols + tlist:PTR TO LONG + ox,oy,oxs,oys + current,ocurrent,curvis +ENDOBJECT + +PROC settext(textlist,width) OF scrolltext + self.lines:=ListLen(textlist) + self.cols:=width + self.tlist:=textlist + self.current:=-1 + self.ocurrent:=-1 + self.curvis:=FALSE +ENDPROC + +PROC refreshwindow() OF scrolltext + self.ox:=0 + self.oy:=0 + self.oxs:=0 + self.oys:=0 + SUPER self.refreshwindow() +ENDPROC + +PROC getactive() OF scrolltext IS self.current + +PROC active(cur,dorefresh=TRUE) OF scrolltext + self.current:=cur + IF dorefresh THEN IF (cur=0) AND self.curvis + a:=a-self.oy*fy+yoff + ClipBlit(r,xoff,a,r,xoff,a,xs*fx,fy,$50) + self.curvis:=FALSE + ENDIF + ny:=y; nys:=ys + IF (self.ox=x) AND (self.oxs=xs) AND (self.oys=ys) + IF (a:=self.oy-y)<>0 + IF ys>Abs(a) -> only max half display + IF a>0 -> scroll up + ClipBlit(r,xoff,yoff,r,xoff,a*fy+yoff,xs*fx,(b:=ys-a)*fy,$C0) + ys:=a + bot:=a*fy+yoff-1 + ELSE -> scroll down + a:=Abs(a) + ClipBlit(r,xoff,a*fy+yoff,r,xoff,yoff,xs*fx,(b:=ys-a)*fy,$C0) + y:=y+b + yoff:=b*fy+yoff + ys:=a + ENDIF + ENDIF + ELSE + de:=FALSE + ENDIF + ENDIF + IF de + Box(xoff,yoff,win.width-win.borderright-1,bot,0) + Colour(1) + FOR a:=0 TO ys-1 + yc:=a*fy+yoff + s:=IF a+y=0 + IF (a>=ny) AND (ny+nys>a) + a:=a-y*fy+yoff + ClipBlit(r,xoff,a,r,xoff,a,xs*fx,fy,$50) + self.curvis:=TRUE + ENDIF + ENDIF + self.ox:=x + self.oy:=ny + self.oxs:=xs + self.oys:=nys + self.ocurrent:=self.current +ENDPROC + +PROC extra_init(screen:PTR TO screen) OF scrolltext + DEF gb:PTR TO gfxbase + gb:=gfxbase + self.font:=gb.defaultfont -> needs openfont? +ENDPROC + +PROC extra_unit() OF scrolltext IS self.font.xsize, self.font.ysize +PROC extra_max() OF scrolltext IS self.cols, self.lines diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/FindString13.e b/amigae33a/E_v3.3a/Src/Src/Utils/FindString13.e new file mode 100644 index 0000000..5739eef --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/FindString13.e @@ -0,0 +1,360 @@ +OPT OSVERSION=37 + +MODULE 'tools/async', + 'tools/ctype', + 'tools/easygui', + 'amigalib/lists', + 'dos/dos', + 'exec/lists', + 'exec/nodes', + 'intuition/intuition', + 'libraries/asl', + 'asl' + +ENUM ERR_NONE, ERR_ADOS, ERR_ASL, ERR_EXAM, ERR_EXNEXT, ERR_GUI, + ERR_LIB, ERR_LOCK, ERR_OPEN, ERR_PATT, ERR_QUIT, ERR_STOP, + ERR_STR, NUM_ERRS + +RAISE ERR_ADOS IF AllocDosObject()=NIL, + ERR_ASL IF AllocAslRequest()=NIL, + ERR_EXAM IF Examine()=FALSE, + ERR_LIB IF OpenLibrary()=NIL, + ERR_LOCK IF Lock()=NIL, + ERR_PATT IF ParsePattern()=-1, + ERR_PATT IF ParsePatternNoCase()=-1, + ERR_STR IF String()=NIL + +CONST MAXSTR=100, BUFFERSIZE=1000 + +CONST MAXPATT=MAXSTR*2+2 + +-> String gadgets +DEF xfindstr[MAXSTR]:STRING, xdirstr[MAXSTR]:STRING, + findstr[MAXSTR]:STRING, dirstr[MAXSTR]:STRING, + findgad, dirgad, + xfpattstr[MAXSTR]:STRING, fpattstr[MAXSTR]:STRING, fpattgad, + fpattbuff[MAXPATT]:STRING + +-> Other gadgets +DEF reslist=NIL:PTR TO lh, resgad, gogad, + xrec=TRUE, xcase=TRUE, xword=FALSE, xbrief=FALSE, + rec, case, word, brief, + xpatt=FALSE, patt, pattbuff[MAXPATT]:STRING + +-> Other globals +DEF ready=TRUE, gh=NIL:PTR TO guihandle, path[MAXSTR]:STRING, + findfunc=NIL, freq=NIL:PTR TO filerequester + +PROC main() HANDLE + StrCopy(xfpattstr, '#?') + newList(NEW reslist) + easyguiA({prog}, + [EQROWS, + findgad:=[STR,{s_ignore},'_Find:',xfindstr,MAXSTR,10,0,0,"f"], + [COLS, + [SPACEH], + [CHECK,{c_patt},'P_attern?',xpatt,TRUE,0,"a"], + [CHECK,{c_case},'_Case sensitive?',xcase,TRUE,0,"c"], + [CHECK,{c_word},'_Whole word?',xword,TRUE,0,"w"] + ], + [BAR], + [COLS, + dirgad:=[STR,{s_ignore},'_Directory:',xdirstr,MAXSTR,10,0,0,"d"], + [BUTTON,{b_pick},'Pic_k...',0,"k"] + ], + [COLS, + fpattgad:=[STR,{s_ignore},'File _Pattern:',xfpattstr,MAXSTR,5,0,0,"p"], + [CHECK,{c_rec},'_Recursive?',xrec,TRUE,0,"r"], + [CHECK,{c_brief},'_Brief output?',xbrief,TRUE,0,"b"] + ], + [BAR], + [TEXT,'Results:',NIL,FALSE,5], + resgad:=[LISTV,{l_ignore},'',25,10,reslist,FALSE,0,0], + [BAR], + [COLS, + [SPACEH], + gogad:=[BUTTON,{b_go},'_GO!',0,"g",0,FALSE], + [SPACEH], + [BUTTON,{b_stop},'_Stop',0,"s"], + [SPACEH], + [BUTTON,{b_quit},'_Quit',0,"q"], + [SPACEH] + ] + ], + [EG_GHVAR,{gh}, NIL]) +EXCEPT DO + IF reslist + freeNodes(reslist) + END reslist + ENDIF + IF freq THEN FreeAslRequest(freq) + IF aslbase THEN CloseLibrary(aslbase) +ENDPROC + +PROC s_ignore(info, str) IS 0 +PROC l_ignore(info, x) IS 0 + +-> Action functions for option gadgets +PROC c_case(info,bool) IS xcase:=bool +PROC c_word(info,bool) IS xword:=bool +PROC c_rec(info,bool) IS xrec:=bool +PROC c_brief(info,bool) IS xbrief:=bool +PROC c_patt(info,bool) IS xpatt:=bool + +PROC b_pick(info) + IF aslbase=NIL + aslbase:=OpenLibrary('asl.library', 37) + -> Only initialise once so position, path, etc. remembered. + freq:=AllocAslRequest(ASL_FILEREQUEST, + [ASLFR_WINDOW, gh.wnd, + ASLFR_TITLETEXT, 'Pick a Directory', + ASLFR_DRAWERSONLY, TRUE, + NIL]) + ENDIF + IF RequestFile(freq) THEN setstr(gh, dirgad, freq.drawer) +ENDPROC + +PROC b_go(info) + -> Only go if not already going! + IF ready + ready:=FALSE + go() + ready:=TRUE + ENDIF +ENDPROC + +PROC b_stop(info) + -> Interrupt if going + IF ready=FALSE THEN Raise(ERR_STOP) +ENDPROC + +PROC b_quit(info) IS Raise(ERR_QUIT) + +-> Copy current gadget values. +PROC copygadgets() + -> Extract the current strings from the text gadgets. + getstr(gh,findgad); getstr(gh,dirgad) + StrCopy(findstr, xfindstr); StrCopy(dirstr, xdirstr) + rec:=xrec; case:=xcase; word:=xword; brief:=xbrief + getstr(gh,fpattgad) + StrCopy(fpattstr, xfpattstr) + patt:=xpatt +ENDPROC + +-> Just scan the selected directory. +PROC go() HANDLE + DEF tmp[MAXSTR]:STRING, p + setdisabled(gh,gogad) + -> Get a copy of current gadget values. + copygadgets() + -> Not much to do if the string is empty... + IF EstrLen(findstr)=0 THEN Raise() + -> Empty the list and redisplay it. + setlistvlabels(gh, resgad, -1) + freeNodes(reslist) + setlistvlabels(gh, resgad, reslist) + IF patt + p:=IF word THEN '((#?[~A-Za-z0-9])|%)' ELSE '#?' + StrCopy(tmp, p); StrAdd(tmp, findstr); StrAdd(tmp, p) + IF case + ParsePattern(tmp, pattbuff, MAXPATT) + findfunc:={find_patt_case} + ELSE + ParsePatternNoCase(tmp, pattbuff, MAXPATT) + findfunc:={find_patt_nocase} + ENDIF + ELSEIF case + findfunc:=IF word THEN {find_word_case} ELSE {find_case} + ELSE + -> Make the findstr lowercase if ignoring case differences. + LowerStr(findstr) + findfunc:=IF word THEN {find_word_nocase} ELSE {find_nocase} + ENDIF + -> Set up pattern buffer. + ParsePatternNoCase(fpattstr, fpattbuff, MAXPATT) + scandir(dirstr) +EXCEPT DO + -> Re-enable the 'Go!' gadget. + setdisabled(gh,gogad,FALSE) + IF exception=ERR_QUIT THEN ReThrow() +ENDPROC + +-> The start of the real work. +PROC scandir(s) HANDLE + DEF lock=NIL, fib=NIL:PTR TO fileinfoblock, oldlock, len + len:=EstrLen(path) + lock:=Lock(s, ACCESS_READ) + oldlock:=CurrentDir(lock) + fib:=AllocDosObject(DOS_FIB, NIL) + -> Examine the file. + Examine(lock, fib) + IF fib.direntrytype>=0 + -> It's a directory, so examine all the files it contains. + WHILE ExNext(lock, fib) + checkgui(gh) + IF fib.direntrytype<0 + IF MatchPatternNoCase(fpattbuff, fib.filename) + scanfile(fib.filename) + ENDIF + ELSEIF rec + -> If directory then call recursively. + StrAdd(path, fib.filename); StrAdd(path, '/') + scandir(fib.filename) + SetStr(path, len) + ENDIF + ENDWHILE + IF IoErr()<>ERROR_NO_MORE_ENTRIES THEN Raise(ERR_EXNEXT) + ENDIF +EXCEPT DO + SetStr(path, len) + IF fib THEN FreeDosObject(DOS_FIB, fib) + IF lock + CurrentDir(oldlock) + UnLock(lock) + ENDIF + SELECT NUM_ERRS OF exception + CASE ERR_ADOS, ERR_EXAM, ERR_EXNEXT, ERR_LOCK + DEFAULT + ReThrow() + ENDSELECT +ENDPROC + +-> The real work. Search the file for the findstr. +PROC scanfile(file) HANDLE + DEF fh=NIL, buffer[BUFFERSIZE]:STRING, line=1 + fh:=myopen(file, OLDFILE) + WHILE myreadstr(fh, buffer) + checkgui(gh) + IF findfunc(buffer) + report(file, buffer, line) + -> Stop here if being brief. + IF brief THEN Raise() + ENDIF + INC line + ENDWHILE +EXCEPT DO + IF fh THEN myclose(fh) + IF exception<>ERR_OPEN THEN ReThrow() +ENDPROC + +-> Use as_Open from tools/async +PROC myopen(file, mode) + DEF fh + IF fh:=as_Open(file, mode, 3, 5000) + RETURN fh + ELSE + Raise(ERR_OPEN) + ENDIF +ENDPROC + +-> Close the file opened with myopen(). +PROC myclose(fh) IS as_Close(fh) + +-> Return FALSE (or NIL) if failed to read string. +PROC myreadstr(fh, s) + DEF res + IF res:=as_FGetS(fh, s, StrMax(s)) THEN SetStr(s, StrLen(s)) +ENDPROC res + +-> Try to find findstr in s (case sensitive) +PROC find_case(s) IS InStr(s, findstr)<>-1 + +-> Try to find the word findstr in s (case sensitive) +PROC find_word_case(s) + DEF i=0, len + len:=EstrLen(s) + WHILE i Try to find findstr in s (not case sensitive) +PROC find_nocase(s) IS lower_find(s, {find_case}) + +-> Try to find the word findstr in s (not case sensitive) +PROC find_word_nocase(s) IS lower_find(s, {find_word_case}) + +PROC find_patt_case(s) IS MatchPattern(pattbuff, s) +PROC find_patt_nocase(s) IS MatchPatternNoCase(pattbuff, s) + +-> Try to find after lowercasing a copy of s. +PROC lower_find(s, real_find) + DEF tmp[MAXSTR]:STRING + StrCopy(tmp, s) + LowerStr(tmp) +ENDPROC real_find(tmp) + +-> Is the bit between i and i+len a complete word in s? +PROC isword(s, i, len) + IF i>0 THEN IF isalnum(s[i-1]) THEN RETURN FALSE + RETURN isalnum(s[i+len])=FALSE +ENDPROC + +-> Report the find and update list. +PROC report(f, s, n) + setlistvlabels(gh, resgad, -1) + addNode(reslist, f, s, n) + setlistvlabels(gh, resgad, reslist) +ENDPROC + +-> Add a new node to the list. +PROC addNode(list, f, s, n) HANDLE + DEF node=NIL:PTR TO ln, len + NEW node + len:=EstrLen(path)+StrLen(f)+10 + IF brief + node.name:=String(len) + StringF(node.name, '\s\s (\d)', path, f, n) + ELSE + filter(s) + node.name:=String(len+EstrLen(s)+4) + StringF(node.name, '\s\s (\d) -> \s', path, f, n, s) + ENDIF + AddTail(list, node) +EXCEPT + IF node + IF node.name THEN DisposeLink(node.name) + END node + ENDIF + ReThrow() +ENDPROC + +-> Free a list of nodes and empty it. +PROC freeNodes(list:PTR TO lh) + DEF worknode:PTR TO ln, nextnode + worknode:=list.head -> First node. + WHILE nextnode:=worknode.succ + IF worknode.name THEN DisposeLink(worknode.name) + END worknode + worknode:=nextnode + ENDWHILE + newList(list) +ENDPROC + +-> Convert non-printing chars to " " or ".". +PROC filter(s) + WHILE s[] + IF 0=(s[] AND $60) + SELECT $E OF s[] + CASE $0 + -> Leave this alone! + CASE $8, $A, $D + -> TAB, linefeed, carriage return. + s[]:=" " + DEFAULT + s[]:="." + ENDSELECT + ENDIF + s++ + ENDWHILE +ENDPROC + + CHAR 0, '$VER:' +prog: + CHAR ' FindString 1.3', 0, 0 diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/GDU.e b/amigae33a/E_v3.3a/Src/Src/Utils/GDU.e new file mode 100644 index 0000000..42c7f63 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/GDU.e @@ -0,0 +1,234 @@ +/* Graphical Recursive Disk Usage Program, remotely based on D.e + + displays whole harddiskpartitions and the like at once on screen, + and is able to zoom in/out, display info etc. [see requester] + +*/ + +OPT OSVERSION=37 + +MODULE 'class/stack', 'tools/clonescreen', + 'dos/dosasl', 'dos/dos', 'utility', 'intuition/intuition' + +CONST MAXPATH=250 + +ENUM ER_NONE,ER_BADARGS,ER_MEM,ER_UTIL,ER_COML +ENUM ARG_DIR,NUMARGS + +RAISE ER_MEM IF New()=NIL, ERROR_BREAK IF CtrlC()=TRUE, ER_MEM IF String()=NIL + +OBJECT dir + name,size,sub,x,y,xs,ys +ENDOBJECT + +DEF dir,dirw[100]:STRING,rdargs=NIL,dirno=0,s[200]:STRING,b:PTR TO dir, + screen=NIL,font=NIL,win=NIL,xsize,ysize,depth,st:PTR TO stack + +PROC consdir(name,size,sub) IS NEW [StrCopy(String(StrLen(name)),name),size,sub]:dir + +PROC main() HANDLE + DEF args[NUMARGS]:LIST,templ,x,lock,fib:fileinfoblock,do=TRUE,code,qual,mx,my + IF EasyRequestArgs(win,[20,0,'Welcome to GraphicDiskUsage', + 'cli usage = GDU \nleft mouse = display info\nright mouse = quit\nshift left mouse = zoom in\nshift right mouse = zoom out\nctrl c = quit [while scanning dir]\n', + 'Go and Scan|Cancel'],0,NIL)=1 + NEW st.stack() + IF (utilitybase:=OpenLibrary('utility.library',37))=NIL THEN Raise(ER_UTIL) + FOR x:=0 TO NUMARGS-1 DO args[x]:=0 + templ:='DIR' + rdargs:=ReadArgs(templ,args,NIL) + IF rdargs=NIL THEN Raise(ER_BADARGS) + dir:=args[ARG_DIR] + IF dir THEN StrCopy(dirw,dir,ALL) + lock:=Lock(dirw,-2) + IF lock /* if yes, the prob. dir, else wildcard */ + IF Examine(lock,fib) AND (fib.direntrytype>0) + AddPart(dirw,'#?',100) + ENDIF + UnLock(lock) + ENDIF + screen,font:=openclonescreen('Workbench','Graphic Disk Usage ($%#!)') + win:=backdropwindow(screen,$8,$10000) + depth,xsize,ysize:=getcloneinfo(screen) + WriteF('Scanning...\n') + b:=recdir(dirw) + SetTopaz(8) + refresh() + WHILE do + WaitIMessage(win) + code:=MsgCode() + qual:=MsgQualifier() + mx:=MouseX(win); my:=MouseY(win) + IF code=MENUDOWN + IF qual AND 1 + zoomout() + ELSE + IF EasyRequestArgs(win,[20,0,'Quit?','Zure, man?','Yez|Noo'],0,NIL)=1 THEN do:=FALSE + ENDIF + ELSEIF code=SELECTDOWN + IF qual AND 1 + zoomin(mx,my) + ELSE + findxy(b,mx,my) + ENDIF + ENDIF + ENDWHILE + ENDIF +EXCEPT DO + closeclonescreen(screen,font,win) + IF rdargs THEN FreeArgs(rdargs) + IF utilitybase THEN CloseLibrary(utilitybase) + SELECT exception + CASE "SCR"; WriteF('no screen!\n') + CASE "WIN"; WriteF('no window!\n') + CASE ER_BADARGS; WriteF('Bad Arguments for GDU!\n') + CASE ER_MEM; WriteF('No mem!\n') + CASE ER_COML; WriteF('No commandline specified\n') + CASE ER_UTIL; WriteF('Could not open "utility.library" v37\n') + CASE ERROR_BREAK; WriteF('User terminated GDU\n') + CASE ERROR_BUFFER_OVERFLOW; WriteF('Internal error\n') + DEFAULT; PrintFault(exception,'Dos Error') + ENDSELECT +ENDPROC + +PROC refresh() + SetRast(stdrast,0) + dogfx(b,5,20,xsize-10,ysize-30,TRUE) +ENDPROC + +PROC recdir(dirr) HANDLE + DEF er,i:PTR TO fileinfoblock,size=0,anchor=NIL:PTR TO anchorpath, + fullpath,x,num=0,l=NIL,rl:PTR TO dir + CtrlC() + anchor:=New(SIZEOF anchorpath+MAXPATH) + anchor.breakbits:=4096 + anchor.strlen:=MAXPATH-1 + er:=MatchFirst(dirr,anchor) /* collect all strings */ + WHILE er=0 + fullpath:=anchor+SIZEOF anchorpath + i:=anchor.info + IF i.direntrytype<0 + size:=size+Shr(i.size+1023,9) + num++ + ELSE + x:=StrLen(fullpath) + IF x+5l:=NEW [l,rl] + l:=addsorted(l,rl) + ENDIF + er:=MatchNext(anchor) + ENDWHILE + IF er<>ERROR_NO_MORE_ENTRIES THEN Raise(er) + MatchEnd(anchor) + Dispose(anchor) + anchor:=NIL + INC dirno +EXCEPT + IF anchor THEN MatchEnd(anchor) + Raise(exception) +ENDPROC consdir(dirr,IF size THEN size ELSE 1,l) + +PROC addsorted(l:PTR TO LONG,d:PTR TO dir) + DEF d2:PTR TO dir,p:PTR TO LONG,c:PTR TO LONG + IF l=NIL + RETURN NEW [NIL,d] + ELSE + d2:=l[1] + IF d.size>d2.size + RETURN NEW [l,d] + ELSE + c:=l + REPEAT + p:=c; c:=c[] + UNTIL IF c THEN (d2:=c[1]) BUT d.size>d2.size ELSE TRUE + p[]:=NEW [c,d] + ENDIF + ENDIF +ENDPROC l + +PROC dogfx(b:PTR TO dir,x,y,xs,ys,isx) + DEF l:PTR TO LONG,cs=0,sb:PTR TO dir,mc,last + b.x:=x; b.y:=y; b.xs:=xs; b.ys:=ys + IF (xs>2) AND (ys>2) + Line(x,y,x+xs,y) + Line(x,y,x,y+ys) + Line(x+xs,y,x+xs,y+ys) + Line(x,y+ys,x+xs,y+ys) + l:=b.sub + WHILE l + l <=> [l,sb] + dogfx(sb,IF isx THEN Div(Mul(cs,xs),b.size)+x ELSE x, + IF isx THEN y ELSE Div(Mul(cs,ys),b.size)+y, + IF isx THEN Div(Mul(sb.size,xs),b.size) ELSE xs, + IF isx THEN ys ELSE Div(Mul(sb.size,ys),b.size), + Not(isx)) + cs:=cs+sb.size + ENDWHILE + IF isx + x:=x+xs; xs:=xs-Div(Mul(cs,xs),b.size); x:=x-xs + ELSE + y:=y+ys; ys:=ys-Div(Mul(cs,ys),b.size); y:=y-ys + ENDIF + IF ys>10 + IF xs>20 + mc:=xs-4/8 + last:=b.name+EstrLen(b.name) + WHILE (last>b.name) AND (last[]<>"/") AND (last[]<>":") DO last-- + mc:=last-mc + IF mc=b2.x + IF y>=b2.y + IF x<(b2.x+b2.xs) + IF y<(b2.y+b2.ys) THEN st.push(b) BUT (b:=b2) BUT refresh() + ENDIF + ENDIF + ENDIF + l:=l[] + ENDWHILE +ENDPROC + +PROC zoomout() + IF st.is_empty() + DisplayBeep(screen) + ELSE + b:=st.pop() + refresh() + ENDIF +ENDPROC + +PROC findxy(b:PTR TO dir,x,y) + DEF f=FALSE,l:PTR TO LONG,numsub=0 + IF x>=b.x + IF y>=b.y + IF x<(b.x+b.xs) + IF y<(b.y+b.ys) + l:=b.sub + WHILE l + f:=f OR findxy(l[1],x,y) + l:=l[] + numsub++ + ENDWHILE + IF f=FALSE + f:=TRUE + StringF(s,IF numsub THEN '\s, \d bytes [including \d subdir(s)].' ELSE '\s, \d bytes.',b.name,Shl(b.size,9),numsub) + SetWindowTitles(win,s,s) + ENDIF + ENDIF + ENDIF + ENDIF + ENDIF +ENDPROC f diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Mem.e b/amigae33a/E_v3.3a/Src/Src/Utils/Mem.e new file mode 100644 index 0000000..b35fe20 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Mem.e @@ -0,0 +1,29 @@ +/* A very small util to dump memory in a shell. + usage: MEM + + simply dumps memory in a shell, usefull for hardcore-kamikaze + debugging and the like. + + try: + 1> mem $f80000 ; only if you have a non-moved kick2.0 or better + +*/ + +PROC main() + DEF adr,a,b,radr:PTR TO LONG,c,r + adr,r:=Val(arg) + IF r=0 + WriteF('Usage: MEM \n') + ELSE + adr:=adr AND -2 /* no odd adr */ + FOR a:=0 TO 7 + radr:=a*16+adr + WriteF('$\r\z\h[8]: ',radr) + FOR b:=0 TO 3 DO WriteF('\r\z\h[8] ',radr[b]) + WriteF(' "') + c:=radr + FOR b:=0 TO 15 DO Out(stdout,IF (c[b]<32) OR (c[b]>126) THEN "." ELSE c[b]) + WriteF('"\n') + ENDFOR + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Nkript.e b/amigae33a/E_v3.3a/Src/Src/Utils/Nkript.e new file mode 100644 index 0000000..435e98f --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Nkript.e @@ -0,0 +1,71 @@ +/* Nkript.e, very simple file (de)coder + USAGE: nkript + + nkript asks for a 4 letter key, and a 3 letter pincode. + as nkript uses EOR, you may use this program to code and + decode. the key and pincode are not stored anywhere, so it + _relatively_ safe. this has the effect that if you type the + wrong key, no error is given, but the file is simply + decoded wrong. + +*/ + +MODULE 'tools/file' + +ENUM ER_NONE,ER_FILE,ER_MEM,ER_USAGE,ER_OUT,ER_ILLEGAL,ER_NONUM + +PROC main() HANDLE + DEF flen,mem=NIL,key,keyadd,file[200]:STRING,p + WriteF('Nkript (c) 1992 $#%!\n') + IF StrCmp(arg,'',1) OR StrCmp(arg,'?',2) THEN Raise(ER_USAGE) + mem,flen:=readfile(arg) + key:=readpass('key',4,FALSE) + keyadd:=readpass('pin',3,TRUE) OR 3 + WriteF('Now (de)coding "\s".\n',arg) + MOVE.L flen,D7 + LSR.L #2,D7 /* D7 = #of LONGs */ + MOVE.L key,D6 + MOVE.L keyadd,D4 + MOVE.L mem,A0 + loop: + MOVE.L D4,D5 + SUB.L D6,D5 + LSL.L #3,D6 /* random alg. D6*7+keyadd (11) */ + ADD.L D5,D6 + EOR.L D6,(A0)+ + DBRA D7,loop + SUB.L #$10000,D7 + BCC.S loop /* DBRA.L emulation */ + p:=InStr(arg,'.',0) + StrCopy(file,arg,p) + IF StrCmp(arg+p,'.nkr',ALL)=FALSE THEN StrAdd(file,'.nkr',ALL) + writefile(file,mem,flen) +EXCEPT DO + IF mem THEN freefile(mem) + SELECT exception + CASE ER_NONE; WriteF('Done.\n') + CASE "OPEN"; WriteF('Could not access file "\s" !\n',exceptioninfo) + CASE "IN"; WriteF('Could not read from file "\s" !\n',exceptioninfo) + CASE "OUT"; WriteF('Could not write to file "\s" !\n',exceptioninfo) + CASE "MEM"; WriteF('No memory for loading file!\n') + CASE ER_USAGE; WriteF('USAGE: Nkript \n') + CASE ER_ILLEGAL; WriteF('Wrong #of chars\n') + CASE ER_NONUM; WriteF('not a decimal number\n') + ENDSELECT +ENDPROC + +PROC readpass(messy,numchars,decflag) + DEF s[25]:STRING,a,t,n=0,f=1 + WriteF('\s[\d]: ',messy,numchars) + ReadStr(stdout,s) + IF EstrLen(s)<>numchars THEN Raise(ER_ILLEGAL) + IF decflag + t:=s + FOR a:=1 TO numchars + n:=n+(t[]-"0"*f) + IF (t[]<"0") OR (t[]++>"9") THEN Raise(ER_NONUM) + f:=f*10 + ENDFOR + ^s:=n + ENDIF +ENDPROC ^s diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/ShowHunk.e b/amigae33a/E_v3.3a/Src/Src/Utils/ShowHunk.e new file mode 100644 index 0000000..3403b8a --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/ShowHunk.e @@ -0,0 +1,862 @@ +/* simple hunk-dump program with 680x0 disassembler for code hunks */ + +/* + WARNING: hunk_reloc32_short and hunk_relative_reloc hunks have not been + tested. If you find a file with this type of hunk, and this program + doesn't work with it, *PLEASE* contact the program authors so fixes may + be made. +*/ + +/* bugs left: + - link disasms wrong + - bset should give with bit > 31 +*/ + +OPT OSVERSION=37 + +ENUM HUNK_UNIT=$3E7, HUNK_NAME, HUNK_CODE, HUNK_DATA, HUNK_BSS, HUNK_RELOC32, + HUNK_RELOC16, HUNK_RELOC8, HUNK_EXT, HUNK_SYMBOL, HUNK_DEBUG, + HUNK_END, HUNK_HEADER, HUNK_OVERLAY=$3F5, HUNK_BREAK, HUNK_DRELOC32, + HUNK_DRELOC16, HUNK_DRELOC8, HUNK_LIB, HUNK_INDEX, HUNK_RELOC32_S, + HUNK_REL_RELOC32 + +ENUM EXT_SYM=0, EXT_DEF, EXT_ABS, EXT_RES, EXT_NEWCOMMON, EXT_REF32=129, + EXT_COMMON, EXT_REF16, EXT_REF8, EXT_DREF32, EXT_DREF16, EXT_DREF8 + +ENUM ER_NONE,ER_FILE,ER_MEM,ER_USAGE,ER_HUNKID,ER_BREAK,ER_FILETYPE + +DEF flen,o:PTR TO LONG,mem,handle=NIL,hunkid,noreloc=TRUE,hunknr=-1,f=TRUE +DEF pc:PTR TO INT,hibyte,eleven2nine,eight,seven2six,five2three,two2zero,isize +DEF tmp,fname[256]:STRING,disasm + +PROC main() + DEF options:PTR TO LONG,rdargs + + options:=[0,0] + IF rdargs:=ReadArgs('NAME/A,DISASM/S',options,NIL) + IF options[0] THEN StrCopy(fname,options[0]) + disasm:=options[1] + FreeArgs(rdargs) + ELSE + error(ER_USAGE) + ENDIF + + PutStr('ShowHunk v2.0 Copyright (c) 1993 Jim Cooper\n') + PutStr(' Original ShowHunk v0.1 (c) 1992 $#%!\n\n') + + flen:=FileLength(fname) + handle:=Open(fname,OLDFILE) + IF (flen<1) OR (handle=NIL) + error(ER_FILE) + ELSE + mem:=New(flen) + IF mem=NIL + error(ER_MEM) + ELSE + IF Read(handle,mem,flen)<>flen THEN error(ER_FILE) ELSE process() + ENDIF + ENDIF + error(ER_NONE) +ENDPROC + +PROC process() + DEF end,type + + o:=mem + end:=o+flen + IF (o[]<>HUNK_HEADER) AND (o[]<>HUNK_UNIT) AND (o[]<>HUNK_LIB) THEN error(ER_FILETYPE) + PrintF('Hunk layout of file "\s" (\d bytes)\n\n',fname,flen) + WHILE oHUNK_UNIT) AND (hunkid<>HUNK_HEADER) AND (hunkid<>HUNK_BREAK) AND (hunkid<>HUNK_LIB) AND (hunkid<>HUNK_INDEX) + IF f + PrintF('HUNK \d',hunknr) + INC hunknr + ENDIF + f:=FALSE + ENDIF + IF type + IF type=$4000 + PutStr('\t** hunk forced to CHIP-mem\n') + ELSE + PrintF('\t** type: \d\n',type) + ENDIF + ENDIF + SELECT hunkid + CASE HUNK_UNIT; PutStr('\thunk_unit: '); name() + CASE HUNK_NAME; PutStr('\thunk_name: '); name() + CASE HUNK_CODE; + PutStr('\thunk_code') + IF disasm + PutStr('\n'); code() + ELSE + PrintF(': \d bytes\n', skip()) + ENDIF + CASE HUNK_DATA; PrintF('\thunk_data: \d bytes\n',skip()) + CASE HUNK_BSS; PrintF('\thunk_bss: \d bytes\n',Mul(o[]++,4)) + CASE HUNK_RELOC32; PutStr('\thunk_reloc32\n'); reloc(4) + CASE HUNK_RELOC16; PutStr('\thunk_reloc16\n'); reloc(4) + CASE HUNK_RELOC8; PutStr('\thunk_reloc8\n'); reloc(4) + CASE HUNK_EXT; PutStr('\thunk_ext\n'); symbol() + CASE HUNK_SYMBOL; PutStr('\thunk_symbol\n'); symbol() + CASE HUNK_DEBUG; PrintF('\thunk_debug: \d bytes\n',skip()) + CASE HUNK_END; f:=TRUE + CASE HUNK_HEADER; PutStr('\thunk_header\n'); head() + CASE HUNK_OVERLAY; PutStr('\thunk_overlay\n'); overlay() + CASE HUNK_BREAK; PutStr('\thunk_break\n'); hunknr:=1; f:=TRUE + CASE HUNK_DRELOC32; PutStr('\thunk_data-reloc32\n'); reloc(4) + CASE HUNK_DRELOC16; PutStr('\thunk_data-reloc16\n'); reloc(4) + CASE HUNK_DRELOC8; PutStr('\thunk_data-reloc8\n'); reloc(4) + CASE HUNK_LIB; PrintF('\tlibrary_hunk: \d bytes\n',Mul(o[]++,4)); hunknr:=0 + CASE HUNK_INDEX; PrintF('\tlibrary_index: \d bytes\n\n',skip()) + CASE HUNK_RELOC32_S; PutStr('\thunk_reloc32_short\n'); reloc(2); + CASE HUNK_REL_RELOC32; PutStr('\thunk_relative_reloc32\n'); reloc(4); + DEFAULT + error(ER_HUNKID) + ENDSELECT + ENDWHILE + PutStr(IF noreloc THEN '\nPosition independant code!\n' ELSE '\n') +ENDPROC + +PROC overlay() + DEF m,ts + ts:=o[]++ + PrintF('\t tablesize = \d\n',ts) + m:=o[]++-2 + PrintF('\t max. level overlay tree uses = \d\n',m) + o:=ts*4+o + hunknr:=1; f:=TRUE +ENDPROC + +PROC symbol() + DEF t,l,s,c,r + t:=Char(o); l:=Int(o+2); o:=o+4 + WHILE l + IF CtrlC() THEN error(ER_BREAK) + IF t\n') + CASE ER_HUNKID; PrintF('Illegal hunk id: $\h !\n',hunkid) + CASE ER_BREAK; PutStr('** BREAK: ShowHunk\n') + CASE ER_FILETYPE; PutStr('Not an executable or object file.\n') + ENDSELECT + CleanUp() +ENDPROC + +PROC illegal() + PrintF('\n',pc[]) +ENDPROC + +PROC opsize(bit) RETURN ListItem(["b","w","l","?"],bit) + +PROC bitsize(bit) RETURN IF bit THEN "l" ELSE "w" + +PROC immed(val) + PrintF(IF val < 16 THEN '\d' ELSE '$\h',val) +ENDPROC + +PROC ccode(val,b) RETURN ListItem([IF b THEN 'ra' ELSE 't', + IF b THEN 'sr' ELSE 'f','hi','ls','cc','cs','ne','eq','vc', + 'vs','pl','mi','ge','lt','gt','le','??'],val) + +PROC ea(mode,reg,sd) + IF mode < 5 THEN + PrintF(ListItem(['d\d','a\d','(a\d)','(a\d)+','-(a\d)'],mode),reg) + SELECT mode + CASE 5; + PutStr('(') + immed(pc[1]++) + PrintF(',a\d)',reg) + CASE 6; + tmp:=pc[1]++ + PutStr('(') + immed(tmp AND $f) + PrintF(',a\d,\s\d\s',reg, + IF tmp AND $8000 THEN 'a' ELSE 'd', + (Shr(tmp,12) AND 7), + IF tmp AND $800 THEN '.L)' ELSE '.W)') + CASE 7; + SELECT reg + CASE 0; PrintF('(\d).W',pc[1]++) + CASE 1; immed(Long(pc+2)); pc:=pc+4 /* bug! was: immed(^pc++) */ + CASE 2; + PutStr('(') + immed(pc[1]++) + PutStr(',PC)') + CASE 3; + tmp:=pc[1]++ + PutStr('(') + immed(tmp AND $f) + PrintF(',PC,\c\d\s',IF tmp AND $8000 THEN "a" ELSE "d", + (Shr(tmp,12) AND 7), + IF tmp AND $800 THEN '.L)' ELSE '.W)') + CASE 4; + IF sd + PutStr('#') + immed(IF isize=2 THEN pc[1] ELSE Long(pc+2)) + pc:=pc+isize + ELSE + PutStr('SR') + ENDIF + DEFAULT; + PutStr('') + ENDSELECT + ENDSELECT +ENDPROC + +PROC movemregs(val,predec) + DEF index,first=1,regs:PTR TO LONG + + regs:=['d0','d1','d2','d3','d4','d5','d6','d7', + 'a0','a1','a2','a3','a4','a5','a6','a7'] + + IF predec + FOR index:=15 TO 0 STEP -1 + IF val AND Shl(1,index) + IF first = 0 THEN PutStr('/') + PutStr(regs[15-index]) + first:=0 + ENDIF + ENDFOR + ELSE + FOR index:=0 TO 15 STEP 1 + IF val AND Shl(1,index) + IF first = 0 THEN PutStr('/') + PutStr(regs[index]) + first:=0 + ENDIF + ENDFOR + ENDIF +ENDPROC + +PROC code0000() + DEF c,tmp2 + + IF (eleven2nine = 7) OR (seven2six = 3) + IF (eleven2nine = 7) AND (eight = 0) + tmp:=pc[1]++ + PrintF('moves.\c\t',opsize(seven2six)) + IF Shr(tmp,11) AND 1 + ea(five2three,two2zero,1) + PrintF(',\c\d\n',IF tmp AND $8000 THEN "a" ELSE "d",Shr(tmp,12) AND 7) + ELSE + PrintF('\c\d,',IF tmp AND $8000 THEN "a" ELSE "d",Shr(tmp,12) AND 7) + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ELSEIF (eight = 0) AND (seven2six = 3) + tmp:=pc[1]++ + IF (five2three = 7) AND (two2zero = 4) + tmp2:=pc[1]++ + PrintF('cas2\td\d:d\d,d\d:d\d,\c\d:\c\d\n', + (tmp AND 7), (tmp2 AND 7), + (Shr(tmp,6) AND 7), (Shr(tmp2,6) AND 7), + IF tmp AND $8000 THEN "a" ELSE "d", (Shr(tmp,12) AND 7), + IF tmp2 AND $8000 THEN "a" ELSE "d", (Shr(tmp2,12) AND 7)) + ELSE + PrintF('cas\td\d,d\d,',tmp AND 7, Shr(tmp,6) AND 7) + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ELSE + illegal() + ENDIF + ELSE + IF five2three = 1 + PrintF('movep.\c\t',bitsize(seven2six AND 1)) + IF seven2six AND 2 + PrintF('d\d,\d(a\d)\n',eleven2nine,pc[1]++,two2zero) + ELSE + PrintF('\d(a\d),d\d\n',pc[1]++,two2zero,eleven2nine) + ENDIF + ELSEIF (eight = 1) OR ((((eleven2nine AND 3) = 0) AND (eight = 0))) + PrintF(ListItem(['btst\t','bchg\t','bclr\t','bset\t'],seven2six)) + IF eight = 1 + PrintF('d\d,',eleven2nine) + ELSE + PrintF('#\d,',pc[1]++) + ENDIF + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + IF seven2six = 3 + tmp:=pc[1]++ + PrintF('\s.\c\t',IF Shr(tmp,11) AND 1 THEN 'chk2' ELSE 'cmp2',opsize(eleven2nine)) + ea(five2three,two2zero,1) + PrintF(',\c\d\n',IF tmp AND $8000 THEN "d" ELSE "a",Shr(tmp,12) AND 3) + ELSE + c:=ListItem(['ori.','andi.','subi.','addi.',0,'eori.','cmpi.',0],eleven2nine) + IF c THEN PutStr(c) ELSE illegal() + PrintF('\c\t#',opsize(seven2six)) + immed(IF seven2six < 2 THEN pc[1]++ ELSE ^pc++) + PutStr(',') + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC code0100() + DEF subfield,bitseven,bitsix,curcode + + bitseven:=Shr(seven2six,1) + bitsix:=seven2six AND 1 + + IF pc[] = $4afa + PutStr('bgnd\n') + ELSE + IF eight = 1 + IF bitsix = 1 + PutStr('lea\t') + ea(five2three,two2zero,1) + PrintF(',a\d\n',eleven2nine) + ELSE + PutStr('chk\t') + ea(five2three,two2zero,0) + PrintF(',d\d\n',eleven2nine) + ENDIF + ELSE + subfield:=Shl(eleven2nine,1)+eight + + SELECT subfield + CASE 0; + IF seven2six = 3 + PutStr('move.w\t') + ea(five2three,two2zero,1) + PutStr(',sr\n') + ELSE + PrintF('negx.\c\t',opsize(seven2six)) + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + CASE 1; + IF seven2six = 3 + PutStr('move.w\tccr,') + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + illegal() + ENDIF + CASE 2; + PrintF('clr.\c\t',opsize(seven2six)) + ea(five2three,two2zero,0) + PutStr('\n') + CASE 4; + IF seven2six = 3 + PutStr('move.w\t') + ea(five2three,two2zero,1) + PutStr(',ccr\n') + ELSE + PrintF('neg.\c\t',opsize(seven2six)) + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + CASE 6; + IF seven2six = 3 + PutStr('move.w\tsr,') + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + PrintF('not.\c\t',opsize(seven2six)) + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + CASE 8; + IF seven2six = 0 + IF five2three = 1 + PrintF('link.l\ta\d,#-$\h\n',two2zero,0-1-^pc++) + ELSE + PutStr('nbcd\t') + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ELSEIF seven2six = 1 + IF five2three = 0 + PrintF('swap\td\d\n',two2zero) + ELSEIF five2three = 1 + PrintF('bkpt\t#\d\n',two2zero) + ELSE + PutStr('pea\t') + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ELSE + IF five2three = 0 + IF (Shl(eight,2)+seven2six) = 7 THEN PrintF('extb.l\td\d\n',two2zero) ELSE PrintF('ext.\c\td\d\n',bitsize(bitsix),two2zero) + ELSE + PrintF('movem.\c\t',bitsize(bitsix)) + movemregs(pc[1]++, IF five2three = 4 THEN 1 ELSE 0) + PutStr(',') + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ENDIF + CASE 10; + IF pc[] = $4afc + PutStr('illegal\n') + ELSE + IF seven2six = 3 + PutStr('tas\t') + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + PrintF('tst.\c\t',opsize(seven2six)) + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ENDIF + CASE 12; + tmp:=pc[1]++ + + IF (Shl(eight,2)+seven2six) < 2 + IF seven2six = 1 + PrintF('div\c',IF Shr(tmp,11) AND 1 THEN "s" ELSE "u") + IF ((Shr(tmp,10) AND 1) = 0) AND ((Shr(tmp,12) AND 7) <> (tmp AND 7)) + PutStr('l.l\t') + ea(five2three,two2zero,1) + PrintF(',d\d:d\d\n',Shr(tmp,12) AND 7,tmp AND 7) + ELSE + PutStr('.l\t') + ea(five2three,two2zero,1) + PrintF(',d\d',Shr(tmp,12) AND 7) + IF Shr(tmp,10) AND 1 THEN PrintF(':d\d',tmp AND 7) + PutStr('\n') + ENDIF + ELSE + PrintF('mul\c.l\t',IF Shr(tmp,11) AND 1 THEN "s" ELSE "u") + ea(five2three,two2zero,1) + PrintF(',d\d',Shr(tmp,12) AND 7) + IF Shr(tmp,10) AND 1 THEN PrintF(':d\d',tmp AND 7) + PutStr('\n') + ENDIF + ELSE + PrintF('movem.\c\t',bitsize(bitsix)) + ea(five2three,two2zero,0) + PutStr(',') + movemregs(tmp, IF five2three = 4 THEN 1 ELSE 0) + PutStr('\n') + ENDIF + CASE 14; + curcode:=pc[] + + SELECT curcode + CASE $4e70; + PutStr('reset\n') + CASE $4e71; + PutStr('nop\n') + CASE $4e72; + PutStr('stop\n') + CASE $4e73; + PutStr('rte\n') + CASE $4e74; + PrintF('rtd\t#\d\n',(Shl(pc[1]<32767+1,16)-pc[1]++)) + CASE $4e75; + PutStr('rts\n') + CASE $4e76; + PutStr('trapv\n') + CASE $4e77; + PutStr('rtr\n') + DEFAULT; + IF bitseven = 1 + PutStr(IF bitsix = 1 THEN 'jmp\t' ELSE 'jsr\t') + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + IF bitsix = 1 + tmp:=Shr(five2three,1) + + SELECT tmp + CASE 0; + PrintF('trap\t\d\n',(Shl((five2three AND 1),2)+two2zero)) + CASE 1; + IF five2three AND 1 + PrintF('unlk\ta\d\n',two2zero) + ELSE + PrintF('link.w\ta\d,#-$\h\n',two2zero,65536-pc[1]); pc++ + + ENDIF + CASE 2; + PrintF(IF five2three AND 1 THEN 'move\tusp,a\d\n' ELSE 'move\ta\d,usp\n',two2zero) + CASE 3; + PrintF('rtm\t\c\d\n',IF five2three AND 1 THEN "a" ELSE "d",two2zero) + ENDSELECT + ELSE + illegal() + ENDIF + ENDIF + ENDSELECT + DEFAULT; illegal() + ENDSELECT + ENDIF + ENDIF +ENDPROC + +PROC code0101() + IF seven2six < 3 + PutStr(IF eight = 1 THEN 'subq.' ELSE 'addq.') + PrintF('\c\t#\d,',opsize(seven2six),eleven2nine) + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + IF five2three = 1 + PrintF('db\s\td\d,L\z\h[8]\n', + ccode((Shl(eleven2nine,1)+eight),0), + two2zero, + pc-o-2-(Shl(pc[1]<32767+1,16)-pc[1])) + pc++ + ELSEIF five2three = 7 + PrintF('trap\s',ccode(Shl(eleven2nine,1)+eight,0)) + IF two2zero < 4 + IF two2zero AND 1 THEN PrintF('.w\t#\d',pc[1]++) ELSE PrintF('.l\t#\d',^pc++) + ENDIF + PutStr('\n') + ELSE + PrintF('s\s\t',ccode(Shl(eleven2nine,1)+eight,0)) + ea(five2three,two2zero,0) + PutStr('\n') + ENDIF + ENDIF +ENDPROC + +PROC code0110() + DEF tmp2,ctl:PTR TO LONG + + IF (pc[] AND $fffe) = $4e7a + tmp:=pc[1]++ + tmp2:= tmp AND $fff + IF tmp2 > 7 + ctl:=ListItem(['usp','vbr','caar','msp','isp','mmusr','urp','srp'],tmp2 - $800) + ELSE + ctl:=ListItem(['sfc','dfc','cacr','tc','itt0','itt1','dtt0','dtt1'],tmp2) + ENDIF + IF ctl + PutStr('movec\t') + IF pc[-1] AND 1 + PrintF('\s,\c\d\n',ctl,IF tmp AND $8000 THEN "a" ELSE "d",Shr(tmp,12) AND 7) + ELSE + PrintF('\c\d,\s\n',IF tmp AND $8000 THEN "a" ELSE "d",Shr(tmp,12) AND 7,ctl) + ENDIF + ELSE + illegal() + ENDIF + ELSE + PrintF('b\s',ccode((Shl(eleven2nine,1)+eight),1)) + tmp:=Char(pc+1) + IF tmp = 0 + PrintF('.w\tL\z\h[8]\n',pc-o-2-(Shl(pc[1]<32767+1,16)-pc[1])) + pc++ + ELSE + PrintF('.b\tL\z\h[8]\n',pc-o-2-(Shl(tmp<127+1,8)-tmp)) + ENDIF + ENDIF +ENDPROC + +PROC code1000() + IF Shr(pc[],4) AND %11111 = %10100 /* bug!: was Shr(five2three,1) = 0 */ + IF eight + IF seven2six + SELECT seven2six + CASE 1; PutStr('pack\t') + CASE 2; PutStr('unpk\t') + DEFAULT; illegal() + ENDSELECT + PrintF(IF five2three AND 1 THEN '-(a\d),-(a\d),#\d\n' ELSE 'd\d,d\d,#\d\n',two2zero,eleven2nine,pc[1]++) + ELSE + PrintF(IF five2three AND 1 THEN 'sbcd\t-(a\d),-(a\d)\n' ELSE 'sbcd\td\d,-d\d\n',two2zero,eleven2nine) + ENDIF + ELSE + illegal() + ENDIF + ELSE + IF seven2six = 3 + PutStr(IF eight = 1 THEN 'divs\t' ELSE 'divu\t') + ea(five2three,two2zero,1) + PrintF(',d\d\n',eleven2nine) + ELSE + PrintF('or.\c\t',opsize(seven2six)) + IF eight = 1 + PrintF('d\d,',eleven2nine) + ea(five2three,two2zero,0) + ELSE + ea(five2three,two2zero,1) + PrintF(',d\d',eleven2nine) + ENDIF + PutStr('\n') + ENDIF + ENDIF +ENDPROC + +PROC code1001() + IF seven2six = 3 + PrintF('suba.\c\t',bitsize(eight)) + ea(five2three,two2zero,1) + PrintF(',a\d\n',eleven2nine) + ELSE + IF (Shr(five2three,1) = 0) AND (eight = 1) + PrintF('subx.\c\t',opsize(seven2six)) + PrintF(IF five2three AND 1 THEN '-(a\d),-(a\d)\n' ELSE 'd\d,d\d\n',two2zero,eleven2nine) + ELSE + PrintF('sub.\c\t',opsize(seven2six)) + IF eight = 1 + PrintF('d\d,',eleven2nine) + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + ea(five2three,two2zero,1) + PrintF(',d\d\n',eleven2nine) + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC code1011() + IF seven2six = 3 + PrintF('cmpa.\c\t',bitsize(eight)) + ea(five2three,two2zero,1) + PrintF(',a\d\n',eleven2nine) + ELSE + IF five2three = 1 + PrintF('cmpm.\c\t(a\d)+,(a\d)+\n',opsize(seven2six),two2zero,eleven2nine) + ELSE + IF eight = 1 + PrintF('eor.\c\td\d,',opsize(seven2six),eleven2nine) + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + PrintF('cmp.\c\t',opsize(seven2six)) + ea(five2three,two2zero,1) + PrintF(',d\d\n',eleven2nine) + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC code1100() + IF seven2six = 3 + PutStr(IF eight = 1 THEN 'mulu.w\t' ELSE 'muls.w\t') + ea(five2three,two2zero,1) + PrintF(',d\d\n',eleven2nine) + ELSE + IF Shr(five2three,1) <> 0 + PrintF('and.\c\t',opsize(seven2six)) + IF eight = 1 + PrintF('d\d,',eleven2nine) + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + ea(five2three,two2zero,1) + PrintF(',d\d\n',eleven2nine) + ENDIF + ELSE + IF seven2six = 0 + PrintF(IF five2three AND 1 THEN 'abcd\t-(a\d),-(a\d)\n' ELSE 'abcd\td\d,d\d\n',two2zero,eleven2nine) + ELSE + PutStr('exg\t') + tmp:=Shl(seven2six,3)+five2three + IF tmp = 8 + PrintF('d\d,d\d\n',two2zero,eleven2nine) + ELSEIF tmp = 9 + PrintF('a\d,a\d\n',two2zero,eleven2nine) + ELSEIF tmp = 17 + PrintF('a\d,d\d\n',two2zero,eleven2nine) + ELSE + illegal() + ENDIF + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC code1101() + IF seven2six = 3 + PrintF('adda.\c\t',bitsize(eight)) + ea(five2three,two2zero,1) + PrintF(',a\d\n',eleven2nine) + ELSE + IF (Shr(five2three,1) = 0) AND (eight = 1) + PrintF('addx.\c\t',opsize(seven2six)) + PrintF(IF five2three AND 1 THEN '-(a\d),-(a\d)\n' ELSE 'd\d,d\d\n',two2zero,eleven2nine) + ELSE + PrintF('add.\c\t',opsize(seven2six)) + IF eight = 1 + PrintF('d\d,',eleven2nine) + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + ea(five2three,two2zero,1) + PrintF(',d\d\n',eleven2nine) + ENDIF + ENDIF + ENDIF +ENDPROC + +PROC code1110() + DEF subfield,tmp2 + + IF seven2six = 3 + tmp:=pc[1]++ + tmp2:=tmp AND 31 + subfield:=Shl((eleven2nine AND 3),1)+eight + PutStr(ListItem(['bftst','bfextu','bfchg','bfexts','bfclr','bfffo','bfset','bfins'],subfield)) + PutStr('\t') + IF subfield = 7 THEN PrintF('d\d,',Shr(tmp,12) AND 7) + ea(five2three,two2zero,0) + PrintF(IF Shr(tmp,11) AND 1 THEN '{d\d:' ELSE '{\d:',Shr(tmp,6) AND 31) + PrintF(IF Shr(tmp,5) AND 1 THEN 'd\d}' ELSE '\d}',IF tmp2 THEN tmp2 ELSE 32) + + IF (subfield < 7) AND (subfield AND 1) THEN PrintF(',d\d',Shr(tmp,12) AND 7) + + PutStr('\n') + ELSE + PrintF('\s\c',ListItem(['as','ls','rox','ro'],IF seven2six=3 THEN eleven2nine ELSE five2three AND 3),IF eight=1 THEN "l" ELSE "r") + IF seven2six = 3 + PutStr('\t') + ea(five2three,two2zero,0) + PutStr('\n') + ELSE + PrintF(IF five2three AND 4 THEN '.\c\td\d,d\d\n' ELSE '\c\t#\d,d\d\n',opsize(seven2six),eleven2nine,two2zero) + ENDIF + ENDIF +ENDPROC + +PROC code() + DEF number + + isize:=2 + number:=Shl(o[],2)+o+4 + pc:=o+4 + + PutStr('\n') + + WHILE (pc < number) + hibyte:=Shr(Char(pc),4) + eleven2nine:=Shr(Char(pc),1) AND 7 + eight:=Char(pc) AND 1 + seven2six:=Shr(Char(pc+1),6) AND 3 + five2three:=Shr(Char(pc+1),3) AND 7 + two2zero:=Char(pc+1) AND 7 + + IF CtrlC() THEN error(ER_BREAK) /* essential! */ + + PrintF('L\z\h[8]:',pc-o-4) /* for offsets */ + + PutStr('\t') + + IF (hibyte > 0) AND (hibyte < 4) + PutStr(IF (eight=0) AND (seven2six=1) THEN 'movea.' ELSE 'move.') + SELECT hibyte + CASE 1; PutStr('b') + CASE 2; PutStr('l'); isize:=4 + CASE 3; PutStr('w') + ENDSELECT + PutStr('\t') + ea(five2three,two2zero,1) + PutStr(',') + ea(Shl(eight,2)+seven2six,eleven2nine,0) + PutStr('\n') + isize:=2 + ELSE + SELECT hibyte + CASE 0; /* Bit Manipulation/MOVEP/immediate */ + code0000() + CASE 4; /* Miscellaneous */ + code0100() + CASE 5; /* ADDQ/SUBQ/Scc/DBcc/TRAPcc */ + code0101() + CASE 6; /* Bcc/BSR/BRA/MOVEC */ + code0110() + CASE 7; /* MOVEQ */ + PutStr('moveq\t#') + immed(Char(pc+1)) + PrintF(',d\d\n',eleven2nine) + CASE 8; /* OR/DIV/SBCD */ + code1000() + CASE 9; /* SUB/SUBA/SUBX */ + code1001() + CASE 10; /* (unassigned, reserved) */ + illegal() + CASE 11; /* CMP/EOR */ + code1011() + CASE 12; /* AND/MUL/ABCD/EXG */ + code1100() + CASE 13; /* ADD/ADDX */ + code1101() + CASE 14; /* Shift/Rotate/Bit Field */ + code1110() + CASE 15; /* Coprocessor Interface */ + illegal() + ENDSELECT + ENDIF + pc++ + ENDWHILE + + PutStr('\n') + + o:=number +ENDPROC + diff --git a/amigae33a/E_v3.3a/Src/Src/Utils/Watch.e b/amigae33a/E_v3.3a/Src/Src/Utils/Watch.e new file mode 100644 index 0000000..979787c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Utils/Watch.e @@ -0,0 +1,48 @@ +/* Watch a file by notification + +pops up a requester when a file gets modified. +USAGE: watch +EXAMPLE: run >NIL: watch >NIL: s:startup-sequence + +needs v37 + +simply "watches" a file, using the new notification system +of kick2.0. note: does not _prevent_ files from being modified, +just tells you. usefull, for example, if you're installing a new +software package, and you want to know wether the installer +does something funny to your startup-sequence or user-startup. + +note that the only way to stop watching is asctually modifying +the file. (or rebooting :-) + +*/ + +OPT OSVERSION=37 + +MODULE 'dos/notify' + +PROC main() /* make sure file is there: else we'll */ + DEF nreq:PTR TO notifyrequest,sig,task + IF (FileLength(arg)=-1) OR (arg[0]=0) /* never be notified */ + WriteF('file "\s" does not exist\n',arg) + CleanUp(10) + ENDIF + nreq:=New(SIZEOF notifyrequest) /* memory is cleared */ + IF nreq=NIL THEN RETURN 20 + sig:=AllocSignal(-1) /* we want to be signalled */ + IF sig=-1 THEN RETURN 10 + task:=FindTask(0) + nreq.name:=arg /* fill in structure */ + nreq.flags:=NRF_SEND_SIGNAL + nreq.port:=task /* union port/task */ + nreq.signalnum:=sig + IF StartNotify(nreq) + WriteF('Now watching: "\s"\n',arg) + Wait(Shl(1,sig)) + EasyRequestArgs(0,[20,0,0,'File "\s" modified!','Damn!'],0,[arg]) + EndNotify(nreq) + ELSE + WriteF('Could not watch "\s".\n',arg) + ENDIF + FreeSignal(sig) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/2ndMousePort.e b/amigae33a/E_v3.3a/Src/Src/Various/2ndMousePort.e new file mode 100644 index 0000000..69187e7 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/2ndMousePort.e @@ -0,0 +1,28 @@ +-> switches mouseports + +OPT OSVERSION=37 + +MODULE 'devices/input', 'exec/io' + +PROC main() + DEF request=NIL:PTR TO iostd,port=NIL + IF port:=CreateMsgPort() + IF request:=CreateIORequest(port,SIZEOF iostd) + IF OpenDevice('input.device',0,request,0)=0 + request.command:=IND_SETMPORT + request.data:=[1]:CHAR -> 0 for original port, 1 for joyport + request.length:=1 + DoIO(request) + CloseDevice(request) + ELSE + PutStr('Could not open input device\n') + ENDIF + DeleteIORequest(request) + ELSE + PutStr('Could not create iorequest\n') + ENDIF + DeleteMsgPort(port) + ELSE + PutStr('Could not open port\n') + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/Pi.e b/amigae33a/E_v3.3a/Src/Src/Various/Pi.e new file mode 100644 index 0000000..1236830 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/Pi.e @@ -0,0 +1,79 @@ +/* Another pi-calc program. + A good example of what optimizing using inline assembly can do: + The E source is a translation of the original C source, + which did 48 seconds on 250 decimals, the E version did 30 seconds. + Then, the innermost loop was translated to inline assembly, + this version (E+Asm) timed only 10 seconds (all on 7mhz). + Only a small part needed to be translated to assembly, + as that is where 99% of the calculation is performed */ + +DEF m,k,n,p,i,max,nr,handle,out,num[50]:STRING,a:PTR TO LONG + +PROC main() + WriteF('PI calc\n#of decimals (try 50-250): ') + ReadStr(stdout,num) + IF (nr:=Val(num,NIL))=0 THEN stop('Illegal #!\n') + WriteF('Busy ... press CtrlC to abort.\n\n') + max:=nr*16 + IF (a:=New(max))=NIL THEN stop('No mem!\n') + m:=nr + k:=m!*3.321-1! + WriteF('\d\c',k,13) + FOR n:=k TO 1 STEP -1 + a[0]:=a[0]+2 + p:=n*2+1 + MOVEQ #0,D7 /* D7=c */ + MOVE.L a,A0 /* A0=a array */ + MOVE.L m,D4 /* D4=i counter */ + MOVE.L p,D2 + MOVE.L n,D3 +l: MOVE.L D7,D0 /* this loop is hyper-optimized. */ + LSL.L #3,D0 + ADD.L D7,D0 /* the following is the original E equivalent */ + ADD.L D7,D0 + MOVE.L (A0),D1 /* c:=0 */ + MULU D3,D1 /* x:=a */ + ADD.L D1,D0 /* FOR i:=0 TO m */ + DIVU D2,D0 /* c:=10*c+(n*^x) */ + MOVE.L D0,D7 /* ^x:=c/p */ + EXT.L D0 /* c:=c-(^x*p) */ + MOVE.L D0,(A0) /* x:=x+4 */ + SWAP D7 /* ENDFOR */ + EXT.L D7 + ADDQ.L #4,A0 + DBRA D4,l + IF (n AND $F)=0 /* not every loop */ + WriteF('\d \c',n,13) + IF CtrlC() THEN stop('\n*** Calculation interrupted!\n') + ENDIF + ENDFOR + FOR i:=m TO 1 STEP -1 + IF a[i]>9 + a[i]:=a[i]-10 + a[i-1]:=a[i-1]+1 + ENDIF + ENDFOR + handle:=Open('ram:pi.txt',1006) + IF handle<>NIL + out:=SetStdOut(handle) + writenum() + SetStdOut(out) + Close(handle) + WriteF('\n\nSee ram:pi.txt for output.\n') + ELSE + WriteF('Could not open file!\n') + ENDIF + WriteF('\n') + writenum() +ENDPROC + +PROC stop(messy) + WriteF(messy) + CleanUp(5) +ENDPROC + +PROC writenum() + WriteF('pi=3.') + FOR i:=1 TO m DO WriteF('\d',a[i]) + WriteF('\n') +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/Race.e b/amigae33a/E_v3.3a/Src/Src/Various/Race.e new file mode 100644 index 0000000..5ee4461 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/Race.e @@ -0,0 +1,301 @@ +/* computer version of autorace game + + Just play it too see how it works. The objective is to + balance speed so that you drive fast without bumping into + things. If you drive too fast to be able to take a curve, + you loose. This game is easy to play on paper, too. + Apart from that you can design some nice curves with it :-) + +*/ + +OPT OSVERSION=37 + +MODULE 'tools/clonescreen', 'gadtools', 'libraries/gadtools', + 'intuition/screens', 'graphics/text', 'intuition/intuition', + 'graphics/rastport' + +CONST MAXP=10, + MAXBOUND=1000, + MAXTRAS=50000, + OFF=7 +CONST MAXAREA=MAXBOUND*5+10, + OURIDCMP=IDCMP_MENUPICK+IDCMP_MOUSEMOVE+IDCMP_MOUSEBUTTONS + +DEF xres=60,yres=40,xpixel,ypixel,xoff=20,yoff,xsize,ysize,window=NIL, + curx[MAXP]:LIST, cury[MAXP]:LIST, lastx[MAXP]:LIST, lasty[MAXP]:LIST, + players=2,curp,stat,midx,midy,pointx,pointy,p[18]:LIST, + kx1,kx2,ky1,ky2,boundary[MAXBOUND]:LIST,area[MAXAREA]:ARRAY, + ainfo:areainfo,tras:tmpras,nogreen=FALSE + +PROC main() + DEF screen=NIL:PTR TO screen,font=NIL:PTR TO textfont,depth,title,menu,visual + title:='AutoRace v0.1' + IF gadtoolsbase:=OpenLibrary('gadtools.library',37) + screen,window,font:=openscreenwindow(title) + IF screen + font:=Long(stdrast+52) + depth,xsize,ysize:=getcloneinfo(screen) + yoff:=screen.wbortop+font.ysize+1+30 + xpixel:=xsize-10-xoff/xres + ypixel:=ysize-10-yoff/yres + SetColour(screen,0,$04,$C2,$73) + SetColour(screen,1,$00,$00,$00) + SetColour(screen,2,$DF,$DF,$DF) + SetColour(screen,3,$E1,$5A,$03) + IF window + Colour(3,2) + TextF(10,20,'\d \d',xpixel,ypixel) + IF menu:=CreateMenusA([1,0,'Project',0,0,0,0, + 2,0,'New','n',0,0,0, + 2,0,'No Green','g',0,0,0, + 2,0,'Quit','q',0,0,0, + 1,0,'Players',0,0,0,0, + 2,0,'One','1',0,0,0, + 2,0,'Two','2',0,0,0, + 2,0,'Three','3',0,0,0, + 2,0,'Four','4',0,0,0, + 2,0,'Five','5',0,0,0, + 0,0,0,0,0,0,0]:newmenu,NIL) + IF visual:=GetVisualInfoA(screen,NIL) + IF LayoutMenusA(menu,visual,NIL) + IF SetMenuStrip(window,menu) + loop() + ClearMenuStrip(window) + ELSE + WriteF('Could not set menustrip!\n') + ENDIF + ELSE + WriteF('Could not layout menus!\n') + ENDIF + FreeVisualInfo(visual) + ELSE + WriteF('Could not get visual infos!\n') + ENDIF + FreeMenus(menu) + ELSE + WriteF('Could not create menus!\n') + ENDIF + ELSE + WriteF('Could not open window!\n') + ENDIF + ELSE + WriteF('Could not open screen!\n') + ENDIF + closeclonescreen(screen,font,window) + CloseLibrary(gadtoolsbase) + ELSE + WriteF('Could not open gadtools v37+\n') + ENDIF +ENDPROC + +PROC openscreenwindow(t) HANDLE + DEF s=NIL,w=NIL,f=NIL + s,f:=openclonescreen('Workbench',t,3) + w:=backdropwindow(s,OURIDCMP,$1B00) +EXCEPT +ENDPROC s,w,f + + +PROC wait4message(window:PTR TO window) + DEF mes:PTR TO intuimessage,type,infos + REPEAT + type:=0 + IF mes:=Gt_GetIMsg(window.userport) + type:=mes.class + IF type=IDCMP_MENUPICK + infos:=mes.code + IF infos=-1 THEN type:=0 + ELSEIF type=IDCMP_MOUSEBUTTONS + IF mes.code<>SELECTUP THEN type:=0 + ELSEIF type=IDCMP_REFRESHWINDOW + Gt_BeginRefresh(window) + Gt_EndRefresh(window,TRUE) + type:=0 + ENDIF + Gt_ReplyIMsg(mes) + ELSE + Wait(-1) + ENDIF + UNTIL type +ENDPROC type,infos + +ENUM NO_ACTION,SELECTING,GAME_OVER -> stat +CONST BACKC=2,FRONTC=1,PLAYERC=3,GRASSC=0 + +PROC loop() HANDLE + DEF quit=FALSE,class,infos,menu,item,rast:PTR TO rastport + ListCopy(boundary,[11,7, 24,5, 42,10, 45,16, 43,26, 39,29, 25,33, 10,30, 7,23, 6,17, 11,7]) + + rast:=stdrast + rast.aolpen:=GRASSC + ->rast.flags:=rast.flags OR RPF_AREAOUTLINE + rast.tmpras:=InitTmpRas(tras,NewM(MAXTRAS,2),MAXTRAS) + InitArea(ainfo,area,MAXAREA) + rast.areainfo:=ainfo + + resetgame() + REPEAT + IF stat=NO_ACTION THEN startselection() + class,infos:=wait4message(window) ->WaitIMessage(window) -> crashes? + SELECT class + CASE IDCMP_MENUPICK + menu:=infos AND %11111 + item:=Shr(infos AND %11111100000,5) + SELECT menu + CASE 0 + SELECT item + CASE 0; nogreen:=FALSE; resetgame() + CASE 1; nogreen:=TRUE; resetgame() + CASE 2; quit:=TRUE + ENDSELECT + CASE 1 + players:=item+1 + resetgame() + ENDSELECT + CASE IDCMP_MOUSEMOVE + IF stat SrcGen bla +1> EC bla +1> bla + +"bla.e" contains the routines for opening your interface, as well +as some routines to handle idcmpmessages, errors etc., and a dummy +"main" that just waits for one selection. here you can put in +your own code. see the commandline template how to stop SrcGen from +generating these routines. + +That's all there's to it. If you have problems, just check the +source that has been generated. + +TODO: + - check and implement all possible tags + - open screen. + - Wait4Message <-> IDCMP + - Other fonts than topaz-8 as gadgettext + - hotkey support? + - In gen of OpeWindowTaglist(): tag "AUTO_ADJUST,1," generated twice. + - does not generate code for reverse bevel boxes +*/ + +OPT OSVERSION=37 + +ENUM NONE,NOMEM,BADARGS,NOGTXLIB,LOADGUI,NOGUI,NOWINDOWS,NOFILEOUT +SET HASGADGETS,HASMENUS + +MODULE 'gtx', 'gadtoolsbox/forms', 'gadtoolsbox/gui', 'gadtoolsbox/gtxbase', + 'nofrag', 'libraries/gadtools', 'utility', 'intuition/gadgetclass', + 'intuition/intuition' + +DEF guiptr:guidata, + wlist:windowlist, + kinds:PTR TO LONG, + gttags1:PTR TO LONG,gttags2:PTR TO LONG,gatags:PTR TO LONG, + pgatags:PTR TO LONG,latags:PTR TO LONG,strtags:PTR TO LONG, + watags:PTR TO LONG, + win[100]:LIST, + infile[100]:STRING,outfile[100]:STRING, + mainf=TRUE,erf=TRUE,mesf=TRUE,layoutf=TRUE, + lastkind,wname + +PROC main() HANDLE + DEF myargs:PTR TO LONG,rdargs=NIL,chain=NIL,gbase:PTR TO gtxbase,valid=NIL + myargs:=[0,0,0,0,0] + IF (rdargs:=ReadArgs('GUIFILE/A,NOMAIN/S,NOERR/S,NOMES/S,NOLAYOUT/S',myargs,NIL))=NIL THEN Raise(BADARGS) + WriteF('Amiga E GadToolsBox SourceGenerator v0.4 (c) 1993 $#%!\n') + IF (gtxbase:=OpenLibrary('gadtoolsbox.library',0))=NIL THEN Raise(NOGTXLIB) + IF myargs[1] THEN mainf:=FALSE /* generate no PROC main() */ + IF myargs[2] THEN erf:=FALSE /* no error report function */ + IF myargs[3] THEN mesf:=FALSE /* no wait4message() */ + IF myargs[4] THEN layoutf:=FALSE /* no layout: all tags on one line */ + StrCopy(infile,myargs[0],ALL) + StrCopy(outfile,infile,ALL) + StrAdd(infile,'.gui',ALL) + StrAdd(outfile,'.e',ALL) + gbase:=gtxbase + nofragbase:=gbase.nofragbase + utilitybase:=gbase.utilitybase + IF (chain:=GetMemoryChain(4096))=NIL THEN Raise(NOMEM) + IF GtX_LoadGUIA(chain,infile,[RG_GUI,guiptr,RG_WINDOWLIST,wlist,RG_VALID,{valid},NIL]) THEN Raise(LOADGUI) + IF (valid AND VLF_GUI)=0 THEN Raise(NOGUI) + IF (valid AND VLF_WINDOWLIST)=0 THEN Raise(NOWINDOWS) + WriteF('Generating source...\n\n') + generate() + Raise(NONE) +EXCEPT + IF valid AND VLF_WINDOWLIST THEN GtX_FreeWindows(chain,wlist) + IF chain THEN FreeMemoryChain(chain,TRUE) + IF gtxbase THEN CloseLibrary(gtxbase) + IF rdargs THEN FreeArgs(rdargs) + WriteF('\s!\n',ListItem(['Done', + 'Out of Memory', + 'Bad args', + 'Could not open gadtoolsbox library', + 'Problems reading GUI file', + 'missing GUI definition', + 'missing window definitions', + 'problems while writing E source'],exception)) +ENDPROC + +PROC generate() + DEF fh + IF ( fh:=Open(outfile,NEWFILE) )=NIL THEN Raise(NOFILEOUT) + fh:=SetStdOut(fh) + initlists() + WriteF('/* E Source generated by SRCGEN v0.1 */\n\nOPT OSVERSION=37\n\n' + + 'MODULE ''gadtools'',''libraries/gadtools'',''intuition/intuition' + + ''',\n ''intuition/screens'', ''intuition/gadgetclass'', ''graphics/text''\n\n'+ + 'ENUM NONE,NOCONTEXT,NOGADGET,NOWB,NOVISUAL,OPENGT,NOWINDOW,NOMENUS\n\n') + WriteF('DEF') + checkwindows() + IF mesf THEN WriteF('\tinfos:PTR TO gadget,\n') + WriteF('\tscr:PTR TO screen,\n\tvisual=NIL,\n\toffx,offy,tattr\n\n') + genscreenstuff() + genwindows() + genmain() + Close(SetStdOut(fh)) +ENDPROC + +PROC genwindows() + DEF w:PTR TO projectwindow,wnum=0 + w:=wlist.first + WHILE w.next + wname:=w.name + lastkind:=-1 + WriteF('PROC open\swindow()\n',wname) + WriteF(' DEF g:PTR TO gadget\n') + WriteF(' IF (g:=CreateContext({\sglist}))=NIL THEN RETURN NOCONTEXT\n',wname) + gengadgets(w) + IF win[wnum] AND HASMENUS + WriteF(' IF (\smenus:=CreateMenusA([',wname) + genmenus(w.menus) + WriteF('0,0,0,0,0,0,0]:newmenu,NIL))=NIL THEN RETURN NOMENUS\n') + WriteF(' IF LayoutMenusA(\smenus,visual,NIL)=FALSE THEN RETURN NOMENUS\n',wname) + ENDIF + WriteF(' IF (\swnd:=OpenWindowTagList(NIL,',wname) + WriteF(IF layoutf THEN '\n [' ELSE '[') + createtags(w.tags) + IF win[wnum] AND HASGADGETS + WriteF('WA_GADGETS,\sglist,',wname) + IF layoutf THEN WriteF('\n ') + ENDIF + WriteF('NIL]))=NIL THEN RETURN NOWINDOW\n') + IF w.windowtext THEN gentexts(w.windowtext) + genboxes(w) + IF win[wnum] AND HASMENUS + WriteF(' IF SetMenuStrip(\swnd,\smenus)=FALSE THEN RETURN NOMENUS\n',wname,wname) + ENDIF + WriteF(' Gt_RefreshWindow(\swnd,NIL)\n',wname) + WriteF('ENDPROC\n\nPROC close\swindow()\n',wname) + IF win[wnum] AND HASMENUS + WriteF(' IF \swnd THEN ClearMenuStrip(\swnd)\n',wname,wname) + WriteF(' IF \smenus THEN FreeMenus(\smenus)\n',wname,wname) + ENDIF + WriteF(' IF \swnd THEN CloseWindow(\swnd)\n',wname,wname) + WriteF(' IF \sglist THEN FreeGadgets(\sglist)\n',wname,wname) + WriteF('ENDPROC\n\n') + w:=w.next + INC wnum + ENDWHILE +ENDPROC + +PROC gengadgets(w:PTR TO projectwindow) + DEF egl:PTR TO extgadgetlist,eng:PTR TO extnewgadget,ng:PTR TO newgadget,kind + egl:=w.gadgets; eng:=egl.first + IF eng=NIL THEN RETURN + WHILE eng.next + ng:=eng.newgadget /* offx,offy */ + kind:=eng.kind + WriteF(' IF (g:=CreateGadgetA(\s,g,',kinds[kind]) + IF layoutf THEN WriteF('\n ') + WriteF('[offx+\d,offy+\d,\d,\d,''\s'',' + + 'tattr,\d,\d,visual,0]:newgadget,', + ng.leftedge,ng.topedge,ng.width,ng.height,ng.gadgettext, + ng.gadgetid,ng.flags) + WriteF(IF layoutf THEN '\n [' ELSE '[') + createtags(eng.tags) + WriteF('NIL]))=NIL THEN RETURN NOGADGET\n') + lastkind:=kind + eng:=eng.next + ENDWHILE +ENDPROC + +PROC genmenus(eml:PTR TO extmenulist) + DEF enm:PTR TO extnewmenu,nm:PTR TO newmenu,ckey[10]:STRING + enm:=eml.first + IF enm=NIL THEN RETURN + WHILE enm.next + nm:=enm.newmenu + IF nm.commkey THEN StringF(ckey,'''\s''',nm.commkey) ELSE StrCopy(ckey,'0',ALL) + WriteF('\d,0,',nm.type) + WriteF(IF StrCmp(enm.menutitle,'NM_BARLABEL') THEN '-1' ELSE '''\s''',enm.menutitle) + WriteF(',\s,$\h,\d,\d,',ckey,nm.flags,nm.mutualexclude,nm.userdata) + IF layoutf THEN WriteF('\n ') + IF enm.items THEN genmenus(enm.items) + enm:=enm.next + ENDWHILE +ENDPROC + +PROC gentexts(i:PTR TO intuitext) + WriteF(' PrintIText(\swnd.rport,',wname) + IF layoutf THEN WriteF('\n ') + WriteF('[\d,\d,\d,\d,\d,tattr,''\s'',NIL]' + + ':intuitext,offx,offy)\n',i.frontpen,i.backpen, + i.drawmode,i.leftedge,i.topedge,i.itext) + IF i.nexttext THEN gentexts(i.nexttext) +ENDPROC + +PROC genboxes(w:PTR TO projectwindow) + DEF bl:PTR TO bevellist,bb:PTR TO bevelbox + bl:=w.boxes; bb:=bl.first + IF bb=NIL THEN RETURN + WHILE bb.next + WriteF(' DrawBevelBoxA(\swnd.rport,\d+offx,\d+offy,\d,\d,',wname,bb.left,bb.top,bb.width,bb.height) + IF layoutf THEN WriteF('\n ') + WriteF('[GT_VISUALINFO,visual,') + IF bb.flags AND BBF_RECESSED THEN WriteF('GTBB_RECESSED,1,') + WriteF('NIL])\n') + bb:=bb.next + ENDWHILE +ENDPROC + +PROC createtags(taglist) + DEF tag:PTR TO LONG,item,str1=NIL,v:PTR TO LONG,type=0 + WHILE tag:=NextTagItem({taglist}) + item:=tag[0] + IF (item>GT_TAGBASE) AND (GT_TAGBASE+65>item) + item:=item-GT_TAGBASE + IF (item>=4) AND (item<=24) + item:=item-4*2 + str1:=gttags1[item] + type:=gttags1[item+1] + ELSEIF (item>=38) AND (item<=64) + item:=item-38*2 + str1:=gttags2[item] + type:=gttags2[item+1] + ENDIF + ELSEIF (item>GA_DUMMY) AND (GA_DUMMY+25>item) + item:=item-GA_DUMMY-1*2 + str1:=gatags[item] + type:=gatags[item+1] + ELSEIF (item>PGA_DUMMY) AND (PGA_DUMMY+11>item) + item:=item-PGA_DUMMY-1*2 + str1:=pgatags[item] + type:=pgatags[item+1] + ELSEIF (item>STRINGA_DUMMY) AND (STRINGA_DUMMY+$13>item) + item:=item-STRINGA_DUMMY-1*2 + str1:=strtags[item] + type:=strtags[item+1] + ELSEIF (item>LAYOUTA_DUMMY) AND (LAYOUTA_DUMMY+25>item) + item:=item-LAYOUTA_DUMMY-1*2 + str1:=latags[item] + type:=latags[item+1] + ELSEIF (item>=$80000064) AND (item<=$80000092) + item:=item-$80000064*2 + str1:=watags[item] + type:=watags[item+1] + ENDIF + WriteF(IF str1 THEN str1 ELSE '$\h',tag[0]) + WriteF(',') + v:=tag[1] + /* 0=num, 1=(list), 2=array of text, 3=text, 4="NIL", 5="tattr", 6="visual" + 7="g/NIL", 8=(ptr to menu), 9="scr", 10="_", 11="+offx", 12="+offy" */ + SELECT type + CASE 0 + WriteF(IF (v>=-100) AND (v<=500) THEN '\d' ELSE '$\h',v) + CASE 2 + WriteF('[') + WHILE v[] + WriteF('''\s'',',v[]) + v++ + ENDWHILE + WriteF('0]') + CASE 3; WriteF('''\s''',v) + CASE 5; WriteF('tattr') + CASE 6; WriteF('visual') + CASE 7; WriteF(IF lastkind=STRING_KIND THEN 'g' ELSE 'NIL') + CASE 9; WriteF('scr') + CASE 10; WriteF('"_"') + CASE 11; WriteF('offx+\d',v) + CASE 12; WriteF('offy+\d',v) + DEFAULT; WriteF('NIL') + ENDSELECT + WriteF(',') + IF layoutf THEN WriteF('\n ') + ENDWHILE +ENDPROC + +PROC checkwindows() + DEF w:PTR TO projectwindow,wname,fl,x + w:=wlist.first + WHILE w.next + wname:=w.name + LowerStr(wname) + fl:=0 + WriteF('\t\swnd:PTR TO window,\n',wname) + x:=Long(w.menus) + IF ^x + fl:=HASMENUS + WriteF('\t\smenus,\n',wname) + ENDIF + x:=Long(w.gadgets) + IF ^x + fl:=fl OR HASGADGETS + ENDIF + WriteF('\t\sglist,\n',wname) + ListAdd(win,[fl],ALL) + w:=w.next + ENDWHILE +ENDPROC + +PROC genscreenstuff() + WriteF('PROC setupscreen()\n IF (gadtoolsbase:=OpenLibrary(''gadtools' + + '.library'',37))=NIL THEN RETURN OPENGT\n IF (scr:=LockPubScreen(''' + + 'Workbench''))=NIL THEN RETURN NOWB\n IF (visual:=GetVisualInfoA(sc' + + 'r,NIL))=NIL THEN RETURN NOVISUAL\n offy:=scr.wbortop+Int(scr.rastp' + + 'ort+58)-10\n tattr:=[''topaz.font'',8,0,0]:textattr\nENDPROC\n\nPR' + + 'OC closedownscreen()\n IF visual THEN FreeVisualInfo(visual)\n IF' + + ' scr THEN UnlockPubScreen(NIL,scr)\n IF gadtoolsbase THEN CloseLib' + + 'rary(gadtoolsbase)\nENDPROC\n\n') +ENDPROC + +PROC genmain() + DEF w:PTR TO projectwindow,wname + IF mesf + WriteF('PROC wait4message(win:PTR TO window)\n' + + ' DEF mes:PTR TO intuimessage,type\n' + + ' REPEAT\n' + + ' type:=0\n' + + ' IF mes:=Gt_GetIMsg(win.userport)\n' + + ' type:=mes.class\n' + + ' IF type=IDCMP_MENUPICK\n' + + ' infos:=mes.code\n' + + ' ELSEIF (type=IDCMP_GADGETDOWN) OR (type=IDCMP_GADGETUP)\n' + + ' infos:=mes.iaddress\n' + + ' ELSEIF type=IDCMP_REFRESHWINDOW\n' + + ' Gt_BeginRefresh(win)\n' + + ' Gt_EndRefresh(win,TRUE)\n' + + ' type:=0\n' + + ' ELSEIF type<>IDCMP_CLOSEWINDOW /* remove these if you like */\n' + + ' type:=0\n' + + ' ENDIF\n' + + ' Gt_ReplyIMsg(mes)\n' + + ' ELSE\n' + + ' WaitPort(win.userport)\n' + + ' ENDIF\n' + + ' UNTIL type\n' + + 'ENDPROC type\n\n') + ENDIF + IF erf + WriteF('PROC reporterr(er)\n DEF erlist:PTR TO LONG\n IF er\n' + + ' erlist:=[''get context'',''create gadget'',''lock wb'',''get visual' + + ' infos'',\n ''open "gadtools.library" v37+'',''open window'',''create menus'']\n' + + ' EasyRequestArgs(0,[20,0,0,''Could not \\s!'',''ok''],0,[erlist[er-1]])\n' + + ' ENDIF\nENDPROC er\n\n') + ENDIF + IF mainf + WriteF('PROC main()\n ') + WriteF(IF erf THEN 'IF reporterr(setupscreen())=0\n' ELSE 'IF setupscreen()=0\n') + w:=wlist.first + WHILE w.next + wname:=w.name + WriteF(IF erf THEN ' reporterr(open\swindow())\n' ELSE ' open\swindow()\n',wname) + WriteF(IF mesf THEN ' wait4message(\swnd)\n' ELSE ' Delay(500)\n',wname) + WriteF(' close\swindow()\n',wname) + WriteF(' IF CtrlC() THEN BRA x\n') + w:=w.next + ENDWHILE + WriteF(' ENDIF\n x: closedownscreen()\nENDPROC\n\n') + ENDIF +ENDPROC + +PROC initlists() + + kinds:=['GENERIC_KIND','BUTTON_KIND','CHECKBOX_KIND','INTEGER_KIND', + 'LISTVIEW_KIND','MX_KIND','NUMBER_KIND','CYCLE_KIND','PALETTE_KIND', + 'SCROLLER_KIND','RESERVED_KIND','SLIDER_KIND','STRING_KIND','TEXT_KIND'] + + /* GT_TAGBASE 4-23 */ + + gttags1:=['GTCB_CHECKED',0,'GTLV_TOP',0,'GTLV_LABELS',1,'GTLV_READONLY',0, + 'GTLV_SCROLLWIDTH',0,'GTMX_LABELS',2,'GTMX_ACTIVE',0,'GTTX_TEXT',3, + 'GTTX_COPYTEXT',0,'GTNM_NUMBER',0,'GTCY_LABELS',2,'GTCY_ACTIVE',0, + 'GTPA_DEPTH',0,'GTPA_COLOR',0,'GTPA_COLOROFFSET',0, + 'GTPA_INDICATORWIDTH',0,'GTPA_INDICATORHEIGHT',0,'GTSC_TOP',0, + 'GTSC_TOTAL',0,'GTSC_VISIBLE',0] + + /* GT_TAGBASE 38-64 */ + + gttags2:=['GTSL_MIN',0,'GTSL_MAX',0,'GTSL_LEVEL',0,'GTSL_MAXLEVELLEN',0, + 'GTSL_LEVELFORMAT',3,'GTSL_LEVELPLACE',0,'GTSL_DISPFUNC',4, + 'GTST_STRING',3,'GTST_MAXCHARS',0,'GTIN_NUMBER',0, + 'GTIN_MAXCHARS',0,'GTMN_TEXTATTR',5,'GTMN_FRONTPEN',0, + 'GTBB_RECESSED',0,'GT_VISUALINFO',6,'GTLV_SHOWSELECTED',7, + 'GTLV_SELECTED',0,'GT_RESERVED0',0,'GT_RESERVED1',0, + 'GTTX_BORDER',0,'GTNM_BORDER',0,'GTSC_ARROWS',0,'GTMN_MENU',8, + 'GTMX_SPACING',0,'GTMN_FULLMENU',0,'GTMN_SECONDARYERROR',4, + 'GT_UNDERSCORE',10] + + /* GA_DUMMY 1-$24 */ + + gatags:=['GA_LEFT',0,'GA_RELRIGHT',0,'GA_TOP',0,'GA_RELBOTTOM',0, + 'GA_WIDTH',0,'GA_RELWIDTH',0,'GA_HEIGHT',0,'GA_RELHEIGHT',0, + 'GA_TEXT',0,'GA_IMAGE',0,'GA_BORDER',0,'GA_SELECTRENDER',0, + 'GA_HIGHLIGHT',0,'GA_DISABLED',0,'GA_GZZGADGET',0,'GA_ID',0, + 'GA_USERDATA',0,'GA_SPECIALINFO',0,'GA_SELECTED',0, + 'GA_ENDGADGET',0,'GA_IMMEDIATE',0,'GA_RELVERIFY',0, + 'GA_FOLLOWMOUSE',0,'GA_RIGHTBORDER',0,'GA_LEFTBORDER',0, + 'GA_TOPBORDER',0,'GA_BOTTOMBORDER',0,'GA_TOGGLESELECT',0, + 'GA_SYSGADGET',0,'GA_SYSGTYPE',0,'GA_PREVIOUS',0,'GA_NEXT',0, + 'GA_DRAWINFO',0,'GA_INTUITEXT',0,'GA_LABELIMAGE',0,'GA_TABCYCLE',0] + + /* PGADUMMY, 1-$A */ + + pgatags:=['PGA_FREEDOM',0,'PGA_BORDERLESS',0,'PGA_HORIZPOT',0, + 'PGA_HORIZBODY',0,'PGA_VERTPOT',0,'PGA_VERTBODY',0,'PGA_TOTAL',0, + 'PGA_VISIBLE',0,'PGA_TOP',0,'PGA_NEWLOOK',0] + + /* STRINGA_DUMMY, 1-$13 */ + + strtags:=['STRINGA_MAXCHARS',0,'STRINGA_BUFFER',0,'STRINGA_UNDOBUFFER',0, + 'STRINGA_WORKBUFFER',0,'STRINGA_BUFFERPOS',0,'STRINGA_DISPPOS',0, + 'STRINGA_ALTKEYMAP',0,'STRINGA_FONT',0,'STRINGA_PENS',0, + 'STRINGA_ACTIVEPENS',0,'STRINGA_EDITHOOK',0,'STRINGA_EDITMODES',0, + 'STRINGA_REPLACEMODE',0,'STRINGA_FIXEDFIELDMODE',0, + 'STRINGA_NOFILTERMODE',0,'STRINGA_JUSTIFICATION',0, + 'STRINGA_LONGVAL',0,'STRINGA_TEXTVAL',0,'STRINGA_EXITHELP',0] + + /* LAYOUTA_DUMMY 1-3 */ + + latags:=['LAYOUTA_LAYOUTOBJ',0,'LAYOUTA_SPACING',0,'LAYOUTA_ORIENTATION',0] + + /* $8000000, $64-$92 */ + + watags:=['WA_LEFT',0,'WA_TOP',0,'WA_WIDTH',11,'WA_HEIGHT',12,'WA_DETAILPEN',0, + 'WA_BLOCKPEN',0,'WA_IDCMP',0,'WA_FLAGS',0,'WA_GADGETS',0, + 'WA_CHECKMARK',0,'WA_TITLE',3,'WA_SCREENTITLE',0, + 'WA_CUSTOMSCREEN',9,'WA_SUPERBITMAP',0,'WA_MINWIDTH',0, + 'WA_MINHEIGHT',0,'WA_MAXWIDTH',0,'WA_MAXHEIGHT',0,'WA_INNERWIDTH',0, + 'WA_INNERHEIGHT',0,'WA_PUBSCREENNAME',0,'WA_PUBSCREEN',0, + 'WA_PUBSCREENFALLBACK',0,'WA_WINDOWNAME',0,'WA_COLORS',0, + 'WA_ZOOM',0,'WA_MOUSEQUEUE',0,'WA_BACKFILL',0,'WA_RPTQUEUE',0, + 'WA_SIZEGADGET',0,'WA_DRAGBAR',0,'WA_DEPTHGADGET',0, + 'WA_CLOSEGADGET',0,'WA_BACKDROP',0,'WA_REPORTMOUSE',0, + 'WA_NOCAREREFRESH',0,'WA_BORDERLESS',0,'WA_ACTIVATE',0, + 'WA_RMBTRAP',0,'WA_WBENCHWINDOW',0,'WA_SIMPLEREFRESH',0, + 'WA_SMARTREFRESH',0,'WA_SIZEBRIGHT',0,'WA_SIZEBBOTTOM',0, + 'WA_AUTOADJUST',0,'WA_GIMMEZEROZERO',0,'WA_MENUHELP',0] + +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/Trees.e b/amigae33a/E_v3.3a/Src/Src/Various/Trees.e new file mode 100644 index 0000000..56d3111 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/Trees.e @@ -0,0 +1,43 @@ +/* A different style of programming in E: + working with and building large dynamic datastructures + without using the keyword PTR + + / \ + / \ + / \ + / \ / \ + /\ /\ /\ /\ +1 2 3 4 5 6 7 8 + +*/ + +PROC main() + DEF tree,a + tree:=node( + node( + node(leaf(1),leaf(2)), + node(leaf(3),leaf(4)) + ), + node( + node(leaf(5),leaf(6)), + node(leaf(7),leaf(8)) + ) + ) + WriteF('sum = \d\n',sum(tree)) + FOR a:=1 TO 10 + tree:=node(leaf(100),tree) + WriteF('sum = \d\n',sum(tree)) + ENDFOR +ENDPROC + +PROC node(l,r) IS NEW ["node",l,r] +PROC leaf(n) IS NEW ["leaf",n] + +PROC sum(t) + DEF left,right,n + IF t <=> ["node",left,right] + RETURN sum(left)+sum(right) + ELSEIF t <=> ["leaf",n] + RETURN n + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/breukfind.e b/amigae33a/E_v3.3a/Src/Src/Various/breukfind.e new file mode 100644 index 0000000..32deef6 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/breukfind.e @@ -0,0 +1,35 @@ +/* find breuk + +try: 0.14159 -> 1/7 (22/7 = pi) +try: 0.618034 -> fibonacci +try: 0.1234568 -> 10/81 + +*/ + +PROC main() + DEF br[20]:STRING,b,max=1,a,best=2.0,bst,bsta,d,s[20]:STRING,t[20]:STRING,u[20]:STRING + b:=RealVal(arg) + WriteF('Ctrl-C to stop searching for \s ...\n',RealF(s,b,7)) + WHILE CtrlC()=FALSE + bst:=2.0 + FOR a:=0 TO max + d:=dist(a!/(max!),b) + IF !d)9YJyG_=uJph_f2waF)z^P8 zz4!is=dh!Tw*9Zw!kUj+nl?SZ^fOJHkM+>&zwgmv)3e%Q;XBQN;cI^u+U*ZtP)~QR z-8|9u~+o^R;)0)*@IF@OCdi;e)H)~s9mmamh|N4ob)%_SeWllAI z>wG0>jlZGW@)7Qc5_4Ra**>k>N6$QmTYl;P++}4EU}w+3KEF2bi`S>8gTtEE-2d^v z?|w{se?G6h7k6*Wm9mrRzCWb>;KcRTG2N-0eRhyp+;fBOZ|@kfrEvI+_ln`=gvo8c zcE_9B+t+M6^0z0a)D?7%a#&^4>D|IRO%)>jmB}GvelG%FJVy>JD zxrblmgkuUO%a(4!5}Op#pxrsI#OzSGa>5ivnPZN?@BRXEp=|fK0!F4R){`uFrok-J zW^N*g-~Og<8`XH%7Exrjv~*-j=C~bJLfjxtK?Zf1g#o5}!pwV?H6=wjRX&GrTqXoF zWF~0s`7s+0;@UqA9_Et%_moL;2sTAEerOD5c}W*$PRDuLo(eXYJ4W*DpbT#J2zkop z;e?!^kXLRzG-{HU51bK2BnA#xCX7qG^Ss2nu$c5*7FiTLh>wj;&0M<4y_8?u{*SjK z{Q6$GK03d`jW&M$ucuQ$@Z?JxtIW)6%&u;DTFcHnsZmglbiJ(0A^<<=WmH73#FqcoKFM#V(9gq^2b{*RVfI&t>WOOAIWS6*$0bz9&t$-(g)+fpTJBKr{>~v*wO*{ zl!Q;A9$I=BB_a`)bw@8adbt?7WhjjsW>IcnzT_dD%`;|@G=2ZYBGYAMD%wRUf{iSR zEhVYMQHPLmNOd?7a%fg`H03XR=+>EKmsg#OAWhI=U~jMz7%w0X22_|lRdTaj;g;zN z@ay!VZn<1S(y@bN}yeoqdFxA+R&Fj^G*@i34e7hItxn*&HKM^%z3q1|36kR}-Eu7?NvkdLk z0s}rA1q;%yGC&EZUPcpg6LYcCi%}bbWE{AuLR#re=!m%1Ax^amR5k`_)e~VONlUhC zbPuhFnROlIGdAWHm6s&W5v6F9h~i%7PKEl9lZEFcI!LmUwbaBBo>Fa?4kjddX4>S6 zY*eEC{=&x)U~uyA5>8Qvu?N#628jOwC{$`Xc{KWxEAw+jeq&;6Ib%Gu$qh&^%5qAo?cL}$emsT!a&CF-K&(v zO{h^o@G{LuN+}4P`+S;W=es^~;e6Z1Gp$PPJzp9mj&I(5e{Cswu({##kbYjHEx2kiKB+(cd=T_qC@U-=y7!@9Cl64qVc!vDd~YW?uCQV29e7ud*-E04ipy9tORF}p&PWzq5?q}qY%`r1(Ycj0I}P%kveb!` QoihC|{L?ZVyP?*90Ne0JMgRZ+ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.e b/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.e new file mode 100644 index 0000000..eaba3b5 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.e @@ -0,0 +1,213 @@ +-> DokkeNou! + +OPT OSVERSION=37, PREPROCESS + +MODULE 'tools/file', 'tools/ctype' + +DEF slist:PTR TO LONG,snum,scur=0,ofh=NIL,tabwidth=8, + detailstemp[1000]:STRING,style + +PROC main() HANDLE + DEF m=NIL,l,args:PTR TO LONG,rdargs=NIL,texf[100]:STRING,x + args:=[0,0,0,0,0,0] + IF (rdargs:=ReadArgs('TEXT/A,TEXFILE,TABWIDTH/K/N,STYLE,A4/S,A4COL/S',args,NIL))=NIL THEN Raise("ARGS") + IF args[1] + texf:=args[1] + ELSE + IF (x:=InStr(args[0],'.'))<1 THEN x:=ALL + StrCopy(texf,args[0],x) + StrAdd(texf,'.tex') + ENDIF + IF args[2] THEN tabwidth:=Long(args[2]) + style:=IF args[3] THEN args[3] ELSE '' + IF args[4] THEN style:='[a4din]' + IF args[5] THEN style:='[a4din,twocolumn]' + WriteF('DokkeNou! (c) 1994 Text2Tex conversion by Wouter\n' + + 'converting "\s" to "\s"\n',args[0],texf) + m,l:=readfile(args[0]) + snum:=countstrings(m,l) + slist:=stringsinfile(m,l,snum) + IF (ofh:=Open(texf,NEWFILE))=NIL THEN Raise("OPEN") + all() +EXCEPT DO + IF rdargs THEN FreeArgs(rdargs) + IF m THEN freefile(m) + IF ofh THEN Close(ofh) + SELECT exception + CASE "ARGS"; WriteF('Bad Args!\n') + CASE "EOF"; WriteF('Done.\n') + DEFAULT; WriteF('exception: "\s" (\h), info: "\s"\n', + [exception,0],exception,IF exceptioninfo THEN exceptioninfo ELSE '') + ENDSELECT +ENDPROC + +PROC next(n) IS IF scur+n" ") AND (c<>"\t") + +PROC spaces(s) + DEF n=0 + LOOP + IF s[]=" " + n++ + ELSEIF s[]="\t" + n:=n+tabwidth + ELSE + RETURN n,s + ENDIF + s++ + ENDLOOP +ENDPROC + +PROC all() HANDLE + DEF str[3]:ARRAY OF LONG,a=0,s,d + REPEAT + s:=GETCUR + d,s:=spaces(s) + IF s[] THEN str[a++]:=s + getnext() + UNTIL a=3 + put('% generated by DokkeNou! (tm) text2tex formatting utility (c) Wouter 1994\n\n') + put('\\documentstyle') + put(style) + put('{article}\n') + put('\\title{') + put(str[0]) + put('}\n\\author{') + put(str[1]) + put('}\n\\date{') + put(str[2]) + put('}\n') + put('\\begin{document}\\maketitle\n') + process() +EXCEPT DO + putln('\\end{document}') + ReThrow() +ENDPROC + +PROC process(indent=0) + DEF s,sn,sp,spn,numblank=0 + s:=GETCUR + LOOP + s[-1]:=" " + IF s[] + IF numblank>1 THEN putln('\\vskip .0cm\\noindent ') + numblank:=0 + ELSE + numblank++ + ENDIF + sp,s:=spaces(s) + IF spic) OR isnotwhite(s[1]) + BACK +EXCEPT DO + put('\\end{itemize}\n') + ReThrow() +ENDPROC + +PROC verbatim(s) HANDLE + DEF d + put('\\begin{verbatim}\n') + REPEAT + putln(s+1) + d,s:=spaces(getnext()) + UNTIL (s[]<>">") OR isnotwhite(s[1]) + BACK +EXCEPT DO + put('\\end{verbatim}\n') + ReThrow() +ENDPROC + +PROC details(s) + DEF r + IF StrLen(s)>500 THEN RETURN 'TOO LONG' + r:=detailstemp + s,r:=dodet(s,r,0) + r[]:=0 +ENDPROC detailstemp + +PROC dorange(s,r,end,text,c) + IF iswhite(s[-2]) + AstrCopy(r,text) + r:=r+StrLen(text) + s,r:=dodet(s,r,end) + r[]++:="}" + ELSE + r[]++:=c + ENDIF +ENDPROC s,r + +PROC dodet(s,r,stop) + DEF c + WHILE c:=s[]++ + IF c=stop THEN RETURN s,r + SELECT 128 OF c + CASE "#","$","%","&","~","^","\\","{","}" ->,"|",">","<" + r[]++:="\\" + r[]++:=c + CASE "[" + s,r:=dorange(s,r,"]",'\\footnote{',c) -> footnotes + CASE "_" + IF isgraph(s[]) + s,r:=dorange(s,r,"_",'{\\em ',c) -> emphasized + ELSE + r[]++:="\\" + r[]++:=c + ENDIF + CASE "*" + s,r:=dorange(s,r,"*",'{\\bf ',c) -> bold + CASE "`" + IF iswhite(s[-2]) -> inline verbatim + AstrCopy(r,'\\verb|') + r:=r+STRLEN + WHILE ((c:=s[]++)<>"'") AND (c<>0) DO r[]++:=c + IF c=0 THEN s-- + r[]++:="|" + ELSE + r[]++:=c + ENDIF + DEFAULT -> normal chars + r[]++:=c + ENDSELECT + ENDWHILE + s-- +ENDPROC s,r diff --git a/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.tex b/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.tex new file mode 100644 index 0000000..66b8046 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.tex @@ -0,0 +1,68 @@ +% generated by DokkeNou! (tm) text2tex formatting utility (c) Wouter 1994 + +\documentstyle{article} +\title{DokkeNou} +\author{Wouter van Oortmerssen} +\date{sept '94} +\begin{document}\maketitle + + +\vskip .0cm\noindent +\section{Marvelous Introduction} + +Dokkenou is a tool that enables you to write plain text documents with +certain 'style'-guidelines, and then later convert it to a beautifully +typesetted TeX document automatically. If you don't know what TeX is, +this utility is of little use to you. + +\subsection{even better subsection} +As an example, this document is written in dokkenou-style. If you translate +this with dokkenou from .txt to .tex, you'll see what each feature does: + +\begin{verbatim} + 1> dokkenou dokkenou.txt +\end{verbatim} + +the result will be a \verb|dokkenou.tex|, which can be translated to .dvi the +usual way. Commandline options: + +\begin{verbatim} + TEXT/A,TEXFILE,TABWIDTH/K/N,STYLE,A4/S,A4COL/S: +\end{verbatim} + +If \verb|TEXFILE| isn't given, dokkenou automatically replaces the .txt in \verb|TEXT| +into .tex. \verb|TABWIDTH| is important, since dokkenou has to calculate indents +for itemize etc. default is 8. With \verb|STYLE| you can set the TeX \verb|\documentstyle|, +and with \verb|A4| and \verb|A4COL| you can set page-size to A4 (with or without columns). + +\subsubsection{features of dokkenou} + +\begin{itemize} +\item auto-line layout a la TeX, paragraph splits by two linefeeds, heavy splits by +more than two linefeeds. +\item itemize, as demonstated by this feature list. also nested: +\begin{itemize} +\item even nested +\begin{itemize} +\item sub-nested +\item no big deal +\end{itemize} +\item if indented more than encapsulating itemize, and starting with \verb|*| or \verb|-| +in toggle-mode +\item itemize automatically ends if text follows with lower indentation level. +\end{itemize} +\item chapters, sections and subsections underlined with \verb|=====|, \verb|-----| and \verb|*****| +as shown by this text +\item verbatim for blocks of text, and inline \verb|verbatim| +\begin{verbatim} + for n=1 to 10 + print n + end +\end{verbatim} +\item footnotes: A gnu \footnote{a wonderful african animal} +\item {\em emphasized} and {\bf bold} +\item usage of TeX special chars without problems: \# \$ \% \& \~ \_ \^ \{ \} +\item title/author/date (3 lines, see top of this text) +\end{itemize} + +\end{document} diff --git a/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.txt b/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.txt new file mode 100644 index 0000000..e393bb2 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/dokkenou/dokkenou.txt @@ -0,0 +1,57 @@ + + + DokkeNou + + Wouter van Oortmerssen + + sept '94 + + +Marvelous Introduction +====================== + +Dokkenou is a tool that enables you to write plain text documents with +certain 'style'-guidelines, and then later convert it to a beautifully +typesetted TeX document automatically. If you don't know what TeX is, +this utility is of little use to you. + +even better subsection +---------------------- +As an example, this document is written in dokkenou-style. If you translate +this with dokkenou from .txt to .tex, you'll see what each feature does: + +> 1> dokkenou dokkenou.txt + +the result will be a `dokkenou.tex', which can be translated to .dvi the +usual way. Commandline options: + +> TEXT/A,TEXFILE,TABWIDTH/K/N,STYLE,A4/S,A4COL/S: + +If `TEXFILE' isn't given, dokkenou automatically replaces the .txt in `TEXT' +into .tex. `TABWIDTH' is important, since dokkenou has to calculate indents +for itemize etc. default is 8. With `STYLE' you can set the TeX `\documentstyle', +and with `A4' and `A4COL' you can set page-size to A4 (with or without columns). + +features of dokkenou +******************** + +* auto-line layout a la TeX, paragraph splits by two linefeeds, heavy splits by + more than two linefeeds. +* itemize, as demonstated by this feature list. also nested: + - even nested + * sub-nested + * no big deal + - if indented more than encapsulating itemize, and starting with `*' or `-' + in toggle-mode + - itemize automatically ends if text follows with lower indentation level. +* chapters, sections and subsections underlined with `=====', `-----' and `*****' + as shown by this text +* verbatim for blocks of text, and inline `verbatim' + > for n=1 to 10 + > print n + > end +* footnotes: A gnu [a wonderful african animal] +* _emphasized_ and *bold* +* usage of TeX special chars without problems: # $ % & ~ _ ^ { } +* title/author/date (3 lines, see top of this text) + diff --git a/amigae33a/E_v3.3a/Src/Src/Various/freq.e b/amigae33a/E_v3.3a/Src/Src/Various/freq.e new file mode 100644 index 0000000..19707be --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/freq.e @@ -0,0 +1,379 @@ +/* compute frequency of words in file. read in any ascii file, and spits + the result (as table) on stdout, or process on existing freqlist + + FILE/A,SERVER/S,FREQFILE/S,ENGLISHOPTI/S,HEAVY/S + + FILE: words to process + SERVER: go into server mode + FREQFILE: expect input to be in frequency list format or just any ascii text + ENGLISHOPTI: perform merges on english words (note: needs multiple passes) + HEAVY: do heavy english opti (does more damage to semantics :-) + FREQFACTOR: minimum factor of frequency for output words in server mode [default: 100] + +*/ + +OPT REG=5,OSVERSION=37 + +MODULE 'tools/file', 'tools/exceptions', 'class/hash', 'tools/ctype', 'tools/arexx', + 'tools/constructors', 'exec/nodes', 'exec/lists' + +OBJECT hlink OF hashlink + count, sig +ENDOBJECT + +CONST NUMTOP=1000 + +DEF ght:PTR TO hashtable,pht:PTR TO hashtable, -> silly + gsize,psize, -> number of words + isheavy=FALSE,iseng=FALSE, + minsig=100,top:PTR TO lh,largest + +PROC main() HANDLE + DEF m,l,ht=NIL:PTR TO hashtable,myargs:PTR TO LONG,rdargs=NIL + myargs:=[0,0,0,0,0,0] + IF (rdargs:=ReadArgs('FILE/A,SERVER/S,FREQFILE/S,ENGLISHOPTI/S,HEAVY/S,FREQFACTOR/N',myargs,NIL))=NIL THEN Raise("ARGS") + m,l:=readfile(myargs[0]) + ght:=NEW ht.hashtable(HASH_HEAVIER) + gsize:=IF iseng:=myargs[2] THEN process_fl(m,l,ht) ELSE process(m,l,ht) + IF gsize<1 THEN gsize:=1 + isheavy:=myargs[4] + IF myargs[5] THEN minsig:=Long(myargs[5]) + IF myargs[3] THEN ht.iterate({engfilter}) + IF myargs[1] THEN server() ELSE ht.iterate({print}) +EXCEPT DO + IF rdargs THEN FreeArgs(rdargs) + report_exception() +ENDPROC + +PROC process(mem,len,ht:PTR TO hashtable,listd=NIL) + DEF p,c,a,b,h,end,hl:PTR TO hlink,numw=0,list + end:=mem+len + p:=mem + LOOP + SELECT 128 OF c:=p[]++ + CASE "\n" + IF p>end THEN RETURN numw + CASE "A" TO "Z", "a" TO "z" + IF c<="Z" THEN p[-1]:=c+32 + a:=p-1 + WHILE isalpha(c:=p[]) + IF c<="Z" THEN p[]:=c+32 + p++ + ENDWHILE + hl,h:=ht.find(a,b:=p-a) + IF hl=NIL THEN ht.add(NEW hl,h,a,b) + hl.count:=hl.count+1 + numw++ + p[]++:=0 + IF listd + ^listd:=list:=NEW [NIL,hl]:LONG + listd:=list + ENDIF + ENDSELECT + ENDLOOP +ENDPROC + +PROC process_fl(m,l,ht:PTR TO hashtable) + DEF b,h,end,hl:PTR TO hlink,v,s,numw=0 + end:=m+l + s:=m + WHILE s"\n" DO b++ + b:=b-s + hl,h:=ht.find(s,b) + IF hl=NIL THEN ht.add(NEW hl,h,s,b) + hl.count:=hl.count+v + numw:=numw+v + s:=s+b + s[]++:=0 + ENDWHILE +ENDPROC numw + +/* + ["."=checked, "*"=sem_danger, "#"=not_impl] + + safe extension optimisations: + +.. Xed X | Xe conversed +. Xied Xy crucified +. XYYed XY crammed, abhorred +.. Xing X | Xe conspiring +. Xan Xa american, an + . Xian Xy | Xia hungarian, australian +. Xier Xy copier +. Xs X conveys, as?, this? +. Xous X courageous +. Xies Xy contemporaries +. Xness X remoteness + Xy Xe argueably +.# Xly X | Xe convincingly +. Xility Xle intangibility +. Xacy Xate indelicacy + + less safe extension optimisations: + + activities -> activity -> active -> act + +* Xic X alcoholic +* Xive X | Xe constructive +** Xable X | Xe argueable +### Xial X | Xe | Xia residential +# Xtial Xce consequential +* Xism X alcoholism +* Xion X | Xe damnation, deallocation +* Xor X | Xe coordinator +# Xious Xy ceremonious +## Xant X | Xe colorant +## Xment X | Xe containment +# Xlet X booklet +.*# Xily X | Xe | Xy particularily, family? +* Xity X actuality + + not used for now: + + Xves Xfe leaves + Xer X | Xe manager? + Xward X upward, awkward?, reward? + Xar X singular? + Xss + Xibly + Xend + + safe prefix optimisations: + + unX X unacceptable -> same as "not X" + imX X imperfect, image? + inX X incoherent + + less safe prefix optimisations: + + deX X decompression + reX X rebuilt + misX X misguided + + not used for now: + + overX X overflow? + preX X prefixed? + disX X dissatisfied, discover? + upX X uproar? + superX X superimpose? + nonX X nondeterministically? + +*/ + +PROC engfilter(tl:PTR TO hlink,d) + DEF l,s,hl=NIL:PTR TO hlink,v,w,x,y,z,t[100]:STRING,min=3 ->4? + l:=tl.len + s:=tl.data + z:=s[l-1] + IF l>1 + y:=s[l-2] + IF l>2 + x:=s[l-3] + IF l>3 + w:=s[l-4] + IF l>4 THEN v:=s[l-4] + ENDIF + ENDIF + ENDIF + SELECT 128 OF z + CASE "c" + IF y="i" THEN hl:=fh(s,l-2) -> ic + CASE "d" + IF y="e" + IF x="i" -> ied + hl:=suf(t,s,l-3,'y') + ELSEIF x=w -> XXed + hl:=f(s,l-3) + ELSE -> ed + IF (hl:=f(s,l-2))=NIL THEN hl:=f(s,l-1) + ENDIF + ENDIF + CASE "e" + IF (x="i") AND (y="v") -> ive + IF (hl:=fh(s,l-3))=NIL THEN hl:=sufh(t,s,l-3,'e') + ELSEIF (w="a") AND (x="b") AND (y="l") + IF (hl:=fh(s,l-4))=NIL THEN hl:=sufh(t,s,l-4,'e') + ENDIF + CASE "g" + IF (x="i") AND (y="n") -> ing + IF (hl:=f(s,l-3))=NIL THEN hl:=suf(t,s,l-3,'e') + ENDIF + CASE "m" + IF (x="i") AND (y="s") THEN hl:=fh(s,l-3) -> ism + CASE "n" + IF y="a" + IF x="i" -> ian + IF (hl:=suf(t,s,l-3,'y'))=NIL THEN hl:=f(s,l-1) + ELSE -> an + hl:=f(s,l-1) + ENDIF + ELSEIF (y="o") AND (x="i") -> ion + IF (hl:=fh(s,l-3))=NIL THEN hl:=sufh(t,s,l-3,'e') + ENDIF + CASE "r" + IF y="o" -> or + IF (hl:=fh(s,l-2))=NIL THEN hl:=sufh(t,s,l-2,'e') + ENDIF + CASE "s" + IF (x="o") AND (y="u") -> ous + hl:=f(s,l-3) + ELSEIF (x="i") AND (y="e") -> ies + hl:=suf(t,s,l-3,'y') + ELSEIF (w="n") AND (x="e") AND (y="s") -> ness + hl:=f(s,l-4) + ELSE -> s + hl:=f(s,l-1) + ENDIF + CASE "y" + IF y="l" + IF x="i" -> ily + IF (hl:=fh(s,l-3))=NIL THEN hl:=sufh(t,s,l-3,'e') + ELSE -> ly + hl:=f(s,l-2) + ENDIF + ELSEIF (y="t") AND (x="i") + IF (v="i") AND (w="l") -> ility + hl:=suf(t,s,l-5,'le') + ELSE -> ity + hl:=fh(s,l-3) + ENDIF + ELSEIF y="c" -> acy + hl:=suf(t,s,l-2,'te') + ELSE -> y + hl:=suf(t,s,l-1,'e') + ENDIF + ENDSELECT + IF hl=NIL + min:=4 + IF IF ((x:=s[])="u") THEN s[1]="n" ELSE IF x="i" THEN -> un/in/im + ((y:=s[1])="n") OR (y="m") ELSE FALSE + hl:=f(s+2,l-2) + ENDIF + ENDIF + IF hl + IF (hl.len>=min) AND ((hl.count>1) OR (hl.count=0)) + hl.count:=hl.count+tl.count + tl.count:=0 + ENDIF + ENDIF +ENDPROC + +PROC suf(dest,src,len,suf) + StrCopy(dest,src,len) + StrAdd(dest,suf) +ENDPROC ght.find(dest,EstrLen(dest)) + +PROC f(s,l) IS ght.find(s,l) +PROC fh(s,l) IS IF isheavy THEN ght.find(s,l) ELSE NIL +PROC sufh(d,s,l,su) IS IF isheavy THEN suf(d,s,l,su) ELSE NIL + +PROC print(l:PTR TO hlink,d) + PrintF('\d[8]\t\s\n',l.count,l.data) +ENDPROC + +PROC server() + WriteF('Starting Arexx Server, port: "FREQPORT", commands: "QUIT", "FREQ"\n') + rx_HandleAll({process_msg},'FREQPORT') +ENDPROC + +PROC process_msg(s) + DEF cl,a=NIL,q=FALSE + IF (cl:=InStr(s,' '))>0 THEN a:=s+cl+1 + IF StrCmp(s,'QUIT',cl) + WriteF('Terminating server.\n') + q:=TRUE + ELSEIF StrCmp(s,'FREQ',cl) + WriteF('Processing file "\s".\n',a) + do(a) + ELSE + WriteF('Unknown Command: "\s"\n',s) + ENDIF +ENDPROC q,0,NIL + +PROC do(filename) HANDLE + DEF m=NIL,l,ht=NIL:PTR TO hashtable,list=NIL + top:=pht:=NIL + m,l:=readfile(filename) + pht:=NEW ht.hashtable(HASH_HEAVY) + psize:=process(m,l,ht,{list}) + IF psize<1 THEN psize:=1 + IF iseng THEN ht.iterate({engfilter}) + WriteF('word ratio = \d:\d\n',gsize,psize) + largest:=0 + ht.iterate({significant}) + top:=newlist() + largest:=largest/127+1 + ht.iterate({sort}) + writenewfile(list,filename) + writetop(filename) +EXCEPT DO + END top + IF pht THEN pht.end_links(SIZEOF hlink) + END pht + IF m THEN freefile(m) + report_exception() +ENDPROC + +PROC significant(phl:PTR TO hlink,d) + DEF numg=1,nump,hl:PTR TO hlink,sig + nump:=phl.count + IF hl:=ght.find(phl.data,phl.len) THEN numg:=hl.count + IF numg<1 THEN numg:=1 + IF nump<1 THEN nump:=1 + phl.sig:=sig:=Div(Div(gsize,numg),Div(psize,nump)) + IF sig>largest THEN largest:=sig +ENDPROC + +PROC sort(phl:PTR TO hlink,d) + IF phl.sig>minsig THEN Enqueue(top,newnode(NIL,phl,0,phl.sig/largest)) +ENDPROC + +PROC writenewfile(list:PTR TO LONG,fn) + DEF hl:PTR TO hlink,o:PTR TO LONG,fh,nfn[200]:STRING,numc=0 + StrCopy(nfn,fn) + StrAdd(nfn,'.sig') + IF fh:=Open(nfn,NEWFILE) + WHILE o:=list + hl:=list[1] + list:=list[] + END o[2] + IF hl.sig>minsig + IF numc+hl.len+1>78 THEN (numc:=0) BUT FputC(fh,"\n") + Fputs(fh,hl.data) + FputC(fh," ") + numc:=numc+hl.len+1 + ENDIF + ENDWHILE + FputC(fh,"\n") + Close(fh) + ELSE + WriteF('Problem opening "\s"\n',nfn) + ENDIF +ENDPROC + +PROC writetop(fn) + DEF n:PTR TO ln,o,fh,nfn[200]:STRING,hl:PTR TO hlink,num,totsig=0,f + StrCopy(nfn,fn) + StrAdd(nfn,'.top') + IF fh:=Open(nfn,NEWFILE) + n:=top.head; num:=0 + WHILE o:=n.succ + hl:=n.name; num++; EXIT num=NUMTOP; totsig:=totsig+hl.sig; n:=o + ENDWHILE + f:=totsig/num/100+1 + WriteF('tot=\d,num=\d,f=\d\n',totsig,num,f) + n:=top.head; num:=0 + WHILE o:=n.succ + hl:=n.name; num++; EXIT num=NUMTOP; VfPrintf(fh,'\s:\d\n',[hl.data,hl.sig/f]:LONG); END n; n:=o + ENDWHILE + FputC(fh,"\n") + Close(fh) + ELSE + WriteF('Problem opening "\s"\n',nfn) + ENDIF +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/huff.e b/amigae33a/E_v3.3a/Src/Src/Various/huff.e new file mode 100644 index 0000000..164d342 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/huff.e @@ -0,0 +1,112 @@ +/* huffman crunching in E + + all it does is tell you how much gain you would have had + if crunching with huffman, it doesn't actually do it. + + sorry for the messy implementation here and there +*/ + +MODULE 'tools/file' + +PROC countfreq(adr,num,freq:PTR TO LONG) + DEF a,ch,list=NIL + FOR a:=0 TO 255 DO freq[a]:=0 + FOR a:=1 TO num + ch:=adr[]++ + freq[ch]:=freq[ch]+1 + ENDFOR + FOR a:=0 TO 255 DO list:=Link(c([freq[a],a]),list) +ENDPROC Link(c([]),list) + +PROC c(l) + DEF m + IF (m:=List(ListLen(l)))=NIL THEN Raise("MEM") + ListCopy(m,l) +ENDPROC m + +PROC takelowest(list:PTR TO LONG) + DEF l:PTR TO LONG,lf=1000000000,lp + WHILE l:=Next(list) + IF l[]1 + lowest:=takelowest(trees) + low:=takelowest(trees) + Link(trees,Link(c([lowest[]+low[],lowest,low]),Next(trees))) + DEC numtrees + ENDWHILE +ENDPROC Next(trees) + +PROC writetree(tree:PTR TO LONG,off=0) + DEF a + IF ListLen(tree)=2 + IF off THEN FOR a:=1 TO off DO WriteF(' ') + WriteF('[char=\d,freq=\d]\n',tree[1],tree[]) + ELSE + writetree(tree[1],off+1) + writetree(tree[2],off+1) + ENDIF +ENDPROC + +PROC computetree(tree:PTR TO LONG,res:PTR TO LONG,bit,depth=0) + DEF a,b,r:PTR TO LONG,t,ar + IF ListLen(tree)=2 + r:=36*tree[1]+res + r[0]:=depth + ar:=bit + FOR a:=1 TO 8 + t:=0 + FOR b:=0 TO 31 DO t:=t+IF ar[]++ THEN Shl(1,b) ELSE 0 + r[a]:=t + ENDFOR + ELSE + bit[depth]:=1 + computetree(tree[1],res,bit,depth+1) + bit[depth]:=0 + computetree(tree[2],res,bit,depth+1) + ENDIF +ENDPROC + +PROC writebits(b:PTR TO LONG) + DEF a,d,e + d:=b + FOR a:=0 TO 255 + WriteF('b=\d\td=\d\t',b-d/36,b[]++) + FOR e:=0 TO 7 DO WriteF('\h[8]',b[]++) + WriteF('\n') + ENDFOR +ENDPROC + +PROC crunch(adr,num) + DEF trees, huffbits, bitarray[256]:ARRAY OF CHAR, a,freq[256]:ARRAY OF LONG,t=0 + trees:=countfreq(adr,num,freq) + trees:=optimize(trees) + ->writetree(trees) + FOR a:=0 TO 255 DO bitarray[a]:=0 + computetree(trees,huffbits:=NewR(36*256),bitarray) + ->writebits(huffbits) + FOR a:=0 TO 255 DO t:=t+Mul(freq[a],Long(a*36+huffbits)) + WriteF('%crunched(gain)=\d%\n',100-Div(Mul(Div(t,8),100),num)) +ENDPROC + +PROC main() HANDLE + DEF m,l + m,l:=readfile(arg) + WriteF('crunching file \s length \d\n',arg,l) + crunch(m,l) +EXCEPT + SELECT exception + CASE "MEM"; WriteF('No Mem!\n') + CASE "OPEN"; WriteF('No File!\n') + ENDSELECT +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/prime.e b/amigae33a/E_v3.3a/Src/Src/Various/prime.e new file mode 100644 index 0000000..b6cf13c --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/prime.e @@ -0,0 +1,4 @@ +PROC main() + DEF i=9,j=99 + WHILE i-- DO IF Mod(j,i)=0 THEN IF i-- THEN i:=j-- ELSE WriteF('\d ',j) +ENDPROC diff --git a/amigae33a/E_v3.3a/Src/Src/Various/radix.e b/amigae33a/E_v3.3a/Src/Src/Various/radix.e new file mode 100644 index 0000000..a8a29c8 --- /dev/null +++ b/amigae33a/E_v3.3a/Src/Src/Various/radix.e @@ -0,0 +1,108 @@ +/* Super fast sort program. + whereas slow methods like quicksort/mergesort use O(n * log n) methods, + radixsort is a true O(n) method. Especially for large textfiles, it is a + LOT faster than other sorters (a log order of magnitude ;-). + Radixsort uses a 256 buckets at each level to put the strings in. arrays + of buckets are only allocated when the number of strings left to sort is + large. + Radix.e reads from a file, and outputs to stdout. +*/ + +MODULE 'tools/file', 'tools/exceptions' + +DEF rad1:PTR TO LONG,radsize:PTR TO LONG + +OBJECT str + next,data +ENDOBJECT + +PROC main() HANDLE + DEF m,l,n,list + m,l:=readfile(arg) + n:=countstrings(m,l) + list:=stringsinfilenolist(m,l,n) + doradix(NEW rad1[256],NEW radsize[256],list,n) + restradix(rad1,radsize) +EXCEPT + report_exception() +ENDPROC + +PROC doradix(table:PTR TO LONG,size:PTR TO LONG,str:PTR TO LONG,num) + DEF a,s,c + FOR a:=1 TO num + s:=str[]++ + c:=s[] + table[c]:=NEW [table[c],s]:str + size[c]:=size[c]+1 + ENDFOR +ENDPROC + +PROC restradix(table:PTR TO LONG,size:PTR TO LONG,level=1) + DEF a + FOR a:=0 TO 255 DO recradix(table[]++,size[]++,level) +ENDPROC + +PROC recradix(l:PTR TO str,num,level) + DEF tab:PTR TO LONG,size:PTR TO LONG,s,c,temp:PTR TO str + IF num + IF num<20 + straight(l,num) + ELSE + NEW tab[256],size[256] + WHILE l + s:=l.data + temp:=l + l:=l.next + c:=s[level] + temp.next:=tab[c] + tab[c]:=temp + size[c]:=size[c]+1 + ENDWHILE + restradix(tab,size,level+1) + END tab[256],size[256] + ENDIF + ENDIF +ENDPROC + +PROC straight(l:PTR TO str,num) -> sort these with a silly method + DEF a,tl:PTR TO str,best:PTR TO str,fbest + fbest:=[NIL,[$7F7F7F7F,$7F7F7F7F,$7F7F7F7F,0]:LONG]:str + FOR a:=1 TO num + tl:=l + best:=fbest + WHILE tl + IF tl.data THEN IF OstrCmp(best.data,tl.data)=-1 THEN best:=tl + tl:=tl.next + ENDWHILE + IF best<>fbest + PutStr(best.data) + FputC(stdout,"\n") + best.data:=NIL + ENDIF + ENDFOR +ENDPROC + +PROC stringsinfilenolist(mem,len,max) -> to eliminate 32k strings boundary + DEF list:PTR TO LONG,l + NEW list[max] + MOVE.L list,A1 + MOVE.L max,D3 + MOVE.L mem,A0 + MOVE.L A0,D1 + ADD.L len,D1 + MOVEQ #0,D0 + MOVEQ #10,D2 +stringsl: + CMP.L D3,D0 + BPL.S done + ADDQ.L #1,D0 + MOVE.L A0,(A1)+ +findstringl: + CMP.B (A0)+,D2 + BNE.S findstringl + CLR.B -1(A0) + CMPA.L D1,A0 + BMI.S stringsl +done: + MOVE.L D0,l +ENDPROC list,l

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%0DPCc=+3U}6PKArI%Iv^+kA3mb( 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

cm5%;6ucBZ~+}>cm1>KnIBJpegIN3cQnP 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 TQSWdZDskMn)v13O@|wTDdLBAu literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/regions.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/regions.m new file mode 100644 index 0000000000000000000000000000000000000000..f3a651dd9efc8ac3c6058f0979f20cfc90963df8 GIT binary patch literal 252 zcmZ?u^><-lWq^VUFa{Tx!2~34FbMqr&%jWWnx2`TSCpDul9-pClghxr#=yeBke6Cf z!oUEO7r-jdQc#pyhC`kMXf{VueraAxF<1o`lGzLl0zg@i?LajM+d({#5Dr}eKo@bK Oy92A+7#Mg!<^TWvUy literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/rpattr.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/rpattr.m new file mode 100644 index 0000000000000000000000000000000000000000..cfe751a42b4c3c8c6cd90eef6429d817105371d7 GIT binary patch literal 200 zcmZ?u^><-lWq^VUFa{Tx!3ZRmFz_@0si1%mNB4L)f4>kQ2PDD-5pfJ~^@EDAKtx=E zd|iMd0zfrv5Rvd8&k$E%$6#-WPG*Rx6GW#FP#r5o#6L8|$J5UhAuD$R$O3F(Pg-Kq>b|u1T}_|AmmJ-njqXT1!;pMX_f=FQSi-+E{iCj z1&8yXPxU6Ad03TrZ9q%dYtre4++8IPB_AU{v(B|vG810BDQbm`tu@ZrkI@GhKz21b J$`RUQ`vW4ZQY`=g literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/sprite.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/sprite.m new file mode 100644 index 0000000000000000000000000000000000000000..ea29aadb79c59f12e563b028a6612dbde60ee5d4 GIT binary patch literal 486 zcmZ8b+e*Vg5Iu$%N(iC!!DkVFWKGg0&}2ipL469r#x~H}(nMMx)gSW{{2-yuq*<^o z%yQ;jW+sTGk4yCLTLZfT2K`^Kk4K<7w9R%`w-w;B*3|3ms?roW+;avt3^@DEZoaSQ z?UExFG4AuKTr}JPLn_`t6M4hGyaN;1ZknfdH80z;^A5;wE~|R6Y`dI6y>(#7Xz<3! zBxJw5t{DRk)dkfLMjycKWTwQVn8~r4rCFo`QijCeoOq#>@WQ|+cJvMmP99PG;jf6d zH7}>WFO(R|EEb9~pA_sjcp~v-emCV|oH2FgF$>aZT literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/text.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/text.m new file mode 100644 index 0000000000000000000000000000000000000000..e0f8ab0bf118bebbc5467b509aff0c2f80dcda7f GIT binary patch literal 1874 zcmbVM&u^P(5d9$3wW26%RZ&}2)vE1bwTIOzD^>k{2)4mNwT)%7Y4_w3jBONb5YVRC z%jQqqzh^Jm_XgwOXitlbVBXBUnR)YJYv6X(J+-<1u3q-#MOVuBRUO>iC{={t<+m>2 zX()IuqgkT4b`ViWS~NbkR(*Xpx0!e3fERj4)Oyd=2;x3RwlPCf=eVTv1Cy zwGz&nvJGrX7wqU3gXWy#G467j{rWUOsi0b69I1wvZP(Rx%n z6}o!-y^5qBPtN^3jH9)rib7A%lX#Y|LO)|6#{B39L73-BCMSy;J&P0WlmVjI^JTQP z_tD{t+Qv0R=<26cGW!}Qn+!w!%m}b>N@n~*J5T)pjg-hSk&7_ngjC|?=82v}5w5~7 zuoqEVt^HLw1HV6GM~%jg8ux2zV1xg$rTTZcRlh9tziXA}Q^P3#VB>gnylHQ2{b9R9 zk7r3K4M@lByWQkAG;)g6?* zVE6WPV2)(}u!*UT*REr%Vw82yMy7XKY02GLHRPIgJ+s%7nq_aOxkbo*LY}TQae8HE z#2TESh8-#O*UiBE%;PjLz0T<;%junB%`$I`44)jxS#2J@wQrHbYo1;cglA62>W&=b G;rbVnx_XuX literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/graphics/videocontrol.m b/amigae33a/E_v3.3a/Modules/Modules/graphics/videocontrol.m new file mode 100644 index 0000000000000000000000000000000000000000..165f324a17f5f0a6598a476acf9ec83c8d692cc3 GIT binary patch literal 1888 zcmZ{l=~fgm5QT$^D54@FA|kl&+u*MJ$#gQ%hu-YYjPk2r1-JL}k*vCvNv8+o91g?% zQn^W0rN-u^QS-|G{GEPS#D_Vh7IxLzky1Y=Nn4ajnU!^=GwYnqN^O){Cw4?EEu5`$ zYf|lOl8q}vf0bG$`eEYqUYq6~(!LzC3)R?BQ`ISj+NNmttRu>9pFl_BEc0fbZ4i48 zR*iOASGE#OTgU?DZ#^HJz*mXyfX~{p>r0SfSsPmmmt8sPiH|CcX@|P8LOANNCw5|s z2&olfkHGk>T@33Fy*`-H??E3owobCN5)WQ~8~UW8TG`Ze-nXC+wM+I}%3|IKg7;>` zl3W1a*9l~6{V|nF+Bxm=Xykk zwB><6A+t4Mse{*nJ@kzIu0?(wVZW;&lhl5z%G%lQ@`@gQvvxV55PhX1^q7c&_hALD0`uYs2!kl1Kybt&_kV}^NF{h$Fl+mUA`(Yy*DM4BUeC^=uLHO87zKN!uaHuB1h^h0M6mDi%VKgudYPg`g$MCQ6e8 zNju3~9_|mk5BLA1=gg8ctt12#bI#7r&YU^3M9i5pRu5G9{I7cH$xB8V5#QzAXvhI#tMNPkq3#F?>Aul-_k6(#Xy6>Ypp(zM9xJkPXUpJr+M z1^s)ft=x;izfO}}S3+c7B03|bmhc2Cc)DaI^K(s#a1saa3&nc7H7@L2gvGU=>XqtU z&g*9Hlie;4unP~*>t!Drh!PI;c}G0&HVodSNmk&X%vY!x&-*AAj`>$Oeq4FUiM=~Z zqCFv_k^f;6g(>&-vS3sA@nsa~-A`|6U(m$EZa&*);jQi(tPc9$R?l~lf0@&xi{D9- zg_j|YXYECrgfS~(?Z1QJW3)hfcGRD+PfA;`pU|q8-(B{MCEiXZSUy zDfOeED1uUQPywDi0D)IYrthtsEn$W~@4_rEc3B`gk_m__>k#WFvYuc0S+HdoD(_|7 zv^(mTEZA*iGPL4;_oFDm7*bLi`SWg8$?Kh^`iM7VI8LT?wiJsRV{c=I8eKmCKdPQn zTCL(kst17;wB@el+0?LB&)wt$QQcd(Ba@>llai_x`bk8brn+T`XT z@W(NgAC-4o`JqB|d~r5OkZpp!6;?dB;P=9Vu&zbN-NL`5p?mT4Hl?OQX{X!}&!`uD z@sg80^{_+#(Un~IdEf=Nfs{!6=LVi^tBANoFH-NhM|W~Tot*$Vt`VhP0!J4Q{;wY4 ztv#9xTP0|wInc;fNx31}}U;I+uF#Gs#8vnTV%=6{k z@XictGMrDBCNo0{Yj@}wC(loi67AEqJE`nGGZ;Gau{rmKmSMk{+OHKf3v{-2nbvr^ za4q945Tbo|ZjPplsbhQ7kz)g44Qel=V~<~5uI$%v>>&xsqQk6~rhWF8w)@PgwE697 z%|?zSFf(WRYt||=5XFzvCoUM%OU z(GpRP@Pq%*8_vfziz+chpX^~R_1d&8XY|H1R^zFIEI#3Bur)R(#>%Rq4(_UWy_%NH zt=;p9hr^BW*fJO1$ty@#szKM!ho7y8+FjF@30as+krQ^v_Y}Bvv4KnffK#7$Fj((^ zJxvI9vs0b5XBnf4@oyScym-Z)_gULr1?IUyx)@(cKIZwzS}msQDnd)LX`*D7C}yvA z6}GGSS-4Z4#9EZ}aGHoD$oSjWSasTq}A~c`M3*H71U$+}XH8>S^TK(SNb#3|((x zOsy&A5m&0PR_RwN6&-wpF3zTyb?q_0Y_42$UP7{~3*|T~4A){L)4|yr?CJQ`adodf z*we9I;pr{eGnt#FH)DT^De=CKwZ#t|vW!JFOWZr;_&2bFN(1Ol<#$?Xpv0)H!D@j! x9Cs$_@tD%bHmvT{Z$3GF_KKTFu literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/gtx.m b/amigae33a/E_v3.3a/Modules/Modules/gtx.m new file mode 100644 index 0000000000000000000000000000000000000000..b8db51e58ed46911896aee79c1d0e7dbedaeb2de GIT binary patch literal 493 zcma)2%TB{E5Oe{dq+I$X{6pG2h}0A*4bU6f;3bXZ+GxF{>DNQ-xb(_l4>Ovb+1adm zPQ`r(l8sTeHN&IoTLL&p9d7?nx7>SWr2e3IF zTBIm;3oCQfUSYkwGT-R+v0o_jJR@q%mPyQacauSJn{@~aePK|j5-75vrpLJQ;ZaS;RFLl1cu~u+kCYuE76d6ADYiLo~ zX)PrTwvplL+*o2_8prDOru{aY@#vtBH)dFR$LKDyZAO zf+hIpR}X7GL;&#*;5mZ4IyILjcO%dpR(LP`eS`NSzdyS=wHW}BdsZmf0_?@3ZCX3j zB`T1?hE+48%1FJ;l!zBq78mqlf_1U?a)tZqyw^h5XFpT|$^TLOZ*{O{HtQ%e*34u| zC6l_~OeW~H6902PjKy%m8uEV<)juXW9MTxmIdQwHe`Y%&59%MtLN)2+cSv1v4}t7e zW31l|RmpCMU{A-8pT2WGvhToN-$G9Z^-8Rtd8uB3(06WV^V#J4zEh2ot9ZM5EI$UB oZO0lVn12ZQW#3vOyL)C8{S1N4y%UppV0)_*Hv1(nJP&?~KMGxckN^Mx literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/hardware/blit.m b/amigae33a/E_v3.3a/Modules/Modules/hardware/blit.m new file mode 100644 index 0000000000000000000000000000000000000000..d08b9613f038ab5aa847d1cb80cf4a59f1bd540c GIT binary patch literal 1006 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/hardware/intbits.m b/amigae33a/E_v3.3a/Modules/Modules/hardware/intbits.m new file mode 100644 index 0000000000000000000000000000000000000000..74bf73f76a8b0f7fab0491f7762f6b05a12d3540 GIT binary patch literal 594 zcmYk2Yfi&35QI0Og;GlC5qbi|;{wHrEmaLkl^6uSe3c%NBQdj!9U?{Y%zQiR#J>-% zEamU{$%nNbDv|n8HaPE(eGKW-kI_NVS;BF}*^2B$nRYr&-+coDo@|twJx=bFYlgEQ zN#I>5l^xE}327Qa!~vRKt<>z{jw{iB__Pg$6yDBBJ!Z!`WY>Nk?0<7PtcRcC^&EA2QBW1Or-u9W%b zT&#EUvFY&hIQ5`RcDU)HJ#QcFlYP&P5=B?m0sU+__qtScUGf*pZ*y*XQSw*I*ExsA F^9%EBWW)df literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/icon.m b/amigae33a/E_v3.3a/Modules/Modules/icon.m new file mode 100644 index 0000000000000000000000000000000000000000..e68fd7f358e7491a5393e8af54ed8c00e84f3619 GIT binary patch literal 227 zcmY+8K?}k#425%&bf^9$rA`FrM27dRjaaSgu&v^+*9JuEA&~F!US5_>t6&CJ`*G+4 zfs`wX>r5!BUHWYGjfiJsLqsX(#(YUs*{^K4w8NQn#GENeu&?0Sj;8b8bq^l2+4 z+0LQ%XDG40^U?l5hC^X{sn#iBmb60_7R%KO&&7QkB2TG8%>6?6En-wqk75zAnGD$$ zl$_Q7#|eiXx|kx4D>)k>7MqNpk1L7sMU(ZbJln)A|#dTO53l8I$P7hQ_go6e{SFE0v^B~ z4!x!U_j*8hbS`vNS#Ihc{q!nmM2jeQ;etxS$m~#?{5blrr!(WAGWa0N_=icB9d?0? zm{yDHhHS>+7=J2Q-8G@V;LX-EonN#!4oQ@3y**j}Lo_tIVU@5HYIzY779kJLVaGQ3 zx#B-&{#|>iHq|YyHtD*7WM!D literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/input.m b/amigae33a/E_v3.3a/Modules/Modules/input.m new file mode 100644 index 0000000000000000000000000000000000000000..561071cd9b33ab18ea5ec14e201913057ef5971a GIT binary patch literal 37 scmZ?u^><-lW5~=aC@o1!EKX$*5C}+3%?>P0%*jm4Of3@l&%nR{0MGLaO#lD@ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition.m b/amigae33a/E_v3.3a/Modules/Modules/intuition.m new file mode 100644 index 0000000000000000000000000000000000000000..fb8cff94f8228634d54d3d85cb535405cd2266a4 GIT binary patch literal 1875 zcmZWq+j8PK5S25@mJBccB^#5(RbgO(-Bj(Hu-l-)NFG@ZVSj$NTNem3Jn1x2UrwKH z&lk&*{lTQNqqI`1ofv>Edr(!hWY-hVo90C{d$2rZvkrtQ7i;)A!eF_B3sB?68rgfe z(&!cp0zJT{HUP?>-=%8wIh?gQ7NF`wHXDrrWw-JKJT2wWcjA(FU@YTFfCWI$OFiy7 zn02x~vgF}gX~enErolidO9)jbu}2pynX4w|m%e~4pCO0chEs);e;b*OW!z++_J^^|kiNlpGbXmnv|_i&1vX<}%#h zaZ+*Qa`uc${c>R;jYz_7x)iJ`n>vWAb;Iu<2u_W*GLA+xpU9OzG-u`{l z^|2~w*#1)Z%%3^x(l@9SR-lVCHvCQEjG^#o0{xjKvH1b#wUr;j#x{hPp44X}aH!&q zD3{51ID3(Q)%DY#Bbdwb1I$nhg{r%0yHbwgWy{mqL8yI*Rp`&yuX!WwtJbJ9)Dr0s zosGcRKeG3ka4LK??t<=p@i&~_{Y{l+zg%&)@2G??k1!a{wivrFMv`v~gGIu?u5e?8 z9Z_P-ofT5ORBI9_&I@j|0V4Dyxf+o8%&(985OXnHf{Jppr-_(4as6gzQ!l4ip&DFh z$mwm~w_@)bNTx8I(R5vAl(E}r4-+?&m2x|d@wvg2ulo-Bx!nDL+UA%G$rAUjH&8!v zYt4ZFU@3HDoJQQ28ULD0iP`WZBjL|FfxD1a9!k%Hn@DNbs#ZH`2i-;!DtEYBCw^0T z4>St?l!c$09q*zT+tzX9#?XB=qRETy{#u9&J#Gb-dbHAm`??G&Nz|Rrr`A8$b|tms{5 ztP9Tkc*BCdOC`Ri>=A|R=hE!BRB+6lawNEv#AQ|I1N#06t}12f?L>r}*V4v5+#r`$ uaMaKaxM9y3ipR~{d%6C2Da%)0D03IL$!ZlhalaefAQbIuHAuSizu*t&(`14G literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/classes.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/classes.m new file mode 100644 index 0000000000000000000000000000000000000000..19b10301ea186fa3aa382e63c9b72f3f19671af6 GIT binary patch literal 770 zcmZvZ%}>HW5XGkiNrQxV;NXEnV>m29jR)g_TPY=hR3IrQFHM00RcuKYO!VY`j&FAP z65V9e-8VD8eKU2R2W`3_y}pOL0~OUFM`UDF-foE|%TUT?JkG-G6R|wUaV5m^{DqRE zn^idFKmoU!s^GX8>mx@5HmF!8Q`7NlG+E#PGSL+CUrGtdCzJ!9b(+R< z6|N_XC{wJ$B2C{Q7vZUrMKa1hB4tv!yq2345`VeOBeNRooD$x#;zX{~*-S?4lu786 zH5q@wuTs$O2Iy(H4wX^{L&(io*`K7FM3t7H-s+wY8qexswhZS|71AR<2KEziH-_VN zf^OgI`Xk&_e~#BWD*T_!K`(GT+xKxMx}+<=`{E9`%pci($JM-{5Jt19M|FSf$g=xw ztJcA)H_j5cz0kkP?(eli084N25VK}rO90EUPMA;Kdw4kA^HKOZKW6h literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/classusr.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/classusr.m new file mode 100644 index 0000000000000000000000000000000000000000..c82e4d882f63a0aea27ed0652b5eb9c87c734b5e GIT binary patch literal 1552 zcmcgs+m4$s5FK{elv0H9*gxPqNH7snh!K#s`?Mm#VW}XFz)`zz{lxvF-7&YgZTiqv zRU{OA=FFTkW5*<<9^66y{CFNd!0bM50B%2m_3{G1PYtVUR_|B?7}Wu4CLVcS<{i^O zMCZG&Y%hiq2L56`K0|(%=Wok5d;Kx_FV%-^R2NxUUGqMZ-m9`j=cuGtkDcp_|5>kJ zFeLn;^Gt|FnS{{_-ed&>IVZ62?I$sKIdV}Ro)G=LnnZM2ZSrG?tSAMm0i;i(D31p& zeOg79qor=y$E-t@6>Vo8=D%v5PkAQL(0|b!Ce~h`*jsy4Cpjn_*|&e$k*c7}U9a2X zTK#@sHJs)%&J(m54Ig3>(odwTpxxlw3zCQ?2y_esk!|F;DFS%1G#%F~l42B3hjxc6 z*Yi?0SR-QNtI=rdKLneU#6dVzV?L4tXssA zPF=cxCu`6&@b57NK7bw3PI$R?lSD%J%$*Z2kAgM(Dr;K@5i3Z^mo!jFwu9&NyC_GB zg;xt%D+I8en&+$<319?EC2Tt7ehgWwm~Nw$61AP8;pbB^GHgFyY}1r(6wcf^G`q79 z{5Y|Cj#>zN={Zv=Fq1S^DVEcUW(r$TOn#i0^>8;8C+N2Odrm(5V7-pX zQstoAvZ@-qGDnt~+$ZWp(Z^GJnWrDSAyMNt_M6r0!U#flMHCz8w5;(W8U?_NDOEjK LPQ&@6kK6hR+zw1Q literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/gadgetclass.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/gadgetclass.m new file mode 100644 index 0000000000000000000000000000000000000000..d9867c5c6be927208163653e55a662aab78a3cb2 GIT binary patch literal 3454 zcmc&%TXWh*6kaa2F(D3d+|+H;#=W=yp)U(siH#+#Mp}G(VU(cSnz6xym85y&pS$1L z)nc4Zr(?gA83y*-bG~yw0ud>XZLs>4xG!DvrO8-(pLK6<89Tq8&ad)v2E5DKj9nGg z#e7;$joc=X_IWw`bIu^!JI|-*MP-hR(OqY8JzrFG*Inc{l{wg(-p7mb-35_!@a{Vs zklZZa&i?{N`ullREpAA^Q|0GnRa}wAE4<+$UbTmp`KS5&ip~%6utOe}v$87lOGC$c z_^`}7u!-2u=jAMaSCt=%2eX^_^S2bgdEIgM9QPxct>49mVg_n(^~%}x`>H-8hBoU} z#o`K{SLGaqLzIZBe>H!9Q&46p=S{Y2&Yx=E+H9}N-(D8gG_P{Yx_*Y#KHfGr9qYfb z`na6`f44~vib;=e657~B4X?JQddolK`P4*0}Zu|~Xmz}gNwR_Wnj?E50E zZ(8nV9D8bY(}zye-K@~wvc+>eK z`Z!7t^Mvp0?#kr7gGl_zkw~QvM)DaRB4_Ie$*ch5-An786GHsxJCdTJ4wZ+Zn7DSx zn#}kh6tGW`J_j<+MCx(P>p2Wk;idd|GEM-JCgrIScq-yDp2R9bPLToX#m!Z;GD}QH zP_DiJr;H-u$yy(hyH1kQdPMq|^xIqKBU;UNr|~*g2b{oKN;s4c@rg)D^QI(52cucYcN{4ot?Wj!jp`h@Z%499agoLS<}G%KH}b zZmVvy`HH+zK@bX?ecM6b1EqeEv9GM$E|7XqENJGDxxEvsm@0wz`rDLwtr8n;%N?jQ z`yIMFl9@!a+RQ(55yi@vp%y8AmJ!oFqTO+KzC010FGc9px3p)Uy4zGFAs-5RMOGSQ z#ZQGmpf;Wt0Bn3TBUHgQ5X}BSX-z_8Z@J-WF&s&l;wK{^gORKGQ)rBE4%e`bWm(Bl zCvK5ktw__@v@)qxqb=TZo@1IcxlLOaemBYQfl4tHCDh{!IXm@Sd3Td6$0)i+D{5RYw}#V5`JRb!;oAs8rcKY>8=!SHlQy-Izx z;p~`|LX*ebUbQ1+HTzwXi^Xwh$gp3QZD-ka*0J>T$lBS2FgmeDD83CK_0de3$)DXT zW`9!cU#z@7f!ElquuXmaGjwZF1JcI)2AFMh+gw)iYoHiY2N~_JfKlf-khJ%KndWt% n*|$#&C$*}b^8=je5pH98jT8NPkl4`l8x#L#uyOFI literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/imageclass.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/imageclass.m new file mode 100644 index 0000000000000000000000000000000000000000..88b1a0cc8944ae3b9049e82fdaa404ef0e697c9a GIT binary patch literal 2616 zcmd5;+m6#n5bZdZ37HT=7-rea2Mj{u19)@nPTazFTXuWG@DgQ-GqE5SC6?HI;}iL# z;Z(Picwl(hhuyUl;W~Bcs#B*u@Ibn($;|WRYx%-D`o&_bam~7ScZ}t$?J_SGyV)vZ z@HQA*WyNwc&*wU_%`Dc~Zt`{U*U@fi`)_Uc;cw6LRkq&eoAv&4J};K!7y$2_@MV_Y zE(@K(SQr1I13Z-uifm8*f4hTT$w9W8?X#b<&;l=w-FCAp7~(sKEwsTH@zdTc7W>Q) zM0Us6njqq*d*b09KfM!vkDoqxF#L3?-95<8f7RK6xA|`NxuorZ-Tm|KD6_jSW(8D9 zEH_wxzRTB(4bvN-V~xd#;foWK_ZYrB;rAGRab&n%GE4;@Qs4i7g2NrsTljN>Yx?6I z>XLpxY}Q4#F7_0Isav@Y*3s=#a>YZecYne2t#%|Eaeyd^h@ zNW^-|`#0Q!h>7CQ}jGjuO{AlyPADK{4DZSFq+~FeY>`@=^MycU5_vojtt#cMnm}y=OgN| zVPWD4$J4!A4NSvhJE2+oi0Gh>C&r$SpNe>BW z(40JWa1RjV*`l%8UQ&atZz{6BeW^`bI1vj=QW(&-4?DCPF z`q&!r`&?IXc#_bvv>J8PXqrUa5hGFvp(b}&L8*sF)SYL8IZZt40BZpoj!$+I_NcT6 z@H0K{)K)4M!xW;V6M(-ko2GU}IFdl29P80x+qx^W+cq%hxkMr zI7>5myzK#Z^=+qqYRD!*nce;Zi@RfNH}t7v+EmZ*17e9W%IP7>m{iv~*7bxgtFyW# zt0YbIb%)1E6IH5C%Z=(&zL_Z&IM;O1rk+H|C&Hy{g?Y F{0)t%Em8mg literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/intuition.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/intuition.m new file mode 100644 index 0000000000000000000000000000000000000000..bf241fc774facdafa815facd14f04656c646a2df GIT binary patch literal 11864 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/intuitionbase.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/intuitionbase.m new file mode 100644 index 0000000000000000000000000000000000000000..2d059d45a2c308b7f713b792326c927ab8767a8f GIT binary patch literal 588 zcmZ9K&u)T15XMJ}mKbCD3_bVQLk~Ta!ulsF5YgK7hOjo9D4PIk`<8tguXbi&jd25H zzTY>qv$H|WLLb`DtUnWUIk511g8umopz><3Dy8#vQc3`a{HhjQiN1yThUD55)rD0ZAwJ!&UI^dXsC~j+fD39tH~od4K!5 zn8}?t4P#-FsDl-czb=3~v~C;Vo#MJ_K&&~x*^WB^Phb#raBAU&%K&GfDJ`6_kz8Z> K`0ofqFySBR@OYpA literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/iobsolete.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/iobsolete.m new file mode 100644 index 0000000000000000000000000000000000000000..79ea00b631ae8df0cdb93bf95b330ae4cbc58b90 GIT binary patch literal 3320 zcmY*cTXx$v5FI^iGp?#I@4l zYumy0DpO^naVoEl3;L-x&*3rD@o}&)N%SAprmAgJfNkVt+IVjtJ2Qw4$Ypd7CgK3T z=LDN=G@X9{z&`WN?}Jqt7HOjvD}Mk9_}CCVm>#SQtO8j>g$}NVf>>s|d~UAi?(Xh> zXDzV(2)3hbAMEIMd=gq4iT{Mae@3JIa{}1TEVw5-0mAU_z+?);Nn^%;9bU?_3nv)@ zq$lq?Td7C-GTPl}LsPgIggq^oY2)ey5odM{u9XX>X!+n81xqoe(|mGH)cewm_5vgN z;$ve+1S(#*07Tp1x}mjakh4YKR`n|WeM(wXZtzYzTyaRW=p+24B*W^xLzM%)pf|6 z({5qTQq>EP^M51#*O{R8xTDq-wmr!+;!;(kM+0&^M?!q}t_R;JRmtIN1z*9owu~b) z8Z~cO<66`uMi7-DkbK;*y?XTfz7mjmUF)Qr6f@>}l5%A178&Cri$OgHzrVq+&~=@u zks0Rl3E0lJtv^WOVd)m=tz<)#xO3;|)4`81sc@%eFAhm}Uz(O)U2?A_UwlUL*(89o zo-YPCYW(P)29Gr$r-rZ}cB8BXk++Alyhd!V5gU5ixBKXPPxSt{I4)ZA==ae)!<6mO z3GxN?%6Y=d)*2+4BRNvxN2EOTZnu*PZ79Ui^|iK#YHgt9+e?JzI`!3PYSp1kk+Ssx zxx5B?OuxCGeneortz<*t8)NT*q2MpD*TCwhr!xlKt8yQr?@k!^-4ZM(fOEMR&|?$8 zkm{?9@SHv-G_$|2}72ewb zvn&3}^ES##$E2^&FCU~|N*h9&eYy)=#u`P}j@um0GG=K>qdDll=Lz|NdHT9;t60|oyr?^4zE#m6e^Lw;wco7>jK^M z4Ic80zdg9%a5*Rk+1gF%JFGai^%k~p|Fh){C^jbW6~wt;Qp{&mOUx!0HVI(w%d|5RggKZeq{Q~&g)SVo%yBX;b;ub>r#PxbXk2f# zp0GkQ-6`-V&53qU?`P?VZV#4c2-VK#oL}8&XivV&z%ENWE+Jf_8FJIw9gcB@(N#&} z=n`}Nj4aLR6SOT}R>AkJyn2?cV=zm^`w4O{q1 z_=4M#F}Yb3M7ECeX`_U}l#5%EsVIIAJR+Lu?veU`PP-&$%|P*H_?4 zZ;jSSTl0j0^PJ>nm>{n7GQF85jHl&libF0#u0+OlLx&t(#lgx3Spb`4?$>MW*97tH zeFbFF;7V+`>!$Bmk@8+@Y|EA5*TP3wto$AmZo9&B8}Z(J4-|JQyBEC$eGj`jliG4R zQ{Mr_@|Yl*vu}ZMLroxWrf+~r>rbFe-&bOjuVh$*pW{mh+DRAYxdS$rrlq&?7lxUA z4)$g+cukGH#`7j2Jj^^KC<_vsB=E!A|GAgzNqFEDf|o5G&hnoLWMn}h5QPvb#7bT;cv(@2(9Gnw(s z+IGRHjVj;23=h*#DOH`-btkaTIGci=1{-~jhrwEpQODjM68I;a z)y+SR`)-8Zg1sy3&*bp=;v=ipH>%mWcnZs^CA&w~`=ZsEa)owGE_f)3lf*iccEN#{ zj@-uBT8}NY*e^J~@yabbu#OrkMYuF)&D#fc+X0shjJE+nfNqga6i6QGI$FA&aM==4 u&p0_rQ+8?`JMEy54e5LggE=~r5NdkKYTnM5OP%gHlc4PM`aV4b6zT#?DS3bZ literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/preferences.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/preferences.m new file mode 100644 index 0000000000000000000000000000000000000000..d813ee705c2fe99ea8909d22497384daac14bf97 GIT binary patch literal 2984 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/intuition/sghooks.m b/amigae33a/E_v3.3a/Modules/Modules/intuition/sghooks.m new file mode 100644 index 0000000000000000000000000000000000000000..3f11aa0b15c95a653db2ec35e41c552de055db70 GIT binary patch literal 1418 zcmZWn!EVz~5Zt6`YC@=T=m8;w5JDUfAAw^(CsrLhveQydR%l*Q3u;G>8#r>}`#AG6 zWp0J^5%8wf>QHe^0bo{VdAwKrQMJt>%lBu87dF zcHh)Tr?aWbEMH~$vXE}SSqsBroo{!`r7oe?60E;2^|pa^p)|NH7J9=rc;Z>6w>mcy z`&quetLmD%)TWo$;4+nZs9qVRbs?u2d7asAN3-uiZvg=^9e7uh38bZC0o$HDxEKYaUNP0wf|m)hN;jY>a4XG;az~s z&bE4wo#L#Odd- zJLg8B4~`QkJFXSGsAH8V-VAGS77qxn#$gS{FctX@82{1CJ3!3pKxqNQHN24n_~@2(#6W;VdO~i?GRRA4(14j6`n)kB6K6;40jE;VdVLN3}GL< z_u(Uqc@0QXSy1xBM8z{K3OAioO^dG(x B80P>0 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/keymap.m b/amigae33a/E_v3.3a/Modules/Modules/keymap.m new file mode 100644 index 0000000000000000000000000000000000000000..bf21eb6b4c3ca5f278598091ab4f433675c11201 GIT binary patch literal 81 zcmZ?u^><-lW5`ae%uOsvN-R!g2u>~WPObD!EO1FpODxSP;czU@MiCGI$^|8s1I0Kv U8M%NQN55cC4hA6mKLY~;06o+gx&QzG literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/layers.m b/amigae33a/E_v3.3a/Modules/Modules/layers.m new file mode 100644 index 0000000000000000000000000000000000000000..f4628f01f7a87e04b503727e7e83abab6c06fee7 GIT binary patch literal 554 zcmZWm+irs}3=P{fnf7Jh1hgtrFB1&yIRjIoMKL1Ls_o}Dl0XXDTh7I?eY`teGWN_Q z|HeUoaE&Zi!Wf3>o=OAX$!{gJ&D+zW&HO@Q>YxBx*qAv{IQv57HJ&=?^ zOYkaG)i+~r*r{fEu?!`ex#&ps=TuNB89<;lENBgZ&s9rM-gut~qYJLhD-9-Wjbme1ARrg>>0&XqP?O5gn| zNI`6E_h@X^s~a4M=B?cwwyQ(@SEmkc46BBoVKC2@V+f8)3t&-3mYqY<5O01NV}EVt Bw$}gv literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/amigaguide.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/amigaguide.m new file mode 100644 index 0000000000000000000000000000000000000000..81efb496b1507a927a5d044a30d0cabd8dfa8892 GIT binary patch literal 2530 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 N?Q}4``2v7a{{!AqO^yHn literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/bgui.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/bgui.m new file mode 100644 index 0000000000000000000000000000000000000000..01e586f3b6fed55b57c01bd3abe00e2ffa649eb4 GIT binary patch literal 11052 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 U;(fUpI_uO;OJzuh1udBVQ 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 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/commodities.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/commodities.m new file mode 100644 index 0000000000000000000000000000000000000000..f741341efd6dba24ae931c434fe0e38f5a3f4f78 GIT binary patch literal 1568 zcmZux+iuf95M4WI8bVb{3!;F8DxOlQLWRdlNNmNu&Ll)S+w z@<(N6*KyN`NLD<@XU?3Ny_mLZkPV`KfBqIPq#<8)LbUH>=l-6MIGxUCi)j|+c|1ws zYn^C>+(lUtk{ZO?FbVSwX&O2kb`KUG!0A)JT=+snXKGVU^To@hkyp6*Wdt zJ_IEVv~;pPPvhIUs*Bz1TqWVP?5zrn-Dws}7x2DURQXg^c`==2GeW>&bvy-h2lDp| z)@b-6Ow%ZlWby|7V2+g|+1V@BXSNZXamxaH8=g9IP0tHj)bIyg6O{;gsaOUVwA(eQ zr<;!OG2R2ZXOp+M=bqEOM{?ShMIcEI{}z|9NO@gYJdb#TIZ!gp;|p~~ELAUf{X zpu-L56sta0J(&(|SpZ4w*+cgdM6GJ+PH9&`Tkund!WirD{Rzb1OwUycvOk~umZ|zf zfBV?8Lv00NZH={X@?s$14`O8L4;>eXw$iQQe8EncYunU;q2qeJRgNt#{D5^%0YUxO z3hg=kyobG^zUH)gL5U!XAY$~o7H8B4nmm`vnG4H+`oHgaKX6>nrq+3nT0)@&=2`5V zHn;rcdh0L=+(}Ce^)$eiG1lBbjz=9~$&#|Bu4;l4id*+ z0Fx6#|BmbP_5cu6uPCJp(-Yiv%DDz5AoDhy)(V1aSb>Vd#F-NEl+>|O!29y_kY-am zIeC0TeUMktXKpf!3K1av5HcHV(TTF>|m-B0t@op_cPHu$_uGl=EO~z0UZ?|<<>YNk_deMi7 g(vj@re;GKbg5T5+ml^SO8YV@J^)A$Td7J~(e|PpaQvd(} literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/configregs.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/configregs.m new file mode 100644 index 0000000000000000000000000000000000000000..96c3e863980f627a1c7e2d32826fb426d9cf0f75 GIT binary patch literal 2244 zcma)+&2HLQ6vq#Q5QZ`oMP1C&i!MOwNT!)-JGgiKmp)-KD$Y8*{Y21g`4~2c1f>gC_-_Wew*@H72itayO^i56(J(!tNDCo2zgXy z$%FE!;afGEE~nY&>BMex6k;{Q-ZBHI<1bc-&oNav{jx}A%XB`&(pK609(k22#k|uj zTQ4|!jcWaNGQLZ1@2-+1rzBRSmt-=*B-{n{c(A-%uht9BKsKekg7z|%0jQQ2#_q~6qfq)?Y`%9#=iI{ zLZw7Qgx&7=G6=(9ETzP1NuLr@caPFeK8i3_aBGSFad+%V=j@}?m)_PtcK2uvPs-#U zUkrsSW12R=_nnBi?SE`G8*zCu?gV~Uo;jg#gpVO9w?%ck()VIH5IRePn6lNBEN!+7 zf>^Uxc&~w?M)Fdeg^oY!JE4p(bX@LVe2OuX(76t|`+WvnDF%tScsRyPkD?>HW9i2t z3`fIQ`e)b!@+0K#6R!0`tp{Qd4V?})LF|Zg?X#CA*T9K>S4yE>OsJ)Dnxps zdgG`c#G2H>!p_Mn2rpbGBHfPhgTiWvPeaF#WZ!Z3OrC(*I4vjfxLvyaLPNrhdJBvE#*x6l6Jf`Sc=*is_vBc%@3m9 zC>{+}#dt69w(Ya;yv3vFTzYX2{a7nv=RxQpq*-!2w!4UhW^{Xjm@i$opHs5LJB_!O zHkd9#J|(qPijY;2tZ1tg!W@s=9n!49H)^{pc|82e=m~KGc!lvQJfTj{k-qTM^pVoZ z0nh2_3Dv-x?Td3aa6!_O~%=>dLf QQk7WY8*68~TT~LjzoDbX>i_@% literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/configvars.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/configvars.m new file mode 100644 index 0000000000000000000000000000000000000000..de8d30d774e7337e14cf5b8ae4cde5a7b20771a6 GIT binary patch literal 550 zcmZ9IO-{ow5QQftR8drw9)Sf5gjlfP0_3N_BBW~Rf(YsR~^yqZ#a`znq!Eib4p>YJSg^BenYCkwH3i zU6-cWOB}gjvX@W**R8N>EnSGK@3h=BbBu8ECjm0=Tiw=@$K#hK*dF#beupTCli|l` zoX6>8lA^`zEKZ_h)?)|jCQsAX=?E1QV%34Lufv)+e;GbMW+`fB@I|N0XI=D=WNDU< M-*!59qhki^FM2m}1ONa4 literal 0 HcmV?d00001 diff --git a/amigae33a/E_v3.3a/Modules/Modules/libraries/cybergraphics.m b/amigae33a/E_v3.3a/Modules/Modules/libraries/cybergraphics.m new file mode 100644 index 0000000000000000000000000000000000000000..ca48920956dc1c0edfd885532f261df57bae2fa6 GIT binary patch literal 1208 zcmY*YO>f#j5FLY|Ns17PNYqnLJ@n8+lO|EF{-9vBZd_+8(i3vQ3M)A#ax4{Y{Dl1C zrZcnSk02TCz8Swa^JY8=Z+z&1{G#e`$cGO8Kg00l1z@@RlNJw~Rhr`i&<7j99PxC7 zc{T;hbX(%tLd1p-EB*ACB|E($GJ50VU%e{VbUVP?r**3D*OYIfpI7OliH!`|ZY|qg1?bBa8zaBibW0@Y^t) z?rrFEc0BpH@ItIVbBZF_ArrB`6?O;dznmjGV%@xBYA=DPsoyLNWk=w4hL!Hm6 zUMa%WgrpiK+dA@Y-!s*_fv={EADaiACs`F9pbm)6_g@N)I7TLDYxu@L!mS2Rwt|n4 zpYsiWosIQ#Hk)G