8L2C)pJJJJ IH(ȱH:=IH[H`@HcH  $ +   I/H`JLNGȄBȄF aK  haaFF  mJm# KKJ UJ )J ۈ) ;J3ȱJFȱJGJKaȄM  aaNNJFLGJL L? &PRODOS `DaElH$?EGvѶK+`L HHLy XP LM ŠϠĠӠS)*+,+`F)) (*=GJFjJJA QE'+ '== `@ STSP8QSS8 m P o R(8RLnSOS BOOT 1.1 SOS.KERNEL SOS KRNLI/O ERRORFILE 'SOS.KERNEL' NOT FOUND%INVALID KERNEL FILE: xةw,@  ȱlmi8#)!) >dMԡm#i㰼m#iЕOLԡȱfg hi !dLԡ憦  Ljmkm l y`2 Lԡ8(Je稽)ʈ@LMOVE15402KA' ULTRAMACROS# COPY.ME$33FASTCOPY.SYSTEM)VNZ [*LAUNCHER.SYSTEMG,b$ b1 PRODOSW#Bb  SETTINGSy$ c SYSUTIL.SYSTEM{c% c% UTIL.0~Qc, c, UTIL.1;yc c UTIL.2 c. c. ULTRAMACROSu#' #' '+DOT.GOODIES  wO".FOR.NEXT.LOOPSwC 'COMPARE 0~C -DOT.DB.AND.SS) sO,DOT.DEFAULTS4wO+DOT.EZ.MENU:brO-DOT.MENUTOOLS?d-wxO6(DOT.IIGSW sO&.DOT.MENUTOOLS2_)wxO)DOT.STUFFuwM,TIPS.N.STUFF ~C 'A.NOTESC AO=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===off.e 15, Column 12 or Boldface Begin, etc) even if th*Compile and press SA-Esc for macro menu.labels .goodies\sa-aDemonstrate .awpath\sa-bDemonstrate .case"\sa-cDemonstrate .cachelist\ba-cDemonstrate .choose" \sa-dDemonstrate .deskcount!\ba-eDemonstrate .embedded\sa-eDemonstrate .fdate\sa-fDemonstrate .fdate2 \sa-nDemonstrate .newfile\sa-pDemonstrate .pop\sa-oDemonstrate .search\sa-sDemonstrate .sort\sa-tDemonstrate .speed"\sa-uDemonstrate .substring \sa-wDemonstrate .weekdaystart-----------------------------$1 = .awpathCThis command returns the path where AppleWorks was launched from. a:!-------------------------* $1 = .case "case string","Work String"IGThis command lets you change the case of a string based on the case of LJanother string. If the case string character is not text, the work string character is left as is.?b:!//show result-----------------------------.cachelist FirstStrOMThis command will return the names of the currently cached macro sets in the MKstrings starting with FirstStr. It sets Z equal to the number of currently PNcached files. If you set FirstStr to 0, it will just set Z and not define any strings.<c:!-----------------------------%$1 = .choose "list,of,items",ChoiceLJThis command returns the specified item from a list of items separated by commas within one string.O:!------------------------.deskcount xMKThe .deskcount command sets Z equal to the number of current desktop files MK(active desktop only) of the type specified. Use 1 for DB, 2 for WP, 4 for &SS, or any combination of the three.Hd:!------------------------$1 = .embeddedOMThe .embedded command returns the bottom line string from the Word Processer NL(Line 15, Column 12 or Boldface Begin, etc) even if the screen display is off.1:!-----------------------------$1 = .fdate FormatEThis command returns today's date in a variety of possible formats: 1 - 09/21/92 2 - 09.21.92 3 - 09-21-92 4 - 21/09/92 5 - 21.09.92 6 - 21-09-92 7 - 92/09/21 8 - 92-09-21 9 - 92.09.2110 - 92092111 - Sep 21 9212 - 21 Sep 9213 - September 21, 199214 - 21 September 1992L// This macro shows the various Format options for use by .fdate & .fdate2 E:!-----------------------------$$1 = .fdate2 month,day,year,formatOMThis command works like .fdate except that you can specify a date. Note that Year needs to be 1992, not 92.AF:!-----------------------------.NewFile "FileName",typeOMThis command creates a new file, giving it the name "FileName" as speficied. 2The type indicates which type of file to create: type = 1 : WP, 2 : DB, 3 : SSOMZ returns the file number of the newly created file. If Z = 0, then the file Lcould not be created (because you've already got 12 files on the desktop).NLWhy is this command here (Most people use a macro anyway)? Well, it handles PNthe actions with or wit"hout display and ExpertMode leaving AppleWorks in the same state as you left it.LJWith a DB file, you still need to specify category names. Your macro will have to take care of that. N:!----------------------------- x = .search "ishere",start,endNLThis command will search the string variables for "ishere". The search is a PN"contains" search, not an equal search. Also, start and end specify the range MKof string variables to search through. If a string is found, its number is Lreturned in X. X=0 means failure. You cannot search $0 using this command. O:!+-----------------------------------------+Some Randy Brandt commands snuck in here:+-----------------------------------------.pop LMKPops return address from the subroutine stack. In English, this means that PNwhen a macro calls another macro (not a goto), the second macro can do a .pop &1 to avoid returning to the caller. 2p:!%:!-----------------------------.sort Start,End,DirectionNLThe sort command sorts a range of strings from Start to End in ascending or .descending order, as specified by Direction.9s:!:!----------------------------- .speed 1000NLThis command, written at the request of J.S. Rowe of England, allows you to JHslow down Ultra 4.0. This can be handy for demos or for debugging. It's NLactually a delay command, since higher numbers make Ultra run slower. Use 0 OMto return to full speed. You may press a key during long delays to hurry the macro along.>T:!-----------------------------.x = .substring "hat","Where is my Hat",StartNLThis command searches for "hat" in "Where is my Hat" starting at the string LJposition specified by Start. Case does not matter. If found, the position *found will be returned in x, else x = 0.=U:!-----------------------------x = .weekday month,day,yearIGReturns a value (1=Sun,2=Mon...7=Sat) indicating the day of week for a NLspecified date. Again, year has to be a full year (1992), not just the last two numbers."W: if R = 1 then $7 = "Sunday" : { Sunday }>else : if R = 2 then $7 = "Monday" : { Monday }?else : if R = 3 then $7 = "Tuesday" : { Tuesday }Aelse : if R = 4 then $7 = "Wednesday" : { Wednesday }@else : if R = 5 then $7 = "Thursday" :{ Thursday }>else : if R = 6 then $7 = "Friday":{ Friday }@else : if R = 7 then $7 = "Saturday":{ Saturday }endif :'msg "Mark was born on a " + $7>!"@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== NLFor-Next loops may be nested, and the various loops may have different step NLvalues and do in different directions. For example, the following macro has KIan outer loop going up by 2's, and an inner loop going down by 200's. It 9doesn't do much, but it does illustrate how this works.startf:!// close the outer loopAO=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== oa-q find rtn .getrec 1,r(1),s(1),num #DB Record Compare by Randy BrandtCAThis macro will examine corresponding records from two files and FDdisplay six categories at a time, highlighting categories which are not identical.I !"#$%&'GThe files don't have to have the same number of categories or the same ECcategory names, but there needs to be a one-to-one relationship in IGthat category one has to match category one, category two has to match category two, etc.FDThe purpose is to find out what changes have been made in the newer IGversion of the file, or perhaps to help you determine which record has Ethe newer data. That, and it was a fun little programming exercise.labels .comparedb#findfile=sa-f#getrec=sa-gstart3:!//back to normalBa:!-----(b: to <' + $2 + '>':=P = 6//categories per page9Rec = 1//first record to read.writestr 0,0,%A% :>.writestr 255,0,"Record Compare by Randy Brandt" :D$0 = $1 : F = 1 : #findfile: n = n(9)//open file 1;c = c(9)//record count?$0 = $2 : F = 2 : #findfile//open file 2Eif n > n(9) then n = n(9) : endif//lesser of the twoEif c > c(9) then c = c(9) : endif//lesser of the two8S(1) = 10//1st string for file 1 (10-57)8S(2) = 58//1st string for file 2 (58-99)goto sa-c>!?c:!0D: num then j = num : endif :&.titlebox 0,1,77,19,1,$6 :=.writestr 2,2,%J% + 'Record:' + str$ R(1) + %K% :for i = k to j :6A = S(1) + i - 1 : B = S(2) + i - 1 :=$3 = str$ i : if i < 10 then $3 = " " + $3 :-$3 = $3 + "-" + .catname i :3$3 = left $3, 13 : $3 = $3 + ":" :=if $(A) = "" then $(A) = "" : endif :=if $(B) = "" then $(B) = "" : endif :(ifnot $(A) = $(B) then :$(A) = %J% + $(A) + %K%//invert:$(B) = %J% + $(B) + %K%//invertendif7.writestr 2,V,$3//category name2.writestr 17,V,$(A) : V = V + 1 :2.writestr 17,V,$(B) : V = V + 2 :next i :2.msay "Other categories: " + &J K & +5 "Change records: " + &A-J A-K M & :&//.msay "Use " + &J& + " or " +&K& +?// " for other categories; " + &M& + " for the next record ":/if z = 0 or Z = 209 or Z = 155 then3 oa-q display #on esc stop endif :/ifnot z = 13 or z = 139 or z = 138 =then goto sa-s endif//current record7T = 1 : if z = 139 then T = 0 - 1 : endif :=rec = rec + T : if rec = 0 then rec = 1 : endif :+if rec > c then rec = c endif :goto sa-c>!// z holds keystrokes: 60 then y = 1 : endif :,ifnot y > num then k = y endif :goto sa-d>!f: 42 then n(9) = 42 endif//no room for most DDD c(9) = peekword #dbrecs//how many recordsdisplay #on>!Bg:!(AO=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===$1 = "1992" : .setcell col,row>! get current HThis file demonstrates the commands from I.UM.DB.AND.SS (see page 51).ELoad the files "Sample DB" and "Sample SS" to try out the commands.labels\sa-a demo .getnames\sa-b demo .setna(*+,-./012mes\sa-c demo .getrec\sa-d demo .setrec\sa-e demo .getcat\sa-f demo .setcat\sa-g demo .catname\sa-h demo .catnum\sa-i demo .column\sa-j demo .colwidth\sa-k demo .getcell\sa-l demo .setcell\sa-m demo .cellid\sa-n demo .lastcol\sa-o demo .lastrow.dot.db.and.ss8#sscol=peek $B0// current column number5#ssrow=peekword $AE// current row numberstart----------------------| Data Base commands |---------------------->a:! display the names?b:! redraw the screen to display the new name-----6c:">!5d:! ---------;e: Press a key" :x = key :Acat = cat + 1 : if cat > T then msg "" :stop : else :2 rpt>! f:! ---------Bg:! find category nameFh:! find number of a category name------------------------| Spreadsheet commands |------------------------H// since this is simply a conversion routine, it can be used anywhere,F// not just inside of a spreadsheet (not that it's useful elsewhere)5i:!F// put the cursor in any cell with a formatted number and press sa-k8// for example, move to a "Goal Pct" cell in Sample SSFk:! chr$ 10 and 11 turn inverse on/offH// plugs the date into a cell as a label since chr$ 34 enters a quote,2// forcing label mode. Skip it to enter numbers.Bl:!.// place the cursor on any cell and try sa-m6m:!=n:!:o:!n@O===<=<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===:@O===<=<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===e:! duration, pitch3b:!N----------------------------------------------------------------------------C// get the last entry in a file; make it easy to test for the endCc:!// sets Z to result2d:! works with screen off>e:! load path of current file@f:! try from within a TimeOut applicationEg:!D// online returns Z = to the file size in blocks, or 0 if it failsMh: 1 then $11 = $11 + "s" : endif// grammaticalMmsg $10 + " is " + str$ z + $11>!// display sizeN----------------------------------------------------------------------------Ei:! // an AW stringMKj:! the work promptO// a little wp trick messing with a poke into the AW zero page (techie stuff)Ak:!@l:! set default data pathBm:!// easy path change9n:!4// try this one in each application- wp, db and ss@o:!Z@O=====<====<====<===<=====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<===<=====<====<====<====<====<====<====<====<====<====<====<===.addmenu 40,13,$9 : // anywhere we jolly wMKThis file illustrates simple menus, without using the fancy filecards that NLcomplicate things in the Dot MenuTools file. It does get a bit carried away with the .box command, though.sta9;<=rt9a:FirstStr = 51// first string in menu is $519Count = 3// there are 3 menu items8Spacing = 2// double space the menuAInitial = 1// initial menu item to highlight;.cls 1// clear most of the screen,.box 19,3,34,15,1// outer box,.box 21,4,30,13,1// inner box0.writestr 29,6,$50// display title0.line 22,7,30,#'_'// dividing line// create the menu itself@.makemenu Lefty,Top,FirstStr,Count,Spacing,Initial :E// of course, in a tested macro, you could hard-code the values to 4// save space in your file and in the macro table:D// .makemenu 24,10,51,3,2,1// same result as previous .makemenu#// result is always returned in Z9if z = 0 or z > 30 then $0 = "You Escaped." else :9$0 = "You picked item " + str$ Z : endif.cls 1 : oa-q : msg $0>!BO=====<====<====<===<=====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<===<=====<====<====<====<====<====<====<====<====<====<====<===.addmenu 40,13,$9 : // anywhere we jolly w _________________$| File Card menus |_______________%| |%| by Randy Brandt |%| |%| Commands by Randy Bra>@ABCDEFGHIJKLMNOPQRSTUndt |%| and Mark Munz |%|_________________________________|KIThis macro, along with some dot commands, allows you to create file card &menus just like those in AppleWorks.Creating your own menus-----------------------PNFirst print this file and then follow the macro logic as you step through the Lmenu choices on screen. This is the best way to learn how this mess works.NLI made most of the macros so they couldn't be run accidentally. Don't PNforget that you can't use to run an macro; you have to use or to run them.NLTip: To draw a card from 2 thru 4 by itself, precede the ".FileCard" with a PNspecial poke to cancel the "edges" of the prior cards from getting drawn, and -then reset the poke after drawing the card:;Ex. poke $c3d,0 : .filecard "Lonely card",2 : poke $c3d,1A Quick Tutorial on .filecard-----------------------------OM.filecard is a special dot command making it easy to draw the filecards made MKfamous by AppleWorks. The routine which draws the card titles it using the NLEscape map heading at the top of the screen. When you use a command such as PN.filecard "Sample",1 the string SAMPLE is placed at the top of the screen and $card one is drawn with that title.MKThis is great except when we're backing up from a higher numbered card. If NLthe menu is on card 2 and the user presses Escape to get back to card 1, we PNhave to back up using a .popmap to get rid of the current title and return to OMthe prior one. If .filecard behaves normally though, it will add a new title NL(actually the same one) and the top will be "SAMPLE Escape: Sample" which OMis not what we want. By adding 128 to the card number, we tell .filecard not OMto worry about the Escape map at all. That way everything works the way it's OMsupposed to- the .popmap backs up, and then .filecard redraws the prior card Husing the prior heading. Do a find for **fc** to see this in the code.?// we've got lots of labels to make our source easier to readlabels .dot.menus#setup=sa-s#doit=sa-f#lastkey=peek #key#item0.1=sa-1#item0.2=sa-2#item0.3=sa-3#item0.4=sa-4#item1.1=ba-1#item1.2=ba-2#item1.3=ba-3#mainmenu=sa-m#menu1.1=sa-x#menu2.1=sa-y#menu3.1=sa-ctrl-a#menu3.2=sa-ctrl-b#help2=sa-h#help3=ba-hstartE[:! just in case someone makes this into a task file4--- this is the startup message, full of MouseTextJ]:!A// this file is for demonstrating all of the dot commands foundC// in I.UM.MENUTOOLS, so we'll get a few out of the way here that?// have nothing to do with actual menus as far as we can tell>o:$1 = .stripchar $2,#'*',0 : //strip both ends#msg $1 : x = key : msg "">!8Q:.savevar "test.variables" : // save them in a file8clear 255 : // zap everything to nothingness4.writestr 255,11,"Z(8) = " + str$ Z(8) :3.writestr 255,13,"$69 = (" + $69 + ")"::.say "Press a key to load variables from disk">.loadvar "test.variables",255 : // load everything4.writestr 255,11,"Z(8) = " + str$ Z(8) :3.writestr 255,13,"$69 = (" + $69 + ")":=.say "Press a key for the Main Menu" : oa-q esc>!-------------------------// MENU stuff starts here-------------------------#<#doit>:!<#item0.4>:!-----------------------------G- this is the macro we run if item one from the first card was chosen<#item0.1>:! ------------------------------H- this is the macro we run if item one from the second card was chosen<#item1.1>:! ------------------------------G- this is the macro we run if item one from the third card was chosen%<#menu3.1>:! back up after user hits space bar ------------------------------#- second choice on the third card&<#menu3.2>:! ------------------------------$- second choice on the second card"<#item1.2>:! ------------------------------#- third choice on the second card9<#item1.3>:! ------------------------------- second choice on first card#<#item0.2>:! ------------------------------- third choice on first card6<#item0.3>: 0 then sa-] : stop>! enter selected file and quit ------------------------------/- this macro does the menu for the first card<#mainmenu>:! x, y, first $, count, spacing, begin item ------------------------------5- this macro does the second card menu for item one<#menu1.1>:! ------------------------------'- this macro does the third card menu<#menu2.1>:!// but we gotta demo them all ------------------------------!- here's our second help screenB<#help2>:! ------------------------------ - here's our third help screen9<#help3>:!wait for a key and return to main menu--------------6// define a bunch of strings here and use them later=<#setup>:!@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===next Color : msg "">!C : .spacebar :us colorsckgr*Compile and press SA-Esc for macro menu.labels .iigs.cmds\sa-eDemonstrate .extkb!\sa-gDemonstrate .getcolor!\sa-sDemonstrate .setcolor!\sa-tDemonstrate .timeiVXYZ[\]igsstart-----------------------------.extkbPNThe .extkb command sets Z to true or false to indicate if the latest keypress OMwas a IIgs keypad or extended key. Ultra automatically calls BA macros when PNyou press a keypad or extended key, so you can use this command for different *functions based on what key you pressed.:else msg "Both-Apple-Return"//three keys >!-This example requires an extended keyboard:J:!HFYou can make the function keys go run another macro, so that they are OMcompletely independent of their keystroke equivalents. For example, we could Nhave this one do an so that F1 always goes to the Main Menu.-----------------------------X = .getcolor WhatKIThe .getcolor command allows you to read the border, background and text colors on a IIgs.0g:!-----------------------------.setcolor What,ColorMKThe .setcolor command allows you to change the border, background and text colors on a IIgs.Cs:!-----------------------------$1 = .TimeIIgs 1The .timeiigs command=// Format- 1:time only; 2:AM/PM if Control Panel set for it@t:poke $11ac,27>! restore Esc for stopping runaway macrosBO=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@ O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===if Num > Hi then msg "Escape" : else msg NumCompile, then press SA-Esc.labels .mtools2\sa-aDemonstrate .askyn\sa-bDemonstrate .box!\sa-cDemonstrate .titlebox\sa-fDemonstrate .fcard!\sa-gDemonstr^`abcdefghijklmnopqrsate .getinput"\sa-hDemonstrate .getstring!\sa-iDemonstrate .getvalue$\sa-kDemonstrate .list w/.box\sa-lDemonstrate .list!\sa-mDemonstrate .menuitem \sa-nDemonstrate .ongosub\sa-oDemonstrate .ongoto\sa-pDemonstrate .pick\sa-tDemonstrate .therm#\sa-uDemonstrate .macronamesstart-----------------------------.askyn "prompt"HFThis returns consistent results no matter how a user may have patched their Yes/No order.6// returns Z = 0:Esc, 1=N, 2=Y, 155=OA-Esc, 209=OA-Q8a:!-----------------------------.Box X,Y,W,L,mTxtFDThis command will draw a box starting at X,Y with a given Width and DBnumber of Lines. If mTxt = 0, then a plain (non-mousetext) box is ,drawn, otherwise a mousetext box is drawn. b:!-----------------------------.titlebox X,Y,W,L,T,titleFDThis command will draw a box starting at X,Y with a given Width and /number of Lines, using a title specifed by T. c:.titlebox 30,3,40,5,1,"This box has an inverse title" :4.writeStr 38,7,"Stuff something in the box" :.spacebar :<.titlebox 30,3,40,5,2,"This box has a normal title" :4.writeStr 38,7,"Stuff something in the box" :.spacebar :5.titlebox 30,3,40,5,3,"This is a shadow box" :4.writeStr 38,7,"Stuff something in the box" :.spacebar :Hrestscr// restore the original screen>!-----------------------------.fCard X,"Name",mTxtHFThis command will draw a nice filecard for you. You can specify which HFcard # to draw (1-4) via X, the "Name" of the filecard and whether or IGnot to use Mousetext for drawing the card. See the filecard example in HFthe Dot MenuTools file for more ideas. Two main differences: this one CAhas cards that look different, and it doesn't need to do an OA-Q )first, like the .filecard command does.F:!-----------------------------.$1 = .GetInput X,Y,"Prompt","Default",MaxLenIGThis command allows you get string input at a specific location on the HFscreen with a given prompt and a default string. You also can specify A?the maximum length of the string to get (1-80 char). With this =command, you can set up your own input forms if you'd like.A// returns Z = 0:Esc, 155=OA-Esc, 209=OA-Q, or length of string G: 0 and Z < 155 then :4msg "If you didn't lie, your name is " + $1 :else msg Z>!-----------------------------+$1 = .GetString "Prompt","Default",MaxLenGEThis command is a mix between .GetInput and the UltraMacros DBcommand. With it, you can specify the Prompt for the user and the GEDefault String as well as the maximum length. It is always displayed on the bottom of the screen.A// returns Z = 0:Esc, 155=OA-Esc, 209=OA-Q, or length of string H: 0 and Z < 155 then :7msg ' You came into this world on ' + $1 + ' ' :else msg Z>!IGWhen you're in the AppleWorks Data Base, the internal command @>is used to define a category. Since .getstring, .getinput and F.getvalue all use the same , that can cause a few problems. HFHere's a macro by Jim Parker which works around that. Press Enter for 2a null category, and use OA-Q to stop the macro.@:oa-y : print $10 : rtn//plug it in:goto ba-h>!//repeat-----------------------------(X = .GetValue "Prompt",min,max,defaultFDThis command will prompt the user with a default number and allow a IGnumber to be entered between 0 and 65534 as limited by min and max. If <the user exits via Escape, 65535 is returned and Z is set.A// returns Z = 0:Esc, 155=OA-Esc, 209=OA-Q, or length of string"I: Hi then msg str$ Z : else msg Num>!-----------------------------!.List X,Y,W,L,Start,End,"Title"IGThis command displays a scrolling list with strings specified by Start HFand End. X,Y,W,L specify the X,Y position on the screen for the upper IGleft corner, the Width of the box (in char) and the # of Lines for the Astring display area). The title is drawn at the top of the box.<You may use OA-Down, OA-Up, OA-1 and OA-9 to move quickly.GELimits: You can't use $0 as part of your list (a value of 0 returned (in Z indicates an escape was pressed).A// returns Z = 0:Esc, 155=OA-Esc, 209=OA-Q, or length of stringK: 30 then msg str$ Z : else :)msg "You picked Item #" + str$ z>!L: 30 then msg str$ z : else :)msg "You picked Item #" + str$ z>!-----------------------------$1 = .MenuItemGThis command reads the current menu item from any numbered menu item.M: Cursor through the menu; Esc to quit <--" : x = key : begin@$1 = .menuitem : msg $1// echo menu itemAx = key// get another keyBifnot x = 27 then print chr$ x// check for Escaperpt else msg "">!-----------------------------.ongosub val,"abcdDefghijk"GEThis command lets you call another macro based on a value. val is an DBindex into the string that follows which contains a list of macro FDnames. Lower case represents SA macros, and upper case indicates BA Gmacros. Non-alphabetic macros are run by adding 128 to the character.DIf val = 4, then the command would call the macro SA-D, if 5 BA-D.HFn:! comes back to msg-----------------------------.ongoto val,"ABCDEFGHIJK"IGThis command is identical to .ongosub except that it does not call the 9macro as a subroutine, rather it does a goto MACRONAME.Bo:! msg won't be shown-----------------------------&$1 = .pick X,Y,W,L,Start,End,"Title"IGThis command displays a scrolling list with strings specified by Start HFand End. X,Y,W,L specify the X,Y position on the screen for the upper IGleft corner, the Width of the box (in char) and the # of Lines for the Astring display area). The title is drawn at the top of the box.0Limits: You can't use $0 as part of your list.GE.pick returns a string which indicates which items were picked. Each ECcharacter of the string is an item number that was picked. Use the DBlength of the string to determine how many items were picked. The 7following macro demonstrates how to use this command:G// returns Z = 0:Esc, 155=OA-Esc, 209=OA-Q, or number of picked items P:!-----------------------------.Therm X,Y,Current,MaxGEThis command will draw a thermometer. If Current = 0, then an empty HFthermometer is drawn at X,Y and it is initialized with the Max value. B@If Current <> 0, then the thermometer is updated to reflect the current position.T:!-----------------------------.macronames : goto sa-aCAThis is the "live" SA-Esc command which displays a list of macro IGtitles. Choosing an entry runs that macro. To use it yourself, it MUST FDbe followed by a goto command. The command will plug in the name of "the macro that the user selects.>U:!xAO=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===.setcol Column,Width---- main memory.zp except that it labels.stuff \sa-dDemonstrate .dropdir\sa-lDemonstrate .line\sa-mDemonstrate .msay \sa-nDemonstrate .peekvar \sa-oDemonstrate .pokevar#\sa-pDemotvwxyz{|}~nstrate .peekwordzp"\sa-rDemonstrate .rightmost\sa-sDemonstrate .setcol \ba-sDemonstrate .subchar \sa-tDemonstrate .toinmem \sa-uDemonstrate .uncache\sa-vDemonstrate .vline \sa-zDemonstrate .zapchar!\sa-wDemonstrate .menubar2start------------------------ .dropdirEThis command drops the last subdirectory from the current pathname./d:.spacebar : .dropdir : .spacebar : .dropdir :2oa-q>! drop down a step at a time------------------------.line Horiz,Vert,Length,Char=;The .line command draws a horizontal line at the specified IGcoordinates, using the specified character. If you set the high bit as B@in the example, MouseText will be used. You may use 255 for the &Horizontal value to center the line.-l:!------------------------.msay StringIG.msay is demo'd in the "Compare" file. It is like .say, except that it FDdoesn't save or restore the bottom line, making it useful inside of B@loops since the screen would flicker if .say was used, since it FDrestores the bottom line whenever it exits. Use .say for "one-shot" 'messages, like at the end of a macro.?m:! leaves message on bottom line------------------------#.peekvar Address,Start,Count,SizeB@The .peekvar command is used to read Count consecutive bytes at HFAddress starting with variable Start. Size determines if single bytes GEare read, or two-byte words are used. Unlike loops which use arrays, ECsuch as C(2), C(3), C(4) for three bytes, .peekvar would use C(2), FDD(2), E(2). This allows up to 520 bytes to be read in one pass- 260 words from A(0) to Z(9).Cn:!------------------------#.pokevar Address,Start,Count,SizeCAThe .pokevar works just like .peekvar, except that it stores the ?=variable values in memory instead of reading memory into the variables.4o:!------------------------x = .peekwordzp AddressFDThis command is used to peek a pair of bytes in auxiliary zero page ECmemory. If you don't know what that means, ignore this command. To ;peek main zero page bytes, just use plain old .&p:!------------------------.pokewordzp Address,ValueIG.pokewordzp works just like .pokezp except that it stores two bytes in >memory instead of one. The values are stored in main memory..// no meaningful example yet; maybe some day------------------------x = .rightmostIGThis command returns the rightmost spreadsheet column containing data, DBthe last allowed character position on the current word processor IGline, or the last column on the screen in the data base. A column is a GE"slot" which is independent of the actual category contained in that GEslot. That is, you can rearrange the layout so the category order is ECscrambled, but slots always start at one and count up from left to right.>r:!// try in any application------------------------.setcol Column,WidthECThe .setcol command changes the width of the specified spreadsheet column. No flicker, no pain.s:!------------------------2$1 = .subchar Text, FirstChar, LastChar, NewCharIGThe .subchar command replaces a range of characters with the specified IGnew character. The ASCII values are used, but the compiler can convert Ftext characters for you so you don't have to know the number values.C:!//display the strings------------------------x = .toinmemHFThis command is used at the TimeOut menu. It returns a non-zero value IGif the highlighted application has been loaded into memory or 0 if the application is still on disk.t:!-----------------------------6.uncache "macroset"//uncache the named macro set>.uncache "*"//uncache all macro sets in the cache?.uncache "#"//uncache all sets EXCEPT um4.0.systemHFUltra 4 caches macro sets whenever you use launch, call or link. This HFprovides maximum speed for switching, but ties up memory which may be GEbetter used for other things. The .uncache command removes the named HFmacro set from the cache, freeing up the memory. .uncache returns the number of files uncached in Z.<U:!------------------------ .vline Xpos, Ypos, Count, CharHFThe .vline command allows you to draw a vertical line anywhere on the screen using any character. v:!------------------------.ZapChar "Text", CharFDThe .zapchar command removes the specified character from a string. GEThis is handy for stripping commas from numbers so the extended math commands work.Cz:!------------------------(.MenuBar2 "Prompt","Choices",DelimiterIGThe .menubar2 command is identical to .menubar except that you specify 4the delimiter character following the two strings.Cw:!@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== October 3, 1993To Learn More-------------IGWill Nelken taught an Ultra 4 course in the GEnie University. The same IGseries also ran in TimeOut-Central. Randy Brandt wrote a monthly Ultra series in NAUG's Forum. U4 Compiler -----------GEMake regular use of the new labels feature to make your source files =;readable. Ultra 4 is not designed for recording macros and ECdecompiling, although that does work. The primary goal is to write DBtrue TAPL (The Appleworks Programming Language) programs that are 3readable, commented and modifiable in the future.HFUnfortunately, you may not nest labels. That is, a user-defined label 2may not be used within another label definition.FDUse the labels feature to name all of your macro sets. That way you FDwon't need to type the name when creating task files, and you won't GEhave to worry about making typing mistakes and creating two versions HFof a task file with slightly different names. Your default set stored ECin UM4.0.SYSTEM should be named "um4.0.system" to avoid confusion, Esince that's what it will be called once it's saved as the default.Debug-----FDIf a macro is giving you trouble, place several commands in GEthe macro at key places. That way you can examine the variables, and CAuse oa-v to examine the screen, so that you know exactly what is CAhappening as the macro progresses. When you press Escape to exit IGDebug, the macro will continue as if you never interrupted it, unless, IGof course, you modify some of the variables. Then it might work better than it would have otherwise.Loadvar and Savevar-------------------B@These two commands make is easy to do lots of screens and menus DBwithout using up macro table space. Design your screens and menus IGusing a bunch on the 99 strings available to you. Use one section with ECstring definitions, and make the actual menu commands use variable names instead of literal text.HFThen use .savevar to store these strings on disk. Your run-time macro FDset can use .loadvar to instantly define those strings and then use Gthem in menus without having stored all that text in the macro table.How Many Parentheses?---------------------HFTRIVIA: The highest number of consecutive legal parentheses in a TAPL @program is three, as in the third line of the following macro:start4a:!H@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===SuperFonts is finished.ts, and use to  Mouse Fixer -----------DBSometimes the mouse will lock up in GSOS applications after 8-bit IGprograms such as Ultra 4 have used the mouse. See the file "MouseFixer 7Docs" for a solution to this problem on ROM 3 IIgs's.======================Ultra 4.2 Manual Notes======================Task Files Page 8, 43 ----------@>A new Ultra 4 feature allows task files to be launched from a DBdirectory or disk other than the AppleWorks startup directory and ?=still find AppleWorks. For example, if your AppleWorks is in HF"/HD/APPLEWORKS" you could create a task file in "/HD/TASKS" and when ECit is launched from a program selector or Basic, it will still run APLWORKS.SYSTEM.FDThe task file will still work on other user's Apples if it's in the IGAppleWorks directory, since it checks the current directory first, and Fif that fails, looks where Ultra was when the task file was created.Find Change Page 18 -----------GESpreadsheet find: The "live find" feature in the spreadsheet is even FDmore limited than the manual mentions. If two consecutive cells are DBidentical, will stop on the second one. To keep searching, *press the down arrow followed by SA-Rtn.HFSince Z always returns a result that falls into the "at start" range, HFyou don't need to pre-define Z before doing s that are supposed @to match at the start like with the earlier versions of Ultra..KEY.TEST.MACROrwC )SEARCH.DB ~C )CONVERTER C )SAMPLE.SS!~S$DB.1*n $DB.29)SAMPLE.DBG~-DOT.MATHTOOLS.wx9$P@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== ECWhat do you do when you want a macro to keep running unless a user ECpresses a certain key? Or maybe you want the macro to do something GEdifferent when a key is pressed, but you don't want it waiting for a GEresponse? You can't use because it does nothing until a key is pressed.FDThe answer is simple- just check for the key with a peek, accessing +the Apple II key input location directly.GEThe following macro will keep updating a counter while you press any HFkey you'd like. It will display the key value on the message line and HFkeep going until you press Escape, at which time it will clean up the display, beep and stop.start=a:$1 = 'Press any key (Escape to stop) Last key: ' :2a = 0 : { initialize a counter } begin2x = peek $c000 : { peek the key location }>msg ' ' + $1 + str$ x + ' ' : { show last key pressed }%ifnot x = 27 then a = a + 1 :1oa-1 : print a : rpt : { keep going }Gelse{ Esc isn't aborting the macro, just passing control }1msg "" : bell : { clear bottom and beep }> poke $11ac,27>! restore Esc for stopping runaway macros@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<=== GEThis macro searches a series of DB categories for a specified string HFand returns the name of the category containing the data. It uses the 2"DB.1" file on the Ultra disk for demo purposes.ECThe macro prompts you to enter the desired search string, and then FDautomatically adds commas to the beginning and end of the number it IGwill search for. This is because the macro is specifically designed to CAsearch lists of numbers, and without the commas, you'd get false HFmatches on numbers like 1990 if you were just searching for 19 or 90. EBecause of this, search categories must begin and end with a comma.0Sample category entry: ,1960,1880,17,1776,196,IGOf course, if you just want a generic search macro, you can remove the >automatic comma addition code near the beginning of macro S.GECompile and press SA-A to try it out. Press Return or Escape to exit IGthe macro. Until then it will keep prompting you for another number to &find after each search is completed.labels .searchdb#FirstRec=1#FirstCat=5#LastCat=6#FirstStr=10#Count=C#LastRec=D#FoundCat=E#LastStr=LstartIG// this first macro checks for the desired file on the desktop, and if #it's not found, gets it from disk2a:!//get startedH----------------------------------------------------------------------0s: 0 then goto sa-F else//we found sumpinEnext S//try next categoryC next R //try next recordEmsg ' "' + $1 + '" was not found. '//announce failure,Cbell : goto sa-s>!// then try againH----------------------------------------------------------------------(// found something, so tell user wheref:!// let user look for another number@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===$1 = "call" :$2 = "jsr" :#replace  DBThis Ultra program attempts to simplify the process of converting GEUltra 3.x files to the new format. Compile and press SA-C to convert ?=many of the commands. Read the rest of this file for tips on .converting things we can't do automatically.B@Warning: If you're using tokens in comments or text, they'll be 5changed to the new versions as well, so be careful. inc decECAny items you've created with should be converted using the GE, , and commands, as menus are ?now completely different. See "Dot MenuTools" for an example.HFNow that Ultra has 260 numeric and 100 string variables, and HF have been dropped. The easiest way to convert your variables Gis to use the variable set number for your array number. For example:/Replace:b = 5 : putvar 1 : getvar 8 : c = 1with:b(1) = 5 : c(8) = 1ECFor an type method for checking for a key while a macro is 6running, see the file "Key Test Macro" on this disk.ECDue to formatting variations, we can't automate some commands, but this will help you do the job:1Replace:& "y/n" : & "Do you like Ultra 4.0" :3with:.menubar "Do you like Ultra 4","No|Yes"Replace:& "path" : & "/HD"with:.setdisk "/HD"%Replace:msgxy 255,4 : msg "dudes"#with:.writestr 255,4,"dudes"labels#replace = sa-rstart3:!//back to normalc:!1// subroutine to replace all $1 matches with $2;<#replace>:! CM1 NJ  NJP nS1991-92 Hockey Stats)PosGoalsAssistsPts Goal PctWFLametti, Gerry @ @$@?VDBrandt, Randy @ @$@?UD Polter, Marc @ @$@?1992-93 Hockey Stats)PosGoalsAssistsPts Goal PctZ FNeitenbach, Bryan .@ &@:@b'vb'v?W FLametti, Gerry *@ $@7@! YB?V DBrandt, Randy @ *@4@ffffff? 1993 Summer League)PosGoalsAssistsPts Goal PctWFVasquez, Benny @ @,@?VDBrandt, Randy @ @(@?XFEdmunston, Dave @ @(@?DD/  Namegory 1TeamAverageFourth  ;Y BFifthǀ Ӄ8{Sixth;|<| ߁SeventhLT`%Read an2 John SmithBill and Ted's Automotive1124567" Sue Jones ABC Rentals145howdyBill DoeBob's Automotive158@Jane Doe ABC Rentals215,1960,1972,1979,,1983,1985,1987,82,>Shad RoeTy's Fishworks178,1966,1976,1982,,1991,1993,19,   rbDD/  Namegory 1TeamAverageFourth  ;Y BFifthǀ Ӄ8{Sixth;|<| ߁SeventhLT`%Read an1 John SmithBob's Automotive1124th5th6th7th Susan Jones ABC Rentals145Bill DoeBob's Automotive158Jane Doe ABC Rentals220Koy RoeTy's Fishworks166   rbDD/      FirsttNameLaststameStreetCitytyStateeZipZipPhonee:John L.Weigh 23 Elm St.KenoshaWI11111(100) 555-1001ASusanKnight18 Bluebell Way CharlestonWV22222(100) 555-1002@ByronBlack9 Airport Blvd. TeeterboroNJ33333(100) 555-1003@RobinSmith13 Fertile CrescentPuebloCO44444(100) 555-1004EHarryFallsman155 Lancelot Dr. ArthurvilleTX55555(100) 555-1005;LindaWu108 Hillside Rd.TonopahNV66666(100) 555-1006?GastonGreen 210 Main St. Great FallsMO77777(100) 555-1007>ShawnFarrell2498 Coyote CynTucsonAZ88888(100) 555-10089MarySmits 634 Birch WayTucsonAZ88888(100) 555-1009FBO=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===@O=====<====<====<====<====<====<====<====<====<====<====<====<====<====<====<===NDemonstrate .xIntegersord 61453 : msg "I'd like some "labels#xA=$90#xB=$91 .xMathstuff \sa-aDemonstrate .Andbits!\sa-gDemonstrate .GetBlock\sa-gDemonstrate .GetPtr\sa-hDemonstrate .Hex\ba-hDemonstrate .HexStr \sa-wDemonstrate .HexWord\ba-mDemonstrate .Mod// Extended math commands!\sa-cDemonstrate .xCompare\sa-fDemonstrate .xFixed"\sa-iDemonstrate .xIntegers"\sa-jDemonstrate .xIntegers\sa-mDemonstrate .xMath\sa-sDemonstrate .xStrstartPNAlthough the MathTools init features the extended math commands, they're last MKin the list because we're keeping everything in alphabetical order to make PNcommands easier to find. Some special memory commands are included for direct HFdesktop access. They should be used with EXTREME caution, and only by *programmers who know what they're doing.------------------------x = .andbits a,bLJReturns the logical AND of the two values specified. If that doesn't make KIsense, you probably have no use for this command yet. For those eager to OMlearn, an AND compares two numbers bit by bit and sets the corresponding bit Cin the result byte to true only if both comparison bits are true.ABresult- - ------ 100 000 010 111;a: 53247 then//not text, maybe a carriage return:msg "Non-text line"// or a printer option,8stop endif// so stop right here<Adr = $BB00//IO Buffer for work area<.getblock Ptr,Adr,1//1 means normal GetBlockKz = z - 2//length of text is block length minus 2:poke $bb01,z//set the string length5$1 = .peekstr $bb01//grab the wp lineB// without this next line, would lock up trying to display0// the control characters which represent tabsB$2 = .subchar $1,0,31,#' ' //replace all codes with spacesBmsg $2//display the line as a message >!------------------------Ptr = .getptr AdrNLUse this command to grab a memory pointer from an open AppleWorks file. Adr JHspecifies an auxiliary memory address where the pointer is stored. This Gcommand could also be called .peekauxword, since that's what it does.#See macro G above for an example.------------------------ $1 = .Hex X,Convert a one-byte number to a hex string:<h:!------------------------X = .HexStr "$A"NConvert a hex string into a variable. Works with or without the leading "$".A:!------------------------x = .mod a,b.This command returns the remainder of A / B.L:!------------------------.putblock Ptr,Adr,Size,FlagKIThis command allows you to store a block on the desktop using the memory OMpointer specified by Ptr. Use 0 for Ptr if you want to allocate a new block. MKThe block starts at Adr and is Size bytes long. Flag determines the memory OMbanks involved. If Flag is 1, the block will be stored from main memory, and ?if Flag is 2, the block will be stored from auxiliary memory.NLZ is set to the new pointer value. If 0 is returned, there was insufficient $desktop memory to store the block.------------------------.putptr Adr, PtrIGUse this command to store a memory pointer in an open AppleWorks file, NLmodifying a line, record or row. Adr specifies the auxiliary memory address Fwhere Ptr is stored. This command could also be called .pokeauxword.------------------------.relblock PtrNLThis command releases a memory block back to the desktop. Death will result 'if Ptr is not a valid memory pointer.===========================Extended Math RoutinesCopyright 1992 by Mark Munz===========================G(Modified by Randy Brandt after Mark's retirement from the Apple II.)JHThe extended math commands allow 26 special Ultra 4 variables to handle MKnumbers ranging from negative 21 million to positive 21 million with up to JHtwo decimal places. This allows you to calculate financial transactions OMwithout needing the spreadsheet, or to do any other math which is beyond the *range of Ultra's normal 0-65535 limits. LJOne limitation is that the result of a multiplication or division can not LJexceed 214,748.36, at least if you want an accurate answer. Additions and MKsubtractions work all the way up to the maximum value. Multiplications and JHdivisions are limited because of the need to maintain two decimal place accuracy.PNHere are the ranges. (The second columns have commas to make the numbers more PNreadable, but you can't use commas in your macros. You must write the numbers 5as they appear in the first columns of each group.)BExtended VariablesNormal Ultra 4B--------------------------------?Lowest: -21474836.47-21,474,836.4700DHighest:21474836.47 21,474,836.476553565,535MKTechnical trivia: Ultra variables are two bytes, hence the range from 0 to OM$FFFF. Extended variables are four bytes, with one bit reserved for the sign 9(pos or neg), hence the range is -7FFFFFFF to 7FFFFFFF.MKTwo commands do the majority of the extended variable work: .xMath handles IGthe math operations, and .xStr makes results displayable. All extended Jvariables are identified by a preceding "`" symbol, as in the following:I*** a:!//define a very small number"Debug 2.2 and Extended Variables"--------------------------------JHPress OA-X from the Debug main screen to access extended variables. The PNcurrent values are displayed, along with the .xFixed and .xIntegers settings. 1You may edit the variables directly with Debug.------------------------$1 = .xcompare AMKThe .xCompare command converts extended variables into strings which allow PNyou to compare extended numbers using or statements and have the Nresults work correctly even when negative numbers and decimals are involved.Hc: `B:" + $4 : elseCif #xA < #xB then msg "`A:" + $3 + " < `B:" + $4 : else>if #xA = #xB then msg "`A:" + $3 + " = `B:" + $4>!------------------------ .xFixed 128HFThe .xFixed command sets the number of decimal places used when .xstr PNconverts an extended variable to a displayable string. Legal values are 0, 1, PN2, and 128. 128 defines appropriate (no trailing zeros). The default value is 2 until .xFixed is used.Of:!//restore the default setting------------------------.xIntegers #FalseOMThe .xIntegers command determines how normal Ultra variables are used by the PN.xMath command. The default setting is 1 (#True) which means they are treated LJas integers, or whole numbers. If .xIntegers #False is used to change the FDsetting, the Ultra variables are treated as hundredths. To simplify Munderstanding this, think of integers as dollars and hundredths as pennies.F// treat Ultra variables as integers (dollars) using default settingMi:  N `  ` x V Nx .x- z `V0^*^*>` aI꽌ɪVɭ&Y&&Y& 꽌ɪ\8`&&꽌ɪɖ'*&%&,E'зЮ꽌ɪФ`+*xH&x'8*7Ixix&&  ') + &п x) ++`FG8`0($ p,&" X $ % ) ԠРˮ"_"_ U ! dL])SS` `fU %_zRzKRRU 54#'z5 67L^UǍUL^L^))U*UL^U Dͭ U0UL^#_$_ ၩU D8Ɂ; 5- %  `ɠɯLV^ е _L^ _UUSL^ `^5S `L]S8UUL^S`SS|L^)S SL^#_$_` ){12)͊{L__2Tz)Sz zzz{_ Kz'z({_  m`12)͊{L`2TzU)Sza{  ***` Z{JJJ))_z)` ` (`i ` (8`(` ``UU D` ɮ8``"LchgUU*nUU2RUUUUoLcUU#dUgUcgUUUU LfLfX8 Lf LfU 腐LfLf Lf2RλUULfLZd ޠLfU PLe  DLf 6 C Lf0UU ;U) Lf LfU) ÍU Lf Lf8 U{ U  LfUz魼U U 턐Lf g ÍUUUUUUUUUUUUUUUUU Lf U }LfLf  xLfUUU | LfU_ *n*  x\UUUUUUUU #? : 2UUigUjgUkgUlgU  λUU2L`& 0 pf Kf ! m` _lUUJUnUjUUUn tn# m lii n` 8``S[AASS l( TS(`S) lSTS 舌ST`[A`{a8   i@0@ݩ.٭UUUUU` R RR8 m` R RR mR RR R8R R2R*nU` U ( )LT?]B C Ü s t H   sLq hrS s r H LqN sLq H R]< => ?BSC8 íS0BTBTT/T8SmTATȢSTT`@`ÍUTU &N.) $ UUUU  ` r8` S ؃L1s hTUBU Ӏ {JJJ{ {{{ |Hȱh `{+8 Hhh{{`BFG{C {{,(`l{Hh`{ {` | { { {`z){z)nzjz` {{zzzjz8iH{ zzz |zz |h _| {RH |z |z |z |zh _| {` Ȋ8j`h8``{ |` | |``8{  `{{ ϭ8`{{` ͚L ULX~ =7Y h 쁩UU x" ULX}U Lz} < K ! mU` /]6890U){ |_ zzz K8#6 8#9!z'z( m8k3c KU$U% mL~8L~UUL~SRS ؃RS Kz${% mL} : KU$U% mL}UUL 8w !L~ L~ L~ $L~ $9TT=B<mBT>Ti?L~S= CB  K mH 9` K  mSU` K!  mUU ٩U`#UUU`HHHU KU"U$ȱ% mU:U;ȱ<U)UUSmUUʱ ɠ S Shhh`UU S L3 ){ |_ z t9 DUUUU歊UU ( ` ``UUS KT K mH ZCB =< ?\>8 íU/T(T/!TL]S S/SLx`SDUSDUTDUTDUDUEU`DUDU DU`HH UTUCU nL8CT)BTBT/CTU #/BTSCTȽSCTSBTChhC`HH UTUčU nLT)TT/TTTTȽTTTTChhC`zUzU` UU  Lބ3` <8` UU  LބC`UUOUU ݀`8UUUUUUU*UU*U U`UU  Lބ3`8`UU  C`H)12)ͼh`h8` UUUU Lބ8 ф` UUUU Lބ8 `UUUU Ly8 j` hBTCT/TUBU x0`8`U` ɀ Ӏ0`jUU`S TST`BT TBTT`T BTTBT`T STS`!UU`! `#O`U U`U 8 n`OUU`T//U ( ,% ` , ( ` ɀ Ӏ` . `OUU`O<)#ȹT/򈘠 )U`U iо8`!` U=H ~`cgg\gUcgLlH UUU h ' #  U2RH h`H h8`ͭ :TUȱUU M69UU WUU LUeЯ CЪ` <8`UtUUUUUUU #Ug 5"8 UUU  Κ ϋUU ` 8 íUT!T/TLBT BT/BTL`T=B CB  K mH `!BTDUCT)EUBT+CT/DULOTDUT)EUT T/DUUUDU  <8LyU8UzUU{` 䇭UUUUUU rpU/ mU T 䇀/fg Dgg 䇭fg Ɂcg UU UUUUUUUU ` <8`U RU RU Ɂ rU+ ŎUU ! Rҭ RU8!U L荭U!O8 R R0. R R#O Rǭ R8``#` UFUU ݀L ၠ G$DU $LEU DULLGi̭F $LF $U $U $U $UFLΉU ݀vFG8ΉU ݀XF) $C* $6' $)( $ $ $F`8`U U ݀` F 8i񩀍F` UUU ݀U UUU ` <8`izzjM bi ii8Li𐳥iL`UV7% / )#$%z8z !+mU-,mU .`UV 8` 8`z"z!& &BiߥiLȱ" ߈!ՠ!ȱ"ȱ#ȱ$Lґ`U U`8` ၭi ii8`UU ၠiUU 瀰UUUU` <8`+ , - . U  T T  U U U U ``!8"mUUiV` UU#cgUUUUUU ݀LcgUUUU UUU UUUO` <8` UUULLUUO# ` <8` .$  `UUU#`UU 瀐LK`U! .cg .cg## 토iLՔ ᔰ U Li 4ii  LՔ  `i  L`"`8`O` `!```U UU7 >sU)U edULUU!UUU L)U KU& mU- TL 9̭Ux eUпn K  mU` K:)@ " m 9!U eUU K !! K!  m`U K!  mU`΢U8i#i `8``URR ၢ UULLLL8U LU LmUU $RЬ ၩ ei`U8`U UU DLߘU?U@U ၭU꘍󘨭 Lߘ ၠLg L ΥULg L } K"& m) S .S S Sɀjj(iLi(mm(ΥU K$% mΥU K!  m`U` K!  mU`hhUHHHHH`hhhhhUHH` ee`  S S `8` U`  U '7J UTUCU nCT)BT%LNUL7SCTSBTCTBT ךLNUU U)L>&U%UUL$UUU#U ΥUΦUL b L4UUUUU b LN L")U KU&:"!  m` K!  mU ͚` < ͚ K  m ͚ < K! mU`΢UΤU UUUei`8`U UUUU UUUUUU `L8`UU `U  쁩UU x`r=?Cօ8  Q S K! m`H 1ȹ1)ͯhh1Ӡr `L S`U UU7 >LU_ULU"8%080UUU ݀L ၩeiUUUUU L K& mS L28;;ȱ<< K;$<% m ΥUU K!  m` K!  mU` K  mU`ei`U Ƀ 1R # +L&R L& R RR R-.R/U2RU8+`-./R2R R RL 1R R R#,UL~ RR2RU0R R R RLLHȱhRR1R L1R LRR RORL~ RL~ R8 R RU8&R/-.&`U`HH8 Ƀ 1RUcd , + LLR LR1R L RȭU UȢEU RRR L ݧL ۢL RRR RU <8xyRzhh`HHxyzR 1R R#R R$R6 R RLeUC { 餐 L| R$R8xyRzabhh`U abL蟩!mmUmm#R$RH0F_` 餐 L}L|_`!#Rб$RШL}2RL} m UF  fg! 餰9ݠ 餰- 䇭fgϩ! L|2RL}L|ݠ nLǠ#ݠ`HH 1R#R { 餐LhRRR!HRh LhRL ݧLhR LhU <8whhw`` Ƀ( 1RU +LWȱ X LVR ̦LS LSRRR+R g RRȱ gRRRL ݧLSRHh R1R LS <8`< LV |88JJ`H9YI) RmRh` @HH YL΢ RRRR8ڢhhڢ`HHRHRHRRR LR ϥLRR R" LRRRȽR ϥLR8fhRhRhhf`HHH L}888hhh`HRRLRRRh`HHR%R'R)R+R-R'RR) %R)R+RU)UUUR R!R ̦ ֠LԮ@ ˵L+@ Kҥҭ?BC8 + +Hh@ <ԥ&JJJȱ>'JJJ3ȱ>*JJJfȱ>J&*J&'J&&ȱ>J&*J&'J̻&*)')3*)f>)JJJ`80|'x&Hh & 󸩪 󸩭 󸘠Y'&Yxꪽ' 󸩪 󸽎`Hh` aI꽌ɪ򠚽ɭ&Y&&Y& 꽌ɪ\8`&&꽌ɪɵ'*&%&,E'зЮ꽌ɪФ`2JJJ'J&J>Ƚ3JJJJ&'J&&3>ȽfJJJJ&'J&&f>ȥ&)>ȥ')̻>JJJ >`*xY+&x'8*BIxix&&  x) + ') + &д_ +`FG8`0($ p,&" (0 8@ HPX !"#$`h%&px')*+,-./12345679:;<>) JxR(*iyR{R|RzRwR RS8 xRRyRR`HIHHh݌H6 BGKPUֶڶZlZlZlZlZlZ lZ lZlZlZlZl`@ `(HP  U  ȹȹ @ȹ ȹ ȹ ȹ ȹ {xyz|}~T`