<<

FMSLogo 8.1.0 FMSLogo 8.1.0 Copyright © 1989 The Regents of the University of California Copyright © 1993-1997 George Mills Copyright © 1998-2003 Neil Hodgson

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Portions of the editor are copyrighted by Neil Hodgson.

Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation.

NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Table of Contents

Introduction ...... xvi Why Logo? ...... xvi Where to Start ...... xvii 1. Command Line Options ...... 1 Configuring the FMSLogo shortcut ...... 3 Invoking and Exiting FMSLogo ...... 6 2. Editor ...... 7 Editor Menu ...... 7 File Menu ...... 7 Edit Menu ...... 8 Search Menu ...... 8 Set Menu ...... 9 Test Menu ...... 9 Help Menu ...... 9 Editor Errors ...... 9 Editing with the Clipboard ...... 9 Context Sensitive Help ...... 10 3. Commander ...... 11 Input Box ...... 11 Output/Command-Recall List Box ...... 11 Execute Button ...... 11 Status Button ...... 11 Trace Button ...... 11 Halt Button ...... 12 Reset Button ...... 12 Step Button ...... 12 Pause Button ...... 12 Edall Button ...... 12 4. Main Menu ...... 13 File Menu ...... 13 File - New ...... 14 File - Load...... 14 File - Open...... 14 File - Save ...... 14 File - Save As...... 14 File - Set As Screen Saver ...... 14 File - Edit...... 14 File - Erase...... 14 File - Exit ...... 14 Bitmap Menu ...... 15 Bitmap - New ...... 15 Bitmap - Load...... 15 Bitmap - Save...... 15 Bitmap - Save As...... 15 Bitmap - Print...... 15 Bitmap - Printer Setup...... 15 Bitmap - Active Area...... 15 Set Menu ...... 16 Set - Pen Size...... 16 Set - Label Font...... 16 Set - Commander Font...... 16

iii FMSLogo 8.1.0

Set - Pen Color...... 16 Set - Flood Color...... 16 Set - Screen Color...... 16 Zoom Menu ...... 17 Zoom - In ...... 17 Zoom - Out ...... 17 Zoom - Normal ...... 17 Help Menu ...... 17 Help - Index ...... 17 Help - Tutorial ...... 17 Help - Demo ...... 17 Help - Examples ...... 17 Help - Release Notes ...... 18 Help - About FMSLogo ...... 18 Help - About MS ...... 18 5. Language Mechanics ...... 19 Tokenization ...... 19 Procedure Loading ...... 20 6. Data Structure Commands ...... 21 Data Structure Constructors ...... 22 WORD ...... 22 LIST ...... 22 SENTENCE ...... 23 FPUT ...... 23 LPUT ...... 23 ARRAY ...... 23 MDARRAY ...... 24 LISTTOARRAY ...... 25 ARRAYTOLIST ...... 25 COMBINE ...... 25 REVERSE ...... 26 SORT ...... 26 GENSYM ...... 27 Data Structure Selectors ...... 27 FIRST ...... 28 FIRSTS ...... 28 LAST ...... 28 BUTFIRST ...... 28 BUTFIRSTS ...... 29 BUTLAST ...... 29 ITEM ...... 29 MDITEM ...... 30 PICK ...... 30 REMOVE ...... 30 REMDUP ...... 31 QUOTED ...... 31 Data Structure Mutators ...... 31 SETITEM ...... 32 MDSETITEM ...... 32 .SETFIRST ...... 32 .SETBF ...... 33 .SETITEM ...... 33 PUSH ...... 33 POP ...... 34

iv FMSLogo 8.1.0

QUEUE ...... 34 DEQUEUE ...... 35 Data Structure Predicates ...... 35 WORDP ...... 35 NUMBERP ...... 36 LISTP ...... 36 ARRAYP ...... 36 EMPTYP ...... 37 EQUALP ...... 37 NOTEQUALP ...... 38 BEFOREP ...... 39 .EQ ...... 39 MEMBERP ...... 40 SUBSTRINGP ...... 40 BACKSLASHEDP ...... 40 Data Structure Queries ...... 41 COUNT ...... 42 ASCII ...... 42 RAWASCII ...... 42 CHAR ...... 43 MEMBER ...... 43 LOWERCASE ...... 43 UPPERCASE ...... 44 STANDOUT ...... 44 PARSE ...... 44 RUNPARSE ...... 44 TIME ...... 45 TIMEMILLI ...... 45 7. Communication ...... 46 Transmitters ...... 47 PRINT ...... 47 TYPE ...... 48 SHOW ...... 48 Receivers ...... 48 READLIST ...... 48 READWORD ...... 49 READCHAR ...... 50 READCHARS ...... 50 READRAWLINE ...... 51 File Access ...... 51 OPENREAD ...... 52 OPENWRITE ...... 53 OPENAPPEND ...... 53 OPENUPDATE ...... 54 CLOSE ...... 56 ALLOPEN ...... 56 CLOSEALL ...... 56 ERASEFILE ...... 57 DRIBBLE ...... 57 NODRIBBLE ...... 58 SETREAD ...... 58 SETWRITE ...... 59 READER ...... 59 WRITER ...... 59

v FMSLogo 8.1.0

SETREADPOS ...... 60 SETWRITEPOS ...... 60 READPOS ...... 61 WRITEPOS ...... 61 EOFP ...... 62 Hardware Communications ...... 62 PORTOPEN ...... 63 PORTCLOSE ...... 63 PORTFLUSH ...... 63 PORTMODE ...... 64 PORTREADARRAY ...... 64 PORTREADCHAR ...... 64 PORTWRITEARRAY ...... 65 PORTWRITECHAR ...... 65 INPORT ...... 66 OUTPORT ...... 66 INPORTB ...... 66 OUTPORTB ...... 67 INGAMEPORT ...... 67 DLL Communications ...... 67 DLLLOAD ...... 67 DLLCALL ...... 68 DLLFREE ...... 71 Keyboard and Mouse Access ...... 71 KEYP ...... 71 KEYBOARDON ...... 71 KEYBOARDOFF ...... 73 KEYBOARDVALUE ...... 73 MOUSEON ...... 77 MOUSEOFF ...... 77 MOUSEPOS ...... 78 CLEARTEXT ...... 78 SETCURSOR ...... 78 CURSOR ...... 78 SETMARGINS ...... 79 8. Arithmetic ...... 80 Numeric Operations ...... 81 SUM ...... 81 DIFFERENCE ...... 81 MINUS ...... 82 PRODUCT ...... 82 QUOTIENT ...... 82 REMAINDER ...... 83 MODULO ...... 83 INT ...... 84 ROUND ...... 84 ABS ...... 84 SIGN ...... 85 SQRT ...... 85 POWER ...... 85 EXP ...... 85 LOG10 ...... 86 LN ...... 86 PI ...... 86

vi FMSLogo 8.1.0

GOLDENRATIO ...... 86 TAN ...... 87 RADTAN ...... 87 SIN ...... 87 RADSIN ...... 87 COS ...... 88 RADCOS ...... 88 ARCTAN ...... 88 RADARCTAN ...... 89 ARCSIN ...... 89 RADARCSIN ...... 89 ARCCOS ...... 89 RADARCCOS ...... 90 Arithmetic Predicates ...... 90 LESSP ...... 90 LESSEQUALP ...... 90 GREATERP ...... 91 GREATEREQUALP ...... 91 Random Numbers ...... 92 RANDOM ...... 92 RERANDOM ...... 93 Print Formatting ...... 93 FORM ...... 93 Bitwise Operations ...... 93 BITAND ...... 93 BITOR ...... 94 BITXOR ...... 94 BITNOT ...... 94 ASHIFT ...... 94 LSHIFT ...... 95 9. Logical Operations ...... 96 AND ...... 96 OR ...... 96 NOT ...... 96 10. Graphics ...... 98 Multiple Turtles ...... 100 SETTURTLE ...... 101 TURTLE ...... 102 HASOWNPENP ...... 102 TURTLES ...... 102 BITMAPTURTLE ...... 103 NOBITMAPTURTLE ...... 104 SETTURTLEMODE ...... 104 TURTLEMODE ...... 106 ASK ...... 106 Turtle Motion ...... 106 FORWARD ...... 107 BACK ...... 107 LEFT ...... 107 RIGHT ...... 107 LEFTROLL ...... 108 RIGHTROLL ...... 108 DOWNPITCH ...... 108 UPPITCH ...... 108

vii FMSLogo 8.1.0

SETPOS ...... 109 SETPOSXYZ ...... 109 SETXY ...... 110 SETXYZ ...... 110 SETX ...... 111 SETY ...... 111 SETZ ...... 111 HOME ...... 112 SETHEADING ...... 112 SETROLL ...... 112 SETPITCH ...... 113 SETORIENTATION ...... 114 ELLIPSEARC ...... 115 ELLIPSEARC2 ...... 115 ELLIPSE ...... 117 ELLIPSE2 ...... 117 ARC ...... 118 ARC2 ...... 118 CIRCLE ...... 119 CIRCLE2 ...... 119 Turtle Motion Queries ...... 119 POS ...... 120 POSXYZ ...... 120 XCOR ...... 120 YCOR ...... 120 ZCOR ...... 121 HEADING ...... 121 ROLL ...... 121 PITCH ...... 121 ORIENTATION ...... 122 TOWARDS ...... 122 TOWARDSXYZ ...... 122 DISTANCE ...... 123 DISTANCEXYZ ...... 123 PIXEL ...... 123 SCRUNCH ...... 124 Turtle Control ...... 124 SHOWTURTLE ...... 125 HIDETURTLE ...... 125 CLEAN ...... 125 CLEARSCREEN ...... 125 WRAP ...... 126 WINDOW ...... 126 FENCE ...... 126 PERSPECTIVE ...... 127 FILL ...... 129 SLOWDRAW ...... 131 LABEL ...... 131 SETPIXEL ...... 133 FONTFACENAMES ...... 133 SETLABELFONT ...... 134 LABELFONT ...... 135 LABELSIZE ...... 135 Window Control ...... 136

viii FMSLogo 8.1.0

TEXTSCREEN ...... 136 FULLSCREEN ...... 136 SPLITSCREEN ...... 136 SETSCRUNCH ...... 137 REFRESH ...... 137 NOREFRESH ...... 137 ZOOM ...... 137 SCROLLX ...... 138 SCROLLY ...... 138 SETFOCUS ...... 138 GETFOCUS ...... 139 ICON ...... 139 UNICON ...... 139 MINIMIZE ...... 140 RESTORE ...... 140 MAXIMIZE ...... 140 WINDOWSET ...... 141 Using Color ...... 142 Understand Your Orientation in 3D ...... 151 Drawing 3D Solids ...... 152 POLYSTART ...... 153 POLYEND ...... 154 POLYVIEW ...... 154 SETLIGHT ...... 155 LIGHT ...... 155 Polygon Restrictions ...... 156 Restriction #1: A polygon's first 3 vertices must form a triangle ...... 156 Restriction #2: A polygon must be convex ...... 156 Restriction #3: A polygon must be planar ...... 157 Polygon Samples ...... 158 Turtle And Window Queries ...... 158 SHOWNP ...... 158 Pen Control ...... 158 PENDOWN ...... 159 PENUP ...... 159 PENPAINT ...... 159 PENERASE ...... 160 PENREVERSE ...... 160 PENNORMAL ...... 160 SETPENCOLOR ...... 160 SETFLOODCOLOR ...... 161 SETSCREENCOLOR ...... 161 SETPENSIZE ...... 162 SETPENPATTERN ...... 162 SETPEN ...... 162 CLEARPALETTE ...... 163 Pen Queries ...... 163 PENDOWNP ...... 163 PENMODE ...... 164 PENCOLOR ...... 164 FLOODCOLOR ...... 164 SCREENCOLOR ...... 165 PENSIZE ...... 165 PENPATTERN ...... 165

ix FMSLogo 8.1.0

PEN ...... 165 11. Workspace Management ...... 167 Procedure Definition ...... 168 TO ...... 168 END ...... 170 DEFINE ...... 171 TEXT ...... 171 FULLTEXT ...... 172 COPYDEF ...... 172 ARITY ...... 172 Variable Definition ...... 173 MAKE ...... 174 NAME ...... 174 LOCAL ...... 174 LOCALMAKE ...... 175 THING ...... 175 Property Lists ...... 176 PPROP ...... 176 GPROP ...... 176 REMPROP ...... 177 PLIST ...... 177 Workspace Predicates ...... 178 PROCEDUREP ...... 178 PRIMITIVEP ...... 178 DEFINEDP ...... 179 NAMEP ...... 179 MACROP ...... 179 PROPLISTP ...... 180 Workspace Queries ...... 180 CONTENTS ...... 180 PROCEDURES ...... 181 NAMES ...... 181 PLISTS ...... 181 NAMELIST ...... 181 PLLIST ...... 182 BURIED ...... 182 STEPPED ...... 182 TRACED ...... 182 Workspace Inspection ...... 183 PO ...... 183 POALL ...... 183 POPS ...... 184 PONS ...... 184 POPLS ...... 184 PON ...... 185 POPL ...... 185 POT ...... 185 POTS ...... 185 Workspace Control ...... 186 ERASE ...... 186 ERALL ...... 187 ERPS ...... 187 ERNS ...... 188 ERPLS ...... 188

x FMSLogo 8.1.0

ERN ...... 188 ERPL ...... 189 BURY ...... 189 BURYALL ...... 190 BURYNAME ...... 190 UNBURY ...... 190 UNBURYALL ...... 191 UNBURYNAME ...... 191 TRACE ...... 192 UNTRACE ...... 192 STEP ...... 193 UNSTEP ...... 194 EDIT ...... 194 EDALL ...... 194 EDALLBTN ...... 195 EDPS ...... 198 EDNS ...... 199 EDPLS ...... 199 EDN ...... 200 EDPL ...... 200 SAVE ...... 200 SAVEL ...... 201 LOAD ...... 201 Debug Commands ...... 202 NODES ...... 202 STATUS ...... 203 NOSTATUS ...... 203 12. Control Structures ...... 204 Control Commands ...... 205 RUN ...... 206 RUNRESULT ...... 206 REPEAT ...... 206 REPCOUNT ...... 206 IF ...... 207 IFELSE ...... 207 TEST ...... 208 IFTRUE ...... 208 IFFALSE ...... 209 TRUE ...... 209 FALSE ...... 209 STOP ...... 210 OUTPUT ...... 210 CATCH ...... 210 THROW ...... 211 ERROR ...... 212 PAUSE ...... 213 CONTINUE ...... 213 YIELD ...... 214 NOYIELD ...... 214 EVENTCHECK ...... 215 SETCURSORWAIT ...... 216 SETCURSORNOWAIT ...... 216 HALT ...... 216 WAIT ...... 217

xi FMSLogo 8.1.0

SETTIMER ...... 217 CLEARTIMER ...... 217 BYE ...... 217 .MAYBEOUTPUT ...... 218 IGNORE ...... 218 ` ...... 218 FOR ...... 219 FOREVER ...... 220 DO.WHILE ...... 220 WHILE ...... 221 DO.UNTIL ...... 221 UNTIL ...... 222 Template-Based Iteration ...... 222 Explicit-Slot Templates ...... 223 Named-Procedure Templates ...... 223 Named-Slot Templates ...... 223 APPLY ...... 223 INVOKE ...... 224 FOREACH ...... 224 MAP ...... 225 MAP.SE ...... 225 FILTER ...... 226 FIND ...... 226 REDUCE ...... 226 CROSSMAP ...... 227 CASCADE ...... 228 CASCADE.2 ...... 229 TRANSFER ...... 229 ISEQ ...... 229 RSEQ ...... 230 # ...... 230 ? ...... 231 13. Macro Commands ...... 233 .MACRO ...... 233 .DEFMACRO ...... 235 MACROEXPAND ...... 235 14. Error Processing ...... 236 Error Codes ...... 236 15. Special Variables ...... 239 CASEIGNOREDP ...... 239 ERRACT ...... 239 PRINTDEPTHLIMIT ...... 239 PRINTWIDTHLIMIT ...... 240 REDEFP ...... 240 STARTUP ...... 241 16. Help Commands ...... 242 HELP ...... 242 WINHELP ...... 242 17. Environment Commands ...... 243 LOGOVERSION ...... 243 MACHINE ...... 243 SHELL ...... 245 18. Directory Commands ...... 247 DIR ...... 247

xii FMSLogo 8.1.0

FILES ...... 247 DIRECTORIES ...... 247 CHDIR ...... 248 POPDIR ...... 248 MKDIR ...... 248 RMDIR ...... 248 19. Windows Commands ...... 250 Window Commands ...... 251 WINDOWCREATE ...... 251 WINDOWDELETE ...... 252 WINDOWENABLE ...... 252 Dialog Commands ...... 253 DIALOGCREATE ...... 253 DIALOGDELETE ...... 253 DIALOGENABLE ...... 254 Listbox Commands ...... 254 LISTBOXCREATE ...... 254 LISTBOXDELETE ...... 255 LISTBOXENABLE ...... 255 LISTBOXGETSELECT ...... 256 LISTBOXADDSTRING ...... 256 LISTBOXDELETESTRING ...... 257 Combobox Commands ...... 257 COMBOBOXCREATE ...... 257 COMBOBOXDELETE ...... 258 COMBOBOXENABLE ...... 258 COMBOBOXGETTEXT ...... 259 COMBOBOXSETTEXT ...... 259 COMBOBOXADDSTRING ...... 259 COMBOBOXDELETESTRING ...... 260 Scrollbar Commands ...... 260 SCROLLBARCREATE ...... 261 SCROLLBARDELETE ...... 262 SCROLLBARENABLE ...... 262 SCROLLBARSET ...... 263 SCROLLBARGET ...... 263 Button Commands ...... 264 BUTTONCREATE ...... 264 BUTTONDELETE ...... 265 BUTTONENABLE ...... 265 BUTTONUPDATE ...... 265 Static Commands ...... 266 STATICCREATE ...... 266 STATICDELETE ...... 267 STATICUPDATE ...... 267 Group Box Commands ...... 267 GROUPBOXCREATE ...... 267 GROUPBOXDELETE ...... 268 Checkbox Commands ...... 268 CHECKBOXCREATE ...... 269 CHECKBOXDELETE ...... 270 CHECKBOXENABLE ...... 270 CHECKBOXSET ...... 270 CHECKBOXGET ...... 271

xiii FMSLogo 8.1.0

Radio Button Commands ...... 271 RADIOBUTTONCREATE ...... 271 RADIOBUTTONDELETE ...... 273 RADIOBUTTONENABLE ...... 273 RADIOBUTTONSET ...... 273 RADIOBUTTONGET ...... 274 Debug Commands ...... 274 DEBUGWINDOWS ...... 274 Modal vs. Modeless Windows ...... 275 MESSAGEBOX ...... 275 YESNOBOX ...... 275 SELECTBOX ...... 276 QUESTIONBOX ...... 276 DIALOGFILEOPEN ...... 277 DIALOGFILESAVE ...... 277 WINDOWFILEEDIT ...... 278 Example Code for Constructing a Window ...... 278 20. Bitmap Commands ...... 280 BITCUT ...... 280 BITCOPY ...... 281 BITPASTE ...... 281 BITPASTETOINDEX ...... 281 BITFIT ...... 282 SETBITINDEX ...... 283 BITINDEX ...... 284 SETBITMODE ...... 284 BITMODE ...... 285 BITBLOCK ...... 285 BITLOAD ...... 286 BITSAVE ...... 286 BITSIZE ...... 287 BITLOADSIZE ...... 287 GIFLOAD ...... 287 GIFSAVE ...... 287 GIFSIZE ...... 289 SETACTIVEAREA ...... 289 ACTIVEAREA ...... 289 21. Networking Commands ...... 290 Networking Tools (Outside of FMSLogo) ...... 290 NETSTARTUP ...... 292 NETSHUTDOWN ...... 292 NETACCEPTON ...... 292 NETACCEPTOFF ...... 293 NETACCEPTRECEIVEVALUE ...... 293 NETACCEPTSENDVALUE ...... 294 NETCONNECTON ...... 295 NETCONNECTOFF ...... 296 NETCONNECTSENDVALUE ...... 296 NETCONNECTRECEIVEVALUE ...... 297 22. Multimedia Commands ...... 299 MIDI Commands ...... 299 MIDIOPEN ...... 299 MIDICLOSE ...... 300 MIDIMESSAGE ...... 300

xiv FMSLogo 8.1.0

MIDI Table ...... 301 MIDI Instrument ...... 302 Sound Wave Commands ...... 306 PLAYWAVE ...... 306 Sound Commands ...... 307 SOUNDON ...... 307 SOUNDOFF ...... 307 TONE ...... 308 SOUND ...... 308 Media Control Commands ...... 308 The Media Control Interface ...... 308 MCI ...... 313 Glossary ...... 314

xv Introduction

Why Logo? ...... xvi Where to Start ...... xvii

Why Logo?

With so many programming languages to choose from, why would someone choose Logo? When Logo was created in 1967, it was at least as powerful as any of its contemporaries. The world of computing has changed a lot since then and the demands of the industry have given rise to many new languages that offer new powerful features. During that time, Logo did not change much. Today, Logo lacks many features that are necessary in industry and so it is not used by professional programmers for anything but small projects.

So if Logo is not used by professional programmers, why use it at all?

For one, Logo was not designed to create industry-grade software, it was designed as a tool to help children learn an important skill, one that is as important today as it was in 1967: the skill of learning how to learn. The new language features that industry has demanded are irrelevant for helping people learn to learn. While other languages are designed around abstract concepts in computer science, Logo is designed around how people learn. The basic philosophy of Logo is that education should focus on learning, not teaching, and that learning happens best when the learner is mentally engaged in a constructive project. The programmer assumes the role of "teacher" and learns by "teaching" a computer to do things. The Logo language is not, itself, the subject to learn, rather it is a tool to explore ideas in areas such as art, music, mathematics, intelligence, and language.

In a sense, Logo's lack of features is one of its best features. Many full-featured programming languages require complex setup. Before you can start to program in them, you must learn about things like , syntax, virtual machines, classes, and entry points. Such things are important for a professional, but they are unnecessary obstacles for a beginner. With Logo, you are ready to start programming as soon as the Logo environment starts. Every instruction that you type is run immediately. This gives you instant feedback on your instructions, whether they do what you expect or not.

Another advantage of Logo is its support for "". Turtle graphics is a simple and powerful set of commands used to manipulate a screen object called a turtle. The idea behind turtle graphics is that you program by giving instructions to a "turtle" (represented in FMSLogo as a triangle) and these instructions make the turtle walk around on the screen, drawing a line wherever it goes. With just a few keystrokes, you can program the computer to draw a line on the screen. For example FD 100 means "turtle, walk 100 steps forward". By adding more instructions, you can program the computer to draw complete pictures.

Turtle graphics brings computer programming into a world that is familiar to children, one of colors, shapes, and art. It enables a child to start programming at a stage in their cognitive development before they understand symbolic reasoning.

Logo has a simple syntax that requires less typing than other languages, which is especially important for children who are not yet confident typists. As you've seen, you can draw a line on the screen by writing FD 100. In other languages, an equivalent instruction might be Turtle.Forward(100); and if you forget one of the syntactic elements, like the semi-colon at the end, you'll get a difficult-to-understand error message, like "syntax error: unterminated statement", which is meaningless to a beginner.

Even though Logo is not for professional programming, this doesn' mean that it's only for children. Many adults mistakenly think that programming is like arithmetic and that programming must be as boring as doing taxes or balancing a checkbook. In truth, programming is closer to carpentry and art. It couples the

xvi Introduction

excitement and satisfaction of constructing something with an artistic sense of refinement in making that thing beautiful in its expression. This may sound far-fetched, but the more you program, the more you'll come to understand it as true. Moreover, programming is a rewarding and worthwhile intellectual pastime for an adult, whether or not they are a professional programmmer. In the same way that trying to prove Fermat's Last Theorem is worthwhile for someone who isn't a professional mathematician, or painting is worthwhile for someone who is never going to be a professional artist, or learning to play the piano is worthwhile for someone who is never going to perform for anyone beyond their friends and family, amateur programming can enrich your life. If you're not trying to create software for the industry, then you don't need to use any of the languages that are used by the industry. Logo is a good place to start. Where to Start

Novices can start in Logo without having to program at all by just learning how to command the turtle. Learning turtle graphics teaches the user about geometry. It's amazing how soon you can introduce the concept of programming once they grasp the turtle concept. Let's look at some simple examples:

Draw a square using the turtle.

FORWARD 100 RIGHT 90 FORWARD 100 RIGHT 90 FORWARD 100 RIGHT 90 FORWARD 100 RIGHT 90

That was easy but too much typing, let's try again.

REPEAT 4 [FD 100 RT 90]

That's it? Yes, that's the same square. We did two things. We noticed a lot of repeated instructions in our first example, so we asked Logo to repeat the same sequence 4 times. We also used abbreviated forms of the same commands. But we can still do better. Wouldn't it be more useful just to say "square" when you wanted a square?

EDIT "SQUARE TO SQUARE REPEAT 4 [FORWARD 100 RIGHT 90] END

SQUARE

What are the TO and END for? They define a procedure (a small program) for the square. The TO can be thought of as "to do something", the END terminates the TO. Once SQUARE was "defined" we then called it. That's all you need to get a square now, just type SQUARE. There is a problem, however. SQUARE only draws squares of 100 by 100. What about square of other sizes?

EDIT "SQUARE

TO SQUARE :length REPEAT 4 [FORWARD :length RIGHT 90] END

xvii Introduction

SQUARE 100 SQUARE 200

Note all we did is replace 100 with a variable name called :length. Now when we call square we must specify how big we want it. Above we asked Logo to draw one square at 100x100 and another at 200x200. Note the ":" in front of the word length tells Logo that length is a variable. However, we can still do better. Wouldn't it be nice if we could draw something other than a square, like a triangle?

TO TRIANGLE :length REPEAT 3 [FORWARD :length RIGHT 120] END

TO SQUARE :length REPEAT 4 [FORWARD :length RIGHT 90] END

TO PENTAGON :length REPEAT 5 [FORWARD :length RIGHT 72] END

TRIANGLE 100 SQUARE 100 PENTAGON 100

That works, but it's more typing than we need to do. Worse, the different procedures are mostly the same and we need to define a different procedure for every shape. Let's try again.

TO POLYGON :length :sides REPEAT :sides [FORWARD :length RIGHT 360/:sides] END

POLYGON 100 3 POLYGON 100 4 POLYGON 100 5

What happened to TRIANGLE, SQUARE and PENTAGON? We don't need them because POLYGON can draw every equal-sided polygon possible and with only one line of code. We now repeat the sequence based on how many :sides the caller asked for and we turn (RIGHT) the amount of degrees appropriate for that shape. You may not realize it but this is programming.

Now that we have a program, it's a good idea to save it to a file. The edits you've made so far are all in Logo's memory and not on the disk. How do you save your work? It's easy.

SAVE "SHAPES.LGO BYE

If you ever want to use these definitions again you'll have to load them. How do you load you work from disk?

LOAD "SHAPES.LGO

I could go on forever, yes forever, even to the point of writing Logo within Logo.

That's a quick introduction. Do you want to learn more? Almost every command in this help file has a simple example that shows how to use it. Also check out the examples that come with FMSLogo (see the

xviii Introduction

Help Menu). These examples show how to combine several procedures to perform a simple task. You can search for some tutorials on the Web, like The Logo Workshop [http://fmslogo.sourceforge.net/workshop/ ]. Jim Muller's book "The Great Logo Adventure" is based on MSWLogo, but should be applicable to FMSLogo. For more advanced topics, see 's three volume Computer Science Logo Style [https://people.eecs.berkeley.edu/~bh/v1-toc2.html] from the MIT Press.

However you choose to learn more, make sure that you have fun learning it.

xix Chapter 1. Command Line Options

Configuring the FMSLogo shortcut ...... 3 Invoking and Exiting FMSLogo ...... 6

FMSLogo supports the following command-line options:

-W width The -W option sets the width of the drawing surface to width pixels. Be aware that the larger you set this the more memory is required. The default is 1000.

For example, the following command starts FMSLogo with a drawing surface that's 2000 x 2000 pixels:

.exe -W 2000 -H 2000

If the -F command-line option is given in addition to -W, then the width of the drawing surface is reduced to fit within the dimensions of the display.

Your Logo programs can get the width of the drawing surface by running ITEM 3 MACHINE.

-H height The -H option sets the height of your drawing surface to height pixels. Be aware that the larger you set this the more memory is required. The default is 1000.

For example, the following command starts FMSLogo with a drawing surface that's 2000 x 2000 pixels:

fmslogo.exe -W 2000 -H 2000

If the -F command-line option is given in addition to -H, then the height of the drawing surface is reduced to fit within the dimensions of the display.

Your Logo programs can get the width of the drawing surface by running ITEM 4 MACHINE.

-F The -F option tells FMSLogo not to use scrollbars on the screen window ("F" stands for "fixed-size"). If this option is not given, then scrollbars are used, as needed. If you use this option without using -H or -W, then

1 Command Line Options

FMSLogo automatically calculates a drawing surface fit your full screen.

FULLSCREEN, SPLITSCREEN, and TEXTSCREEN do not change the dimensions of the screen window when FMSLogo is started in fixed-size mode.

Your Logo programs can get the width and height of the screen window by running ITEM 14 MACHINE and ITEM 15 MACHINE, respectively. Similarly, ITEM 3 MACHINE and ITEM 4 MACHINE output the width and height of the drawing surface.

The following example starts FMSLogo with a drawing surface that has the same size as your display:

fmslogo.exe -F

The following example starts FMSLogo with a drawing surface that's 400 x 200 pixels and never has scrollbars on the screen window, no matter how small it is:

fmslogo.exe -F -W 400 -H 200

-P The -P option tells FMSLogo to start in PERSPECTIVE mode.

For example:

fmslogo.exe -P

-E The -E option enables "Expert" mode.

In "Expert" mode the following occurs:

POS and POSXYZ do not "round" their output and you may see positions such as [0 -1.0e-12]. This is due to "normal" floating point errors. Rounding POS serves no purpose other than to make the POS look good. But in some applications this rounding can introduce errors if you save and restore the position. In other words, SETPOS POS has no side effect (does not round) in "Expert" mode.

FMSLogo allows multiple edit sessions. Multiple edit sessions can lead to unexpected behavior if you don't understand how FMSLogo manages the workspace. If procedures are lost or have unexpected

2 Command Line Options

changes then you should not be using expert mode.

FMSLogo allows you to save directly to the workspace. Saving directly to workspace can lead to unexpected behavior if you don't understand how FMSLogo manages the workspace. If procedures are lost or change unexpectedly then you should not be using expert mode.

Example:

fmslogo.exe -E

-L filename1 [filename2] ... The -L option tells FMSLogo to LOAD one or more files when it starts. These files are loaded before the starts reading commands from the commander. If you load a file that runs a program that includes a BYE instruction, FMSLogo runs that program and exits. You can therefore write stand-alone programs in FMSLogo and run them as new shortcuts. Note, the "-L" switch must follow any other switches.

The following example will LOAD the program that's in myprogram.lgo.

fmslogo.exe -L myprogram.lgo Configuring the FMSLogo shortcut

Command line options can be set as properties of your shortcut to FMSLogo. Just add these switches after the fmslogo.exe.

You can add any command line option to the FMSLogo desktop shortcut so that when you double-click on it, FMSLogo starts with the selected option. For example, if you want to start FMSLogo in "expert" mode:

1. Right-click on the FMSLogo desktop shortcut.

2. Select Properties from the popup menu.

3 Command Line Options

3. Click the Shortcut tab in the Properties dialog.

4 Command Line Options

4. In the Target field, append "-E" so the line looks like this "C:\Program Files (x86)\FMSLogo \fmslogo.exe" -E.

5 Command Line Options

5. Click the OK button.

The next time you double-click the shortcut, FMSLogo will start in expert mode. Invoking and Exiting FMSLogo

To start FMSLogo, just click on the FMSLogo icon. To exit FMSLogo, enter the command BYE or File- Exit.

If you invoke a procedure that has not been defined, FMSLogo first looks for a file in the current directory named proc.lgo where "proc" is the procedure name in lower case letters. If such a file exists, FMSLogo loads that file. If the missing procedure is still undefined, or if there is no such file, FMSLogo then looks in the library directory for a file named proc (without the ".lgo" extension) and, if it exists, loads it. If neither file contains a definition for the procedure, then FMSLogo signals an error.

Many of FMSLogo's built-in procedures are included in the default library, so if you use a different library you may want to include some or all of the default library in it.

6 Chapter 2. Editor

Editor Menu ...... 7 File Menu ...... 7 Edit Menu ...... 8 Search Menu ...... 8 Set Menu ...... 9 Test Menu ...... 9 Help Menu ...... 9 Editor Errors ...... 9 Editing with the Clipboard ...... 9 Context Sensitive Help ...... 10

When you exit the editor, FMSLogo loads the revised definitions and modifies the workspace accordingly. Multiple edit sessions are supported, but be careful of having multiple edit sessions that include the same definition. The final editor that is exited (and saved) takes precedence. Also realize if you delete procedures, property lists, or names while in the editor, then they are erased (see ERASE) from the workspace at the time of exiting (and saving) the edit session you deleted them from. Editor Menu

File Menu ...... 7 Edit Menu ...... 8 Search Menu ...... 8 Set Menu ...... 9 Test Menu ...... 9 Help Menu ...... 9 File Menu

File - Save and Exit

Saves the contents of the editor to the workspace and exits the editor. When you exit the editor, FMSLogo loads the revised definitions and modifies the workspace accordingly. Multiple edit sessions are supported, but be careful not to have multiple edit sessions that include the definition of the same procedure, property, or variable. The final editor that is exited (and saved) takes precedence. Also realize if you delete procedures, property lists, or names while in the editor, then they are erased (see ERASE) from the workspace at the time of exiting (and saving) the edit session you deleted them from. See also Edit Errors. File - Save to Workspace

Saves the contents of the editor to the Logo workspace without exiting. This is only available in expert mode. File - Print...

Prints the contents of the editor.

7 Editor

File - Exit

Prompts you whether to save the changes to the Logo workspace and then exits the editor. Select this option if you want to discard your changes. Edit Menu

Edit - Undo

Undoes the previous editor operation. Edit - Redo

Reverts the previous undo operation. Edit - Cut

Copies the selected text to the clipboard and deletes it. See also Editing with the Clipboard. Edit - Copy

Copies the selected text to the clipboard. See also Editing with the Clipboard. Edit - Paste

Pastes the text in the clipboard to the cursor position. If text is selected it is replaced with the pasted text. See also Editing with the Clipboard. Edit - Delete

Deletes the selected text. Edit - Clear All

Deletes all text in the editor. Edit - Select All

Selects all text in the editor. Search Menu

Search - Find

Displays a dialog box that allows you to search for text within the editor. Search - Replace

Displays a dialog box that allows you to search for text within the editor and replace it with other text.

8 Editor

Search - Next

Repeats the previous Search - Find operation. Set Menu

Set - Font

You can change the editor's font by going to the Font Menu of the editor and selecting the desired font. The new font affects the entire Editor not just selected Text. The chosen font remains selected even after FMSLogo has been restarted. Test Menu

Run Selection

You can test your code by selecting a section of code and clicking on Run Selection in the menu. This sends each selected line to the commander for execution. Keep in mind that if you select code that has variables or other context that they must be defined in the selection or already defined in the workspace. Using this feature is as if you typed in that selection into the commander. Help Menu

Help - Index

Brings you to the help on FMSLogo. See also Context Sensitive Help. Help - Editor

Brings you to the help on FMSLogo's editor. See also Context Sensitive Help. Help - Topic Search

Searches for the topic selected by the mouse in the online help. See also Context Sensitive Help. Editor Errors

If an error occurs when Logo "loads" your edit, it prompts you to fix the error in the Editor. This situation commonly occurs when a continuation "~" is missing within a list or missing a matching "]". When the editor is reopened, FMSLogo places the cursor at the start of the definition that has the error. When this occurs make sure to check the commander window for a hint of what the problem was when loading. Editing with the Clipboard

The Editor and many controls support the clipboard. The clipboard is where most Windows application store data during cut and paste operations. This means that when you cut text from an application, such as Notepad, it can be pasted into Logo's Editor (the reverse is also true). Even Help supports the clipboard. This means you can copy examples in this document directly to the editor (see HELP command).

9 Editor

The Input Box also supports the clipboard. Only one line of text is supported between the Input Box and the clipboard. You can either use the context-sensitive popup menu or keyboard shortcuts for the desired actions (Cut Ctrl+X, Copy Ctrl+C, Paste Ctrl+V).

The Output/Command-Recall also supports the clipboard. This means you can turn code you entered in the commander into procedure by copying the Commander Output to the clipboard and pasting it into the editor. Or take text output you generated and paste it into another application. Context Sensitive Help

FMSLogo's Editor, Input Box and Output/Command-Recall all support context sensitive Help. If you select a keyword (such as FORWARD) in these places (double-click works best in the editor) you can ask FMSLogo to look up the keyword without going through the Help Menu followed by a Search and so on. You simply ask by clicking the right button on the mouse (or by hitting the F1 key), abbreviations are also supported. See also Editing with the Clipboard to bring information back from the help system (like example code) for you to work with.

10 Chapter 3. Commander Input Box ...... 11 Output/Command-Recall List Box ...... 11 Execute Button ...... 11 Status Button ...... 11 Trace Button ...... 11 Halt Button ...... 12 Reset Button ...... 12 Step Button ...... 12 Pause Button ...... 12 Edall Button ...... 12

The Commander is where you spend most of your FMSLogo session. It is the means by which you instruct FMSLogo to do what you want. It is also where FMSLogo communicates back to you, displaying output and error message. The Commander also has buttons that give you quick-access to important ways of controlling your Logo environment. Input Box

The input box is tied to the Output/Command-Recall List and the Execute button. You type instructions in the input box and then have Logo run them when you press the Enter key or the Execute button. Pressing the Up/Down arrow keys automatically jumps (gives focus) to the output/command-recall list box.

The Input Box supports Context Sensitive Help. Output/Command-Recall List Box

The output/command-recall list box records all output, as well as every instruction you run from the Input Box. You can select an instruction to be re-run by clicking on the desired line or by using the arrow keys. When a line is clicked, it is automatically copied to the Input Box. Double-clicking on a line in the Output box runs it as a Logo instruction.

The output/command-recall list box supports Context Sensitive Help. Execute Button

Pressing the Execute button runs whatever is in the Input Box. It is the same as pressing the Enter key, except that you can use it to interrupt Logo while is busy running other instructions. Status Button

Pressing the Status button displays a status window that shows you what FMSLogo is up to. Pressing it a second time closes the window.

See also the STATUS and NOSTATUS commands. Trace Button

Pressing the Trace button enables tracing on all procedures. This makes it easier to debug your programs. Pressing it a second time disables tracing. You can enable or disable tracing while FMSLogo is running. Note that the trace button works independent of what you are tracing with the TRACE command.

11 Commander

See also the TRACE and UNTRACE commands. Halt Button

Pressing the Halt button stops FMSLogo from running any further instructions. It works by throwing a "Stopping..." error. Pressing the Halt button leaves FMSLogo waiting for your next instruction, assuming that the "Stopping..." error isn't caught.

The Halt button is disabled when FMSLogo is not running instructions.

See also the HALT command. Reset Button

The Reset button is like the CLEARSCREEN command; it resets the FMSLogo screen and sends the turtle home. Step Button

Pressing the Step button enables single stepping on all procedures. This is helpful when debugging your programs. Pressing the Step button a second time disables single stepping. You can enable or disable single stepping while FMSLogo is running. Note that the Step button works independent of what you are stepping with the STEP command.

See also the STEP and UNSTEP commands. Pause Button

Pressing the Pause button temporarily suspends FMSLogo from running further instructions so that you can examine variables, make changes, or whatever else you want to do. To continue you can run the CONTINUE command or press the Cancel button. You can also run the PAUSE command from your programs to act as a "Break Point".

The Pause button is disabled when FMSLogo is not running instructions. Edall Button

By default, pressing the Edall button opens the contents of the entire workspace (all unburied procedures, variables, and property lists) in the Editor. When you press it, FMSLogo runs the EDALLBTN command, which, by default, is equivalent to EDALL. However, you can change the definition of EDALLBTN to customize the Edall button's behavior.

12 Chapter 4. Main Menu

File Menu ...... 13 File - New ...... 14 File - Load...... 14 File - Open...... 14 File - Save ...... 14 File - Save As...... 14 File - Set As Screen Saver ...... 14 File - Edit...... 14 File - Erase...... 14 File - Exit ...... 14 Bitmap Menu ...... 15 Bitmap - New ...... 15 Bitmap - Load...... 15 Bitmap - Save...... 15 Bitmap - Save As...... 15 Bitmap - Print...... 15 Bitmap - Printer Setup...... 15 Bitmap - Active Area...... 15 Set Menu ...... 16 Set - Pen Size...... 16 Set - Label Font...... 16 Set - Commander Font...... 16 Set - Pen Color...... 16 Set - Flood Color...... 16 Set - Screen Color...... 16 Zoom Menu ...... 17 Zoom - In ...... 17 Zoom - Out ...... 17 Zoom - Normal ...... 17 Help Menu ...... 17 Help - Index ...... 17 Help - Tutorial ...... 17 Help - Demo ...... 17 Help - Examples ...... 17 Help - Release Notes ...... 18 Help - About FMSLogo ...... 18 Help - About MS ...... 18

The main menu is where you do high-level tasks in FMSLogo, such as loading a Logo program, loading an image, setting up a printer, or even reading this help file. File Menu

File - New ...... 14 File - Load...... 14 File - Open...... 14 File - Save ...... 14 File - Save As...... 14 File - Set As Screen Saver ...... 14 File - Edit...... 14

13 Main Menu

File - Erase...... 14 File - Exit ...... 14

The File menu includes options that enable you to operate on Logo procedure files. Note that, as a side effect, any selection in this menu that has a directory in its dialog box effectively changes the current working directory to that directory. File - New

This ERASEs all procedures, variables, and property lists in the workspace. It's like starting with a "new" session. File - Load...

This loads procedures from disk into memory so that they can be executed or edited. See also the LOAD command. File - Open...

This erases all procedures in the workspace, then loads procedures from disk into memory. This is equivalent to File - New followed by File - Load. It exists to emphasize the difference between File - Load (which is modeled after the LOAD command) and the way File - Open behaves in most Windows applications. File - Save

This saves everything that is loaded in memory onto the disk. See also the SAVE command. File - Save As...

This is the same as File - Save, except that it prompts you for a file name. File - Set As Screen Saver

This saves the current workspace to a file, configures the FMSLogo screen saver to load this file, and sets the FMSLogo screen saver as the active screen saver. If the FMSLogo screen saver is not installed, then this option is disabled. File - Edit...

This is how you edit procedures that have already been loaded (or developed) in memory. This menu option prompts you to select which existing procedures you want to edit. You can also enter a new one. See also the EDIT command. File - Erase...

This is how you erase procedures that have already been loaded (or developed) in memory. This menu option prompts you to select which existing procedures you want to erase. See also the ERASE command. File - Exit

This is how you exit FMSLogo. See also the BYE command.

14 Main Menu

Bitmap Menu

Bitmap - New ...... 15 Bitmap - Load...... 15 Bitmap - Save...... 15 Bitmap - Save As...... 15 Bitmap - Print...... 15 Bitmap - Printer Setup...... 15 Bitmap - Active Area...... 15

The Bitmap menu includes options that operate on bitmap files. Bitmap - New

This clears the work done on the screen and creates a new environment to save things in. Bitmap - Load...

This reads an image that is stored on your file system. You can load images in either the Bitmap (BMP) format or the Graphical Interlace Format (GIF) format. Also see the BITLOAD command.

See also the section on using color. Bitmap - Save...

This saves the picture that you're working so that you can use it with other applications or continue to work on it later. You can save pictures as either a Microsoft Windows Bitmap (BMP) or a Graphical Interlace Format (GIF). Remember, if your image was generated with a Logo program you really don't need to save it as an image unless you want to use the image in another application such as Microsoft Paint or as a wallpaper. Also see the BITSAVE command.

See also the SETACTIVEAREA command. Bitmap - Save As...

This is similar to the Bitmap - Save menu option, but it prompts you for a new file name. Bitmap - Print...

This prints the active area on the screen to the printer. Bitmap - Printer Setup...

This brings up a dialog box to configure the default printer. Bitmap - Active Area...

This allows you to select which portion of the screen will be printed or saved. The primary purpose of this option is performance and space. You no longer need to wait for the software to build a full image. It takes less time and less memory to print and disk space to save a partial image. As a side effect you can adjust

15 Main Menu

where your image ends up on the page by selecting different extents. You may at anytime click on reset to put the extents back to the full image. FMSLogo remembers what you set them to even after you exit.

This menu option also allows you to set how many "turtle steps" are mapped to an inch on your printout. The default is 125 turtle steps per inch of paper. Since FMSLogo's drawing surface defaults to 1000 x 1000 turtle steps, that equates to about 8 x 8 inches (1000/125 x 1000/125). You may increase this number to take advantage of higher resolution printers but your image will become smaller. You can compensate for this by increasing your drawing surface (and your drawing's size).

You can also set the active area with the Logo command SETACTIVEAREA and get it with the Logo operation ACTIVEAREA. Set Menu

Set - Pen Size...... 16 Set - Label Font...... 16 Set - Commander Font...... 16 Set - Pen Color...... 16 Set - Flood Color...... 16 Set - Screen Color...... 16

The Set menu allows you to change some of the characteristics of how FMSLogo behaves when drawing. Set - Pen Size...

This allows you to set the pen size with which the turtle draws. You can also set the pen size with the Logo command SETPENSIZE and get it with the Logo command PENSIZE. Set - Label Font...

This allows you to set the font with which the LABEL command writes. You can also set the font with the Logo command SETLABELFONT and get it with the Logo command LABELFONT. Set - Commander Font...

This allows you to choose the font that is used by the Commander. The chosen font remains selected even after FMSLogo has been restarted. Set - Pen Color...

This allows you to set the pen color. You can also set the pen color with the Logo command SETPENCOLOR and get it with the Logo command PENCOLOR. Set - Flood Color...

This allows you to set the flood color with which the turtle FILLs. You can also set the flood color with the Logo command SETFLOODCOLOR and get it with the Logo command FLOODCOLOR. Set - Screen Color...

This allows you to set the screen color. You can also set the screen color with the Logo command SETSCREENCOLOR and get it with the Logo command SCREENCOLOR.

16 Main Menu

Zoom Menu

Zoom - In ...... 17 Zoom - Out ...... 17 Zoom - Normal ...... 17

The Zoom menu allows you set the zoom factor. You can also set the zoom factor with the Logo command ZOOM. Zoom - In

This menu option doubles the current zoom factor. Zoom - Out

This menu option halves the current zoom factor. Zoom - Normal

This menu option restores the zoom factor to 1.0 (no zooming). Help Menu

Help - Index ...... 17 Help - Tutorial ...... 17 Help - Demo ...... 17 Help - Examples ...... 17 Help - Release Notes ...... 18 Help - About FMSLogo ...... 18 Help - About MS ...... 18

The Help menu allows you to learn more about FMSLogo. For more information, select the Help menu command name. Also see the HELP command. Help - Index

This displays the manual for FMSLogo and presents you with a searchable index. Help - Tutorial

This brings you to the tutorial section in the help menu. Help - Demo

This runs the DEMO program from the Logo library. Help - Examples

This brings you to an HTML page that describes each example program that comes with FMSLogo.

17 Main Menu

Help - Release Notes

This displays the release notes for this version of FMSLogo. Help - About FMSLogo

This displays the copyright and version information for FMSLogo. Help - About MS

This displays information on Multiple Sclerosis.

18 Chapter 5. Language Mechanics

Tokenization ...... 19 Procedure Loading ...... 20

This chapter explains how the Logo language works. Tokenization

Names of procedures, variables, and property lists are case-insensitive. So are the special words END, TRUE, and FALSE. Case of letters is preserved in everything you type, however.

Within square brackets, words are delimited only by spaces and square brackets. [2+3] is a list containing one word.

A word not after a quotation mark or inside square brackets is delimited by a space, a bracket, a parenthesis, or an infix operator +-*/=<>. Words that follow colons are also in this category. Note that quote and colon are not delimiters.

A word consisting of a question mark followed by a number (e.g., ?3), is parsed as if it were the sequence

(? 3)

making the number an input to the ? procedure. (See the section on Template-Based Iteration). This special treatment does not apply to words read as data, to words with a non-number following the question mark, or if the question mark is backslashed.

A line (an instruction line or one read by READLIST or READWORD) can be continued onto the following line if its last character is a tilde (~). READWORD preserves the tilde and the newline; READLIST does not. A tilde which appears anywhere else in a line has no special meaning.

A semicolon begins a comment in an instruction line. Logo ignores characters from the semicolon to the end of the line. A tilde (~) as the last character in the line still indicates a continuation line, but not a continuation of the comment.

Example:

print "abc;comment ~ def abcdef

Semicolon has no special meaning in data lines read by READLIST or READWORD, but such a line can later be reparsed using RUNPARSE and then comments will be recognized.

To include an otherwise delimiting character (including semicolon or tilde) in a word, precede it with backslash (\). If the last character of a line is a backslash, then the newline character following the backslash is part of the last word on the line, and the line continues onto the following line. To include a backslash in a word, use two backslashes: \\. All of this applies to data lines read with READLIST or READWORD as well as to instruction lines.

FMSLogo translates \n (a backslash followed by a lowercase en) into a newline character.

Example:

PRINT "Hello\ how\ are\ you?\nI'm\ fine,\ thank\ you.

19 Language Mechanics

Hello how are you? I'm fine, thank you.

A character entered with backslash is EQUALP to the same character without the backslash, but can be distinguished by the BACKSLASHEDP predicate. Backslashing is effective only on characters for which it is necessary: whitespace, parentheses, brackets, infix operators, backslash, vertical bar, tilde, quote, question mark, colon, and semicolon.

An alternative notation to include otherwise delimiting characters in words is to enclose a group of characters in vertical bars (|). All characters between vertical bars are treated as if they were letters. In data read with READWORD the vertical bars are preserved in the resulting word. In data read with READLIST (or resulting from a PARSE or RUNPARSE of a word) the vertical bars do not appear explicitly; all potentially delimiting characters (including spaces, brackets, parentheses, and infix operators) appear as though entered with a backslash. Within vertical bars, backslash may still be used, but the only characters which must be backslashed in this context are the backslash and the vertical bar. Within vertical bars, the sequence \n is translated to a newline character.

Example:

PRINT "|Hello how are you?\nI'm fine, thank you.| Hello how are you? I'm fine, thank you.

Characters entered between vertical bars are forever special, even if the word or list containing them is later reparsed with PARSE or RUNPARSE. The same is true of a character typed after a backslash, except that when a quoted word containing a backslashed character is runparsed, the backslashed character loses its special quality and acts thereafter as if typed normally. This distinction is important only if you are building a Logo expression out of parts, to be RUN later, and you want to use parentheses. For example,

PRINT RUN (SENTENCE "\( 2 "+ 3 "\))

prints 5, but

RUN (SENTENCE "MAKE ""|(| 2)

creates a variable whose name is open-parenthesis. (Each example would fail if vertical bars and backslashes were interchanged.) Procedure Loading

When FMSLogo encounters a token that it neither a variable, a number, a word, an infix operator, a parenthesis, nor a bracket, then the token is interpreted as the name of a procedure. If this is the name of a primitive or a procedure that has already been defined, then FMSLogo calls that procedure. Otherwise, FMSLogo attempts to load the procedure into the workspace. If a ".lgo" file with the same name as with the procedure exists in the current working directory, then FMSLogo loads that file (as with the LOAD command). If no errors were encountered and the procedure was defined by loading the file, then that procedure is called. However, if the procedure is still not defined and a file with the same name exists in the Logolib directory, then that Logolib file is loaded. If no errors were encountered and the procedure was defined by loading the Logolib file, then the procedure is called. If the procedure is still not defined, then FMSLogo throws an "I don't know how to" error.

20 Chapter 6. Data Structure Commands

Data Structure Constructors ...... 22 WORD ...... 22 LIST ...... 22 SENTENCE ...... 23 FPUT ...... 23 LPUT ...... 23 ARRAY ...... 23 MDARRAY ...... 24 LISTTOARRAY ...... 25 ARRAYTOLIST ...... 25 COMBINE ...... 25 REVERSE ...... 26 SORT ...... 26 GENSYM ...... 27 Data Structure Selectors ...... 27 FIRST ...... 28 FIRSTS ...... 28 LAST ...... 28 BUTFIRST ...... 28 BUTFIRSTS ...... 29 BUTLAST ...... 29 ITEM ...... 29 MDITEM ...... 30 PICK ...... 30 REMOVE ...... 30 REMDUP ...... 31 QUOTED ...... 31 Data Structure Mutators ...... 31 SETITEM ...... 32 MDSETITEM ...... 32 .SETFIRST ...... 32 .SETBF ...... 33 .SETITEM ...... 33 PUSH ...... 33 POP ...... 34 QUEUE ...... 34 DEQUEUE ...... 35 Data Structure Predicates ...... 35 WORDP ...... 35 NUMBERP ...... 36 LISTP ...... 36 ARRAYP ...... 36 EMPTYP ...... 37 EQUALP ...... 37 NOTEQUALP ...... 38 BEFOREP ...... 39 .EQ ...... 39 MEMBERP ...... 40 SUBSTRINGP ...... 40 BACKSLASHEDP ...... 40 Data Structure Queries ...... 41

21 Data Structure Commands

COUNT ...... 42 ASCII ...... 42 RAWASCII ...... 42 CHAR ...... 43 MEMBER ...... 43 LOWERCASE ...... 43 UPPERCASE ...... 44 STANDOUT ...... 44 PARSE ...... 44 RUNPARSE ...... 44 TIME ...... 45 TIMEMILLI ...... 45 Data Structure Constructors

WORD ...... 22 LIST ...... 22 SENTENCE ...... 23 FPUT ...... 23 LPUT ...... 23 ARRAY ...... 23 MDARRAY ...... 24 LISTTOARRAY ...... 25 ARRAYTOLIST ...... 25 COMBINE ...... 25 REVERSE ...... 26 SORT ...... 26 GENSYM ...... 27 WORD

Synopsis WORD word1 word2 (WORD word1 word2 word3 ...)

Description Outputs a word formed by concatenating its inputs.

Examples SHOW WORD "o "k ok

SHOW (WORD "a "o "k "to) aokto LIST

Synopsis LIST thing1 thing2 (LIST thing1 thing2 thing3 ...)

Description Outputs a list whose members are its inputs, which can be any Logo thing (word, list, or array).

Example SHOW (LIST "This "is "a "List) [This is a List]

SHOW LIST [1 2 3] [a b c]

22 Data Structure Commands

[[1 2 3] [a b c]]

MAKE "red 100 MAKE "green 100 MAKE "blue 100 SHOW (LIST :red :green :blue) [100 100 100] SENTENCE

Synopsis SENTENCE thing1 thing2 SE thing1 thing2 (SENTENCE thing1 thing2 thing3 ...) (SE thing1 thing2 thing3 ...)

Description Outputs a list whose members are its inputs, if those inputs are not lists. Outputs the members of its inputs, if those inputs are lists.

SENTENCE throws an error if any of its inputs is an array.

Example SHOW (SENTENCE "A "sentence "is "simply "a "list "of "words) [A sentence is simply a list of words]

SHOW (SENTENCE "A "sentence [is simply a] "list [of words]) [A sentence is simply a list of words] FPUT

Synopsis FPUT thing list

Description Outputs a list equal to list with thing put on the front.

Example SHOW FPUT 1 [2 3 4] [1 2 3 4] LPUT

Synopsis LPUT thing list

Description Outputs a list equal to list with thing added as the last item.

Example SHOW LPUT 4 [1 2 3] [1 2 3 4] ARRAY

Synopsis ARRAY size (ARRAY size origin)

Description Outputs an array of size items, each of which initially is the empty list. The size input must be a non-negative integer.

Array items can be selected with ITEM and changed with SETITEM. The first element in an array is item number 1, unless an origin input is given, in which case the first element of the array has that number as its index. If given,

23 Data Structure Commands

the origin input must be an integer. You can get the origin of an array with FIRST.

FMSLogo has a special syntax for creating arrays and specifying its members at the same time. Arrays are delimited by curly braces and the origin can be optionally specified by appending an @ character after the closing curly brace, followed by the origin. For example, {a b c}@0 creates an array with three items and an origin of 0. PRINT and friends render arrays using the same syntax.

Unlike lists, items in arrays can be modified after the array is created. This can lead to confusing behavior if the same array is referenced from multiple places. This is shown in the following program, which modifies an array in one list and, in doing so, also modifies it in a second list.

MAKE "array {a b c} MAKE "list1 LIST 1 :array MAKE "list2 LIST 2 :array SHOW :list1 [1 {a b c}]

SHOW :list2 [2 {a b c}]

SETITEM 2 ITEM 2 :list1 "X SHOW :list1 [1 {a X c}]

SHOW :list2 [2 {a X c}]

Example MAKE "myarray (ARRAY 3 0) SETITEM 2 :myarray 1 SETITEM 1 :myarray 2 SETITEM 0 :myarray 3 SHOW :myarray {3 2 1} MDARRAY

Synopsis MDARRAY sizelist (MDARRAY sizelist origin)

Description Outputs a multi-dimensional array.

The sizelist input describes the size of each dimension in the multi- dimensional array. The number of items in this list determines the dimension of the array. sizelist must be a list of one or more positive integers.

The origin input is the index of the first element of every dimension in the output array. If given, it must be a single integer. If no origin input is given, then every dimension in the array has an origin of 1.

Example MAKE "myarray (MDARRAY [2 3] 0) MDSETITEM [0 0] :myarray 1

24 Data Structure Commands

MDSETITEM [0 1] :myarray 2 MDSETITEM [0 2] :myarray 3 MDSETITEM [1 0] :myarray 4 MDSETITEM [1 1] :myarray 5 MDSETITEM [1 2] :myarray 6 SHOW :myarray {{1 2 3} {4 5 6}}

See Also MDITEM MDSETITEM ARRAY LISTTOARRAY

Synopsis LISTTOARRAY list (LISTTOARRAY list origin)

Description Outputs an array with the same elements as the input list.

If an origin input is given, then the first element of the new array is at index origin. Otherwise, the default of 1 is used.

Example SHOW LISTTOARRAY [1 2 3] {1 2 3} ARRAYTOLIST

Synopsis ARRAYTOLIST array

Description Outputs a list whose members are the elements of the input array. The first item of the output is the first element of the array, regardless of the array's origin.

ARRAYTOLIST can be used to make data in an array available to list processing procedures, such as MAP.

Example A simple example:

SHOW ARRAYTOLIST {1 2 3} [1 2 3]

Using MAP on data in an array:

MAKE "myarray {1 2 3 4 5} MAKE "myarray LISTTOARRAY MAP [? * ?] ARRAYTOLIST :myarray SHOW :myarray {1 4 9 16 25}

See Also LISTTOARRAY COMBINE

Synopsis COMBINE thing1 thing2

Description Combines both of its inputs into a single value. If the second input is a word, this acts like WORD. If the second input is a list, this acts like FPUT.

25 Data Structure Commands

Example SHOW COMBINE "a "b ab

SHOW COMBINE "a [b] [a b] REVERSE

Synopsis REVERSE thing

Description Outputs the reverse of its input.

If thing is a list, then REVERSE outputs a list with the same members in the reverse order.

If thing is a word, then REVERSE outputs a word with the same letters in the reverse order.

REVERSE throws an error if thing is an array.

Example SHOW REVERSE [1 2 3] [3 2 1]

SHOW REVERSE "abc cba SORT

Synopsis SORT sequence (SORT sequence predicate)

Description Sorts a sequence (list, array, or word) in ascending order, or according to a given predicate. The output is a new sequence of the same type as sequence that contains the same items ordered such that there are no two successive items, a and b, where (predicate a b) is FALSE and (predicate b a) is TRUE.

The predicate input must be either an explicit-slot template or the name of a procedure that acts as the predicate. The predicate must input two values and output either TRUE or FALSE.

If no predicate input is given, then the predicate used depends on the sequence input, as defined by the following table.

sequence type output A list of numbers A list sorted by LESSP A list of non-numbers A list sorted by BEFOREP An array of numbers An array sorted by LESSP An array of non-numbers An array sorted by BEFOREP A word A word whose characters are sorted by BEFOREP

Example Sorting in ascending order:

26 Data Structure Commands

SHOW SORT [3 1 2] [1 2 3]

Sorting in descending order:

SHOW (SORT [3 1 2] "GREATERP) [3 2 1]

Sorting complex records:

; [name age height] MAKE "a [Ana 12 52] MAKE "b [Bob 11 54] MAKE "c [Cole 12 57] MAKE "d [Dan 12 52] MAKE "e [Erin 11 54] MAKE "data (LIST :e :d :c :b :a)

; Sort by height. SHOW (SORT :data [LESSP LAST ?1 LAST ?2]) [[Dan 12 52] [Ana 12 52] [Erin 11 54] [Bob 11 54] [Cole 12 57]]

; Sort by height with ties sorted by name. SHOW (SORT (SORT :data [BEFOREP FIRST ?1 FIRST ?2]) [LESSP LAST ?1 LAST ?2]) [[Ana 12 52] [Dan 12 52] [Bob 11 54] [Erin 11 54] [Cole 12 57]] GENSYM

Synopsis GENSYM

Description Outputs a unique word each time it is invoked. The words are of the form G1, G2, etc. This is typically used to dynamically generate variable names.

Example MAKE GENSYM 1 SHOW :g1 1

MAKE GENSYM "Hello SHOW :g2 Hello Data Structure Selectors

FIRST ...... 28 FIRSTS ...... 28 LAST ...... 28 BUTFIRST ...... 28 BUTFIRSTS ...... 29 BUTLAST ...... 29 ITEM ...... 29 MDITEM ...... 30 PICK ...... 30 REMOVE ...... 30

27 Data Structure Commands

REMDUP ...... 31 QUOTED ...... 31 FIRST

Synopsis FIRST thing

Description If thing is a word, outputs the first character of the word. If thing is a list, outputs the first member of the list. If thing is an array, outputs the origin of the array (that is, the index of the first element of the array).

FIRST throws a bad input error if given the empty list, the empty string, or the empty array.

Example SHOW FIRST [1 2 3] 1

SHOW FIRST "Hello H

SHOW FIRST {a b c} 1 FIRSTS

Synopsis FIRSTS list

Description Outputs a list containing the FIRST of each member of the input list. It is an error if any member of the input list is empty. The input itself may be empty, in which case the output is also empty.

Example SHOW FIRSTS [[1 2 3] [a b c]] [1 a] LAST

Synopsis LAST thing

Description If thing is a word, outputs the last character of the word. If thing is a list, outputs the last member of the list.

LAST throws a bad input error if given the empty list, the empty string, or an array.

Example SHOW LAST [1 2 3] 3

SHOW LAST "Hello o BUTFIRST

Synopsis BUTFIRST thing BF thing

28 Data Structure Commands

Description If thing is a word, outputs a word containing all but the first character of the input. If thing is a list, outputs a list containing all but the first member of the input.

BUTFIRST throws a bad input error if given the empty list, the empty string, or an array.

Example SHOW BUTFIRST [1 2 3] [2 3]

SHOW BUTFIRST "Hello ello BUTFIRSTS

Synopsis BUTFIRSTS list BFS list

Description Outputs a list containing the BUTFIRST of each member of the input list. It is an error if any member of the input list is empty. The input itself may be empty, in which case the output is also empty.

Example SHOW BUTFIRSTS [[1 2 3] [a b c]] [[2 3] [c d]] BUTLAST

Synopsis BUTLAST thing BL thing

Description If the input is a word, BUTLAST outputs a word containing all but the last character of the input. If the input is a list, BUTLAST outputs a list containing all but the last member of the input.

BUTLAST throws a bad input error if given the empty list, the empty string, or an array.

Example SHOW BUTLAST [1 2 3] [1 2]

SHOW BUTLAST "Hello Hell ITEM

Synopsis ITEM index thing

Description If thing is a word, ITEM outputs the index-th character of the word.

If thing is a list, ITEM outputs the index-th member of the list.

If thing is an array whose origin is 1 (which is most arrays), ITEM outputs the index-th element. If thing is an array whose origin is not 1, then ITEM outputs the element that is at index - origin + 1.

29 Data Structure Commands

An index starts at 1 for words and lists; the starting index of an array is specified when the array is created.

Example SHOW ITEM 2 [a b c] b

SHOW ITEM 3 "abc c

SHOW ITEM 1 {a b c} a

SHOW ITEM 1 {a b c}@0 b MDITEM

Synopsis MDITEM indexlist mdarray

Description Outputs an item of the multi-dimensional array (or multi-dimensional list) selected by the list of numbers (an index list).

Example SHOW MDITEM [2 2] {{0 1} {2 3}} 3

See Also MDARRAY MDSETITEM ITEM PICK

Synopsis PICK thing

Description Outputs a randomly chosen item from thing.

Example SHOW PICK [1 2 3] 2

SHOW PICK [1 2 3] 3

SHOW PICK [1 2 3] 2

SHOW PICK "Hello e REMOVE

Synopsis REMOVE thingtoremove things

Description Outputs a new thing that is equal to things with all members equal to thingtoremove removed.

The things input must be either a list or a word.

30 Data Structure Commands

Because the members of a word are single characters, if things is a word, then thingtoremove should be a single character. REMOVE does not remove multi-character substrings from a word.

Example SHOW REMOVE "b [a b c b] [a c]

SHOW REMOVE "e "Hello Hllo REMDUP

Synopsis REMDUP things

Description Outputs a copy of its input with duplicate members removed. If two or more members of the input are equal, the rightmost of those members is the one that remains in the output.

REMDUP throws an error if things is an array.

Example SHOW REMDUP [a b c c b] [a c b]

SHOW REMDUP "Hello Helo QUOTED

Synopsis QUOTED thing

Description If the input is a word, QUOTED outputs the word with a double-quote character (") appended to the front. Otherwise, QUOTED outputs whatever the input is.

Example SHOW "Hello Hello

SHOW QUOTED "Hello "Hello

SHOW QUOTED [1 2 3] [1 2 3] Data Structure Mutators

SETITEM ...... 32 MDSETITEM ...... 32 .SETFIRST ...... 32 .SETBF ...... 33 .SETITEM ...... 33 PUSH ...... 33 POP ...... 34 QUEUE ...... 34

31 Data Structure Commands

DEQUEUE ...... 35 SETITEM

Synopsis SETITEM index array value

Description Replaces the index-th item of an input array with a new value.

SETITEM ensures that the resulting array is not circular. That is, value may not be a list or array that contains the same array.

Example MAKE "myarray (ARRAY 3 0) SETITEM 2 :myarray 1 SETITEM 1 :myarray [2] SETITEM 0 :myarray 3 SHOW :myarray {3 [2] 1} MDSETITEM

Synopsis MDSETITEM indexlist mdarray value

Description Replaces an item in a multi-dimensional array with a new value. The item to replace is selected by a list of indices.

Example MAKE "myarray (MDARRAY [2 3] 0) MDSETITEM [0 0] :myarray 1 MDSETITEM [0 1] :myarray 2 MDSETITEM [0 2] :myarray 3 MDSETITEM [1 0] :myarray 4 MDSETITEM [1 1] :myarray 5 MDSETITEM [1 2] :myarray 6 SHOW :myarray {{1 2 3} {4 5 6}}

See Also MDARRAY MDITEM SETITEM .SETFIRST

Synopsis .SETFIRST list value

Description Changes the first member of list to be value.

The list input must be list and cannot be empty.

WARNING: Primitives whose names start with a period are dangerous. Their use by non-experts is not recommended. The use of .SETFIRST can lead to circular list structures, which causes infinite loops for some primitives; unexpected changes to other data structures that share storage with the list being modified; and the permanent loss of memory if a circular structure is released.

Examples MAKE "mylist [1 2 3]

32 Data Structure Commands

.SETFIRST :mylist 0 SHOW :mylist [0 2 3] .SETBF

Synopsis .SETBF list value

Description Changes the BUTFIRST of the list input to a given value.

The list input must be a list and cannot be empty.

WARNING: Primitives whose names start with a period are dangerous. Their use by non-experts is not recommended. The use of .SETBF can lead to circular list structures, which gets some primitives into infinite loops; unexpected changes to other data structures that share storage with the list being modified; crashes and core dumps if the BUTFIRST of a list is not itself a list; and the permanent loss of memory if a circular structure is released.

Example MAKE "mylist [1 2 3] .SETBF :mylist [a b] SHOW :mylist [1 a b] .SETITEM

Synopsis .SETITEM index array value

Description Change the indexth item of array to be value. This similar to SETITEM, except that it does not check for circularity.

WARNING: Primitives whose names start with a period are dangerous. Their use by non-experts is not recommended. The use of .SETITEM can lead to circular array structures, which can lead to very unintuitive behavior.

Example MAKE "myarray (ARRAY 3 0) .SETITEM 2 :myarray 1 .SETITEM 1 :myarray 2 .SETITEM 0 :myarray 3 SHOW :myarray {3 2 1} PUSH

Synopsis PUSH stackname value

Description Adds a thing to the front of a stack whose name is stackname.

This variable must have a list as its value; the initial value should be the empty list. New members are added at the front of the list. Later, you can POP value off the stack.

Example MAKE "mystack [] PUSH "mystack 1

33 Data Structure Commands

PUSH "mystack 2 PUSH "mystack 3 SHOW :mystack [3 2 1]

SHOW POP "mystack 3

SHOW :mystack [2 1] POP

Synopsis POP stackname

Description Outputs the most recent thing that was pushed on the stack named stackname (using PUSH) and removes that member from the stack.

Example MAKE "mystack [] PUSH "mystack 1 PUSH "mystack 2 PUSH "mystack 3 SHOW :mystack [3 2 1]

SHOW POP "mystack 3

SHOW :mystack [2 1]

SHOW POP "mystack 2

SHOW :mystack [1] QUEUE

Synopsis QUEUE queuename value

Description Adds a thing to the back of a queue whose name is queuename. This variable must have a list as its value; the initial value should be the empty list. New members are added at the back of the list. Later, you can DEQUEUE value from the queue.

Example MAKE "myqueue [] QUEUE "myqueue 1 QUEUE "myqueue 2 QUEUE "myqueue 3 SHOW :myqueue [1 2 3]

SHOW DEQUEUE "myqueue

34 Data Structure Commands

1

SHOW :myqueue [2 3] DEQUEUE

Synopsis DEQUEUE queuename

Description Outputs the least recent (oldest) thing that was enqueued onto a queue with QUEUE. This value is removed from the queue.

Example MAKE "myqueue [] QUEUE "myqueue 1 QUEUE "myqueue 2 QUEUE "myqueue 3 SHOW :myqueue [1 2 3]

SHOW DEQUEUE "myqueue 1

SHOW :myqueue [2 3]

SHOW DEQUEUE "myqueue 2

SHOW :myqueue [3] Data Structure Predicates

WORDP ...... 35 NUMBERP ...... 36 LISTP ...... 36 ARRAYP ...... 36 EMPTYP ...... 37 EQUALP ...... 37 NOTEQUALP ...... 38 BEFOREP ...... 39 .EQ ...... 39 MEMBERP ...... 40 SUBSTRINGP ...... 40 BACKSLASHEDP ...... 40 WORDP

Synopsis WORDP thing WORD? thing

Description Outputs TRUE if the input is a word, FALSE otherwise.

35 Data Structure Commands

Example SHOW WORDP "Hello true

SHOW WORDP [Hello] false

SHOW WORDP {Hello} false NUMBERP

Synopsis NUMBERP thing NUMBER? thing

Description Outputs TRUE if thing is a number, FALSE otherwise.

Example SHOW NUMBERP 1 true

SHOW NUMBERP "1 true

SHOW NUMBERP [1] false LISTP

Synopsis LISTP thing LIST? thing

Description Outputs TRUE if the input is a list, FALSE otherwise.

Example SHOW LISTP "Hello false

SHOW LISTP [Hello] true

SHOW LISTP {Hello} false ARRAYP

Synopsis ARRAYP thing ARRAY? thing

Description Outputs TRUE if the input is an array, FALSE otherwise.

Example SHOW ARRAYP "Hello false

SHOW ARRAYP [Hello] false

SHOW ARRAYP {Hello}

36 Data Structure Commands

true EMPTYP

Synopsis EMPTYP thing EMPTY? thing

Description Outputs TRUE if thing is either the empty string or the empty list, FALSE otherwise.

Example SHOW EMPTYP "Hello false

SHOW EMPTYP " true

SHOW EMPTYP [1 2 3] false

SHOW EMPTYP [] true EQUALP

Synopsis EQUALP thing1 thing2 EQUAL? thing1 thing2 thing1 = thing2

Description Outputs TRUE if both inputs are equal, FALSE otherwise.

Two numbers are equal if they have the same numeric value. Two non-numeric words are equal if they contain the same characters in the same order. By default, an upper case letter is equal to its corresponding lower case letter. Similarly, any two characters which are defined to be equivalent in Unicode, such as the word-final sigma (ς) and the normal sigma (σ), are also equal. However, if a variable named CASEIGNOREDP is defined and its value is not TRUE, then an upper case letter is not equal to its corresponding lower case letter; two characters are only equal if they have the same Unicode code point.

Two lists are equal if their members are equal and appear in the same order.

An array is only equal to itself; two separately created arrays are never equal even if all of their items are equal. It is important to be able to know if two expressions have the same array as their value because arrays are mutable. For example, if two different variables have the same array as their value, then running SETITEM on one of them would change both of them.

Example SHOW 1=1 true

SHOW EQUALP 1 1 true

SHOW EQUALP 1 2 false

37 Data Structure Commands

SHOW EQUALP [1 2 3] [1 2 3] true

SHOW EQUALP [1 2 3] [3 2 1] false

SHOW EQUALP {1 2 3} {1 2 3} false

MAKE "myarray1 {1 2 3} MAKE "myarray2 :myarray1 SHOW EQUALP :myarray1 :myarray2 true NOTEQUALP

Synopsis NOTEQUALP thing1 thing2 NOTEQUAL? thing1 thing2 thing1 <> thing2

Description Outputs FALSE if both inputs are equal, TRUE otherwise.

Two numbers are equal if they have the same numeric value. Two non-numeric words are equal if they contain the same characters in the same order. By default, an upper case letter is equal to its corresponding lower case letter. Similarly, any two characters which are defined to be equivalent in Unicode, such as the word-final sigma (ς) and the normal sigma (σ), are also equal. However, if a variable named CASEIGNOREDP is defined and its value is not TRUE, then an upper case letter is not equal to its corresponding lower case letter; two characters are only equal if they have the same Unicode code point.

Two lists are equal if their members are equal and appear in the same order.

An array is only equal to itself; two separately created arrays are never equal even if all of their items are equal. It is important to be able to know if two expressions have the same array as their value because arrays are mutable. For example, if two different variables have the same array as their value, then running SETITEM on one of them would change both of them.

Example SHOW 1 <> 1 false

SHOW NOTEQUALP 1 1 false

SHOW NOTEQUALP 1 2 true

SHOW NOTEQUALP [1 2 3] [1 2 3] false

SHOW NOTEQUALP [1 2 3] [3 2 1] true

SHOW NOTEQUALP {1 2 3} {1 2 3}

38 Data Structure Commands

true

MAKE "myarray1 {1 2 3} MAKE "myarray2 :myarray1 SHOW NOTEQUALP :myarray1 :myarray2 false

See Also EQUALP BEFOREP

Synopsis BEFOREP word1 word2 BEFORE? word1 word2

Description Outputs TRUE if word1 comes before word2. Outputs FALSE, otherwise.

By default, BEFOREP compares the words in alphabetical order, or more precisely Unicode collation order. That is, an upper case letter is equal to its corresponding lower case letter. Similarly, any two characters which are defined to be equivalent in Unicode, such as the word-final sigma (ς) and the normal sigma (σ), are also treated as equal. However, if a variable named CASEIGNOREDP is defined and its value is not TRUE, then an upper case letter is not equal to its corresponding lower case letter; the characters are compared by their Unicode code point.

If one of the words is a prefix of the other word, then the shorter word comes before the longer word.

Note that if the inputs are numbers, the result may not be the same as with LESSP. For example, BEFOREP 9 10 outputs FALSE because 9 collates after 1.

Example SHOW BEFOREP "ABC "abd true

SHOW BEFOREP "abd "ABC false

SHOW BEFOREP "a "a false

SHOW BEFOREP 9 10 false .EQ

Synopsis .EQ thing1 thing2

Description Outputs TRUE if thing1 and thing2 are the same object, so that applying a mutator to one will change the other as well. Outputs FALSE otherwise, even if the inputs are equal in value.

WARNING: Primitives whose names start with a period are dangerous. Their use by non-experts is not recommended. The use of mutators can lead to circular data structures, infinite loops, or crashes.

39 Data Structure Commands

Example MAKE "x 1 MAKE "y 1 SHOW .EQ :x :y false

MAKE "x 1 MAKE "y :x SHOW .EQ :x :y true MEMBERP

Synopsis MEMBERP thing1 thing2 MEMBER? thing1 thing2

Description Outputs TRUE if thing1 is a member of thing2. Outputs FALSE, otherwise.

If thing2 is a list or an array, outputs TRUE if thing1 is EQUALP to an item of thing2, FALSE otherwise.

If thing2 is a word, outputs TRUE if thing1 is a single character that is EQUALP to a character in thing2, FALSE otherwise.

Example SHOW MEMBERP 1 [1 2 3] true

SHOW MEMBERP 4 [1 2 3] false

SHOW MEMBERP "b "abc true

SHOW MEMBERP "bc "abc false SUBSTRINGP

Synopsis SUBSTRINGP thing1 thing2 SUBSTRING? thing1 thing2

Description If thing2 is a word, SUBSTRINGP outputs TRUE if thing1 is EQUALP to a substring of thing2, FALSE otherwise.

If thing1 or thing2 is a list or an array, SUBSTRINGP outputs FALSE.

Example SHOW SUBSTRINGP "bc "abc true

SHOW SUBSTRINGP "bd "abc false BACKSLASHEDP

Synopsis BACKSLASHEDP character

40 Data Structure Commands

BACKSLASHED? character

Description Outputs TRUE if character was originally entered between vertical bars (|) and is a space, tab, newline, or one of ()[]{}|+-*/=<>":;\~? . Outputs FALSE, otherwise.

In FMSLogo, BACKSLASHEDP has nothing to do with backslashes, but its name was retained for compatibility with older programs. All regular backslashes are removed after tokenization, but the vertical barring is retained. VBARREDP would be a more appropriate name.

In older versions of Logo, BACKSLASHEDP output whether or not a character had been escaped with a backlash in order to suppress the normal semantics of the character. For example, a space character normally terminates a word, but a backslashed space is included within the word. When Logo only supported the 7-bit ASCII character set, each character was stored internally as an 8-bit byte and the backslash was stored in the 8th bit of each byte. Thus, every character could have a backslash and the name "BACKSLASHEDP" made sense.

To enable FMSLogo to support languages other than English, it was expanded to store characters as 16-bit values from the Unicode BMP. As a result, the 8th bit can no longer be used to store the backslash. Fortunately, preceding most characters with a backslash doesn't change their meaning. For example \A and A mean the same thing; the backslash is essentially ignored. However, for a small number of characters, including the space character, the backslash still needs to be stored with the character. To preserve this information, such characters are mapped to the Private Use Area of the Unicode BMP. For example, the space character has a code point of 32, but a backslashed space is internally represented as code point 57344.

Example SHOW BACKSLASHEDP "a false

SHOW BACKSLASHEDP "|a| false

SHOW BACKSLASHEDP "|(| true

SHOW BACKSLASHEDP "\( false Data Structure Queries

COUNT ...... 42 ASCII ...... 42 RAWASCII ...... 42 CHAR ...... 43 MEMBER ...... 43 LOWERCASE ...... 43 UPPERCASE ...... 44 STANDOUT ...... 44 PARSE ...... 44 RUNPARSE ...... 44

41 Data Structure Commands

TIME ...... 45 TIMEMILLI ...... 45 COUNT

Synopsis COUNT thing

Description Outputs the number of characters in thing, if thing is a word; outputs the number of items in thing, if it is a list or an array. (For an array, this may or may not be the index of the last item, depending on the array's origin.)

Example SHOW COUNT [1 2 3] 3

SHOW COUNT "ab 2 ASCII

Synopsis ASCII character

Description Outputs the number from 0-65535 that corresponds to the Unicode code point for character.

ASCII interprets control characters as representing backslashed punctuation and outputs the character code corresponding to the punctuation character without the backslash.

This command is called "ASCII" because FMSLogo was originally restricted to the ASCII character set.

Example SHOW ASCII "a 97

SHOW ASCII "A 65

SHOW ASCII "# 945

SHOW ASCII "|(| 40

See Also RAWASCII CHAR RAWASCII

Synopsis RAWASCII character

Description Outputs the number from 0-65535 that corresponds to the Unicode code point for character.

Unlike ASCII , RAWASCII interprets control characters as representing themselves.

42 Data Structure Commands

Example SHOW RAWASCII "a 97

SHOW RAWASCII "A 65

SHOW RAWASCII "# 945

SHOW RAWASCII "|(| 57347

See Also ASCII CHAR

Synopsis CHAR codepoint

Description Outputs the character which corresponds to codepoint within the Unicode character set. The input codepoint must be an integer between 0 and 65535.

Example SHOW CHAR 97 a

SHOW CHAR 65 A

SHOW CHAR 945 #

See Also ASCII MEMBER

Synopsis MEMBER thing1 thing2

Description If thing2 is a word or list and if MEMBERP with these inputs would output TRUE, then MEMBER outputs the portion of thing2 from the first instance of thing1 to the end. If MEMBERP would output FALSE, then MEMBER outputs the empty word or list according to the type of thing2. It is an error for thing2 to be an array.

Example SHOW MEMBER "b [a b c d] [b c d]

SHOW MEMBER "c [a b c d] [c d]

SHOW MEMBER "b "abba" bba LOWERCASE

Synopsis LOWERCASE word

43 Data Structure Commands

Description Outputs a word which is a copy of word, but with all uppercase letters changed to the corresponding lowercase letter.

Example SHOW LOWERCASE "HeLlo hello UPPERCASE

Synopsis UPPERCASE word

Description Outputs a word which is a copy of word, but with all lowercase letters changed to the corresponding uppercase letter.

Example SHOW UPPERCASE "HeLlo HELLO STANDOUT

Synopsis STANDOUT thing Description Note

STANDOUT is not yet supported in FMSLogo.

In other Logo environments, STANDOUT outputs a word that, when printed, appears like the input but displayed in standout mode (boldface, reverse video, or whatever your terminal does for standout). The word contains terminal- specific magic characters at the beginning and end; in between is the printed form (as if displayed using TYPE) of the input. The output is always a word, even if the input is of some other type, but it may include spaces and other formatting characters.

Example SHOW (LIST "This "is STANDOUT "very "important) This is very important

SHOW STANDOUT [1 2 3] [1 2 3] PARSE

Synopsis PARSE word

Description Outputs the list that would result if word were entered in response to a READLIST operation. That is, PARSE READWORD outputs the same value as READLIST for the same characters read.

Example SHOW PARSE "Hello [Hello] RUNPARSE

Synopsis RUNPARSE thing

Description Outputs the list that would result if thing (word or list) were entered as an instruction line; characters such as infix operators and parentheses are separate

44 Data Structure Commands

members of the output. Note that sublists of a runparsed list are not themselves runparsed.

Example SHOW RUNPARSE "a

Synopsis TIME

Description Outputs the current time on the system as a list of words.

Example SHOW TIME [Wed Jul 14 23:34:08 1993] TIMEMILLI

Synopsis TIMEMILLI

Description Outputs the time since Windows started, measured in milliseconds. Use this for precision timing. The output is also known as the "tick count".

Example MAKE "start TIMEMILLI REPEAT 36 [ELLIPSE 100 200 RIGHT 5] SHOW TIMEMILLI - :start 8189

45 Chapter 7. Communication

Transmitters ...... 47 PRINT ...... 47 TYPE ...... 48 SHOW ...... 48 Receivers ...... 48 READLIST ...... 48 READWORD ...... 49 READCHAR ...... 50 READCHARS ...... 50 READRAWLINE ...... 51 File Access ...... 51 OPENREAD ...... 52 OPENWRITE ...... 53 OPENAPPEND ...... 53 OPENUPDATE ...... 54 CLOSE ...... 56 ALLOPEN ...... 56 CLOSEALL ...... 56 ERASEFILE ...... 57 DRIBBLE ...... 57 NODRIBBLE ...... 58 SETREAD ...... 58 SETWRITE ...... 59 READER ...... 59 WRITER ...... 59 SETREADPOS ...... 60 SETWRITEPOS ...... 60 READPOS ...... 61 WRITEPOS ...... 61 EOFP ...... 62 Hardware Communications ...... 62 PORTOPEN ...... 63 PORTCLOSE ...... 63 PORTFLUSH ...... 63 PORTMODE ...... 64 PORTREADARRAY ...... 64 PORTREADCHAR ...... 64 PORTWRITEARRAY ...... 65 PORTWRITECHAR ...... 65 INPORT ...... 66 OUTPORT ...... 66 INPORTB ...... 66 OUTPORTB ...... 67 INGAMEPORT ...... 67 DLL Communications ...... 67 DLLLOAD ...... 67 DLLCALL ...... 68 DLLFREE ...... 71 Keyboard and Mouse Access ...... 71 KEYP ...... 71 KEYBOARDON ...... 71

46 Communication

KEYBOARDOFF ...... 73 KEYBOARDVALUE ...... 73 MOUSEON ...... 77 MOUSEOFF ...... 77 MOUSEPOS ...... 78 CLEARTEXT ...... 78 SETCURSOR ...... 78 CURSOR ...... 78 SETMARGINS ...... 79 Transmitters

PRINT ...... 47 TYPE ...... 48 SHOW ...... 48

If there is a variable named PRINTDEPTHLIMIT with a nonnegative integer value, then complex list and array structures are printed only to the allowed depth. That is, members of members of ... of members are allowed only so far. An elispsis indicates when items are omitted because they exceed the depth limit. For example, a list with two items that is just before the depth limit is printed as [...... ].

If there is a variable named PRINTWIDTHLIMIT with a nonnegative integer value, then only the first so many items of any array or list are printed. A single ellipsis replaces all missing objects within the structure. The width limit also applies to the number of characters printed in a word, except that a PRINTWIDTHLIMIT between 0 and 9 is treated as if it were 10 when applied to words. This limit applies not only to the top-level printed object but to any substructures within it. PRINT

Synopsis PRINT thing PR thing (PRINT thing1 thing2 ...) (PR thing1 thing2 ...)

Description Prints the input or inputs to the current write stream (initially the command- recall window). All the inputs are printed on a single line, separated by spaces, ending with a newline. If an input is a list, square brackets are not printed around it, but brackets are printed around sublists. Braces are always printed around arrays.

If the current write stream is a file that was opened as a text file (that is, not opened in binary mode), then PRINT writes each newline character as the Windows end-of-line sequence: a carriage return followed by a newline character.

If the current write stream is a file that was opened in binary mode, then only the lower byte of each character is printed. Furthermore, a newline character is printed simply as a newline character.

Example PRINT "Hello Hello

PRINT [Hello how are you] Hello how are you

47 Communication

See Also PRINTDEPTHLIMIT PRINTWIDTHLIMIT TYPE

Synopsis TYPE thing (TYPE thing1 thing2 ...)

Description Prints the input or inputs like PRINT, except that no newline character is printed at the end and multiple inputs are not separated by spaces.

Example TYPE "Hello TYPE "How TYPE "Are PRINT "You HelloHowAreYou SHOW

Synopsis SHOW thing (SHOW thing1 thing2 ...)

Description Prints the input or inputs to the current write stream, just like PRINT, except that if an input is a list it is printed inside square brackets.

Example SHOW [1 2 3] [1 2 3]

PRINT [1 2 3] 1 2 3

See Also PRINTDEPTHLIMIT PRINTWIDTHLIMIT Receivers

READLIST ...... 48 READWORD ...... 49 READCHAR ...... 50 READCHARS ...... 50 READRAWLINE ...... 51 READLIST

Synopsis READLIST RL

Description Reads a line from the read stream (initially the popup dialog) and outputs that line as a list. The line is separated into items as though it were typed in square brackets in an instruction. If the read stream is a file and the last character in the file is not an end-of-line sequence, then READLIST treats the end-of-file as an end-of-line. After the file as been completely read, READLIST outputs the empty word (not the empty list).

48 Communication

READLIST processes backslash, vertical bar, and tilde characters in the read stream; the output list does not contain these characters but they have their usual effect. Similarly, square brackets have their usual effect of spanning multiple lines and every open bracket must be matched by a close bracket. The contents enclosed in square brackets appear in the output list as a nested list.

READLIST treats curly braces analogously to how it treats brackets, except that the enclosed content appears in the output as a nested array.

READLIST does not treat semicolon as a comment character, so the semicolon and whatever follows it appears in the output list.

Example SHOW READLIST Hello how are you? [Hello how are you?] READWORD

Synopsis READWORD RW

Description Reads a line from the read stream and outputs that line as a word (without the end-of-line sequence). The output is a single word even if the line contains spaces, brackets, etc. A blank line is output as the empty word. If the read stream is a file and the last character in the file is not an end-of-line sequence, then READWORD treats the end-of-file as an end-of-line. After the file as been completely read, READWORD outputs the empty list (not the empty word).

READWORD processes backslash, vertical bar, and tilde characters in the read stream. In the case of a tilde used for line continuation, the output word does include the tilde and the newline characters. Vertical bars in the line are also preserved in the output. Backslash characters are not preserved in the output, except for the ones that follow a backslash. This strange behavior enables the resulting word to be parsed into a list with PARSE in a way that preserves the normal sematics.

The notion that vertical bars are both processed and preserved in the output warrants a fuller explanation. In processing, vertical bars retain their ability to allow a single line of text to include newline characters. So if a newline follows a vertical bar, READWORD continues reading more text until it finds a vertical bar that closes the vertical bar grouping, then it reads until it finds another newline, which terminates the line. None of the newlines between the vertical bars are considered line breaks and READWORD outputs all of the text as a single word. The output also includes the vertical bars.

Example A simple example:

SHOW READWORD Hello how are you? Hello how are you?

The following example shows how vertical bars are processed and preserved. Notice that READWORD outputs all of the text as a single word.

49 Communication

SHOW READWORD This is a line | WITH ONE VERTICAL BAR THIS IS NOW WITHIN A VERTICAL BAR THE END | some more text | BACK IN VERTICAL BAR THIS | ends it. This is a line | WITH ONE VERTICAL BAR THIS IS NOW WITHIN A VERTICAL BAR THE END | some more text | BACK IN VERTICAL BAR THIS | ends it. READCHAR

Synopsis READCHAR RC

Description Reads a single character from the read stream and outputs it. If the read stream was opened for text reading, then the character is output as a word. If the read stream was opened for binary reading, then the character is output as a number.

If the read stream is a file and the end of file is reached, READCHAR outputs the empty list (not the empty word).

If the read stream is the Commander, then the "Input Mode" dialog prompts the user for a line of text and READCHAR outputs the first character entered by the user. Successive calls to READCHAR read the rest of the line until there are no more characters, in which case the "Input Mode" dialog is shown again.

Backslash, vertical bar, and tilde characters have no special meaning in this context.

Example SHOW READCHAR Hello how are you? H SHOW READCHAR e

See Also READCHARS READWORD READLIST READCHARS

Synopsis READCHARS number RCS number

Description Reads number characters (or bytes) from the read stream and outputs them as a word.

If the read stream is a file that was opened in text mode, then READCHARS reads number characters from the file according to whatever character encoding was detected when the file was opened. If the read stream is a file that was opened in binary mode, then READCHARS reads number bytes from the file and outputs a word where each character uses the code point of

50 Communication

the corresponding byte (0 - 255). If the read stream is the Commander, then READCHARS reads nothing and outputs the empty list.

If number is larger than the number of characters (or bytes, for binary files) remaining in the read stream, then READCHARS outputs the rest of the read stream. If the read stream is a file and there are no unread characters in the file, then READCHARS outputs the empty list (not the empty word).

Backslash, vertical bar, and tilde characters have no special meaning in this context.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt SHOW READCHARS 5 Hello SETREAD [] CLOSE "example.txt READRAWLINE

Synopsis READRAWLINE

Description Reads a line from the read stream and outputs that line as a word. READRAWLINE outputs the exact string of characters as they appear in the line, with no special meaning for backslash, vertical bar, tilde, or any other formatting characters. The output is a single word even if the line contains spaces, brackets, etc.

If the read stream is a file and the last character in the file is not an end-of- line sequence, then READRAWLINE treats the end-of-file as an end-of-line. After the file as been completely read, READRAWLINE outputs the empty list (not the empty word).

Example SHOW READRAWLINE Special | Characters Special | Characters File Access OPENREAD ...... 52 OPENWRITE ...... 53 OPENAPPEND ...... 53 OPENUPDATE ...... 54 CLOSE ...... 56 ALLOPEN ...... 56 CLOSEALL ...... 56 ERASEFILE ...... 57 DRIBBLE ...... 57 NODRIBBLE ...... 58

51 Communication

SETREAD ...... 58 SETWRITE ...... 59 READER ...... 59 WRITER ...... 59 SETREADPOS ...... 60 SETWRITEPOS ...... 60 READPOS ...... 61 WRITEPOS ...... 61 EOFP ...... 62 OPENREAD

Synopsis OPENREAD filename (OPENREAD filename binarymode)

Description Opens the file named filename for reading. The read position is initially at the beginning of the file.

If the filename input is the reserved word "clipboard, then any text data on the clipboard can be read as if it were in a file. If the clipboard is opened in binary mode, then the clipboard's contents are encoded in UTF-8. Even in binary mode, only text data can be read from the clipboard.

The optional binarymode input is a boolean value (TRUE or FALSE). If binarymode is FALSE or not given, then the file is opened as a text file. If binarymode is TRUE, then the file is opened as a binary file.

When opening a text file, OPENREAD infers the character encoding from the Unicode signature, a byte order mark (BOM) that is at the beginning of the file. OPENREAD only recognizes two Unicode character encodings: UTF-8 and UTF-16LE. If a Unicode signature is recognized, it is excluded from the characters that are read from the file. If there is no Unicode signature or if the Unicode signature is not recognized, then the file is assumed to be encoded in the system default Windows code page. In addition, when reading from a text file, the end-of-line sequence is converted from CRLF to LF.

When reading from a binary file, the data is read as bytes (values from 0 - 255) and no end-of-line sequence conversion is performed. If a Unicode signature is present, it is included in the data that is read from the file as a sequence of bytes.

OPENREAD throws an error if no file named filename exists or if the file cannot be opened for reading.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READLIST] [Hello] [Good Bye]

52 Communication

SETREAD [] CLOSE "example.txt

See Also CLOSE OPENWRITE

Synopsis OPENWRITE filename (OPENWRITE filename binarymode)

Description Opens the file named filename for writing. If a file by the given filename already exists, the contents are discarded and OPENWRITE starts with an empty file.

If the filename input is the reserved word "clipboard, then you can write text data to the clipboard as if it were a file. If the clipboard is opened for writing in binary mode, then you must encode the text in UTF-8. Even in binary mode, only text data can be written to the clipboard.

The optional binarymode input is a boolean value (TRUE or FALSE). If binarymode is FALSE or not given, then the file is opened as a text file. If binarymode is TRUE, then the file is opened as a binary file.

When opening a text file, OPENWRITE creates a new file with a UTF-8 BOM. All characters written to the file are encoded in UTF-8. In addition, when writing to a text file, the end-of-line sequence is converted from LF to CRLF.

When writing to a binary file, the data is written as bytes (values from 0 - 255) and no end-of-line sequence conversion is performed.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READLIST] [Hello] [Good Bye] SETREAD [] CLOSE "example.txt

See Also CLOSE OPENAPPEND

Synopsis OPENAPPEND filename (OPENAPPEND filename binarymode)

Description Opens the file named filename for writing. If a file with the given filename already exists, the write position is initially set to the end of the old file, so that newly written data is appended to it. If no file with the given filename exists, then OPENAPPEND creates an empty file.

53 Communication

If the filename input is the reserved word "clipboard, then you can append text data to the clipboard as if it were a file. If the clipboard doesn't contain text when it is opened, then it's treated as if it contained nothing (you start appending at the beginning). If the clipboard is opened for appending in binary mode, then you must encode the text that you append in UTF-8. Even in binary mode, only text data can be written to the clipboard.

The optional binarymode input is a boolean value (TRUE or FALSE). If binarymode is FALSE or not given, then the file is opened as a text file. If binarymode is TRUE, then the file is opened as a binary file.

When opening a text file, OPENAPPEND infers the character encoding from the existing file's Unicode signature, a byte order mark (BOM) that is at the beginning of the file. OPENAPPEND only recognizes two Unicode character encodings: UTF-8 and UTF-16LE. If there is no Unicode signature or if the Unicode signature is not recognized, then an existing file is assumed to be encoded in the system default Windows code page. If the file doesn't exist, then OPENAPPEND creates a new file with a UTF-8 BOM and characters are written as UTF-8. In addition, when appending to a text file, the end-of-line sequence is converted from LF to CRLF.

When appending to a binary file, the data is written as bytes (values from 0 - 255) and no end-of-line sequence conversion is performed.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello SETWRITE [] CLOSE "example.txt

OPENAPPEND "example.txt SETWRITE "example.txt PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READLIST] [Hello] [Good Bye] SETREAD [] CLOSE "example.txt

See Also CLOSE OPENUPDATE

Synopsis OPENUPDATE filename (OPENUPDATE filename binarymode)

Description Opens the file named filename for reading and writing. The read and write position is initially set to the end of the old file. Each open file has only one position, for both reading and writing. If a file opened for update

54 Communication

is both READER and WRITER at the same time, then SETREADPOS also affects WRITEPOS and vice versa. Also, if you alternate reading and writing the same file, you must SETREADPOS between a write and a read, and SETWRITEPOS between a read and a write.

If the filename input is the reserved word "clipboard, then you can update text data on the clipboard as if it were a file. If the clipboard doesn't contain text when it is opened, then it's treated as if it contained nothing (you start with an empty file). If the clipboard is opened for reading and writing in binary mode, then the clipboard's existing contents are encoded in UTF-8 and you must encode any text that you write in UTF-8. Even in binary mode, only text data can be written to the clipboard.

The optional binarymode input is a boolean value (TRUE or FALSE). If binarymode is FALSE or not given, then the file is opened as a text file. If binarymode is TRUE, then the file is opened as a binary file.

When opening a text file, OPENUPDATE infers the character encoding from the file's Unicode signature, a byte order mark (BOM) that is at the beginning of the file. OPENUPDATE only recognizes two Unicode character encodings: UTF-8 and UTF-16LE. If a Unicode signature is recognized, it is excluded from the characters that are read from the file. If there is no Unicode signature or if the Unicode signature is not recognized, then the file is assumed to be encoded in the system default Windows code page. The character encoding is used both when reading from the file and when writing to the file. In addition, when reading from a text file, the end-of-line sequence is converted from CRLF to LF. When writing to a text file, the end-of-line sequence is converted from LF to CRLF.

When updating a binary file, the data is both read and written as bytes (values from 0 - 255) and no end-of-line sequence conversion is performed. If a Unicode signature is present, it is included in the data that is read from the file as a sequence of bytes.

OPENUPDATE throws an error if no file named filename exists or if the file cannot be opened for reading and writing.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENUPDATE "example.txt SETREAD "example.txt SETREADPOS 0 SHOW READLIST [Hello] SETWRITE "example.txt SETWRITEPOS 7 PRINT [And how are you today] SETWRITE [] SETREAD "example.txt SETREADPOS 0

55 Communication

REPEAT 3 [SHOW READLIST] [Hello] [And how are you today]

CLOSE "example.txt

See Also CLOSE CLOSE

Synopsis CLOSE filename

Description Closes the file named filename. All subsequent attempts to read from or write to the file will fail.

You can also close the reserved file "clipboard with this command.

If you close the current READER or WRITER, then the reader or writer is reset to the Commander.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READLIST] [Hello] [Good Bye] SETREAD [] CLOSE "example.txt ALLOPEN

Synopsis ALLOPEN

Description Outputs a list whose members are the names of all files currently open. This list does not include the DRIBBLE file.

Example OPENWRITE "example1.txt OPENWRITE "example2.txt SHOW ALLOPEN [example1.txt example2.txt] CLOSEALL

Synopsis CLOSEALL

Description Closes all open files.

This is equivalent to FOREACH ALLOPEN [CLOSE ?]

56 Communication

Example OPENWRITE "example1.txt OPENWRITE "example2.txt SHOW ALLOPEN [example1.txt example2.txt] CLOSEALL SHOW ALLOPEN [] ERASEFILE

Synopsis ERASEFILE filename ERF filename

Description Erases (deletes, removes) the file named filename. The file must not be currently be open.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt CLOSE "example.txt

ERASEFILE "example.txt OPENREAD "example.txt File system error: Could not open file DRIBBLE

Synopsis DRIBBLE filename

Description Creates a new file whose name is the filename input, like OPENWRITE, and begins recording in that file everything that is read from the keyboard. This writing is in addition to the writing to WRITER. The intent is to create a transcript of a Logo session, including things like prompt characters and interactions.

Example For the following example, you must run each instruction separately.

; Dribble a few instructions, then stop. DRIBBLE "dribble.txt FORWARD 100 RIGHT 90 NODRIBBLE

; Open the dribble file and see what was written. OPENREAD "dribble.txt SETREAD "dribble.txt REPEAT 3 [SHOW READLIST] [FORWARD 100] [RIGHT 90] [NODRIBBLE]

57 Communication

SETREAD [] CLOSE "dribble.txt

See Also NODRIBBLE NODRIBBLE

Synopsis NODRIBBLE

Description Stops copying information to the dribble file and closes the file.

Example For the following example, you must run each instruction separately.

DRIBBLE "dribble.txt FORWARD 100 RIGHT 90 NODRIBBLE OPENREAD "dribble.txt SETREAD "dribble.txt REPEAT 3 [SHOW READLIST] [FORWARD 100] [RIGHT 90] [NODRIBBLE] SETREAD [] CLOSE "dribble.txt

See Also DRIBBLE SETREAD

Synopsis SETREAD filename

Description Sets the read stream to the file named filename. The read stream is used by READLIST , READWORD , etc. The file must already be open with OPENREAD or OPENUPDATE. If the input is the empty list, then the read stream becomes the Commander, as usual. Changing the read stream does not close the file that was previously the read stream, so it is possible to alternate between files.

If you CLOSE the current reader, then the read stream is closed and READER is changed back to the Commander.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READLIST] [Hello] [Good Bye] SETREAD []

58 Communication

CLOSE "example.txt

See Also SETWRITE READER SETWRITE

Synopsis SETWRITE filename

Description Sets the write stream to the file named filename. The write stream is used by PRINT, SHOW, etc. The file must already be open with OPENWRITE, OPENAPPEND, or OPENUPDATE. If the input is the empty list, then the write stream becomes the Commander, as usual. Changing the write stream does not close the file that was previously the write stream, so it is possible to alternate between files.

If you CLOSE the current writer, then the write stream is closed and WRITER is changed back to the Commander.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READLIST] [Hello] [Good Bye] SETREAD [] CLOSE "example.txt

See Also SETREAD WRITER READER

Synopsis READER

Description Outputs the name of the current read stream file, or the empty list if the read stream is the Commander.

Example OPENREAD "example.txt SETREAD "example.txt SHOW READER example.txt WRITER

Synopsis WRITER

Description Outputs the name of the current write stream file, or the empty list if the write stream is the Commander.

59 Communication

Example OPENWRITE "example.txt SETWRITE "example.txt

; Can't use "SHOW WRITER", because the output ; would go to example.txt, not the commander. ; Use "MESSAGEBOX" instead. MESSAGEBOX "writer WRITER SETREADPOS

Synopsis SETREADPOS bytepos

Description Sets the file pointer of the read stream's file so that the next READLIST, etc., begins reading at the bytepos-th byte in the file, counting from 0.

SETREADPOS 0 starts reading at the beginning of the file. However, if the file was opened in text mode and has a byte order mark at the beginning, then SETREADPOS 0 sets the read position to just after the byte order mark. This is still conceptually the beginning of the file.

If the read stream's file was opened in text mode, then, depending on the file's character encoding, a single character may occupy one or more bytes. Setting the read stream's position to the middle of a character is likely to have undesirable results. Therefore, it's advisable to only run SETREADPOS with an input that was previously output from READPOS.

SETREADPOS is meaningless and has no effect when the current read stream is [] (the Commander).

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt SHOW READLIST [Hello] SETREADPOS 0 SHOW READLIST [Hello] SETREAD [] CLOSE "example.txt SETWRITEPOS

Synopsis SETWRITEPOS bytepos

Description Sets the file pointer of the write stream's file so that the next PRINT, etc., begins writing at the bytepos-th byte in the file, counting from 0.

SETWRITEPOS 0 starts writing at the beginning of the file. However, if the file was opened in text mode and has a byte order mark at the beginning, then

60 Communication

SETWRITEPOS 0 sets the write position to just after the byte order mark. This is still conceptually the beginning of the file.

If the write stream's file was opened in text mode, then, depending on the file's character encoding, a single character may occupy one or more bytes. Setting the write stream's position to the middle of a character is likely to have undesirable results. Therefore, it's advisable to only run SETWRITEPOS with an input that was previously output from READPOS or WRITEPOS.

SETWRITEPOS is meaningless and has no effect when the current write stream is [] (the Commander).

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello SETWRITEPOS 0 TYPE "J SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt SHOW READLIST [Jello] SETREAD [] CLOSE "example.txt READPOS

Synopsis READPOS

Description Outputs the byte position of the current read stream's file as a number. READPOS outputs 0 when the read position is at the beginning of the file.

READPOS outputs -1 when the current read stream is the Commander.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READPOS SHOW READLIST] 0 [Hello] 7 [Good Bye] SETREAD [] CLOSE "example.txt WRITEPOS

61 Communication

Synopsis WRITEPOS

Description Outputs the byte position of the current write stream's file as a number. WRITEPOS outputs 0 when the write position is at the beginning of the file.

WRITEPOS outputs -1 when the current write stream is the Commander.

Example Note that, in the following example, the output from WRITEPOS is stored in a list and shown after the writer is set back to the Commander ([]).

OPENWRITE "example.txt SETWRITE "example.txt MAKE "history [] MAKE "history LPUT WRITEPOS :history PRINT "Hello MAKE "history LPUT WRITEPOS :history PRINT [Good Bye] MAKE "history LPUT WRITEPOS :history SETWRITE [] CLOSE "example.txt SHOW :history [0 7 17] EOFP

Synopsis EOFP EOF?

Description Outputs TRUE if there are no more characters to be read in the read stream file, FALSE otherwise.

Example OPENWRITE "example.txt SETWRITE "example.txt PRINT "Hello PRINT [Good Bye] SETWRITE [] CLOSE "example.txt

OPENREAD "example.txt SETREAD "example.txt REPEAT 2 [SHOW READLIST SHOW EOFP] [Hello] false [Good Bye] true SETREAD [] CLOSE "example.txt Hardware Communications

PORTOPEN ...... 63 PORTCLOSE ...... 63 PORTFLUSH ...... 63 PORTMODE ...... 64

62 Communication

PORTREADARRAY ...... 64 PORTREADCHAR ...... 64 PORTWRITEARRAY ...... 65 PORTWRITECHAR ...... 65 INPORT ...... 66 OUTPORT ...... 66 INPORTB ...... 66 OUTPORTB ...... 67 INGAMEPORT ...... 67

All commands that start with PORT are for serial (RS-232) and parallel port communications. All commands that start with INPORT or OUTPORT are for "hardware" port communications. PORTOPEN

Synopsis PORTOPEN port

Description Gives you access to the serial and parallel ports of your computer. The port input is a string that is the name of the port you wish to open (for example, COM1-COM4 and LPT1-LPT3).

Once the desired port is open you can read from it with PORTREADCHAR or PORTREADARRAY , or you can write to it with PORTWRITECHAR or PORTWRITEARRAY . You can set the characteristics of the port with PORTMODE. Only one port can be open at any given time. When you have finished with the port, you should close it with PORTCLOSE.

Do not confuse PORTOPEN with INPORT and OUTPORT, which are for "hardware" port communications.

Example PORTOPEN "com1 PORTCLOSE PORTCLOSE

Synopsis PORTCLOSE

Description Closes a port that was opened by PORTOPEN.

Example PORTOPEN "com1 PORTCLOSE PORTFLUSH

Synopsis PORTFLUSH input

Description Flushes all buffered output to the open port.

Because writing to a port can be slow, the stores data which you write in a temporary holding place called a "buffer" and writes it to the port at the appropriate speed. This buffering makes your program faster, as your program does not need to wait for the data to be sent to the port before continuing its execution. The act of flushing actively pushes all data which is in the buffer to the port. After the flush is complete, you can be sure that all of the data which you have previously written to the port has really been sent there.

63 Communication

The input input is required, but is otherwise ignored. It is retained as a required input for backward compatibility with older programs.

Example PORTFLUSH 1 PORTMODE

Synopsis PORTMODE modestring

Description Sets the mode (speed, parity, data bits, and stop bits) of the open COM port. The flow control characteristic cannot be set through FMSLogo.

The modestring must be of the form "COMn:SPEED,PARITY,DATA,STOP. This is the same format that is used by MODE, the Windows command shell program.

Example PORTOPEN "com1 PORTMODE "com1:9600,n,8,1 PORTREADARRAY

Synopsis PORTREADARRAY count buffer

Description Reads data from the currently open port into the given buffer array. PORTREADARRAY attempts to read count bytes from the port, if they are available. When bytes are written to buffer, they are written as small integers (between -128 and 127). PORTREADARRAY outputs the actual number of bytes read.

If count is larger than the size of the buffer array, then the number of bytes read is limited to the size of the buffer.

Example PORTOPEN "com1 PRINT SENTENCE [Sending...] PORTWRITEARRAY 3 LISTTOARRAY MAP [ASCII ?] [a t] Sending... 2 SHOW PORTWRITECHAR 13 1 WAIT 60 MAKE "buff {0 0 0 0 0 0 0 0 0 0} PRINT SENTENCE [Receiving...] PORTREADARRAY 10 :buff Receiving... 9 PRINT SENTENCE [Data Rx...] MAP [CHAR ?] REMOVE [] ARRAYTOLIST :buff Data Rx... at | | O K | PORTCLOSE PORTREADCHAR

Synopsis PORTREADCHAR

Description Reads one byte from the currently open port and outputs it as an integer from -128 to 127. It also outputs "-1" if no character is available. Therefore, if PORTREADCHAR outputs -1, it could be there was no character available or that it successfuly read the -1 byte. For this reason, if -1 is a possible byte in the data your program expects, then it's better to use PORTREADARRAY.

64 Communication

Example PORTOPEN "com1 SHOW PORTWRITECHAR ASCII "a 1 SHOW PORTWRITECHAR ASCII "t 1 SHOW PORTWRITECHAR 13 1 WAIT 60 PRINT "Reading... Reading... REPEAT 10 [MAKE "x PORTREADCHAR IF NOT :x = -1 [TYPE CHAR :x]] PRINT ". at|| OK| . PORTCLOSE PORTWRITEARRAY

Synopsis PORTWRITEARRAY count buffer

Description PORTWRITEARRAY writes to the currently open port with the data in buffer, which must be an array of byte-sized integers. It attempts to write count bytes to the port, if possible. PORTWRITEARRAY outputs 1 on success and 0 on failure.

If count is larger than the size of the buffer array, then the entire array is written.

Example PORTOPEN "com1 PRINT SENTENCE [Sending...] PORTWRITEARRAY 3 LISTTOARRAY MAP [ASCII ?] [a t] Sending... 2 SHOW PORTWRITECHAR 13 1 WAIT 60 MAKE "buff {0 0 0 0 0 0 0 0 0 0} PRINT SENTENCE [Receiving...] PORTREADARRAY 10 :buff Receiving... 9 PRINT SENTENCE [Data Rx...] MAP [CHAR ?] REMOVE [] ARRAYTOLIST :buff Data Rx... at | | O K | PORTCLOSE PORTWRITECHAR

Synopsis PORTWRITECHAR data

Description Writes one byte to the currently open port. PORTWRITECHAR outputs 1 if the byte was written succesfully and outputs -1 otherwise. The data input must be an integer from 0 to 255.

Example PORTOPEN "com1 SHOW PORTWRITECHAR ASCII "a 1 SHOW PORTWRITECHAR ASCII "t

65 Communication

1 SHOW PORTWRITECHAR 13 1 WAIT 60 PRINT "Reading... Reading... REPEAT 10 [MAKE "x PORTREADCHAR IF NOT :x = -1 [TYPE CHAR :x]] PRINT ". at|| OK| . PORTCLOSE INPORT

Synopsis INPORT portid

Description Reads 2 bytes (16 bits) from the port specified by portid and output the data as an integer. The portid input specifies a "Hardware" port.

Do not confuse INPORT with PORTOPEN and PORTREADCHAR which are for communications through the serial and parallel ports.

Example SHOW INPORT 198 25730

See Also INPORTB OUTPORT OUTPORT

Synopsis OUTPORT portid data

Description Writes data to the "hardware" port specified by portid. The data input must be a 2 byte integer (a number from 0 to 65525).

Do not confuse OUTPORTB with PORTOPEN and PORTWRITECHAR which are for communications through the serial and parallel ports.

Example OUTPORT 198 0

See Also OUTPORTB INPORT INPORTB

Synopsis INPORTB portid

Description Reads one byte from the port specified by portid and output the data as an integer. The portid input specifies a "Hardware" port.

Do not confuse INPORTB with PORTOPEN and PORTREADCHAR which are for communications through the serial and parallel ports.

Example SHOW INPORTB 198 130

66 Communication

See Also INPORT OUTPORTB OUTPORTB

Synopsis OUTPORTB portid data

Description Writes data to the "hardware" port specified by portid. The data input must be a one byte integer (a number from 0 to 255).

Do not confuse OUTPORTB with PORTOPEN and PORTWRITECHAR which are for communications through the serial and parallel ports.

Example OUTPORTB 198 0

See Also OUTPORT INPORTB INGAMEPORT

Synopsis INGAMEPORT mask

Description Reads the value (or resistance across) the game port channel specified by mask. The mask input must be either 1, 2, 4, or 8. If mask is 1, then INGAMEPORT reads the x-axis. If mask is 2, then INGAMEPORT reads the y-axis. If mask is 4, then INGAMEPORT reads the rudder. If mask is 8, then INGAMEPORT reads the z-axis. You can read the button states using INPORT 513.

INGAMEPORT outputs -1 if nothing is connected to the game port or if the mask input is an unsupported value.

Example REPEAT 10000 [SHOW INGAMEPORT 1 WAIT 10]

Now move the Joystick around. DLL Communications DLLLOAD ...... 67 DLLCALL ...... 68 DLLFREE ...... 71 DLLLOAD

Synopsis DLLLOAD dllfilename

Description Loads the DLL (Dynamic Linked Library) called dllfilename into FMSLogo. Once loaded you can call functions with DLLCALL. When you have finished, you can unload the DLL with DLLFREE.

You may load more than one DLL at a time. Loading a DLL that is already loaded simply increments a reference count and requires an additional call to DLLFREE to actually unload the DLL.

Example DLLLOAD "user32.dll DLLFREE

67 Communication

DLLCALL

Synopsis DLLCALL function_parameter_list (DLLCALL function_parameter_list dllname)

Description Calls a native Windows function with the given arguments and outputs the function's return value. The function must be exported by a DLL which was loaded with DLLLOAD.

The function_parameter_list is of the form [typef function type1 arg1 type2 arg2 type3 arg3 ...].

DLLCALL interprets typef as describing the function's return value. The return value is parsed into a list, as with PARSE. Any buffers that were created for "out" parameters are appened to the list and it is the output of DLLCALL. The meaning of each supported typef is given in the table below:

typef Native Type DLLCALL Output V void Nothing W WORD, SHORT, or Outputs the lower 16 bits USHORT of the function's return value as a one member list. L DWORD, LONG, or Outputs the function's ULONG return value, interpreted as a 32-bit integer, as a one member list. F DOUBLE Outputs the function's return value as a one member list. S LPSTR Copies the data from the returned pointer into a word, interpreting it as a NUL-terminated string of ANSI characters in the system default Windows code page, and calls GlobalFreePtr() on the returned pointer. The word is then parsed as with PARSE and the resulting list is output.

function must be a word that exactly matches a symbol which is exported from the DLL. For Win32 functions that take a parameter of type TCHAR, the exported symbol probably ends in either W or A, even if you wouldn't call it like that from C.

DLLCALL passes arg1 as a type1, arg2 as a type2, and so on. Keep in mind that the win32 "stdcall" convention pass arguments from right to left, so arg1 is really the last parameter. The actions taken for each argument are given in the following table:

68 Communication type# Native Type DLLCALL action V void Ignores the argument W WORD, SHORT, or Pushes the lowest 16 bits USHORT of the argument onto the stack as a 32-bit value. L DWORD, LONG, or Pushes the integral value ULONG of the argument onto the stack as a 32-bit value. F DOUBLE Interprets the argument as a double and pushes the value as a 64-bit floating point onto the stack. S LPCSTR Converts the argument to a NUL-terminated string of ANSI characters according to the system default Windows code page and pushes its pointer onto the stack. U LPCWSTR Converts the argument to a NUL-terminated string of wide (16-bit) characters and pushes its pointer onto the stack. B PBYTE, PULONG, Allocates a buffer that LPSTR, or LPWSTR has as many bytes as the given argument when interpreted as an integer. Fills the buffer with zero bytes. Marks it as a "vertical barred" word so that it can hold non-printing characters. Pushes a pointer to this buffer onto the stack. After the function returns, appends the buffer to the output list. If the function returns void, then a list is created so that the buffer can be output to the caller.

The buffer is meant to hold binary data, bytes from 0 - 255. If the data that is written to the buffer are

69 Communication

type# Native Type DLLCALL action ANSI characters, then they are NOT interpreted according to the system default Windows code page and any character whose code point is greater than 127 may be mapped to a different character in FMSLogo. Similarly, if the data that is written to the buffer are Unicode characters (LPWSTR), they are intepreted as if encoded in UTF-16LE (the low byte and the high byte of each WCHAR become two separate FMSLogo characters, with the character for the low byte first).

If the optional dllname input is given, then DLLCALL only looks for the function within that DLL.

The "B" argument types are returned as words of the exact length given. Any byte that is not overwritten by the function call is translated to NUL (the character whose code point is 0). So if the function fills in a string of bytes and only uses part of the buffer, the returned word will have a lot of zero characters at the end. Such a word does not behave like a regular word. However, you can convert it to a regular word by removing the NUL characters with something like:

MAKE "buffer FILTER [NOTEQUALP CHAR 0 ? ] :buffer

DLLCALL is meant for experienced programmers who are familiar with the native Windows calling conventions. If you do not properly match the argument list the results will be unpredictable and likely crash FMSLogo. DLLCALL can handle a wide variety of function calls but certainly not all.

DLLCALL allows to extend the reach of FMSLogo when its existing commands are insufficient. You can write your own DLL with a compatible call interface to call more complex interfaces.

Example The following example is equivalent to the C call:

MessageBox(NULL, L"Do you like FMSLogo?", L"Question", MB_YESNO);

Note how a "W" is added to the end of the name "MessageBox" and how the arguments are passed in reverse order to conform to the stdcall calling convention.

DLLLOAD "user32.dll IGNORE DLLCALL [L MessageBoxW L 4 U [Question] U [Do you like FMSLogo?] L 0]

70 Communication

See a message box pop up.

DLLFREE DLLFREE

Synopsis DLLFREE (DLLFREE dllname)

Description Unloads a DLL that was loaded with DLLLOAD. If a dllname input is given, then the DLL by that name is unloaded. Otherwise, the most recently loaded DLL is unloaded.

Example DLLLOAD "user32.dll DLLFREE Keyboard and Mouse Access

KEYP ...... 71 KEYBOARDON ...... 71 KEYBOARDOFF ...... 73 KEYBOARDVALUE ...... 73 MOUSEON ...... 77 MOUSEOFF ...... 77 MOUSEPOS ...... 78 CLEARTEXT ...... 78 SETCURSOR ...... 78 CURSOR ...... 78 SETMARGINS ...... 79 KEYP

Synopsis KEYP KEY?

Description A predicate that outputs TRUE if there are more characters to read from the read stream. If the read stream is a file, then KEYP is equivalent to NOT EOFP. If the read stream is set to the Commander, then KEYP always outputs TRUE.

KEYP is provided for compatibility with other Logo environments. The traditional semantics of KEYP are not appropriate to FMSLogo's graphical environment.

See Also KEYBOARDON READER KEYBOARDON

Synopsis KEYBOARDON keydown (KEYBOARDON keydown keyup)

Description Starts trapping keyboard events and sending them to keydown and keyup. When a key is pressed down, keydown is called. When a key is released,

71 Communication

keyup is called. You can determine the key that was pressed or released by calling KEYBOARDVALUE in your keydown or keyup procedure.

keydown or keyup may either be a word that is the name of a procedure to call, or a list of commands.

Note the "Screen" must have focus (NOT the commander) to catch the key events. You can force this by calling SETFOCUS [FMSLogo] after you call KEYBOARDON. All the "callbacks" for the keyboard are automatically run in NOYIELD mode.

For historical reasons, the set of keys that are captured when KEYBOARDON is given one input is different from the set of keys that are captured when it is given two inputs. When only a keydown input is given, the keys are trapped as characters, not as strict keydown events. This means that lowercase a has a different value than uppercase A, even though the same key is pressed. Because of this, a program that only looks for ASCII "a doesn't work when Caps Lock is on. This also means that when only one input is given to KEYBOARDON, it ignores keystrokes that don't have a textual character representation. This includes ignoring the arrow keys, the function keys, most navigation keys, the Shift key, the Control key, and others.

In contrast, when KEYBOARDON has two inputs, it captures nearly all key events, including the arrow keys, the function keys, the navigation keys, the Shift key, and the Control key. Furthermore, each unique key press generates a separate callback. So uppercase A might generate the following keyboard events: a Shift keydown event, followed by an A keydown event, followed by an A keyup event, followed by a Shift keyup event.

Example Using KEYBOARDON on with one input to print characters that are typed:

KEYBOARDON [PRINT CHAR KEYBOARDVALUE] FULLSCREEN SETFOCUS [FMSLogo]

Press the 'A' key on the keyboard a Press the 'B' key on the keyboard b

SPLITSCREEN KEYBOARDOFF

Using KEYBOARDON with two inputs to perform actions only while keys are held down:

TO ONKEYDOWN IF KEYBOARDVALUE = ASCII "T [ HIDETURTLE ] IF KEYBOARDVALUE = ASCII "S [ IF SCREENCOLOR <> 1 [SETSCREENCOLOR 1] ] END

TO ONKEYUP IF KEYBOARDVALUE = ASCII "T [ SHOWTURTLE ] IF KEYBOARDVALUE = ASCII "S [ SETSCREENCOLOR 7 ] END

72 Communication

(KEYBOARDON [ONKEYDOWN] [ONKEYUP]) FULLSCREEN

While you hold down the "T" key, the turtle hides. While you hold down the "S" key, the screen turns blue.

SPLITSCREEN KEYBOARDOFF KEYBOARDOFF

Synopsis KEYBOARDOFF

Description Disables trapping of keyboard events.

Example KEYBOARDON [PRINT CHAR KEYBOARDVALUE] FULLSCREEN SETFOCUS [FMSLogo] a a b b SPLITSCREEN KEYBOARDOFF KEYBOARDVALUE

Synopsis KEYBOARDVALUE

Description Outputs a number that corresponds to last key that was either pushed or released. The number which it outputs depends on both the key that was pressed and whether KEYBOARDON was given one or two inputs.

If KEYBOARDON was given one input, then the keyboard input is captured as the character that was typed. That is, KEYBOARDVALUE outputs the ASCII value of last character that was typed. For example, on a US keyboard, "5" and "%" are both painted on the same key. If user hits the '5' key without a Shift, then KEYBOARDVALUE outputs 53, which is ASCII 5. On the other hand, if the user hits the '5' key while holding the Shift key down, then KEYBOARDVALUE outputs 37, which is ASCII "%.

Furthermore, if KEYBOARDON was only given one input, then keystrokes that are not directly related to textual characters are ignored. For example, the Shift, Ctrl, Home, and End keys are ignored.

If KEYBOARDON was given two inputs, then KEYBOARDVALUE outputs the keystrokes as distinct physcial keys on the keyboard, but not necessarily the intended character. In this case, when the 5 key is pressed, KEYBOARDVALUE outputs the same number regardless of whether Shift was being held at the time. However, there are distinct events when the Shift key is pressed and when it is released, so you can still identify the difference between a 5 and a %.

73 Communication

In general, if KEYBOARDON was given two inputs, then each physical key generates a unique number, but there are exceptions. The number that is assigned to some keys may vary across keyboards and keyboard layouts (for example, US or French). Similarly, some keyboards (such as the Microsoft Natural Keyboard or the Microsoft Comfort Keyboard) have more keys than a normal keyboard and can generate keyboard events that cannot be generated on other keyboards (such as a "Left Shift" as distict from a "Right Shift", or a "Volume Up" key). Finally, some small keyboards, such as those on a laptop, have special modes where the same physical key might act as two distinct keys depending on the keyboard's mode. For example, the J key might act as a Num Pad 1 when a special "alternate mode" key is held down. The KEYBOARDVALUE assignments shown in the table below should be portable across all keyboards.

Key KEYBOARDVALUE Backspace 8 Tab 9 Clear 12 Enter 13 Shift 16 Ctrl 17 Alt 18 Pause 19 Caps Lock 20 Esc 27 Spacebar 32 Page Up 33 Page Down 34 End 35 Home 36 Left Arrow 37 Up Arrow 38 Right Arrow 39 Down Arrow 40 Print Screen 44 Insert 45 Delete 46 0 Key 48 1 Key 49 2 Key 50 3 Key 51 4 Key 52

74 Communication

Key KEYBOARDVALUE 5 Key 53 6 Key 54 7 Key 55 8 Key 56 9 Key 57 A Key 65 B Key 66 C Key 67 D Key 68 E Key 69 F Key 70 G Key 71 H Key 72 I Key 73 J Key 74 K Key 75 L Key 76 M Key 77 N Key 78 O Key 79 P Key 80 Q Key 81 R Key 82 S Key 83 T Key 84 U Key 85 V Key 86 W Key 87 X Key 88 Y Key 89 Z Key 90 Left Windows Key 91 Right Windows Key 92 Applications Key 93 0 Key on Num Pad 96 1 Key on Num Pad 97 2 Key on Num Pad 98 3 Key on Num Pad 99

75 Communication

Key KEYBOARDVALUE 4 Key on Num Pad 100 5 Key on Num Pad 101 6 Key on Num Pad 102 7 Key on Num Pad 103 8 Key on Num Pad 104 9 Key on Num Pad 105 * Key on Num Pad 106 + Key on Num Pad 107 - Key on Num Pad 109 . Key on Num Pad (decimal separator) 110 / Key on Num Pad 111 F1 112 F2 113 F3 114 F4 115 F5 116 F6 117 F7 118 F8 119 F9 120 F10 121 F11 122 F12 123 Num Lock 144 Scroll Lock 145 Volume Mute 173 Volume Down 174 Volume Up 175 + Key 187 , Key 188 - Key 189 . Key 190

The following KEYBOARDVALUE assignments should be portable across all keyboards with a standard US layout.

Key KEYBOARDVALUE ; or : 186 / or ? 191

76 Communication

Key KEYBOARDVALUE ` or ~ 192 [ or { 219 \ or | 220 } or ] 221 ' or " 222

Example KEYBOARDON [PRINT CHAR KEYBOARDVALUE] FULLSCREEN SETFOCUS [FMSLogo]

Press the 'A' key on the keyboard a Press the 'B' key on the keyboard b

KEYBOARDOFF SPLITSCREEN MOUSEON

Synopsis MOUSEON leftbuttondown leftbuttonup rightbuttondown rightbuttonup move

Description Starts trapping mouse events that are sent to the "FMSLogo" window and passes them to leftbuttondown, leftbuttonup , rightbuttondown, rightbuttonup, or move, depending on the type of event. The callbacks may either be a word that is the name of a procedure to call, or a list of instructions to run. All "callbacks" for the mouse are automatically run in NOYIELD mode.

To obtain where the mouse was when a button was pushed or the mouse moved call MOUSEPOS in your button or move procedure.

Example PENUP MOUSEON [SETPOS MOUSEPOS PENDOWN] [PENUP] [] [] [SETPOS MOUSEPOS]

Move the mouse around. Hold down the left button to draw.

MOUSEOFF

See Also MOUSEOFF MOUSEOFF

Synopsis MOUSEOFF

Description Disables trapping of mouse events.

Example PENUP MOUSEON [SETPOS MOUSEPOS PENDOWN] [PENUP] [] [] [SETPOS MOUSEPOS]

Move the mouse around.

77 Communication

Hold down the left button to draw.

MOUSEOFF

Move the mouse around and hold down the left button. Nothing happens anymore.

See Also MOUSEON MOUSEPOS

Synopsis MOUSEPOS

Description Output the position of the mouse at the time the last mouse event was generated. The position is given as a list with two items: [X, Y]. The mouse must first be turned on by calling MOUSEON.

Example PENUP MOUSEON [SETPOS MOUSEPOS PENDOWN] [PENUP] [] [] [SETPOS MOUSEPOS]

Move the mouse around. Hold down the left button to draw.

MOUSEOFF CLEARTEXT

Synopsis CLEARTEXT CT

Description Clears all text within the command recall box in the commander window.

Example PRINT "Hello Hello CLEARTEXT SETCURSOR

Synopsis SETCURSOR vector Description Note

SETCURSOR is not supported in FMSLogo.

In other Logo environments, SETCURSOR moves the screen cursor to an x,y coordinate given by an input vector (a list of two numbers). The origin is the upper left corner, positive direction is down and right. This command also forces the immediate printing of any buffered characters. CURSOR

Synopsis CURSOR Description Note

CURSOR is not supported in FMSLogo.

78 Communication

In other Logo environments, CURSOR outputs a list containing the current x and y coordinates of the screen cursor. In FMSLogo, it always outputs [0 0]. SETMARGINS

Synopsis SETMARGINS margins Description Note

SETMARGINS is not supported (or needed) in FMSLogo.

In other Logo environments, SETMARGINS clears the text screen and then arrange for all further printing to be shifted down and to the right according to the margins input, effectively adding margins to the text screen. Specifically, every time a newline character is printed (explicitly or implicitly) Logo types x_margin spaces, and on every invocation of SETCURSOR the margins are added to the input x and y coordinates. (CURSOR reports the cursor position relative to the margins, so this shift is invisible to Logo programs.)

The input is a list of two numbers, as for SETCURSOR.

The purpose of this command is to accommodate the display of screens in lecture halls with inadequate TV monitors that miss the top and left edges of the screen. This is not necessary in FMSLogo, as the window can just be moved to the visible portion of the TV monitor.

79 Chapter 8. Arithmetic

Numeric Operations ...... 81 SUM ...... 81 DIFFERENCE ...... 81 MINUS ...... 82 PRODUCT ...... 82 QUOTIENT ...... 82 REMAINDER ...... 83 MODULO ...... 83 INT ...... 84 ROUND ...... 84 ABS ...... 84 SIGN ...... 85 SQRT ...... 85 POWER ...... 85 EXP ...... 85 LOG10 ...... 86 LN ...... 86 PI ...... 86 GOLDENRATIO ...... 86 TAN ...... 87 RADTAN ...... 87 SIN ...... 87 RADSIN ...... 87 COS ...... 88 RADCOS ...... 88 ARCTAN ...... 88 RADARCTAN ...... 89 ARCSIN ...... 89 RADARCSIN ...... 89 ARCCOS ...... 89 RADARCCOS ...... 90 Arithmetic Predicates ...... 90 LESSP ...... 90 LESSEQUALP ...... 90 GREATERP ...... 91 GREATEREQUALP ...... 91 Random Numbers ...... 92 RANDOM ...... 92 RERANDOM ...... 93 Print Formatting ...... 93 FORM ...... 93 Bitwise Operations ...... 93 BITAND ...... 93 BITOR ...... 94 BITXOR ...... 94 BITNOT ...... 94 ASHIFT ...... 94 LSHIFT ...... 95

80 Arithmetic

Numeric Operations

SUM ...... 81 DIFFERENCE ...... 81 MINUS ...... 82 PRODUCT ...... 82 QUOTIENT ...... 82 REMAINDER ...... 83 MODULO ...... 83 INT ...... 84 ROUND ...... 84 ABS ...... 84 SIGN ...... 85 SQRT ...... 85 POWER ...... 85 EXP ...... 85 LOG10 ...... 86 LN ...... 86 PI ...... 86 GOLDENRATIO ...... 86 TAN ...... 87 RADTAN ...... 87 SIN ...... 87 RADSIN ...... 87 COS ...... 88 RADCOS ...... 88 ARCTAN ...... 88 RADARCTAN ...... 89 ARCSIN ...... 89 RADARCSIN ...... 89 ARCCOS ...... 89 RADARCCOS ...... 90 SUM

Synopsis SUM addend1 addend2 (SUM addend1 addend2 ...) addend1 + addend2

Description Outputs the sum of its inputs. If no inputs are given, then SUM outputs 0.

Example SHOW 2 + 3 5

SHOW (SUM 1 2 3) 6 DIFFERENCE

Synopsis DIFFERENCE number1 number2 number1 - number2

Description Outputs the difference of its inputs.

81 Arithmetic

The minus sign (-) means infix difference in ambiguous contexts (when preceded by a complete expression), unless it is preceded by a space and followed by a non-space.

Example SHOW 3 - 2 1

SHOW DIFFERENCE 3 2 1 MINUS

Synopsis MINUS number -number

Description Outputs the negative of its input.

The minus sign means unary minus if it is immediately preceded by something requiring an input, or preceded by a space and followed by a non-space. There is a difference in binding strength between the two forms:

MINUS 3 + 4 means -(3+4)

- 3 + 4 means (-3)+4

Example SHOW 2 - -3 5

SHOW 2 - MINUS 3 5 PRODUCT

Synopsis PRODUCT factor1 factor2 (PRODUCT factor1 factor2 ...) factor1 * factor2

Description Outputs the product of its inputs. If no inputs are given, then PRODUCT outputs 1.

Example SHOW 2 * 3 6

SHOW (PRODUCT 2 3 4) 24 QUOTIENT

Synopsis QUOTIENT dividend divisor (QUOTIENT divisor) dividend / divisor

Description Outputs the quotient of its inputs. That is, it outputs dividend divided by divisor. QUOTIENT outputs an integer if and only if dividend is a

82 Arithmetic

multiple of divisor. For example, QUOTIENT 5 2 is 2.5, not 2, but QUOTIENT 4 2 is 2, not 2.0.

When the single input form is called, QUOTIENT outputs the reciprocal of the input.

It is an error to call QUOTIENT with a divisor of 0.

Example SHOW 5 / 2 2.5

SHOW (QUOTIENT 5 2) 2.5

SHOW (QUOTIENT 2) 0.5 REMAINDER

Synopsis REMAINDER dividend divisor

Description Outputs the remainder of dividing dividend by divisor. Both dividend and divisor must be numbers and divisor must not be 0.

Mathematically, a remainder is a number such that

dividend = quotient * divisor + remainder

Where quotient is an integer and -divisor < remainder < divisor. By this definition, two remainders may be possible for a given divisor and dividend, one positive and one negative. To make REMAINDER well-defined, it always outputs the remainder whose sign matches that of dividend. In contrast, MODULO uses the sign of divisor.

Example SHOW REMAINDER 5 3 2

SHOW REMAINDER -5 3 -2

SHOW REMAINDER 3.8 1.2 0.2

See Also MODULO MODULO

Synopsis MODULO dividend divisor

Description Outputs the remainder of dividing dividend divided by divisor. Both dividend and divisor must be numbers and divisor must not be 0.

Mathematically, a remainder is a number such that

dividend = quotient * divisor + remainder 83 Arithmetic

Where quotient is an integer and -divisor < remainder < divisor. By this definition, two remainders may be possible for a given divisor and dividend, one positive and one negative. To make MODULO well-defined, it always outputs the remainder whose sign matches that of divisor. In contrast, REMAINDER uses the sign of dividend.

Example SHOW MODULO 5 3 2

SHOW MODULO -5 3 1

SHOW MODULO 3.8 1.2 0.2

See Also REMAINDER INT

Synopsis INT num

Description Outputs its input with fractional part removed. That is, INT outputs an integer with the same sign as the input, whose absolute value is the largest integer less than or equal to the absolute value of the input.

Inside the computer, numbers are represented with two different formats, one for integers and one for numbers with fractional parts. On most computers the largest number that can be represented in integer format is smaller than the largest integer that can be represented in fractional format. The INT operation always outputs a number whose value is mathematically an integer, but if its input is very large the output may not be in integer format. In that case, operations like REMAINDER that require an integer input will not accept this number.

Example SHOW INT 8.2 8

SHOW INT 8.7 8 ROUND

Synopsis ROUND num

Description Outputs the nearest integer to the input.

Example SHOW ROUND 8.2 8

SHOW ROUND 8.7 9 ABS

84 Arithmetic

Synopsis ABS num

Description Outputs the absolute value (magnitude) of its input.

Example SHOW ABS 5 5

SHOW ABS -5 5 SIGN

Synopsis SIGN num

Description Outputs the sign (-1 if negative, 0 if zero, 1 is positive) of its input. This is handy for when you want to apply the sign of one number to another.

Example SHOW SIGN 5 1

SHOW SIGN 0 0

SHOW SIGN -98.6 -1 SQRT

Synopsis SQRT num

Description Outputs the square root of the input, which must be nonnegative.

Example SHOW SQRT 4 2

SHOW SQRT 2 1.4142135623731 POWER

Synopsis POWER base exponent

Description Outputs base raised to the power of exponent. If base is negative, then exponent must be an integer.

Example SHOW POWER 2 3 8 EXP

Synopsis EXP exponent

Description Outputs e (2.718281828...) to the power of exponent.

Example SHOW EXP 2

85 Arithmetic

7.38905609893065 LOG10

Synopsis LOG10 num

Description Outputs the common logarithm of num. That is, 10 raised to the output is num.

Example SHOW LOG10 1 0

SHOW LOG10 10 1

SHOW LOG10 100 2 LN

Synopsis LN num

Description Outputs the natural logarithm of the num. That is, e (2.718281828...) raised to the output = num.

Example SHOW LN 1 0

SHOW LN EXP 2 2 PI

Synopsis PI

Description Outputs the value pi (3.14159265358979...).

Example SHOW PI 3.14159265358979

SHOW RADSIN PI/2 1 GOLDENRATIO

Synopsis GOLDENRATIO

Description Outputs a close approximation to the golden ratio, which is (1 + SQRT 5)/2.

The golden ratio expresses the relationship when the sum of two quantities is to the larger quantity as the larger quantity is to the smaller quantity. That is:

GOLDENRATIO = ((A + B) / A) = (A / B)

Example SHOW GOLDENRATIO

86 Arithmetic

1.61803398874989 TAN

Synopsis TAN angle

Description Outputs the tangent of angle, which is taken in degrees.

Example SHOW TAN 0 0

SHOW TAN 45 1

See Also RADTAN RADTAN

Synopsis RADTAN angle

Description Outputs the tangent of angle, which is taken in radians.

Example SHOW RADTAN 0 0

SHOW RADTAN PI/4 1

See Also TAN SIN

Synopsis SIN angle

Description Outputs the sine of angle, which is taken in degrees.

Example SHOW SIN 0 0

SHOW SIN 90 1

SHOW SIN 180 0

See Also RADSIN RADSIN

Synopsis RADSIN angle

Description Outputs the sine of angle, which is taken in radians.

Example SHOW RADSIN 0 0

87 Arithmetic

SHOW RADSIN PI/2 1

SHOW RADSIN PI 0

See Also SIN COS

Synopsis COS angle

Description Outputs the cosine of angle, which is taken in degrees.

Example SHOW COS 0 1

SHOW COS 90 0

SHOW COS 180 -1

See Also RADCOS RADCOS

Synopsis RADCOS angle

Description Outputs the cosine of angle, which is taken in radians.

Example SHOW RADCOS 0 1

SHOW RADCOS PI/2 0

SHOW RADCOS PI -1

See Also COS ARCTAN

Synopsis ARCTAN num (ARCTAN x y)

Description With one input, outputs the inverse tangent angle of num. The output is given in degrees in the range [-90,90].

With two inputs, outputs the inverse tangent angle of y / x. The output is given in degrees in the range [-180,180].

Example SHOW ARCTAN 1

88 Arithmetic

45

See Also RADARCTAN RADARCTAN

Synopsis RADARCTAN angle (RADARCTAN x y)

Description With one input, outputs the inverse tangent angle of num. The output is given in radians in the range [-PI/2,PI/2].

With two inputs, outputs the inverse tangent angle of y / x. The output is given in radians in the range [-PI,PI].

Example SHOW (RADARCTAN 1) = PI/4 true

See Also ARCTAN ARCSIN

Synopsis ARCSIN num

Description Outputs the inverse sine of its input. The output is given in degrees in the range [-90, 90]. num must be in the range [-1, 1].

Example SHOW ARCSIN 0.5 30

SHOW ARCSIN SIN 45 45

See Also RADARCSIN RADARCSIN

Synopsis RADARCSIN num

Description Outputs the inverse sine of its input. The output is given in radians in the range [-PI/2, PI/2]. num must be in the range [-1, 1].

Example SHOW (RADARCSIN 1) = PI/2 true

See Also ARCSIN ARCCOS

Synopsis ARCCOS num

Description Outputs the inverse cosine of its input. The output is given in degrees in the range [0, 180]. num must be in the range [-1, 1].

Example SHOW ARCCOS 0.5

89 Arithmetic

60

SHOW ARCCOS COS 45 45

See Also RADARCCOS RADARCCOS

Synopsis RADARCCOS num

Description Outputs the inverse cosine of its input. The output is given in radians in the range [0, PI]. num must be in the range [-1, 1].

Example SHOW (RADARCCOS (SQRT 2)/2) = PI/4 true

See Also ARCCOS Arithmetic Predicates

LESSP ...... 90 LESSEQUALP ...... 90 GREATERP ...... 91 GREATEREQUALP ...... 91 LESSP

Synopsis LESSP num1 num2 LESS? num1 num2 num1 < num2

Description Outputs TRUE if num1 is strictly less than num2. Outputs FALSE, otherwise.

Example SHOW 1 < 2 true

SHOW 2 < 1 false

SHOW 2 < 2 false

SHOW LESSP 1 2 true LESSEQUALP

Synopsis LESSEQUALP num1 num2 LESSEQUAL? num1 num2 num1 <= num2

Description Outputs TRUE if num1 is less than or equal to num2. Outputs FALSE, otherwise.

90 Arithmetic

Example SHOW 1 <= 2 true

SHOW LESSEQUALP 1 2 true

SHOW LESSEQUALP 2 2 true

SHOW LESSEQUALP 2 1 false

See Also LESSP EQUALP GREATERP GREATERP

Synopsis GREATERP num1 num2 GREATER? num1 num2 num1 > num2

Description Outputs TRUE if num1 is strictly greater than num2 . Outputs FALSE, otherwise.

Example SHOW 1 > 2 false

SHOW 2 > 1 true

SHOW 2 > 2 false

SHOW GREATERP 2 1 true GREATEREQUALP

Synopsis GREATEREQUALP num1 num2 GREATEREQUAL? num1 num2 num1 >= num2

Description Outputs TRUE if num1 is greater than or equal to num2. Outputs FALSE, otherwise.

Example SHOW 1 >= 1 true

SHOW GREATEREQUALP 1 1 true

SHOW GREATEREQUALP 1 2 false

SHOW GREATEREQUALP 2 1

91 Arithmetic

true

See Also LESSP EQUALP GREATERP Random Numbers

RANDOM ...... 92 RERANDOM ...... 93 RANDOM

Synopsis RANDOM range

Description Outputs a uniform random integer from 0 to the range input (not including the range input). The range input must be a nonnegative integer.

For example, if the input is 10, then RANDOM outputs any of these integers with equal probability: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

Computers are inherently deterministic, which means that, given a set of inputs, computers always follow a program to produce the exact same output. This makes it difficult for a computer to generate truly random numbers. For this reason, when a computer generates a random number, it is often called a pseudo-random number, which means "fake random number". Here's how RANDOM works. Imagine that RANDOM has a giant list of numbers that appear in a predetermined, random-looking order. Each time you run RANDOM, it reads the next number from the list, scales it to the requested range, and outputs the result. If RANDOM always started at the top of this list, then it would always produce the same sequence of numbers each time Logo was run, which wouldn't appear random at all. Of course, RANDOM can't just pick a random place in the list to start, because computers can't create true randomness. To get around this problem, when Logo starts up, it uses the current time to determine where in the list it should start getting numbers from. As long as you start each program at a different time, the random sequence is different, which is usually good enough to simulate true randomness. But if you manage to start two instances of Logo at exactly the same time, then RANDOM would output the exact same sequence of numbers.

Normally, you want RANDOM to output different values each time your program is run. But sometimes you may want to produce the exact same sequence of numbers. In these cases, you can use RERANDOM to reset the location in the list where RANDOM gets its next number from.

Example REPEAT 5 [SHOW RANDOM 10] 6 8 3 0 9

See Also RERANDOM PICK

92 Arithmetic

RERANDOM

Synopsis RERANDOM (RERANDOM seed)

Description Makes the output of RANDOM reproducible. Ordinarily the sequence of random numbers is different each time Logo is used. If you need the same sequence of pseudo-random numbers repeatedly, for example, to debug a program, run RERANDOM before the first invocation of RANDOM or PICK. If you need more than one repeatable sequence, you can give RERANDOM an integer input called a "seed"; each distinct seed selects a unique sequence of numbers.

Example RERANDOM REPEAT 2 [SHOW RANDOM 10] 6 2 RERANDOM REPEAT 2 [SHOW RANDOM 10] 6 2 Print Formatting

FORM ...... 93 FORM

Synopsis FORM num width precision

Description Outputs a word containing a printable representation of num, possibly preceded by spaces (and therefore not a number for purposes of performing arithmetic operations). The output has at least width characters, including exactly precision digits after the decimal point. If precision is 0 then there is no decimal point in the output.

Example SHOW FORM 123.1 10 10 123.1000000000 Bitwise Operations

BITAND ...... 93 BITOR ...... 94 BITXOR ...... 94 BITNOT ...... 94 ASHIFT ...... 94 LSHIFT ...... 95 BITAND

Synopsis BITAND int1 int2 (BITAND int1 int2 int3 ...)

93 Arithmetic

Description Outputs the bitwise AND of its inputs, which must be integers. If no inputs are given, then BITAND outputs a value with all bits set.

Example SHOW BITAND 5 2 0 SHOW BITAND 5 1 1 SHOW (BITAND 6 2 10) 2 BITOR

Synopsis BITOR int1 int2 (BITOR int1 int2 int3 ...)

Description Outputs the bitwise OR of its inputs, which must be integers. If no inputs are given, then BITOR outputs a value with no bits set.

Example SHOW BITOR 5 2 7 SHOW BITOR 5 1 5 SHOW (BITOR 6 2 10) 14 BITXOR

Synopsis BITXOR int1 int2 (BITXOR int1 int2 int3 ...)

Description Outputs the bitwise exclusive OR of its inputs, which must be integers. If no inputs are given, then BITXOR outputs a value with no bits set.

Example SHOW BITXOR 5 2 7 SHOW BITXOR 5 1 4 SHOW (BITXOR 6 2 10) 14 BITNOT

Synopsis BITNOT int

Description Outputs the bitwise negation of its input, which must be an integer.

Example SHOW BITNOT 1 -2 SHOW BITNOT 5 -6 ASHIFT

Synopsis ASHIFT int amount

94 Arithmetic

Description Outputs int arithmetic-shifted to the left by amount bits. If amount is negative, the shift is to the right with sign extension. The inputs must be integers.

Example SHOW ASHIFT 5 2 20 SHOW ASHIFT 20 -1 10 SHOW ASHIFT -20 -1 -10 LSHIFT

Synopsis LSHIFT int amount

Description Outputs int shifted logically to the left by amount bits. If amount is negative, the shift is to the right with zero fill. The inputs must be integers.

Example SHOW LSHIFT 5 2 20 SHOW LSHIFT 20 -1 10 SHOW LSHIFT -20 -1 2147183638

95 Chapter 9. Logical Operations

AND ...... 96 OR ...... 96 NOT ...... 96 AND

Synopsis AND boolean1 boolean2 (AND boolean1 boolean2 boolean3 ...)

Description Outputs TRUE if all inputs are TRUE, otherwise FALSE. All inputs must be TRUE or FALSE.

The comparison is always case-insensitive, regardless of the value of CASEIGNOREDP. That is, "true", "True", and "TRUE" are all the same.

If given no inputs, AND outputs TRUE.

Example SHOW AND "true "true true SHOW AND "true "false false OR

Synopsis OR boolean1 boolean2 (OR boolean1 boolean2 boolean3 ...)

Description Outputs TRUE if at least one input is TRUE. Outputs FALSE, otherwise. All inputs must be TRUE or FALSE.

The comparison is always case-insensitive, regardless of the value of CASEIGNOREDP. That is, "true", "True", and "TRUE" are all the same.

If given no inputs, OR outputs FALSE.

Example SHOW OR "true "true true SHOW OR "true "false true SHOW OR "false "false false NOT

Synopsis NOT boolean

Description Outputs TRUE if the input is FALSE, and vice versa. The input must be a boolean value.

Example SHOW NOT "true

96 Logical Operations false SHOW NOT "false true

97 Chapter 10. Graphics

Multiple Turtles ...... 100 SETTURTLE ...... 101 TURTLE ...... 102 HASOWNPENP ...... 102 TURTLES ...... 102 BITMAPTURTLE ...... 103 NOBITMAPTURTLE ...... 104 SETTURTLEMODE ...... 104 TURTLEMODE ...... 106 ASK ...... 106 Turtle Motion ...... 106 FORWARD ...... 107 BACK ...... 107 LEFT ...... 107 RIGHT ...... 107 LEFTROLL ...... 108 RIGHTROLL ...... 108 DOWNPITCH ...... 108 UPPITCH ...... 108 SETPOS ...... 109 SETPOSXYZ ...... 109 SETXY ...... 110 SETXYZ ...... 110 SETX ...... 111 SETY ...... 111 SETZ ...... 111 HOME ...... 112 SETHEADING ...... 112 SETROLL ...... 112 SETPITCH ...... 113 SETORIENTATION ...... 114 ELLIPSEARC ...... 115 ELLIPSEARC2 ...... 115 ELLIPSE ...... 117 ELLIPSE2 ...... 117 ARC ...... 118 ARC2 ...... 118 CIRCLE ...... 119 CIRCLE2 ...... 119 Turtle Motion Queries ...... 119 POS ...... 120 POSXYZ ...... 120 XCOR ...... 120 YCOR ...... 120 ZCOR ...... 121 HEADING ...... 121 ROLL ...... 121 PITCH ...... 121 ORIENTATION ...... 122 TOWARDS ...... 122 TOWARDSXYZ ...... 122

98 Graphics

DISTANCE ...... 123 DISTANCEXYZ ...... 123 PIXEL ...... 123 SCRUNCH ...... 124 Turtle Control ...... 124 SHOWTURTLE ...... 125 HIDETURTLE ...... 125 CLEAN ...... 125 CLEARSCREEN ...... 125 WRAP ...... 126 WINDOW ...... 126 FENCE ...... 126 PERSPECTIVE ...... 127 FILL ...... 129 SLOWDRAW ...... 131 LABEL ...... 131 SETPIXEL ...... 133 FONTFACENAMES ...... 133 SETLABELFONT ...... 134 LABELFONT ...... 135 LABELSIZE ...... 135 Window Control ...... 136 TEXTSCREEN ...... 136 FULLSCREEN ...... 136 SPLITSCREEN ...... 136 SETSCRUNCH ...... 137 REFRESH ...... 137 NOREFRESH ...... 137 ZOOM ...... 137 SCROLLX ...... 138 SCROLLY ...... 138 SETFOCUS ...... 138 GETFOCUS ...... 139 ICON ...... 139 UNICON ...... 139 MINIMIZE ...... 140 RESTORE ...... 140 MAXIMIZE ...... 140 WINDOWSET ...... 141 Using Color ...... 142 Understand Your Orientation in 3D ...... 151 Drawing 3D Solids ...... 152 POLYSTART ...... 153 POLYEND ...... 154 POLYVIEW ...... 154 SETLIGHT ...... 155 LIGHT ...... 155 Polygon Restrictions ...... 156 Restriction #1: A polygon's first 3 vertices must form a triangle ...... 156 Restriction #2: A polygon must be convex ...... 156 Restriction #3: A polygon must be planar ...... 157 Polygon Samples ...... 158 Turtle And Window Queries ...... 158 SHOWNP ...... 158

99 Graphics

Pen Control ...... 158 PENDOWN ...... 159 PENUP ...... 159 PENPAINT ...... 159 PENERASE ...... 160 PENREVERSE ...... 160 PENNORMAL ...... 160 SETPENCOLOR ...... 160 SETFLOODCOLOR ...... 161 SETSCREENCOLOR ...... 161 SETPENSIZE ...... 162 SETPENPATTERN ...... 162 SETPEN ...... 162 CLEARPALETTE ...... 163 Pen Queries ...... 163 PENDOWNP ...... 163 PENMODE ...... 164 PENCOLOR ...... 164 FLOODCOLOR ...... 164 SCREENCOLOR ...... 165 PENSIZE ...... 165 PENPATTERN ...... 165 PEN ...... 165

FMSLogo provides both traditional and extended Logo turtle graphics. Multiple turtles are supported but dynamic turtles and collision detection are not supported.

The center of the graphics surface (which may not be the center of the screen window, depending on how it is scrolled) is turtle location [0 0]. Positive X is to the right; positive Y is up. Headings (angles) are measured in degrees clockwise from the positive Y axis. (This differs from the common mathematical convention of measuring angles counterclockwise from the positive X axis.) The turtle is represented as an isosceles triangle; the actual turtle position is at the midpoint of the base (the long side).

FMSLogo begins with a white background and black pen.

FMSLogo supports color-by-index, color-by-name, and true color. See Using Color for details. Multiple Turtles

SETTURTLE ...... 101 TURTLE ...... 102 HASOWNPENP ...... 102 TURTLES ...... 102 BITMAPTURTLE ...... 103 NOBITMAPTURTLE ...... 104 SETTURTLEMODE ...... 104 TURTLEMODE ...... 106 ASK ...... 106

FMSLogo supports multiple turtles. Each turtle maintains its own heading (orientation in 3D), position, and pen control. Turtles can be individually represented as a picture using BITMAPTURTLE. By default, all turtles share the same pen mode, pen color, and pen size, but you can make individual turtles have their own pen by supplying an optional input to SETTURTLE.

100 Graphics

Turtles start at index 0, which is the default turtle. All turtles between 0 and the highest turtle ever selected are "activated", so don't choose turtle 100 and 200 if you only need 2 turtles. Having thousands of active turtles may slow FMSLogo down considerably as it pauses to redraw every turtle after every instruction. Pressing the "Reset" button or running CLEARSCREEN selects turtle 0 and deactivates all other turtles.

In addition to the turtles which you can create, there are also three special turtles which are used in PERSPECTIVE mode. Index Turtle -1 His position represents where your eye is when viewing a 3D scene (defaults to [400 400 600]). His orientation does not matter. Changing this turtle's position does not have any effect on the screen until something new is drawn. -2 Her position represents where your eye is looking when viewing a 3D scene (defaults to [0 0 0]). Her orientation represents which direction is "up" on the screen (defaults to [0 0 0], the positive Y axis is up). Changing this turtle's position does not have any effect on the screen until something new is drawn. -3 Its position represents where the light source is positioned (defaults to [0 0 1000]). Its orientation does not matter. This turtle only matters when you're using POLYSTART and POLYEND.

Note that you cannot look in the same direction as "up". For example, if turtle -2 is in her default position and orientation and you set turtle -1 to somewhere along the position Y axis, say [0 1000 0], you won't be able to see anything.

These special turtles are never shown or bitmapped. Each time you enter PERSPECTIVE mode all special turtles are reset to their default position and orientation. SETTURTLE

Synopsis SETTURTLE index (SETTURTLE index hasownpen)

Description Selects turtle index for control. If the turtle was not previously activated, then all turtles from zero to index are activated. From now until you select a different turtle, all turtle commands refers to the newly selected turtle.

Normally, all turtles share the same PENMODE, PENSIZE and PENCOLOR. However, if you supply the optional boolean hasownpen input as "true, then the selected turtle, as well as all newly activated turtles, have their own PENMODE, PENSIZE, and PENCOLOR. You also can change a previously activated turtle to use its own pen (or not) by specifying a hasownpen input.

If no hasownpen input is given and SETTURTLE does not activate any new turtles, then the selected turtle's pen remains unchanged. If no hasownpen input is given and SETTURTLE activates a new turtle, then the new turtle uses the shared pen (the one that FMSLogo initally gave to turtle 0 when it started).

Example An example in 2D: REPEAT 8 [SETTURTLE REPCOUNT RIGHT REPCOUNT*30 FORWARD 20*REPCOUNT]

101 Graphics

An example in 3D that draws a cube from the default vantage point:

PERSPECTIVE CLEARSCREEN REPEAT 4 [REPEAT 4 [FORWARD 100 RIGHT 90] FORWARD 100 DOWNPITCH 90]

An example in 3D that uses SETTURTLE to draw the same cube from a different vantage point:

PERSPECTIVE CLEARSCREEN SETTURTLE -1 ; Select the "eye position" turtle SETXYZ 500 500 500 ; Move the vantage point

; Draw a cube from the new vantage point. SETTURTLE 0 REPEAT 4 [REPEAT 4 [FORWARD 100 RIGHT 90] FORWARD 100 DOWNPITCH 90]

See Also TURTLE TURTLES TURTLE

Synopsis TURTLE

Description Outputs the number which corresponds to the currently selected turtle (the one that is obeying all turtle commands). Use SETTURTLE to select a turtle.

Example SETTURTLE 8 SHOW TURTLE 8

See Also TURTLES HASOWNPENP

Synopsis HASOWNPENP HASOWNPEN?

Description Outputs TRUE if the currently selected turtle has its own setting for PENMODE, PENSIZE, and PENCOLOR. Outputs FALSE if the currently selected turtle shares its pen settings with other turtles.

Example SETTURTLE 1 SHOW HASOWNPENP false

(SETTURTLE 1 "true) SHOW HASOWNPENP true

See Also SETTURTLE TURTLES

102 Graphics

Synopsis TURTLES

Description Outputs the maximum turtle that has been selected since the last time you executed a CLEARSCREEN.

Example CLEARSCREEN (SHOW TURTLE TURTLES) 0 0 SETTURTLE 8 (SHOW TURTLE TURTLES) 8 8 SETTURTLE 4 (SHOW TURTLE TURTLES) 4 8 CLEARSCREEN (SHOW TURTLE TURTLES) 0 0

See Also TURTLE SETTURTLE BITMAPTURTLE

Synopsis BITMAPTURTLE (BITMAPTURTLE rotatebitmap)

Description Maps the current turtle (see SETTURTLE) to the corresponding bitmap buffer (see BITCUT). BITMAPTURTLE can map turtle 0 to bitmap 0, turtle 1 to bitmap 1, turtle 2 to bitmap 2, etc., on a per-turtle basis. Note that there is no way to map a turtle to any bitmap index other than the turtle's index. For example, turtle 2 can only be mapped to bitmap 2, not bitmap 1 or bitmap 3.

Because bitmap 0 is always mapped to the clipboard, BITMAPTURTLE can only map turtle 0 to the clipboard. That is, if you select turtle 0 and run BITMAPTURTLE, then the turtle changes to whatever is in the clipboard and is updated whenever the clipboard subsequently changes. FMSLogo complains if the clipboard is not holding an image while turtle 0 is bitmapped.

Both NOBITMAPTURTLE and CLEARSCREEN restores the turtle to its normal shape, but does not erase the corresponding bitmap.

If the optional rotatebitmap input is TRUE, then the bitmap rotates with the turtle's heading. If the rotatebitmap input is not given, it defaults to FALSE. This must be either TRUE or FALSE.

A turtle with a rotating bitmap treats all white pixels in the bitmap as transparent. There is no way to show white pixels in a rotating bitmap, but you can instead use nearly white pixels that look white, such as a very light grey. Neither turtle 0 (the clipboard bitmap), nor any of the special turtles, can be bitmapped using a rotating bitmap.

A turtle with a rotating bitmap draws the center of the bitmap at the turtle's position. A turtle with a non-rotating bitmap keeps the lower-left corner of the bitmap at the turtle's position.

Example The following example shows a regular bitmapped turtle that traces a circle.

103 Graphics

CLEARSCREEN LABEL "+ SETBITINDEX 1 BITCUT 20 20 HIDETURTLE SETTURTLE 1 BITMAPTURTLE REPEAT 360 [ FORWARD 1 RIGHT 1 WAIT 1 ]

The following example shows a turtle with a rotating bitmap that traces a circle on a blue background.

SETSCREENCOLOR "WHITE CLEARSCREEN LABEL "+ SETBITINDEX 1 BITCUT 20 20 HIDETURTLE SETTURTLE 1 SETSCREENCOLOR "BLUE (BITMAPTURTLE "TRUE) REPEAT 360 [ FORWARD 1 RIGHT 1 WAIT 1 ] NOBITMAPTURTLE

Synopsis NOBITMAPTURTLE

Description Restores the turtle to its original triangle shape. It is the opposite of BITMAPTURTLE.

Example CLEARSCREEN LABEL "+ BITCUT 20 20 BITMAPTURTLE FORWARD 100 NOBITMAPTURTLE SETTURTLEMODE

Synopsis SETTURTLEMODE mode

Description Sets the bitmap mode for the currently selected turtle. The bitmap mode controls how bitmapped turtles (see BITMAPTURTLE) paste their image onto the screen. Sometimes you want the background erased and sometimes not. Sometimes you wish to invert the image before pasting it and sometimes not.

The mode input must be an integer from 1 to 9. The meaning of each value is given by the following table:

Mode Turtle Image 1 The bitmap in memory, without modification

104 Graphics

Mode Turtle Image 2 A bitwise OR of the bitmap in memory and the screen 3 A bitwise AND of the bitmap in memory and the screen 4 A bitwise XOR of the bitmap in memory with the screen 5 A bitwise AND of the bitmap in memory with the bitwise inversion of screen 6 A bitwise inversion of the bitmap in memory 7 A bitwise OR of the bitmap in memory with the bitwise inversion of the screen 8 A bitwise OR of the bitwise inversion of the bitmap in memory and the screen 9 A bitwise inversion of the screen

SETTURTLEMODE has no effect if the selected turtle is not currently bitmapped. It is an error to run SETTURTLEMODE on a turtle that was bitmapped with a rotating bitmap.

Use SETTURTLE to select a different turtle.

Use TURTLEMODE to obtain the selected turtle's mode.

Use BITMAPTURTLE to map a turtle to a bitmap.

Example ; Fill the screen with white SETSCREENCOLOR [255 255 255] CLEARSCREEN

; Draw a circle and fill it with red PENDOWN CIRCLE 50 SETFLOODCOLOR [255 0 0] FILL

; Copy the red circle to the clipboard PENUP SETXY -50 -50 BITCOPY 101 101

; Use a simple copy for the turtle's mode BITMAPTURTLE

; Fill the screen with yellow SETSCREENCOLOR [255 255 0] ; Notice that the white corners show up when using the default turtle mode

105 Graphics

; Set the turtle mode to AND the image onto the background SETTURTLEMODE 3 ; Notice that the white corners disappeared TURTLEMODE

Synopsis TURTLEMODE

Description Outputs the selected turtle's mode. See SETTURTLEMODE for an explaination of turtle modes.

Example REPEAT 4 [ FORWARD 30 RIGHT 90 ] BITCOPY 50 50 BITMAPTURTLE SETTURTLEMODE 3 ASK

Synopsis ASK turtle instructionlist

Description Instructs a specific turtle to run a given set of instructions (which are usually turtle instructions).

ASK selects the turtle whose index matches the turtle input, runs instructionlist, then reselects the previous turtle.

ASK outputs whatever instructionlist outputs. If instructionlist does not output anything, then ASK doesn't output anything, either.

Example Send four turtles in four different directions:

REPEAT 4 [ASK REPCOUNT [ RIGHT 90 * REPCOUNT FORWARD 100 ]

See Also SETTURTLE Turtle Motion

FORWARD ...... 107 BACK ...... 107 LEFT ...... 107 RIGHT ...... 107 LEFTROLL ...... 108 RIGHTROLL ...... 108 DOWNPITCH ...... 108 UPPITCH ...... 108 SETPOS ...... 109 SETPOSXYZ ...... 109 SETXY ...... 110 SETXYZ ...... 110 SETX ...... 111 SETY ...... 111

106 Graphics

SETZ ...... 111 HOME ...... 112 SETHEADING ...... 112 SETROLL ...... 112 SETPITCH ...... 113 SETORIENTATION ...... 114 ELLIPSEARC ...... 115 ELLIPSEARC2 ...... 115 ELLIPSE ...... 117 ELLIPSE2 ...... 117 ARC ...... 118 ARC2 ...... 118 CIRCLE ...... 119 CIRCLE2 ...... 119 FORWARD

Synopsis FORWARD distance FD distance

Description Moves the turtle forward in the direction that it's headed by the specified distance, measured in turtle steps. The heading of the turtle does not change.

Example REPEAT 4 [FORWARD 100 RIGHT 90] BACK

Synopsis BACK distance BK distance

Description Moves the turtle backward, exactly opposite to the direction that it's headed, by the specified distance, measured in turtle steps. The heading of the turtle does not change.

Example REPEAT 4 [BACK 100 RIGHT 90] LEFT

Synopsis LEFT angle LT angle

Description Turns the turtle counterclockwise by the specified angle, measured in degrees (1/360 of a circle).

Example REPEAT 3 [FORWARD 100 LEFT 120] RIGHT

Synopsis RIGHT angle RT angle

Description Turns the turtle clockwise by the specified angle, measured in degrees (1/360 of a circle).

107 Graphics

Example REPEAT 3 [FORWARD 100 RIGHT 120] LEFTROLL

Synopsis LEFTROLL angle LR angle

Description Rolls the turtle toward his left side by the specified angle, measured in degrees (1/360 of a circle).

This command is designed to run in PERSPECTIVE mode.

Example PERSPECTIVE LEFTROLL 45 REPEAT 3 [FORWARD 100 LEFT 120] RIGHTROLL

Synopsis RIGHTROLL angle RR angle

Description Rolls the turtle toward his right side by the specified angle, measured in degrees (1/360 of a circle).

This command is designed to run in PERSPECTIVE mode.

Example PERSPECTIVE RIGHTROLL 45 REPEAT 3 [FORWARD 100 LEFT 120] DOWNPITCH

Synopsis DOWNPITCH angle DOWN angle

Description Pitches the turtle's nose downward by the specified angle, measured in degrees (1/360 of a circle).

This command is designed to run in PERSPECTIVE mode.

Example PERSPECTIVE DOWNPITCH 45 REPEAT 3 [FORWARD 100 LEFT 120] UPPITCH

Synopsis UPPITCH angle UP angle

Description Pitches the turtle's nose upward by the specified angle, measured in degrees (1/360 of a circle).

UPPITCH is designed to run in PERSPECTIVE mode.

108 Graphics

Example PERSPECTIVE UPPITCH 45 REPEAT 3 [FORWARD 100 LEFT 120] SETPOS

Synopsis SETPOS position

Description Moves the turtle to an absolute X,Y coordinate. The position input is a list of two numbers, the X and Y coordinates.

There is often some confusion on how to call SETPOS with variables. Let's look at some code:

MAKE "x 0 MAKE "y 100 SETPOS [:x :y] ; fails SETPOS (LIST :x :y) ; works

The first case is a list that contains 2 words ":x and ":y. In the second case a list is constructed containing the value of :x and :y.

You can see this more clearly by using SHOW:

SHOW [:x :y] [:x :y] SHOW (LIST :x :y) [0 100]

Example Draw a square using SETPOS:

CLEARSCREEN SETPOS [0 100] SETPOS [100 100] SETPOS [100 0] SETPOS [0 0]

See Also POS SETX SETY SETPOSXYZ

Synopsis SETPOSXYZ position

Description Moves the turtle to an absolute X,Y,Z coordinate. The position input is a list of three numbers, the X, Y and Z coordinates.

SETPOSXYZ is designed to run in PERSPECTIVE mode. When used in 2D modes, SETPOSXYZ ignores the Z coordinate and moves the turtle to the given X and Y coordinates.

Example An example that draws a cube using SETPOSXYZ:

CLEARSCREEN

109 Graphics

PERSPECTIVE SETPOSXYZ [0 100 0] SETPOSXYZ [100 100 0] SETPOSXYZ [100 0 0] SETPOSXYZ [0 0 0] SETPOSXYZ [0 0 100] SETPOSXYZ [100 0 100] SETPOSXYZ [100 100 100] SETPOSXYZ [0 100 100] SETPOSXYZ [0 0 100] SETPOSXYZ [0 100 100] SETPOSXYZ [0 100 0] SETPOSXYZ [100 100 0] SETPOSXYZ [100 100 100] SETPOSXYZ [100 0 100] SETPOSXYZ [100 0 0]

See Also POSXYZ SETX SETY SETZ SETXY

Synopsis SETXY xcor ycor

Description Moves the turtle to an absolute X,Y coordinate. The two inputs are numbers, the X and Y coordinates to move to.

Example REPEAT 360 [SETXY REPCOUNT 100*SIN REPCOUNT]

See Also POS SETPOS SETX SETY SETXYZ

Synopsis SETXYZ xcor ycor zcor

Description Moves the turtle to an absolute 3D position. The three inputs are numbers, the X, Y, and Z coordinates to move to.

SETXYZ is designed to run in PERSPECTIVE mode. In 2D modes, SETXYZ ignores the zcor input and moves the turtle to the given X and Y coordinates.

Example ; draw some sine waves in 3D PERSPECTIVE FOR [i 0 360 10] [ FOR [j 0 360] [SETXYZ :j :i*SIN :j -:i] PENUP SETXYZ 0 0 -:i PENDOWN ]

110 Graphics

See Also SETPOSXYZ SETX SETY SETZ SETX

Synopsis SETX xcor

Description Moves the turtle along the X axis from its current position to a new absolute X coordinate. The xcor input is the new X coordinate.

Example SETX 100 SETY 100 SETX 0 SETY 0

See Also XCOR SETY SETZ SETXY SETY

Synopsis SETY ycor

Description Moves the turtle along the Y axis from its current position to a new absolute Y coordinate. The ycor input is the new Y coordinate.

Example SETX 100 SETY 100 SETX 0 SETY 0

See Also SETX SETZ SETXY SETZ

Synopsis SETZ zcor

Description Moves the turtle along the Z axis from its current position to a new absolute Z coordinate. The zcor input is the new Z coordinate.

SETZ is designed to run in PERSPECTIVE mode.

Example PERSPECTIVE PENUP SETX 100 PENDOWN SETZ 100 SETY 100

111 Graphics

SETZ 0 SETY 0

See Also SETX SETY ZCOR HOME

Synopsis HOME

Description Moves the turtle to the center of the screen and sets the turtle's heading, pitch, and roll to 0.

In 2D modes, HOME is equivalent to

SETPOS [0 0] SETHEADING 0

In PERSPECTIVE mode, HOME is equivalent to

SETPOSXYZ [0 0 0] SETORIENTATION [0 0 0]

Example FORWARD 100 RIGHT 90 FORWARD 100 HOME

See Also CLEARSCREEN SETHEADING

Synopsis SETHEADING angle SETH angle

Description Turns the turtle to a new absolute heading. The angle input is the heading in degrees clockwise from the positive Y-axis. In PERSPECTIVE mode, the angle input is the heading in degrees from the positive X-Axis toward the positive Y-Axis rotating about the Z-Axis.

Example SETHEADING 45 SHOW HEADING 45

See Also HEADING SETROLL

Synopsis SETROLL angle

Description Rolls the turtle to a new absolute roll. The angle input is the roll in degrees which is positive from the positive X-Axis to the negative Z-Axis rotating about the Y-Axis. It is important to understand your orientation in 3D.

SETROLL is designed to run in PERSPECTIVE mode.

112 Graphics

Example PERSPECTIVE SETROLL 45 SHOW ROLL 45

See Also ROLL PITCH HEADING SETPITCH

Synopsis SETPITCH angle

Description Pitches the turtle to a new absolute pitch. The angle input is the pitch in degrees which is positive from the negative Z-Axis to the positive Y-Axis rotating about the X-Axis.

SETPITCH is designed to run in PERSPECTIVE mode.

SETPITCH can be confusing because it changes the turtle's orientation (roll, pitch, and heading) to an equivalent orientation, where the pitch may not be what was set. That is, PITCH may output a different angle than was set by SETPITCH, even though SETPITCH correctly set the turtle's pitch. Similarly, running SETPITCH with incrementally increasing angles is not guaranteed to incrementally increase the turtle's pitch, particularly if setting the pitch changes the ROLL or HEADING. Therefore, it is important to understand your orientation in 3D.

To illustrate this, suppose you want to draw the wheel of a bicycle with all spokes joining at the center. You may think that this works:

TO BADWHEEL PERSPECTIVE REPEAT 36 [ SETPITCH REPCOUNT*10 FORWARD 100 BACK 100 ] RIGHTROLL 90 CIRCLE 100 END

But after running BADWHEEL, it looks like some spokes weren't drawn.

The root of this surprising behavior can be seen in its simplest form with the following instructions:

PERSPECTIVE CLEARSCREEN SETPITCH 180 SHOW ORIENTATION [180 0 180]

Here, you set the pitch to 180, which, from an orientation of [0 0 0] can be thought of as "keep nosing up until you're upside-down and looking

113 Graphics

backward", but ORIENTATION shows that the pitch is 0, even though the turtle is upside-down and looking backward. Instead, the turtle's orientation is equivalent to [0 180 0], but it's described as flipping upside-down (roll = 180) and looking backward (heading = 180)—[180 0 180]. So now what happens if you set the pitch to 180 again? Well, you set the orientation to [180 180 180], which means "flip upside down, keep nosing up until you're upside-down and looking backward, then turn around", which puts you back at [0 0 0].

There are two easy ways to account for this. One way is to use SETORIENTATION, which updates both ROLL and HEADING to account for this. Another is to use UPPITCH instead of SETPITCH when making incremental changes to the pitch. With these, we can fix BADWHEEL above.

TO GOODWHEEL1 PERSPECTIVE REPEAT 36 [ SETORIENTATION (LIST 0 REPCOUNT*10 0) ; fix #1 FORWARD 100 BACK 100 ] RIGHTROLL 90 CIRCLE 100 END

TO GOODWHEEL2 PERSPECTIVE REPEAT 36 [ UPPITCH 10 ; fix #2 FORWARD 100 BACK 100 ] RIGHTROLL 90 CIRCLE 100 END

Example PERSPECTIVE SETPITCH 45 SHOW PITCH 45

See Also PITCH SETORIENTATION

Synopsis SETORIENTATION orientation

Description Orients the turtle to a new absolute orientation. The orientation input is a list, the [roll pitch heading] in degrees. It is important to understand your orientation in 3D.

SETORIENTATION is designed to run in PERSPECTIVE mode.

You can get your orientation with ORIENTATION . Keep in mind that ORIENTATION may not output the exact same values that you set, but it does

114 Graphics

output an equivalent orientation. For example, if you run SETORIENTATION [0 105 0], then ORIENTATION may output [180 75 180].

Example PERSPECTIVE SETORIENTATION [180 45 90] SHOW ORIENTATION [180 45 90]

See Also ORIENTATION SETROLL SETPITCH SETHEADING ELLIPSEARC

Synopsis ELLIPSEARC angle crosswise.semiaxis inline.semiaxis startangle

Description Draws part of (or all of) an ellipse based on the turtle heading, turtle position and given inputs. ELLIPSEARC does not move the turtle. The center-point of the elliptic arc is the turtle's current position. The elliptic arc starts at a location given by startangle and sweeps an angle equal to angle degrees in the clockwise direction.

The size and shape of the elliptic arc are determined by the crosswise.semiaxis and inline.semiaxis inputs. The crosswise.semiaxis input is the distance from the turtle to the ellipse in the direction perpendicular to the turtle's current heading. The inline.semiaxis input is the distance from the turtle to the ellipse in the direction in which the turtle is currently heading. This implies that the turtle's heading determines the orientation of the ellipse.

The startangle input is relative to the turtle's current heading. A startangle of 0 indicates that the elliptic arc starts behind the turtle. The startangle is measured in a clockwise direction, so a value of 90 indicates that the elliptic arc should start to the turtle's left (90 degrees clockwise from behind the turtle).

Normally the elliptic arc is draw clockwise, but if the angle input is negative, then the elliptic arc is draw counter-clockwise.

Example A 2D example: ELLIPSEARC 360 100 200 0 CLEARSCREEN ELLIPSEARC 90 50 50 0 CLEARSCREEN ELLIPSEARC 90 50 50 90

A 3D example: PERSPECTIVE REPEAT 72 [ELLIPSEARC 90 100 150 45 RIGHTROLL 5]

See Also ELLIPSEARC2 ELLIPSEARC2

115 Graphics

Synopsis ELLIPSEARC2 arc.angle x.semiaxis y.semiaxis start.angle

Description Moves the turtle clockwise over an elliptic arc. The arc spans arc.angle degrees of the ellipse, starting at the point described by start.angle degrees and ending at the point described by (start.angle + arc.angle) degrees.

The size and shape of the elliptic arc can visualized in the following manner. First, imagine an ellipse drawn in the center of the screen such that the x.semiaxis is the distance from the center to the ellipse along the X-axis and y.semiaxis is the distance from the center to the ellipse along the Y- axis. ELLIPSEARC2 draws part of this ellipse, an arc between two points on the ellipse. The starting point for this arc can be visualized by imagining a turtle at the ellipse's center with a HEADING of start.angle. Wherever this turtle intersects the ellipse as it moves forward is the starting point of the arc. The ending point can be similarly imagined as if that turtle had turned RIGHT an additional arc.angle degrees before moving forward to intersect the ellipse.

Now that you have visualized size and shape of the elliptic arc, you can visualize its position and orientation as follows. First, translate the elliptic arc such that its start position is at the turtle's current position. Next, rotate the elliptic arc such that a line that is tangent to the arc at its start position aligns with the turtle's current HEADING.

Despite the confusing behavior, it is straight-forward to use ELLIPSEARC2 to iteratively draw contiguous segments of an ellipse of equal sweeps. If your first call has a start.angle of 0 and in each subsequent call, the start.angle is the sum of all arc.angle inputs previously given, you'll end drawing contiguous elliptic arcs.

Normally, the arc is drawn in clockwise direction, but if the arc.angle input is negative, then the turtle moves backward in a counter-clockwise direction.

Example A simple 2D example:

ELLIPSEARC2 90 100 200 0 ELLIPSEARC2 90 50 100 0

A 2D ellipse built out of multiple consecutive arcs:

SETPENSIZE 10 SETPENCOLOR "RED ELLIPSEARC2 90 150 100 0 SETPENCOLOR "LIME ELLIPSEARC2 90 150 100 90 SETPENCOLOR "BLUE ELLIPSEARC2 90 150 100 180 SETPENCOLOR "YELLOW ELLIPSEARC2 90 150 100 270

The following draws an ellipse with a dashed line using multiple consecutive arcs. Note that the arc segments are equal sweeps (in degrees) which are not equal lengths (in turtle steps).

REPEAT 18 [

116 Graphics

PENUP ELLIPSEARC2 10 50 200 REPCOUNT*20-20 PENDOWN ELLIPSEARC2 10 50 200 REPCOUNT*20-10 ]

A 3D example:

PERSPECTIVE REPEAT 72 [ELLIPSEARC2 90 50 100 0 RIGHTROLL 5]

See Also ELLIPSEARC ELLIPSE

Synopsis ELLIPSE crosswise.semiaxis inline.semiaxis

Description Draws an ellipse based on the turtle heading, turtle position, and given inputs. The center-point of the ellipse is the turtle's current position. ELLIPSE does not move the turtle. The size and shape of the ellipse is based on the crosswise.semiaxis and inline.semiaxis inputs. The crosswise.semiaxis input is the distance from the turtle to the ellipse in the direction perpendicular turtle's current heading. The inline.semiaxis input is the distance from the turtle to the ellipse in the direction which the turtle is currently heading.

Example A 2D example:

ELLIPSE 100 200 CLEARSCREEN ELLIPSE 50 50 CLEARSCREEN ELLIPSE 50 50

A 3D example:

PERSPECTIVE REPEAT 18 [ELLIPSE 100 200 RIGHTROLL 10]

See Also ELLIPSE2 ELLIPSE2

Synopsis ELLIPSE2 inline.semiaxis crosswise.semiaxis

Description Draws an ellipse as if the turtle moved clockwise in an ellipse. The size and shape of the ellipse are determined by the inline.semiaxis and crosswise.semiaxis inputs. The inline.semiaxis input is the distance from the center-point of the ellipse to the ellipse's edge in the direction which the turtle is currently heading. The crosswise.semiaxis input is the distance from the center-point of the ellipse to the ellipse's edge in the direction perpendicular to the turtle's current heading.

The ellipse is drawn tangent to the turtle's current position and heading. This tangent point is at the extreme of the ellipse's crosswise axis and the whole ellipse appears to the turtle's right.

117 Graphics

Note that the inline.semiaxis and crosswise.semiaxis inputs are given in the reverse order as the inputs to the ELLIPSE command.

Example A 2D example:

ELLIPSE2 100 200 CLEARSCREEN ELLIPSE2 50 50 CLEARSCREEN ELLIPSE2 50 50

A 3D example:

PERSPECTIVE REPEAT 72 [ELLIPSE2 200 100 RIGHTROLL 5 FORWARD 5]

See Also ELLIPSE ARC

Synopsis ARC angle radius

Description Draws an arc (part of a circle) based on the turtle heading, turtle position, and inputs. The center-point of the arc is the turtle's current position. ARC does not move the turtle. The arc sweeps an amount given by the angle input. The size (curvature) of the arc is based on the radius input.

If radius is positive, then the arc starts radius turtle steps behind the turtle. If radius is negative, then the arc starts radius turtle steps in front of the turtle. In both cases, the arc sweeps an angle equal to the angle input. If angle is positive, then the arc is drawn in a clockwise direction. If angle is negative, then the arc is drawn in a counter-clockwise direction. If angle is 360 or greater (or -360 or less), then ARC draws a circle.

Example A 2D example:

ARC 360 100 ARC 90 50

A 3D example:

PERSPECTIVE REPEAT 36 [RIGHTROLL 10 ARC 90 100]

See Also ARC2 ARC2

Synopsis ARC2 angle radius

Description Moves the turtle along an arc (part of a circle). The arc sweeps an amount given by the angle input. The size (curvature) of the arc is based on the radius input.

118 Graphics

If angle is positive, then the turtle moves forward in a clockwise direction. If angle is negative, then the turtle moves backward in a counter-clockwise direction.

Example A 2D example:

ARC2 360 100 ARC2 90 50

A 3D example:

PERSPECTIVE REPEAT 36 [RIGHTROLL 10 ARC2 180 100 ARC2 -180 100]

See Also ARC CIRCLE

Synopsis CIRCLE radius

Description Draws a circle based on the turtle's position and the radius input. The center- point of the circle is the turtle's current position. CIRCLE does not move the turtle.

Example A 2D example:

CIRCLE 100

A 3D example:

PERSPECTIVE REPEAT 36 [CIRCLE 100 RIGHTROLL 5]

See Also CIRCLE2 CIRCLE2

Synopsis CIRCLE2 radius

Description Moves the turtle clockwise along a circle of the given radius. The turtle ends in the same position in which it starts.

Example A 2D example:

CIRCLE2 100

A 3D example:

PERSPECTIVE REPEAT 72 [CIRCLE2 100 RIGHTROLL 5]

See Also CIRCLE Turtle Motion Queries

POS ...... 120

119 Graphics

POSXYZ ...... 120 XCOR ...... 120 YCOR ...... 120 ZCOR ...... 121 HEADING ...... 121 ROLL ...... 121 PITCH ...... 121 ORIENTATION ...... 122 TOWARDS ...... 122 TOWARDSXYZ ...... 122 DISTANCE ...... 123 DISTANCEXYZ ...... 123 PIXEL ...... 123 SCRUNCH ...... 124 POS

Synopsis POS

Description Outputs the turtle's current position, as a list of two numbers, the X and Y coordinates.

Example SETPOS [100 100] SHOW POS [100 100] POSXYZ

Synopsis POSXYZ

Description Outputs the turtle's current position, as a list of three numbers, the X, Y, and Z coordinates.

POSXYZ is designed to run in PERSPECTIVE mode.

Example PERSPECTIVE SETPOSXYZ [100 200 300] SHOW POSXYZ [100 200 300] XCOR

Synopsis XCOR

Description Outputs the turtle's X coordinate.

Example SETX 100 SHOW XCOR 100 YCOR

Synopsis YCOR

120 Graphics

Description Outputs the turtle's Y coordinate.

Example SETY 100 SHOW YCOR 100 ZCOR

Synopsis ZCOR

Description Outputs the turtle's Z coordinate.

ZCOR is designed to run in PERSPECTIVE mode.

Example PERSPECTIVE SETZ 100 SHOW ZCOR 100 HEADING

Synopsis HEADING

Description Outputs the turtle's heading measured in degrees clockwise from the positive Y-axis.

Example SETHEADING 90 SHOW HEADING 90

See Also SETHEADING ROLL

Synopsis ROLL

Description Outputs the angle of the turtle's roll in degrees. It is important to understand your orientation in 3D.

ROLL is designed to run in PERSPECTIVE mode. In 2D modes, ROLL outputs zero.

Example SETROLL 90 SHOW ROLL 90

See Also SETROLL PITCH

Synopsis PITCH

Description Outputs the angle of the turtle's pitch in degrees. It is important to understand your orientation in 3D.

121 Graphics

PITCH is designed to run in PERSPECTIVE mode. In 2D modes, PITCH outputs 0.

Example SETPITCH 90 SHOW PITCH 90

See Also SETPITCH ORIENTATION

Synopsis ORIENTATION

Description Outputs a list, the turtle's [roll pitch heading] each in degrees. It is important to understand your orientation in 3D.

ORIENTATION is designed to run in PERSPECTIVE mode. When used in 2D modes, the roll and pitch outputs are zero.

Example PERSPECTIVE SETORIENTATION [180 45 90] SHOW ORIENTATION [180 45 90]

See Also SETORIENTATION ROLL PITCH HEADING TOWARDS

Synopsis TOWARDS position

Description Outputs the heading in degrees, at which the turtle should be headed so that it would point from its current position towards the position input. The position input must be given as a two item list containing the X and Y coordinates of the position to face.

Example SETPOS [0 0] SHOW TOWARDS [100 100] 45

SETHEADING TOWARDS [100 100] FORWARD DISTANCE [100 100]

See Also DISTANCE TOWARDSXYZ TOWARDSXYZ

Synopsis TOWARDSXYZ position

Description Outputs a list, containing [roll pitch heading] at which the turtle should be oriented so that it would point from its current position to the position given.

122 Graphics

The position must be given as a three item list containing the X, Y, and Z coordinates of the position to face. It is important to understand your orientation in 3D.

TOWARDSXYZ is designed to run in PERSPECTIVE mode.

Example PERSPECTIVE SETPOS [0 0 0] SHOW TOWARDSXYZ [100 100 0] [0 0 45]

SETORIENTATION TOWARDSXYZ [100 100 100] FORWARD DISTANCEXYZ [100 100 100] DISTANCE

Synopsis DISTANCE position

Description Outputs the distance the turtle must travel along a straight line to reach the position given as the position input. The position input must be a list containing two items, the X and Y coordinates.

Example SETPOS [0 0] SHOW DISTANCE [0 100] 100 SHOW DISTANCE [300 400] 500

SETHEADING TOWARDS [300 400] FORWARD DISTANCE [300 400] DISTANCEXYZ

Synopsis DISTANCEXYZ position

Description Outputs a number, the distance the turtle must travel along a straight line to reach a 3D coordinate. The position input must be a three item list containing the position's X, Y, and Z coordinates.

DISTANCEXYZ is designed to run in PERSPECTIVE mode. In 2D modes, DISTANCEXYZ ignores the Z-axis and outputs the straight-line distance between the turtle and the given X and Y coordinates.

Example PERSPECTIVE SETPOSXYZ [0 0 0] SHOW DISTANCEXYZ [0 100 0] 100 SHOW DISTANCEXYZ [100 100 100] 173.205080756888

PERSPECTIVE SETORIENTATION TOWARDSXYZ [300 400 500] FORWARD DISTANCEXYZ [300 400 500] PIXEL

123 Graphics

Synopsis PIXEL

Description Outputs the color of the pixel that is currently under the turtle. Depending on how the color was last set, the output is either a three item list of numbers that represents the red, green, and blue intensities of the pixel, or an integer index of the pixel's color. For an explanation of a color vector see Using Color.

PIXEL can be used in PERSPECTIVE mode but the pixel whose color is output is what ever is under the turtle in the 2D projection.

Example CLEARSCREEN SHOW PIXEL [255 255 255] FORWARD 1 SHOW PIXEL [0 0 0] BACK 1 SHOW PIXEL [0 0 0]

See Also SETPIXEL SCRUNCH

Synopsis SCRUNCH

Description Outputs a list containing two numbers, the X and Y scrunch factors, as used by SETSCRUNCH. Note that SETSCRUNCH takes two numbers as inputs, not one list of numbers.

Example SETSCRUNCH 2.0 1.0 REPEAT 4 [FORWARD 100 RIGHT 90] SHOW SCRUNCH [2 1] Turtle Control

SHOWTURTLE ...... 125 HIDETURTLE ...... 125 CLEAN ...... 125 CLEARSCREEN ...... 125 WRAP ...... 126 WINDOW ...... 126 FENCE ...... 126 PERSPECTIVE ...... 127 FILL ...... 129 SLOWDRAW ...... 131 LABEL ...... 131 SETPIXEL ...... 133 FONTFACENAMES ...... 133 SETLABELFONT ...... 134 LABELFONT ...... 135 LABELSIZE ...... 135

124 Graphics

SHOWTURTLE

Synopsis SHOWTURTLE ST

Description Makes the turtle visible. This is the opposite of HIDETURTLE.

Example HIDETURTLE SHOWTURTLE HIDETURTLE

Synopsis HIDETURTLE HT

Description Makes the turtle invisible. To make the turtle visible again, call SHOWTURTLE.

It's a good idea to hide the turtle just before you start a complicated drawing, because hiding the turtle speeds up the drawing substantially.

Example HIDETURTLE SHOWTURTLE CLEAN

Synopsis CLEAN

Description Erases all lines that the turtle has drawn on the graphics window. The turtle's state (position, heading, pen mode, etc.) is not changed.

Example FORWARD 100 CLEAN CLEARSCREEN

Synopsis CLEARSCREEN CS

Description Fills the screen window with SCREENCOLOR and sends the turtle to its initial position and heading.

CLEARSCREEN also resets some state that is not directly related to the screen.

• It removes all turtles created with SETTURTLE so that there is only one turtle.

• It removes all completed and in-progress polygons which were defined with POLYSTART and POLYEND.

Example FORWARD 100 CLEARSCREEN

See Also HOME SETSCREENCOLOR

125 Graphics

WRAP

Synopsis WRAP

Description Tells the turtle to enter "wrap" mode. From now on, when the turtle is asked to move past the edge of the drawing surface, it "wraps around" and reappears at the opposite edge of the drawing surface. The top edge wraps to the bottom edge, while the left edge wraps to the right edge. (So the drawing surface is topologically equivalent to a torus.) This is the turtle's initial mode.

Compare this command with WINDOW, FENCE, and PERSPECTIVE.

Example WRAP FORWARD 950 RIGHT 90 WINDOW FORWARD 950 FORWARD 100 WINDOW

Synopsis WINDOW

Description Tells the turtle to enter "window" mode. From now on, when the turtle is asked to move past the boundary of the drawing surface, it continues past the boundary where you can't see it. The visible drawing surface is considered as just part of an infinite plane; the turtle can be anywhere on the plane. If you lose the turtle, HOME moves it back to the center of the drawing surface.

Compare this command with WRAP, FENCE, and PERSPECTIVE.

Example WRAP FORWARD 950 RIGHT 90 WINDOW FORWARD 950 FORWARD 100 FENCE

Synopsis FENCE

Description Tells the turtle to enter "fence" mode. In fence mode, when the turtle is asked to move past the boundary of the drawing surface, it moves as far as it can and then stops at the edge with an "out of bounds" error message.

Compare this command with WRAP, WINDOW, and PERSPECTIVE.

Example FENCE FORWARD 10000 turtle out of bounds FORWARD 10 turtle out of bounds BACK 500

126 Graphics

PERSPECTIVE

Synopsis PERSPECTIVE

Description Tells the turtle to enter "perspective" mode. Perspective mode adds a third dimension (Z axis) for the turtle to live in. Perspective is a term to describe how we view a three-dimensional world on a two-dimensional surface. You should be familiar with using FMSLogo in 2D before jumping into 3D.

You can switch out perspective mode by entering any of the 2D modes: WRAP, WINDOW, or FENCE.

Everything that works in 2D applies in 3D (perspective mode). For example, if you had code that drew a 2D picture, say a star, you can run the same code and place that star on six sides of a cube by getting the turtle to the correct 3D coordinate and orientation before you run your 2D command for drawing a star.

You move the turtle just like you fly an airplane. Airplanes have 3 controls to move them through 3D space. They have elevators on the tail (pitch), a rudder on the fin (yaw) and ailerons on the wings (roll). In 2D, you only have a rudder (right/left) also known as "yaw" and you only move around on one geometric plane. FMSLogo offers the additional controls, ailerons (RIGHTROLL and LEFTROLL) and elevators (UPPITCH and DOWNPITCH) to maneuver 3D space. In 3D space, you can move around in an infinite number of geometric planes at any orientation. Once you set the pitch and roll to select the desired geometric plane you can use familiar 2D commands (FORWARD, BACK, LEFT, RIGHT) to traverse it.

When you start at (X=0, Y=0, Z=0) the +Y axis is still up the screen and the +X axis is to the right of the screen. But now you can go into the screen (away from you) or out of the screen (closer to you). How? Just like an airplane flies. When an airplane rolls to the right it does not change its trajectory, and neither does the turtle. But if you rolled 90 degrees to the right and then take a right turn guess what happens. You'll go down real fast, straight down. Think of a real turtle on the floor. Now roll him on to his right side. Now if he takes a right turn towards his right front leg (like he always does) his nose will face the floor. FORWARD will now go down in the Z axis (away from you).

For more information on maneuvering in 3D, read the section on understanding your orientation in 3D.

There is a simple 3D introductory example called 3DSTEPS.LGO in the Examples directory. Load it, run it, and understand it thoroughly before moving on.

The table below summarizes of the relationship between commands in 2D mode and 3D mode. Many commands are repeated in both columns because they are designed for 2D mode but their behavior is affected by being in 3D mode.

2D Command 3D Command SETXY SETXY (does not change z- coordinate)

127 Graphics

2D Command 3D Command SETXYZ SETX (does not change y-coordinate) SETX (does not change y-coordinate or z-coordinate) SETY (does not change x-coordinate) SETY (does not change x-coordinate or z-coordinate) SETZ (does not change x-coordinate or y-coordinate) XCOR XCOR YCOR YCOR ZCOR POS POS (z-coordinate is ignored) POSXYZ SETPOS SETPOS (does not change z- coordinate) SETPOSXYZ TOWARDS TOWARDS TOWARDSXYZ DISTANCE DISTANCE DISTANCEXYZ HEADING HEADING ROLL PITCH ORIENTATION SETHEADING SETHEADING SETROLL SETPITCH SETORIENTATION RIGHT RIGHT (on current plane) RIGHTROLL UPPITCH LEFT LEFT (on current plane) LEFTROLL DOWNPITCH WINDOW PERSPECTIVE WRAP FENCE SETTURTLE (non-negative index) SETTURTLE (non-negative index) SETTURTLE -1 (the eye position) SETTURTLE -2 (where the eye is looking)

128 Graphics

2D Command 3D Command SETTURTLE -3 (the position of the light) POLYSTART POLYEND POLYVIEW LIGHT SETLIGHT ELLIPSEARC ELLIPSEARC (great for spheres)

Limitations of Perspecive Mode. There are several 2D commands which work in perspective mode but still behave in a 2D fashion. Their actions take place at the correct X, Y, Z coordinate, but the orientation is limited to a 2D plane. For example, you can not draw text with LABEL on 6 sides of cube. However, you can LABEL the 8 vertices of the cube by moving to each vertex using 3D maneuvers. Furthermore, nothing prevents you from building a "3D block letter" alphabet library made up of 3D vectors.

The following commands retain their 2D feel, even in perspective mode. • LABEL • BITCUT • BITPASTE • BITCOPY • BITBLOCK • FILL • PIXEL • SETPIXEL

Perspective mode does not do hidden line removal. Hidden line removal requires objects be composed of polygons.

Perspective mode does not allow you to dynamically move the eye view. This is because FMSLogo does not store your object (your vectors) in 3D, it stores them in a 2D bitmap. However you can do "fast" dynamic manipulation in two other ways.

The first way to do "fast" dynamic manipulation requires that you keep your scene very simple (relative to the performance of your computer). You simply clear the screen and change the eye view (turtle -1) or the placement of the objects and draw again. Note curved objects (like those based on ELLIPSEARC) generate many vectors.

The other way to do "fast" dynamic manipulation is to record each "scene" in a bitmap and play them back at any rate you wish. This method is shown in the GROW.LGO example. It does not matter whether you're "recording" 2D scenes or 3D scenes. This is limited by how much memory your computer has.

Example PERSPECTIVE REPEAT 72 [ELLIPSEARC 90 100 150 45 RIGHTROLL 5] FILL 129 Graphics

Synopsis FILL (FILL fillmode)

Description Fills in a region of the graphics window containing the turtle and bounded by lines that have been drawn earlier. It fills using the current value of FLOODCOLOR.

If fillmode is TRUE, then FILL fills until the current PENCOLOR is encountered. If fillmode is FALSE, then FILL fills while on same color. If fillmode is not given, it defaults to FALSE.

FILL can be used in PERSPECTIVE mode as long as the area to filled is bounded and you only fill what's in plain view. For example, if you want to draw a cube, don't draw all six faces since at most three can be in view. Instead, draw just those three faces and fill them.

Example Fill a square:

REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 45 PENUP FORWARD 20 FILL

Fill while on the same color:

SETFLOODCOLOR 4 SETPENCOLOR 1 CIRCLE 50 SETPENCOLOR 2 CIRCLE 100 FILL

Fill until the lines match PENCOLOR:

SETFLOODCOLOR 4 SETPENCOLOR 1 CIRCLE 50 SETPENCOLOR 2 CIRCLE 100 (FILL "TRUE)

A 3D example:

TO SQUARE :color REPEAT 4 [FORWARD 100 RIGHT 90] PENUP RIGHT 45 FORWARD 50 SETFLOODCOLOR :color FILL BACK 50 LEFT 45 PENDOWN END

130 Graphics

PERSPECTIVE RIGHTROLL 45 DOWNPITCH 45 SQUARE 1 RIGHTROLL 90 SQUARE 2 UPPITCH 90 SQUARE 3 SLOWDRAW

Synopsis SLOWDRAW slowness

Description Redefines FORWARD, BACK, FD, and BK to take longer so that you can see the turtle as it moves (otherwise, the turtle moves as fast as it can). The slowness input controls how long it takes for turtle to complete each movement instruction. The larger the slowness input, the slower the turtle moves.

Running SLOWDRAW 0 restores FORWARD, BACK, FD, and BK to their original speed.

The slowness input must be a non-negative integer.

Example SLOWDRAW 100 REPEAT 4 [ FORWARD 100 RIGHT 90 ] LABEL

Synopsis LABEL text

Description Prints text to the screen at the turtle's current position and heading.

You can print any Logo thing (numbers, lists, strings, etc.). If text is a list, then any sub-lists are delimited by square brackets, but the entire object is not delimited by brackets. The text is truncated according to the current values of PRINTWIDTHLIMIT and PRINTDEPTHLIMIT.

The text is printed in the font described by LABELFONT, which is set with SETLABELFONT or the Set->Label Font menu item.

The position of the text is determined by the location of the turtle. More precisely, the top-left corner of the text is placed at the turtle's position.

The angle of the text is determined by the heading (direction) of the turtle. Not all fonts are capable of printing text at different angles, so be sure to use a TrueType or OpenType font if printing at different angles is desired.

The color of the text is determined by the value of PENCOLOR, which is set with SETPENCOLOR.

The width and height of the text's bounding box can be determined with LABELSIZE.

131 Graphics

LABEL can be used in PERSPECTIVE mode, but the text is not printed on the same plane as the turtle. Instead, the text is placed wherever the turtle is on the screen (in two dimensions) and oriented according to the turtle's heading. The capabilities of the text changes depending on the device (screen or printer), the turtle heading (direction), and the font. In other words, sometimes the text can be drawn at the turtle heading and sometimes it cannot. Sometimes what is on the screen is not exactly what you print. If you want to flash a message by writing it in one color, then writing the same message in the background color, you should disable anti-aliasing in the LABELFONT by choosing a Quality of 3 when you run SETLABELFONT. Otherwise, you'll end up with a faint outline of the message which you wanted to completely erase. Example ; label the axes of a 3D Cartesian Coordinate System TO AXIS SETLABELFONT [[Courier New] -19 0 0 700 0 0 0 0 3 2 1 49] RIGHT 90

SETY 200 LABEL "+Y SETY -200 LABEL "-Y SETY 0

SETX 200 LABEL "+X SETX -200 LABEL "-X SETX 0

SETZ 200 LABEL "+Z SETZ -200 LABEL "-Z SETZ 0 LEFT 90 END

PERSPECTIVE CLEARSCREEN SETTURTLE -1 ; select the eye position SETPOSXYZ [600 600 800] SETTURTLE 0 AXIS ; flash a message TO FLASH :message ; Quality=3 disables anti-aliasing SETLABELFONT [[Arial] -19 0 0 700 0 0 0 0 3 2 3 49] PENPAINT LABEL :message WAIT 180

132 Graphics

PENERASE LABEL :message PENPAINT END

TO TELLJOKE FLASH [Q: Why did the chicken cross the road?] FLASH [A: To get to the other side!] FLASH [Ha! ha! ha!] END SETPIXEL

Synopsis SETPIXEL colorvector

Description Sets the pixel under the turtle to the color described by colorvector. The colorvector input must be a three item list of [red green blue] intensities, each of which must be an integer from 0 to 255. For an explanation of color vectors see Using Color. SETPIXEL is similar to running SETPENSIZE 1 SETPENCOLOR colorvector PENPAINT FORWARD 0, except that SETPIXEL is faster and doesn't affect the pen state.

By using PIXEL and SETPIXEL, you can scan and redraw an image at a new orientation (for example, to rotate a bitmap).

SETPIXEL can be used in PERSPECTIVE mode but only the "closest" pixel set is seen. See Examples\3D\3DBITMAP.LGO for an example of using SETPIXEL in perspective mode.

Example PENUP SETXY -128 -128 FOR [red 0 255] [ FOR [green 0 255] [ SETPIXEL (LIST :red :green 0) FORWARD 1 ] BACK 256 RIGHT 90 FORWARD 1 LEFT 90 ] FONTFACENAMES

Synopsis FONTFACENAMES

Description Outputs a list of the names of every font typeface that is supported by the operating system. The order of this list is not defined.

Each typeface name is given as a list and can be used as input to SETLABELFONT.

Example SHOW FONTFACENAMES [[System] [Courier New] [Times New Roman] [Arial] [Verdana] [Webdings] [Microsoft Sans Serif]]

133 Graphics

SETLABELFONT

Synopsis SETLABELFONT font

Description Sets the font to be used by the LABEL command.

The input is a list that completely describes a font. The available fonts depend on your computer. FMSLogo has two ways to specify the font you desire. This command can be used by Logo programs. For interactive use you can use Set - Label Font from the main menu. The easiest way to use fonts in FMSLogo is to set the desired font using the Menu and capturing the attributes using LABELFONT command.

The font input must be a list of the form: [[FaceName] Height Width Orientation Weight Italic Underline StrikeOut CharSet OutPrecision ClipPrecision Quality PitchAndFamily]. The meaning of each item within the list is explained by the following table:

Item Meaning FaceName A word (or list of words) that is the font's typeface name Height An integer that specifies the font's height, in logical units. If this value is greater than zero, it specifies the cell height of the font. If it is less than zero, it specifies the character height of the font. Width An integer that specifies the font's width, in logical units Orientation An integer that specifies the font's orientation, in degrees Weight An integer that specifies the font's weight. This member ranges from 0 to 900 in increments 100. A value of 0 means use default weight. Italic An integer. The font is italicized if and only if this is non-zero. Underlined An integer. The font is underlined if and only if this is non-zero. StrikeOut An integer. The font is rendered with a horizontal line through it if and only if this is non-zero. CharSet An integer that specifies the font's character set. OutPrecision An integer that specifies the font's output precision. Quality An integer that specifies the font's quality. 0 implies the default quality (defined by the current operating system settings). 1 implies draft

134 Graphics

Item Meaning quality. 2 implies proof quality. 3 implies no anti-aliasing. 4 implies anti-aliasing. PitchAndFamily An integer that specifies the font's pitch and family.

If you choose a font typeface that is not available on the system, then SETLABELFONT lists all fonts that are available.

If you want to flash a message by writing it in one color, then writing the same message in the background color, you should disable anti-aliasing by choosing a Quality of 3. Otherwise, you'll end up with a faint outline of the message you wanted to completely erase.

Example SETLABELFONT [[Times New Roman] -24 0 0 400 0 0 0 0 3 2 1 18] LABEL "Hello

See Also FONTFACENAMES LABELFONT

Synopsis LABELFONT

Description Outputs a list describing the current font that is used by the LABEL command.

This output is a list of the form [[FaceName] Height Width Orientation Weight Italic Underline StrikeOut CharSet OutPrecision ClipPrecision Quality PitchAndFamily]. See SETLABELFONT for a description of each member of this list.

Example SETLABELFONT [[Times New Roman] -24 0 0 400 0 0 0 0 3 2 1 18] SHOW LABELFONT [[Times New Roman] -24 0 0 400 0 0 0 0 3 2 1 18] LABELSIZE

Synopsis LABELSIZE text

Description Outputs the size (width and height) of the given text if it were rendered with the LABEL command. The input may be a word or a list. The output is a two item list [width height].

The width and height are always output relative to the text, not the turtle's orientation. The width is the length of the text along the direction that words are read. The height is line height of LABELFONT and is independent of the text input.

LABELSIZE's output may vary slightly depending on the turtle's orientation. For the best results, run LABELSIZE when the turtle's heading matches the heading when you run LABEL.

You can use LABELSIZE to build other forms of LABEL, such as CENTERLABEL or VERTICALLABEL. You can also use this information to "prepare" a site for text (for example, frame it or set a background).

135 Graphics

Example SETLABELFONT [[Times New Roman] -24 0 0 400 0 0 0 0 3 2 1 18] SHOW LABELSIZE "Hello [44 24] Window Control

TEXTSCREEN ...... 136 FULLSCREEN ...... 136 SPLITSCREEN ...... 136 SETSCRUNCH ...... 137 REFRESH ...... 137 NOREFRESH ...... 137 ZOOM ...... 137 SCROLLX ...... 138 SCROLLY ...... 138 SETFOCUS ...... 138 GETFOCUS ...... 139 ICON ...... 139 UNICON ...... 139 MINIMIZE ...... 140 RESTORE ...... 140 MAXIMIZE ...... 140 WINDOWSET ...... 141 TEXTSCREEN

Synopsis TEXTSCREEN TS

Description Undocks the commander window from the screen window so that you can resize it to maximize the space available for text interaction.

Compare this command with SPLITSCREEN and FULLSCREEN. FULLSCREEN

Synopsis FULLSCREEN FS

Description Undocks the commander window from the screen window so that you can resize it to maximize the space available for graphics. The commander window is always on top of the screen window, so you may find it useful to minimize the commander window after undocking it.

Compare this command with SPLITSCREEN and TEXTSCREEN.

Example FULLSCREEN ICON "Commander SPLITSCREEN

Synopsis SPLITSCREEN SS

136 Graphics

Description Docks the commander window and the screen window inside the same frame and separates the two with a movable splitter bar. This leaves some room for text interaction while also keeping most of the graphics window visible.

This is the default configuration.

Compare this command with FULLSCREEN and TEXTSCREEN. SETSCRUNCH

Synopsis SETSCRUNCH xscale yscale Description Note

SETSCRUNCH is not needed to correct display problems, but is available for folks who like to deliberately misadjust the aspect ratio.

Adjusts the aspect ratio and scaling of the graphics display. After SETSCRUNCH is used, all further turtle motion is adjusted by multiplying the horizontal and vertical extent of the motion by the two numbers given as inputs. For example, after the instruction "SETSCRUNCH 2 1" motion at a heading of 45 degrees moves twice as far horizontally as vertically. If your squares don't come out square, try using this command.

Alternatively, you can use SETSCRUNCH to deliberately misadjust the aspect ratio to draw an ellipse.

Example SETSCRUNCH 2.0 1.0 REPEAT 4 [FORWARD 100 RIGHT 90] SHOW SCRUNCH [2 1] REFRESH

Synopsis REFRESH

Description Tells Logo to remember the turtle's motions so that they can be reconstructed in case the graphics window is obscured by another window.

REFRESH is not needed in FMSLogo. It is provided for compatibility with other Logo environments. NOREFRESH

Synopsis NOREFRESH

Description Tells Logo not to remember the turtle's motions. This makes drawing faster, but prevents recovery if the window is obscured by another window.

NOREFRESH is not needed in FMSLogo. It is provided for compatibility with other Logo environments. ZOOM

Synopsis ZOOM scale

137 Graphics

Description Sets the scale of the "Screen" window. The scale input is the amount to zoom (scale) by. A number greater than 1.0 makes things bigger (for example, 2.0 makes it twice as big), a number smaller than 1.0 makes things smaller (0.5 makes it half as big). If an existing image is on the screen when you zoom, then it is stretched or squeezed according to the zoom. The resulting image may look a little jagged, but if you "draw" while zoomed, the new lines are not as jagged.

Even though things may appear jagged FMSLogo remembers everything as if zoom was normal (1.0) and only prints at the normal scale. Once you zoom back to a scale of 1.0, your image will not be stretched or squeezed to fit again. In other words, in a zoom of 1.0 lines are never jagged even if you drew them at zoom 0.5 or 2.0.

ZOOM works best when scale is a power of two, such as 2, 4, 8, 1/2 (0.5), 1/4 (0.25), 1/8 (0.125), etc.

You can also control the zoom factor by using the Zoom Menu.

Example REPEAT 4 [FORWARD 100 RIGHT 90] ZOOM 0.5 ZOOM 2.0 SCROLLX

Synopsis SCROLLX deltax

Description Scrolls the horizontal scrollbar of the "Screen" window. The deltax input is the amount to move the scroll position by. A positive number scrolls to the right and negative number scrolls to the left. If deltax is 0, then the scroller is reset to the center position.

Example REPEAT 10 [SCROLLX 10] SCROLLY

Synopsis SCROLLY deltay

Description Scrolls the vertical scrollbar of the "Screen" window. The deltay is the amount to move the scroll position by. A positive number scrolls down and negative number scrolls up. If deltay is 0, then the scroller is reset to the center position.

Example REPEAT 10 [SCROLLY 10] SETFOCUS

Synopsis SETFOCUS caption

Description Selects a window whose caption (or title) is caption. When a window has focus, it is selected and all keyboard input is directed to it.

A window's "caption" is not the same as the window's "name" used by the windows commands.

Example SETFOCUS [FMSLogo]

138 Graphics

See Also GETFOCUS GETFOCUS

Synopsis GETFOCUS

Description Outputs the caption (title) of the window in focus.

Example SETFOCUS [FMSLogo] SHOW GETFOCUS FMSLogo

See Also SETFOCUS ICON

Synopsis ICON caption

Description Minimizes the window whose title matches caption. The term "ICON" comes from the old days when Windows applications were minimized into small icons.

A window's "caption" is not the same as the window's "name" used by the windows commands.

This command is deprecated in favor of MINIMIZE.

Example TO HIDEANDSHOW ICON "FMSLogo WAIT 120 RESTORE "FMSLogo END

HIDEANDSHOW

See Also RESTORE MAXIMIZE UNICON

Synopsis UNICON caption

Description Unminimizes (restores) the window whose title matches caption. The term "ICON" comes from the old days when Windows applications were minimized into small icons.

A window's "caption" is not the same as the window's "name" used by the windows commands.

This command is deprecated in favor of RESTORE.

Example TO HIDEANDSHOW MINIMIZE "FMSLogo WAIT 120 UNICON "FMSLogo END

139 Graphics

HIDEANDSHOW

See Also MINIMIZE MAXIMIZE MINIMIZE

Synopsis MINIMIZE caption

Description Minimizes the window whose title matches caption.

A window's "caption" is not the same as the window's "name" used by the windows commands.

Example TO HIDEANDSHOW MINIMIZE "FMSLogo WAIT 120 RESTORE "FMSLogo END

HIDEANDSHOW

See Also MAXIMIZE RESTORE RESTORE

Synopsis RESTORE caption

Description Restores (unminimizes or unmaximizes) the window whose title matches caption to the size and position it had before it was minimized or maximized.

A window's "caption" is not the same as the window's "name" used by the windows commands.

Example TO HIDEANDSHOW MINIMIZE "FMSLogo WAIT 120 RESTORE "FMSLogo END

HIDEANDSHOW

See Also MAXIMIZE MINIMIZE MAXIMIZE

Synopsis MAXIMIZE caption

Description Maximizes the window whose title matches caption.

A window's "caption" is not the same as the window's "name" used by the windows commands.

140 Graphics

Example TO MAXLOGO MAXIMIZE "FMSLogo WAIT 120 RESTORE "FMSLogo END

MAXLOGO

See Also MINIMIZE RESTORE WINDOWSET

Synopsis WINDOWSET caption mode

Description Sets the "mode" (for example, hidden, visible, etc.) for a window whose title matches caption. This command is designed for experts, you may lose control of FMSLogo if you are not careful, so save your work frequently.

The mode input must be an integer. The following table details acceptable values and their meanings. Mode Meaning 0 Hides the window and activates another window. 1 Activates and displays a window. If the window is minimized or maximized, it is restored it to its original size and position. An application should specify this flag when displaying the window for the first time. 2 Activates the window and displays it as a minimized window. 3 Activates the window and displays it as a maximized window. 4 Displays the window as a minimized window. The active window remains active. 5 Activates the window and displays it in its current size and position. 6 Minimizes the specified window and activates the next top-level window in the Z order. 7 Minimizes the specified window. The active window remains active. 8 Displays the window in its current state. The active window remains active. 9 Activates and displays the window. If the window is minimized or

141 Graphics

Mode Meaning maximized, it is restored it to its original size and position. An application should specify this flag when restoring a minimized window.

Example TO HIDEANDRESTORE CLEARSCREEN RIGHT 90 LABEL [Back in 2 seconds] WAIT 120 WINDOWSET "FMSLogo 0 ; hide WAIT 120 WINDOWSET "FMSLogo 1 ; restore END

HIDEANDRESTORE Using Color

Several commands (SETPENCOLOR, SETFLOODCOLOR , SETSCREENCOLOR ) exist in Logo to specify red, green, and blue intensities of color. Each input represents how much red, green, and blue you want in the color. Each input has a range of 0-255. You can create 16.7 million different colors by mixing different amounts of red, green, and blue.

Example of instructions that set some common pen colors:

Instruction Color Sample SETPENCOLOR [000 000 000] black

SETPENCOLOR [255 255 255] white

SETPENCOLOR [128 128 128] gray

SETPENCOLOR [255 000 000] red

SETPENCOLOR [000 255 000] green

SETPENCOLOR [000 000 255] blue

For compatibility with other Logo implementations and simplicity for young programmers, FMSLogo also supports single index colors. If you set any color with an 16 color index, then FMSLogo outputs all colors as a 16 color index. If you set any color with an [red green blue] color vector or with a word such as "red, then FMSLogo outputs all colors as [red green blue] color vectors.

Example SETPENCOLOR 5 SHOW PENCOLOR 5

142 Graphics

SETPENCOLOR [255 0 0] SHOW PENCOLOR [255 0 0]

SETPENCOLOR "Red SHOW PENCOLOR [255 0 0]

Any FMSLogo primitive that inputs a color can input it as a color index, color name, or a color vector. When using a color index, the index-to-color mapping is given in the following table.

Index Color Vector Color Sample 0 [0 0 0] Black

1 [0 0 255] Blue

2 [0 255 0] Lime

3 [0 255 255] Cyan (Aqua)

4 [255 0 0] Red

5 [255 0 255] Magenta (Fuchsia)

6 [255 255 0] Yellow

7 [255 255 255] White

8 [155 96 59] Brown

9 [197 136 18] Tan

10 [100 162 64] Olive

11 [120 187 187] Sky Blue

12 [255 149 119] Salmon

13 [144 113 208] Medium Purple

14 [255 163 0] Orange

15 [183 183 183] Dark Gray

When using a color name, the name-to-color mapping is given in the following table.

143 Graphics

Color Name Color Vector Sample AliceBlue [240 248 255]

AntiqueWhite [250 235 215]

Aqua [0 255 255]

Aquamarine [127 255 212]

Azure [240 255 255]

Beige [245 245 220]

Bisque [255 228 196]

Black [0 0 0]

BlanchedAlmond [255 235 205]

Blue [0 0 255]

BlueViolet [138 43 226]

Brown [165 42 42]

BurlyWood [222 184 135]

CadetBlue [95 158 160]

Chartreuse [127 255 0]

Chocolate [210 105 30]

Coral [255 127 80]

CornflowerBlue [100 149 237]

Cornsilk [255 248 220]

Crimson [220 20 60]

Cyan [0 255 255]

144 Graphics

Color Name Color Vector Sample DarkBlue [0 0 139]

DarkCyan [0 139 139]

DarkGoldenRod [184 134 11]

DarkGray [169 169 169]

DarkGreen [0 100 0]

DarkGrey [169 169 169]

DarkKhaki [189 183 107]

DarkMagenta [139 0 139]

DarkOliveGreen [85 107 47]

DarkOrange [255 140 0]

DarkOrchid [153 50 204]

DarkRed [139 0 0]

DarkSalmon [233 150 122]

DarkSeaGreen [143 188 143]

DarkSlateBlue [72 61 139]

DarkSlateGray [47 79 79]

DarkSlateGrey [47 79 79]

DarkTurquoise [0 206 209]

DarkViolet [148 0 211]

DeepPink [255 20 147]

DeepSkyBlue [0 191 255]

145 Graphics

Color Name Color Vector Sample DimGray [105 105 105]

DimGrey [105 105 105]

DodgerBlue [30 144 255]

FireBrick [178 34 34]

FloralWhite [255 250 240]

ForestGreen [34 139 34]

Fuchsia [255 0 255]

Gainsboro [220 220 220]

GhostWhite [248 248 255]

Gold [255 215 0]

GoldenRod [218 165 32]

Gray [128 128 128]

Green [0 128 0]

GreenYellow [173 255 47]

Grey [128 128 128]

HoneyDew [240 255 240]

HotPink [255 105 180]

IndianRed [205 92 92]

Indigo [75 0 130]

Ivory [255 255 240]

Khaki [240 230 140]

146 Graphics

Color Name Color Vector Sample Lavender [230 230 250]

LavenderBlush [255 240 245]

LawnGreen [124 252 0]

LemonChiffon [255 250 205]

LightBlue [173 216 230]

LightCoral [240 128 128]

LightCyan [224 255 255]

LightGoldenRodYellow [250 250 210]

LightGray [211 211 211]

LightGreen [144 238 144]

LightGrey [211 211 211]

LightPink [255 182 193]

LightSalmon [255 160 122]

LightSeaGreen [32 178 170]

LightSkyBlue [135 206 250]

LightSlateGray [119 136 153]

LightSlateGrey [119 136 153]

LightSteelBlue [176 196 222]

LightYellow [255 255 224]

Lime [0 255 0]

LimeGreen [50 205 50]

147 Graphics

Color Name Color Vector Sample Linen [250 240 230]

Magenta [255 0 255]

Maroon [128 0 0]

MediumAquaMarine [102 205 170]

MediumBlue [0 0 205]

MediumOrchid [186 85 211]

MediumPurple [147 112 216]

MediumSeaGreen [60 179 113]

MediumSlateBlue [123 104 238]

MediumSpringGreen [0 250 154]

MediumTurquoise [72 209 204]

MediumVioletRed [199 21 133]

MidnightBlue [25 25 112]

MintCream [245 255 250]

MistyRose [255 228 225]

Moccasin [255 228 181]

NavajoWhite [255 222 173]

Navy [0 0 128]

OldLace [253 245 230]

Olive [128 128 0]

OliveDrab [107 142 35]

148 Graphics

Color Name Color Vector Sample Orange [255 165 0]

OrangeRed [255 69 0]

Orchid [218 112 214]

PaleGoldenRod [238 232 170]

PaleGreen [152 251 152]

PaleTurquoise [175 238 238]

PaleVioletRed [216 112 147]

PapayaWhip [255 239 213]

PeachPuff [255 218 185]

Peru [205 133 63]

Pink [255 192 203]

Plum [221 160 221]

PowderBlue [176 224 230]

Purple [128 0 128]

Red [255 0 0]

RosyBrown [188 143 143]

RoyalBlue [65 105 225]

SaddleBrown [139 69 19]

Salmon [250 128 114]

SandyBrown [244 164 96]

SeaGreen [46 139 87]

149 Graphics

Color Name Color Vector Sample SeaShell [255 245 238]

Sienna [160 82 45]

Silver [192 192 192]

SkyBlue [135 206 235]

SlateBlue [106 90 205]

SlateGray [112 128 144]

SlateGrey [112 128 144]

Snow [255 250 250]

SpringGreen [0 255 127]

SteelBlue [70 130 180]

Tan [210 180 140]

Teal [0 128 128]

Thistle [216 191 216]

Tomato [255 99 71]

Turquoise [64 224 208]

Violet [238 130 238]

Wheat [245 222 179]

White [255 255 255]

WhiteSmoke [245 245 245]

Yellow [255 255 0]

YellowGreen [154 205 50]

150 Graphics

Understand Your Orientation in 3D

In 2D life is simple:

• HEADING is affected by LEFT, RIGHT, and SETHEADING.

In 3D, (PERSPECTIVE) mode things are bit more complicated:

• HEADING is affected by LEFT, RIGHT, and SETHEADING.

• ROLL is affected by LEFTROLL, RIGHTROLL, and SETROLL.

• PITCH is affected by UPPITCH, DOWNPITCH, and SETPITCH.

However, there is more to it than that. ROLL can also affect your HEADING. PITCH can also affect your ROLL, and so on. They all interact with one another. The easiest way to understand this is with an example:

PERSPECTIVE RIGHT 90 (SHOW ROUND ROLL ROUND PITCH ROUND HEADING) 0 0 90 CLEARSCREEN DOWNPITCH 90 RIGHTROLL 90 UPPITCH 90 (SHOW ROUND ROLL ROUND PITCH ROUND HEADING) 0 0 90

The example above only uses rolls and pitches but the heading changed. But it is correct, think about the maneuvers I made and where the turtle should be pointing.

But don't worry, FMSLogo makes it easy, you just need to understand some basic rules so that you don't get lost in 3D space. The turtle controls ROLL, PITCH, and HEADING do affect one another but in a certain way which is important. The most important is that a change in HEADING (with RIGHT, LEFT or SETHEADING) does not effect your ROLL or PITCH. This is what allows you to use a lot of your existing 2D code in 3D.

There is also another rule to understand, you cannot simply say:

PERSPECTIVE SETROLL 45 SETPITCH 45 SETHEADING 45 (SHOW ROUND ROLL ROUND PITCH ROUND HEADING) 45 45 45

And expect to be at an absolute orientation of 45, 45, 45.

CLEARSCREEN RIGHT 45 RIGHTROLL 30 UPPITCH 30 ; Now try to set your self up to 45,45,45 again SETROLL 45 SETPITCH 45

151 Graphics

SETHEADING 45 (SHOW ROUND ROLL ROUND PITCH ROUND HEADING) 248 29 45

But don't worry there is an easy solution, the SETORIENTATION command.

CLEARSCREEN RIGHT 45 RIGHTROLL 30 UPPITCH 30 ; Now try to set your self up to 45,45,45 again SETORIENTATION [45 45 45] (SHOW ROUND ROLL ROUND PITCH ROUND HEADING) 45 45 45

SETORIENTATION understands the interactions between ROLL, PITCH, and HEADING. All SETORIENTATION knows is that it has to do things in the correct order. It basically backs out your current orientation and applies the requested one. It does this in a very specific order. Your current orientation can also be reported or saved using the ORIENTATION command.

CLEARSCREEN RIGHT 45 SHOW ORIENTATION [0 0 45] MAKE "saveit ORIENTATION RIGHT 90 UPPITCH 180 SETORIENTATION :saveit SHOW ORIENTATION [0 0 45]

There is also another command that knows about your ORIENTATION and that is TOWARDSXYZ. TOWARDSXYZ outputs an orientation that is compatible with SETORIENTATION.

SETORIENTATION TOWARDSXYZ [100 100 0] SHOW ORIENTATION [0 0 45] FORWARD DISTANCEXYZ [100 100 0] SHOW POSXYZ [100 100 0]

Having said all that, you don't really need to think in terms of absolute ORIENTATION. ORIENTATION and SETORIENTATION are used mostly to save, report, and restore your ORIENTATION (just like you do with HEADING and SETHEADING in 2D). Futhermore, as explained earlier, changes in your heading with RIGHT, LEFT, and SETHEADING only affect what they affected in 2D (your HEADING).

You should also be thinking the same way you do in 2D. You don't often worry about your absolute HEADING in 2D, it's most often a turn relative to your current HEADING. It's no different in 3D except you have more ways to turn. Think like the turtle is an airplane and you're in the cockpit. Then decide where you want to go next. Drawing 3D Solids

POLYSTART ...... 153

152 Graphics

POLYEND ...... 154 POLYVIEW ...... 154 SETLIGHT ...... 155 LIGHT ...... 155

3D Solids in FMSLogo uses all the standard 3D commands and a few additional commands to help FMSLogo understand what you're drawing. In order to do hidden line removal or hidden surface removal, you must define surfaces, not just vectors. Surfaces are simply filled polygons. You just need to tell FMSLogo when you're starting a surface and when you're done. If you used only vectors to draw a box, FMSLogo would not know if it's a 6-sided closed box (solid cube) or a 4-sided box with an open top and bottom. Vectors alone are ambiguous with respect to surfaces.

Logo programmers are used to dealing with filled polygons, you do it all the time so it should not be a strange new concept. But FMSLogo in 3D mode fills that polygon with respect to the color you should see based on your eye view, light source, obstructions, and the color of the surface.

Here are the new commands:

Command Description POLYSTART Start a new polygon (a surface of PENCOLOR). POLYEND End the definition of the polygon. POLYVIEW Shade and view all polygons that have been defined. SETTURTLE -3 Use this turtle to position light source. SETLIGHT Use to set how objects should be illuminated.

If you drew a box in 3D (6 Polygons) that all were drawn the same color and you FILLed each of them, all you'd see is a flat octagon-looking thing. This is not so with the new commands. The PENCOLOR in effect when drawing 3D a surface becomes the color of that surface. The color is also affected by the angle of the surface between your eye (turtle -1) and the light source (turtle -3).

The 3D lighting model in FMSLogo uses some modern techniques, but is primarily designed for performance. It does not draw shadows, reflections, etc. You may see pixel errors sometimes. This is an expected artifact of the algorithm I chose. POLYSTART

Synopsis POLYSTART

Description Starts the definition of a new polygon. Each subsequent move while the turtle's pen is down adds the destination coordinate as a vertex to the polygon. The polygon's definition is completed by running the POLYEND command.

Make sure you understand the Polygon Restrictions.

After all of the polygons are defined, you can view them as shaded polygons by running the POLYVIEW command.

POLYSTART is designed to run in PERSPECTIVE mode and does not run in 2D modes.

Example TO SQUARE POLYSTART REPEAT 4 [FORWARD 100 RIGHT 90]

153 Graphics

POLYEND END

PERSPECTIVE REPEAT 72 [SQUARE RIGHTROLL 5] POLYVIEW POLYEND

Synopsis POLYEND

Description Completes the definition of a polygon that was started with the most recent POLYSTART call.

Make sure you understand the Polygon Restrictions.

POLYEND is designed to run in PERSPECTIVE mode and does not run in 2D modes.

Example TO SQUARE POLYSTART REPEAT 4 [FORWARD 100 RIGHT 90] POLYEND END

PERSPECTIVE REPEAT 72 [SQUARE RIGHTROLL 5] POLYVIEW POLYVIEW

Synopsis POLYVIEW

Description POLYVIEW erases the screen and renders all polygons defined with POLYSTART and POLYEND as shaded polygons. Only shaded polygons are shown. Polygons are illuminated according to the position of the light source using SETTURTLE -3 and lighting configuration that was set with SETLIGHT. Make sure you understand the Polygon Restrictions.

If you need to add other things to your drawing such as LABELs or BITMAPs etc., you must do them after the last POLYVIEW.

You can call POLYVIEW immediately after any POLYEND to watch polygons get shaded as your program builds your object. But keep in mind POLYVIEW is an expensive operation and slows down the program considerably if you call it with every POLYEND.

POLYVIEW is designed to run in PERSPECTIVE mode and does not run in 2D modes.

Example TO SQUARE POLYSTART REPEAT 4 [FORWARD 100 RIGHT 90] POLYEND END

154 Graphics

PERSPECTIVE REPEAT 72 [SQUARE RIGHTROLL 5] POLYVIEW SETLIGHT

Synopsis SETLIGHT properties

Description Sets how POLYVIEW illuminates polygons. The properties input is a list of two numbers ranging from 0.0 to 1.0, the amount of ambient and diffuse light. The ambient component defines how much background light there is; the larger the number the brighter the light. The diffusion component is not a property of light source, but a property of how smooth the surface is (how much it scatters light). A higher value means the objects are smoother and reflective (like marble) a low value means the objects are rough (like chalk).

To position the light use SETTURTLE -3.

SETLIGHT is designed to run in PERSPECTIVE mode. While it does run in 2D modes, the effect is not noticable without POLYVIEW.

Example ; simple usage SETLIGHT [0.3 0.6] SHOW LIGHT [0.3 0.6]

; a lightshow TO SQUARE POLYSTART REPEAT 4 [FORWARD 100 RIGHT 90] POLYEND END

PERSPECTIVE REPEAT 72 [SQUARE RIGHTROLL 5] POLYVIEW

REPEAT 10 [ SETLIGHT (LIST (RANDOM 100)/100 (RANDOM 100)/100) SHOW LIGHT WAIT 60 ]

See Also LIGHT LIGHT

Synopsis LIGHT

Description Outputs the lighting attributes as a list of two numbers, the Ambient and Diffuse values.

Example SETLIGHT [0.3 0.6] SHOW LIGHT

155 Graphics

[0.3 0.6]

See Also SETLIGHT Polygon Restrictions

Restriction #1: A polygon's first 3 vertices must form a triangle ...... 156 Restriction #2: A polygon must be convex ...... 156 Restriction #3: A polygon must be planar ...... 157 Polygon Samples ...... 158

Polygons in FMSLogo have three easy-to-satisfy restrictions:

1. A polygon's first 3 vertices must form a triangle.

2. A polygon must be convex.

3. A polygon must be planar. Restriction #1: A polygon's first 3 vertices must form a triangle

The triangle can be extremely shallow. This is legal:

POLYSTART MAKE "savepos POSXYZ FORWARD 100 RIGHT 0.00000001 ; very small angles are okay FORWARD 100 SETPOSXYZ :savepos POLYEND

This is NOT legal (even though it produces a convex polygon):

POLYSTART MAKE "savepos POSXYZ FORWARD 50 FORWARD 50 ; error can't have straight angles RIGHT 90 FORWARD 100 SETPOSXYZ :savepos POLYEND Restriction #2: A polygon must be convex

Being "convex" means that if you pick any 2 points within the polygon and connect them with a straight line, the line never goes outside the polygon. Triangles, squares, and circles are all convex. The letter "E" (as a polygon) is not convex.

This is legal:

POLYSTART REPEAT 4 [FORWARD 150 RIGHT 90] ; a square is convex

156 Graphics

POLYEND

This is NOT legal:

POLYSTART REPEAT 3 [ FORWARD 150 RIGHT 90 ] FORWARD 50 RIGHT 90 ; error: these instruction FORWARD 50 ; add a cavity to the LEFT 90 ; polygon FORWARD 50 ; LEFT 90 ; FORWARD 50 ; RIGHT 90 ; FORWARD 50 RIGHT 90 POLYEND

You can always break a convex polygon up into simpler concave polygons. Restriction #3: A polygon must be planar

Being "planar" means that a polygon must be flat. This is easy to do if you never use UPPITCH, DOWNPITCH, RIGHTROLL, or LEFTROLL between POLYSTART and POLYEND.

This is legal:

POLYSTART REPEAT 4 [FORWARD 100 RIGHT 90] ; a square is planar POLYEND

This is NOT legal:

POLYSTART REPEAT 3 [ FORWARD 100 RIGHT 90 ] FORWARD 50 UPPITCH 90 ; error: these instruction move FORWARD 50 ; out of the polygon's plane DOWNPITCH 90 ; FORWARD 50 ; DOWNPITCH 90 ; FORWARD 50 ; UPPITCH 90 ; FORWARD 50 RIGHT 90 POLYEND

If you want to create a polygon with a "bend" in it that leaves the plane, you can break up your polygon into simpler polygons that are coplanar.

157 Graphics

Polygon Samples

An example polygon using CIRCLE.

PERSPECTIVE REPEAT 36 [ POLYSTART CIRCLE 100 POLYEND RIGHTROLL 10 ] POLYVIEW

An example polygon using ARC.

PERSPECTIVE REPEAT 36 [ POLYSTART ARC2 180 100 RIGHT 90 FORWARD 200 RIGHT 90 POLYEND RIGHTROLL 10 ] POLYVIEW Turtle And Window Queries

SHOWNP ...... 158 SHOWNP

Synopsis SHOWNP SHOWN?

Description Outputs TRUE if the turtle is shown (visible), FALSE if the turtle is hidden. You can use SHOWTURTLE and HIDETURTLE to show and hide the turtle.

Example SHOWTURTLE SHOW SHOWNP true HIDETURTLE SHOW SHOWNP false Pen Control

PENDOWN ...... 159 PENUP ...... 159 PENPAINT ...... 159 PENERASE ...... 160

158 Graphics

PENREVERSE ...... 160 PENNORMAL ...... 160 SETPENCOLOR ...... 160 SETFLOODCOLOR ...... 161 SETSCREENCOLOR ...... 161 SETPENSIZE ...... 162 SETPENPATTERN ...... 162 SETPEN ...... 162 CLEARPALETTE ...... 163

The turtle carries a pen that can draw pictures. At any time the pen can be "up" (in which case moving the turtle does not change what's on the graphics screen) or "down" (in which case the turtle leaves a trace). If the pen is down, it can operate in one of three modes: "paint" (so that it draws lines when the turtle moves), "erase" (so that it erases any lines that might have been drawn on or through that path earlier), or "reverse" (so that it inverts the color of each point along the turtle's path). PENDOWN

Synopsis PENDOWN PD

Description Sets the pen's position to "down", without changing its mode.

Example REPEAT 10 [FORWARD 10 PENUP FORWARD 10 PENDOWN]

See Also PENUP PENDOWNP PENUP

Synopsis PENUP PU

Description Sets the pen's position to "up", without changing its mode.

Example REPEAT 10 [FORWARD 10 PENUP FORWARD 10 PENDOWN]

See Also PENDOWN PENDOWNP PENPAINT

Synopsis PENPAINT PPT

Description Sets the pen's position to "down" and the pen's mode to "paint". In paint mode, the pen draws in the color described by PENCOLOR. This is the default mode.

Example PENREVERSE FORWARD 100 BACK 100 PENPAINT FORWARD 100 BACK 100

159 Graphics

See Also PENERASE PENREVERSE PENERASE

Synopsis PENERASE PE

Description Sets the pen's position to "down" and the pen's mode to "erase". In erase mode, the pen draws in the color described by SCREENCOLOR. Use PENPAINT to restore the pen to normal use.

Example FORWARD 100 PENERASE BACK 100

See Also PENPAINT PENREVERSE PENREVERSE

Synopsis PENREVERSE PX

Description Sets the pen's position to "down" and the pen's mode to "reverse". In reverse mode, the pen draws in a color that is the bitwise negation of whatever pixel is under the pen. Use PENPAINT to restore the pen to normal use.

Example SETPENCOLOR [255 0 0] PENPAINT FORWARD 100 PENREVERSE BACK 100

See Also PENERASE PENPAINT PENNORMAL

Synopsis PENNORMAL

Description Sets the pen's state to the startup default of down and paint.

Example PENREVERSE FORWARD 100 PENNORMAL BACK 100 SETPENCOLOR

Synopsis SETPENCOLOR color SETPENCOLOUR color SETPC color

160 Graphics

Description Sets the pen color to color, which can either be a color index or a color vector. A color index is a number from 0 - 15. A color vector is a list of [red green blue] intensities, each in the range of 0 - 255. For an explanation of the color input, see the section on Using Color.

The pen color affects any line drawn by the turtle (such as FORWARD). It also affects text that is drawn with LABEL.

Example Drawing lines in different shades of red:

REPEAT 255 [ SETPENCOLOR (LIST REPCOUNT 0 0) FORWARD 100 BACK 100 RIGHT 1 ]

Using variables in a color vector:

MAKE "red 100 MAKE "green 100 MAKE "blue 100 SETPENCOLOR (LIST :red :green :blue) SETFLOODCOLOR

Synopsis SETFLOODCOLOR color SETFLOODCOLOUR color SETFC color

Description Sets the flood color to color, which can either be a color index or a color vector. A color index is a number from 0 - 15. A color vector is a list of [red green blue] intensities, each in the range of 0 - 255. For an explanation of the color input, see the section on Using Color.

The flood color affects the FILL and BITBLOCK commands.

Example Filling with a square with lime:

CLEARSCREEN REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 45 PENUP FORWARD 20 SETFLOODCOLOR "Lime FILL

Using variables in a color vector:

MAKE "red 100 MAKE "green 100 MAKE "blue 100 SETFLOODCOLOR (LIST :red :green :blue) SETSCREENCOLOR

161 Graphics

Synopsis SETSCREENCOLOR color SETSCREENCOLOUR color SETSC color

Description Sets the screen background color to color and changes the entire screen to that color. The color input may either be a color index or a color vector. A color index is a number from 0 - 15. A color vector is a list of [red green blue] intensities, each in the range of 0 - 255. For an explanation of the color input, see the section on Using Color.

Example SETSCREENCOLOR [0 0 0] SETPENCOLOR [255 255 255] REPEAT 4 [FORWARD 100 RIGHT 90] CLEAN SETPENSIZE

Synopsis SETPENSIZE size

Description Set the pen's thickness. The size input must be either a positive integer that denotes the pen's width or a list of the form [width height]. When the size input is a list, SETPENSIZE ignores the height component, but this may change in a future release. To ensure that your programs are compatible with future versions of FMSLogo, you should either use a height that is the same as the width, or not use the list input at all.

Example SETPENSIZE 5 REPEAT 4 [FORWARD 100 RIGHT 90] SETPENPATTERN

Synopsis SETPENPATTERN pattern Description Note

SETPENPATTERN is not supported in FMSLogo.

Set hardware-dependent pen characteristics. SETPENPATTERN is not guaranteed to be compatible between implementations on different machines. SETPEN

Synopsis SETPEN characteristics

Description Sets the pen's position, mode, and hardware-dependent characteristics according to the information in the characteristics input. The characteristics input is a list with the following members: [PENDOWNP PENMODE PENSIZE PENCOLOR PENPAINT]. The format of this list may change in futures version of FMSLogo, as additional pen characteristics are added. To guarantee portability, the input should be taken from an earlier invocation of PEN.

Example CLEARSCREEN REPEAT 4 [FORWARD 100 RIGHT 90]

162 Graphics

MAKE "savepen PEN

CLEARSCREEN SETPENSIZE [20 20] REPEAT 4 [FORWARD 100 RIGHT 90] SETPEN :savepen

CLEARSCREEN REPEAT 4 [FORWARD 100 RIGHT 90] CLEARPALETTE

Synopsis CLEARPALETTE

Description CLEARPALETTE does nothing. It has been kept for compatibility with old programs, but its function is no longer needed.

Historically, early versions of Microsoft Windows supported video displays that were limited to showing at most 256 colors at one time, although each of the colors used a full 24-bit range. The set of 256 possible colors was called the "palette" and could be changed depending on which colors you wanted to use. Whenever FMSLogo used a new color (for example, when SETPENCOLOR was run), it would add the color to this palette. Once all of the 256 colors in the palette were set, a program could not draw a new color, even if some of the colors in the palette were not in active use. The CLEARPALETTE command used to remove all colors from the palette so that the palette could be refilled with new colors.

Display devices, even old ones, no longer have a limited palette of colors, so CLEARPALETTE is no longer needed.

Example CLEARPALETTE Pen Queries

PENDOWNP ...... 163 PENMODE ...... 164 PENCOLOR ...... 164 FLOODCOLOR ...... 164 SCREENCOLOR ...... 165 PENSIZE ...... 165 PENPATTERN ...... 165 PEN ...... 165 PENDOWNP

Synopsis PENDOWNP PENDOWN?

Description Outputs TRUE if the pen is down, FALSE if it's up.

Example PENUP SHOW PENDOWNP false

163 Graphics

PENDOWN SHOW PENDOWNP true

See Also PENUP PENDOWN PENMODE

Synopsis PENMODE

Description Outputs one of the words "paint", "erase", or "reverse" according to the current pen mode.

Example PENPAINT SHOW PENMODE paint PENERASE SHOW PENMODE erase PENREVERSE SHOW PENMODE reverse PENCOLOR

Synopsis PENCOLOR PENCOLOUR PC

Description Outputs pen color information. This is either a color index (a number from 0 - 15), or a list containing [red green blue] intensities, depending on how the pen color was set.

Example SETPENCOLOR [100 200 50] SHOW PENCOLOR [100 200 50]

SETPENCOLOR 2 SHOW PENCOLOR 2 FLOODCOLOR

Synopsis FLOODCOLOR FLOODCOLOUR

Description Outputs flood color information. This is either a color index (a number from 0 - 15), or a list containing [red green blue] intensities, depending on how the flood color was set.

Example SETFLOODCOLOR [100 200 50] SHOW FLOODCOLOR

164 Graphics

[100 200 50]

SETFLOODCOLOR 2 SHOW FLOODCOLOR 2 SCREENCOLOR

Synopsis SCREENCOLOR SCREENCOLOUR

Description Outputs screen color information. This is either a color index (a number from 0 - 15), or a list containing [red green blue] intensities, depending on how the screen color was set.

Example SETSCREENCOLOR [100 200 50] SHOW SCREENCOLOR [100 200 50]

SETSCREENCOLOR 2 SHOW SCREENCOLOR 2 PENSIZE

Synopsis PENSIZE

Description Outputs the size of the pen as a list with two items: [Width Height]. The width item is ignored by FMSLogo.

Example SETPENSIZE [10 20] SHOW PENSIZE [20 20] SETPENSIZE [1 1] SHOW PENSIZE [1 1] PENPATTERN

Synopsis PENPATTERN Description Note

PENPATTERN is not supported in FMSLogo.

Outputs hardware-specific pen information. PEN

Synopsis PEN

Description Outputs a list containing the pen's position, mode, and hardware-specific characteristics, for use by SETPEN. The output is a list with the following members: [PENDOWNP PENMODE PENSIZE PENCOLOR PENPAINT].

165 Graphics

The format of this list may change in future version of FMSLogo, as additional pen characteristics are added.

Example CLEARSCREEN REPEAT 4 [FORWARD 100 RIGHT 90] MAKE "savepen PEN

CLEARSCREEN SETPENSIZE [20 20] REPEAT 4 [FORWARD 100 RIGHT 90] SETPEN :savepen

CLEARSCREEN REPEAT 4 [FORWARD 100 RIGHT 90]

166 Chapter 11. Workspace Management

Procedure Definition ...... 168 TO ...... 168 END ...... 170 DEFINE ...... 171 TEXT ...... 171 FULLTEXT ...... 172 COPYDEF ...... 172 ARITY ...... 172 Variable Definition ...... 173 MAKE ...... 174 NAME ...... 174 LOCAL ...... 174 LOCALMAKE ...... 175 THING ...... 175 Property Lists ...... 176 PPROP ...... 176 GPROP ...... 176 REMPROP ...... 177 PLIST ...... 177 Workspace Predicates ...... 178 PROCEDUREP ...... 178 PRIMITIVEP ...... 178 DEFINEDP ...... 179 NAMEP ...... 179 MACROP ...... 179 PROPLISTP ...... 180 Workspace Queries ...... 180 CONTENTS ...... 180 PROCEDURES ...... 181 NAMES ...... 181 PLISTS ...... 181 NAMELIST ...... 181 PLLIST ...... 182 BURIED ...... 182 STEPPED ...... 182 TRACED ...... 182 Workspace Inspection ...... 183 PO ...... 183 POALL ...... 183 POPS ...... 184 PONS ...... 184 POPLS ...... 184 PON ...... 185 POPL ...... 185 POT ...... 185 POTS ...... 185 Workspace Control ...... 186 ERASE ...... 186 ERALL ...... 187 ERPS ...... 187 ERNS ...... 188

167 Workspace Management

ERPLS ...... 188 ERN ...... 188 ERPL ...... 189 BURY ...... 189 BURYALL ...... 190 BURYNAME ...... 190 UNBURY ...... 190 UNBURYALL ...... 191 UNBURYNAME ...... 191 TRACE ...... 192 UNTRACE ...... 192 STEP ...... 193 UNSTEP ...... 194 EDIT ...... 194 EDALL ...... 194 EDALLBTN ...... 195 EDPS ...... 198 EDNS ...... 199 EDPLS ...... 199 EDN ...... 200 EDPL ...... 200 SAVE ...... 200 SAVEL ...... 201 LOAD ...... 201 Debug Commands ...... 202 NODES ...... 202 STATUS ...... 203 NOSTATUS ...... 203 Procedure Definition

TO ...... 168 END ...... 170 DEFINE ...... 171 TEXT ...... 171 FULLTEXT ...... 172 COPYDEF ...... 172 ARITY ...... 172 TO

Synopsis (special form)

TO procname :input1 :input2 ...

Description Command that prepares Logo to accept a procedure definition. The procedure is named procname and there must not already be a procedure by that name. The inputs are named input1, input2, etc. Any number of inputs is allowed, including none. Names of procedures and inputs are case-insensitive.

Unlike nearly every other Logo procedure, TO takes as its inputs the actual words typed in the instruction line, as if they were all quoted, rather than the results of evaluating expressions to provide the inputs. (That's what "special form" means.)

168 Workspace Management

FMSLogo allows procedures to have a variable numbers of inputs. Every procedure has a minimum, default, and maximum number of inputs. The maximum may be infinite.

The minimum number of inputs is the number of required inputs, which must come first. A required input is indicated by the

:inputname notation.

After all the required inputs can be zero or more optional inputs, represented by the following notation:

[:inputname default.value.expression]

When the procedure is invoked, if actual inputs are not supplied for these optional inputs, the default.value.expressions are evaluated to set values for the corresponding input names. The inputs are processed from left to right, so a default value expression can be based on earlier inputs. For example:

TO PROC :inlist [:startvalue first :inlist]

When the procedure is invoked as

PROC [a b c] the :inlist input has the value [a b c] and the :startvalue input has the value "a. When the procedure is invoked as

(PROC [a b c] "x) the :inlist has the value [a b c] and :startvalue has the value "x.

After all the required and optional input can come a single "rest" input, represented by the following notation:

[:inputname]

This is a rest input rather than an optional input because there is no default value expression. There can be at most one rest input. When the procedure is

169 Workspace Management

invoked, the value of the rest input is a list containing all inputs that are not used for required or optional inputs. Example:

TO PROC :in1 [:in2 "foo] [:in3]

When this procedure is invoked as:

PROC "x

:in1 has the value "x, :in2 has the value "foo, and :in3 has the value [] (the empty list). When it is invoked as:

(PROC "a "b "c "d)

:in1 has the value "a, :in2 has the value "b, and :in3 has the value [c d].

The maximum number of inputs for a procedure is infinite if a "rest" input is given; otherwise, it is the number of required inputs plus the number of optional inputs.

The default number of inputs for a procedure, which is the number of inputs that it accepts when its invocation is not enclosed in parentheses, is ordinarily equal to the minimum number. If you want a different default number you can indicate that by putting the desired default number as the last thing on the TO line.

For example:

TO PROC :in1 [:in2 "foo] [:in3] 3

This procedure has a minimum of one input, a default of three inputs, and an infinite maximum.

FMSLogo displays a dialog box if you enter a TO instruction in the commander's edit box. Whatever instructions you type into the popup become part of the definition. You can finish the definition by pressing the "end" button or abandon the definition by pressing the "Cancel" button.

Example TO ECHO :times :thing REPEAT :times [PRINT :thing] END

ECHO 2 "Hello Hello Hello ECHO 3 "Bye Bye Bye Bye END

Synopsis (special form)

END

170 Workspace Management

Description END delimits the end of a procedure that is defined with TO.

END is not really a command. As a result, procedures that manipulate other procedures don't work on END. For example, PROCEDUREP "END outputs FALSE.

Example TO ECHO :times :thing REPEAT :times [PRINT :thing] END

ECHO 2 "Hello Hello Hello ECHO 3 "Bye Bye Bye Bye DEFINE

Synopsis DEFINE procname text

Description Defines a procedure with name procname and definition text. If there is already a procedure with the same name, the new definition replaces the old one. The text input must be a list whose members are lists. The first member is a list of inputs; it looks like a TO line without the word TO, without the procedure name, and without the colons before input names. In other words, the members of this first sublist are words for the names of required inputs and lists for the names of optional or rest inputs. The remaining sublists of the text input make up the body of the procedure, with one sublist for each instruction line of the body. (There is no END line in the text input.)

It is an error to redefine a primitive procedure unless the variable REDEFP has the value TRUE.

Example DEFINE "ABC [[a b] [PRINT :a] [PRINT :b]] ABC "Hello "Bye Hello Bye TEXT

Synopsis TEXT procname

Description Outputs the text of the procedure named procname in the form expected by DEFINE: a list of lists, the first of which describes the inputs to the procedure and the rest of which are the lines of its body. The text does not reflect formatting information used when the procedure was defined, such as continuation lines and extra spaces.

Example DEFINE "ABC [[a b] [PRINT :a] [PRINT :b]] ABC "Hello "Bye Hello Bye

171 Workspace Management

SHOW TEXT "ABC [[a b] [PRINT :a] [PRINT :b]] FULLTEXT

Synopsis FULLTEXT procname

Description Outputs a representation of the procedure procname in which formatting information is preserved. If the procedure was defined with TO, EDIT , or LOAD, then the output is a list of words. Each word represents one entire line of the definition in the form output by READWORD, including extra spaces and continuation lines. The last item of the output represents the END line. If the procedure was defined with DEFINE, then the output is a list of lists. If these lists are printed, one per line, the result looks like a definition using TO.

Note: the output from FULLTEXT is not suitable for use as input to DEFINE!

Example DEFINE "ABC [[a b] [PRINT :a] [PRINT :b]] ABC "Hello "Bye Hello Bye SHOW FULLTEXT "ABC [[to ABC :a :b] [PRINT :a] [PRINT :b] end] COPYDEF

Synopsis COPYDEF newname oldname

Description Makes a new procedure called newname that is identical to procedure oldname, which may be a primitive. If newname is already defined, its previous definition is lost. If newname is a primitive, the redefinition is not permitted unless the variable REDEFP has the value TRUE. Definitions created by COPYDEF are not saved by SAVE; primitives are never saved, and user-defined procedures created by COPYDEF are buried. (You are likely to be confused if you PO or POT a procedure defined with COPYDEF because its title line will contain the old name. This is why it's buried.)

Note: dialects of Logo differ as to the order of inputs to COPYDEF. FMSLogo uses MAKE order, not NAME order.

Example TO WELCOME PRINT "Hello END

WELCOME Hello COPYDEF "SAYHELLO "WELCOME SAYHELLO Hello ARITY

Synopsis ARITY procedurename

172 Workspace Management

Description Outputs a list of three numbers: the minimum, default, and maximum number of inputs for the procedure whose name is the input. It is an error if there is no such procedure. A maximum of -1 means that the number of inputs is unlimited.

The procedurename input must be a word.

ARITY is provided to enable introspection. For example, if you wanted to write a Logo syntax checker in FMSLogo, you would need to know how many inputs each procedure accepts.

In some cases, ARITY may output seemingly incorrect results. For example the FOR command is documented to accept exactly two inputs, but ARITY outputs that it can accept 7. This is because FOR is library command that, for implementation convenience, accepts additional, undocumented inputs that have default values, and invokes itself recursively. This does not mean that you should provide more than two inputs, just that FMSLogo does not complain if you do. Wherever ARITY and the documentation appear to be in conflict, follow the documentation.

It is an error for the procedurename input to be the name of a procedure with a special form like TO. These procedures cannot be called in the normal way and their inputs are processed in a special manner. As such, the notion of minimum, default, or maximum inputs is irrelevant.

Example The following example shows ARITY used on some well-known primitives.

SHOW ARITY "FORWARD [1 1 1]

SHOW ARITY "WORD [0 2 -1]

The following example shows ARITY on a user-defined procedure that has one required input but accepts an infinite number of inputs.

TO MYPROC.WITHREST :required [:rest] END

SHOW ARITY "MYPROC.WITHREST [1 1 -1]

This following example shows ARITY on a user-defined procedure that has an optional input which defaults to "foo if not given.

TO MYPROC.WITHDEFAULT :required [:optional "foo] 1 END

SHOW ARITY "MYPROC.WITHDEFAULT [1 1 2] Variable Definition

MAKE ...... 174 NAME ...... 174

173 Workspace Management

LOCAL ...... 174 LOCALMAKE ...... 175 THING ...... 175 MAKE

Synopsis MAKE varname value

Description Command that assigns the value value to the variable named varname, which must be a word. Variable names are case-insensitive. If a variable with the same name already exists, the value of that variable is changed. If not, a new global variable is created.

Example MAKE "foo [Hello how are you] SHOW :foo [Hello how are you] NAME

Synopsis NAME value varname

Description Command that assigns the value value to the variable named varname, which must be a word. Variable names are case-insensitive. If a variable with the same name already exists, the value of that variable is changed. If not, a new global variable is created.

This is the same as MAKE but with the inputs in reverse order.

Example NAME [Hello how are you] "foo SHOW :foo [Hello how are you] LOCAL

Synopsis LOCAL varname LOCAL varnamelist (LOCAL varname1 varname2 ...)

Description Creates variables that are local to the currently running procedure. LOCAL accepts as input one or more words, or a list of words. A local variable is created for each of these words, with that word as its name. Logo variables follow dynamic scope rules; a variable that is local to a procedure is available to any sub procedure invoked by that procedure and may shadow a global variable by the same name. The variables created by LOCAL have no initial value; they must be assigned a value (for example, with MAKE) before the procedure attempts to read their value.

Example TO FOO MAKE "bar 1 PRINT :bar END

FOO 1

174 Workspace Management

SHOW :bar 1

TO ABC LOCAL "xyz MAKE "xyz 1 PRINT :xyz END

ABC 1

SHOW :xyz xyz has no value LOCALMAKE

Synopsis LOCALMAKE varname value

Description LOCALMAKE declares a local variable and assigns it a variable. It is convenient shorthand for the following code:

LOCAL varname MAKE varname value

Example TO SAYHELLO LOCALMAKE "message [Hello] PRINT :message END

SAYHELLO Hello

SHOW :message message has no value THING

Synopsis THING varname :varname

Description Outputs the value of the variable whose name is the input word. If there is more than one such variable, the innermost local variable of that name is chosen.

The colon notation for showing variables is an abbreviation for

THING "

So :foo is the same as (THING "foo).

Example MAKE "foo [Hello how are you] SHOW THING "foo [Hello how are you] SHOW :foo [Hello how are you]

175 Workspace Management

Property Lists

PPROP ...... 176 GPROP ...... 176 REMPROP ...... 177 PLIST ...... 177

Property lists provide a way to associate words with things. Property lists are sometimes called "dictionaries", "associative arrays", or simply "name-value pairs".

Property lists, abbreviated to "plists", are always accessed by their name—you can't get at the plist directly. Among other things, this means you cannot pass a plist into a Logo procedure, you can only pass its name.

You can get, set, and remove properties (name-value pairs) from a plist. If you try to get a property that doesn't exist, or you try to get a property from a plist that doesn't exist, you get the empty list. In general, you shouldn't care if a property list exists or not. However, if you do care, you can use PLISTS to get the names of all unburied property lists.

Names of property lists are always case-insensitive. Names of individual properties are case-sensitive or case-insensitive depending on the value of CASEIGNOREDP, which is TRUE by default. PPROP

Synopsis PPROP plistname propertyname value

Description Adds a property to the property list named plistname . The property is named propertyname and has the value value. If no property list named plistname exists, then it is created. If the property named propertyname already has a value in the property list, then the value is replaced.

The plistname input must be a word.

The propertyname input may be word, list, or array. Property names are compared in the same manner as EQUALP compares its inputs.

Example PPROP "plist1 "p1 1 PPROP "plist1 "p2 2 PPROP "plist2 "p1 10 PPROP "plist2 "p2 20 PPROP "plist2 [p 3] 30

SHOW GPROP "plist1 "p1 1 SHOW GPROP "plist1 "p2 2 SHOW GPROP "plist2 "p1 10 SHOW GPROP "plist2 "p2 20 SHOW GPROP "plist2 [p 3] 30 GPROP

Synopsis GPROP plistname propertyname

176 Workspace Management

Description Outputs the value of the property named propertyname in the property list named plistname, or the empty list if there is no such property or property list.

The plistname input must be a word.

The propertyname input may be word, list, or array. Property names are compared in the same manner as EQUALP compares its inputs.

Example PPROP "plist1 "p1 1 PPROP "plist1 "p2 2 PPROP "plist2 "p1 10 PPROP "plist2 "p2 20 PPROP "plist2 [p 3] 30

SHOW GPROP "plist1 "p1 1 SHOW GPROP "plist1 "p2 2 SHOW GPROP "plist2 "p1 10 SHOW GPROP "plist2 "p2 20 SHOW GPROP "plist2 [p 3] 30 REMPROP

Synopsis REMPROP plistname propertyname

Description Removes the property named propertyname from the property list named plistname, if it exists. If REMPROP removes the final property from a property list, then the property list may be erased.

The plistname input must be a word.

The propertyname input may be word, list, or array. Property names are compared in the same manner as EQUALP compares its inputs.

Example PPROP "plist1 "p1 1 PPROP "plist1 "p2 2 SHOW PLIST "plist1 [p2 2 p1 1] REMPROP "plist1 "p1 SHOW PLIST "plist1 [p2 2] PLIST

Synopsis PLIST plistname

Description Outputs a list of the properties in the property list named plistname. The odd-numbered items in the list are the property names and the even-numbered items are the property values. The output is a copy of the actual property list;

177 Workspace Management

changing properties later does not change the list that was output by PLIST and vice-versa.

plistname must be a word.

Example PPROP "plist1 "p1 1 PPROP "plist1 "p2 2 SHOW PLIST "plist1 [p2 2 p1 1] Workspace Predicates

PROCEDUREP ...... 178 PRIMITIVEP ...... 178 DEFINEDP ...... 179 NAMEP ...... 179 MACROP ...... 179 PROPLISTP ...... 180 PROCEDUREP

Synopsis PROCEDUREP name PROCEDURE? name

Description Outputs TRUE if the input is the name of a procedure, outputs FALSE otherwise.

name must be a word.

Example MAKE "foo 1 TO BAR END

SHOW PROCEDUREP "foo false

SHOW PROCEDUREP "bar true PRIMITIVEP

Synopsis PRIMITIVEP name PRIMITIVE? name

Description Outputs TRUE if the input is the name of a primitive (one that is built into FMSLogo), outputs FALSE otherwise. Note that many of FMSLogo's procedures are library procedures, not primitives.

name must be a word.

Example TO FWD :arg FORWARD :arg END

SHOW PRIMITIVEP "FWD

178 Workspace Management

false

SHOW PRIMITIVEP "FORWARD true DEFINEDP

Synopsis DEFINEDP name DEFINED? name

Description Outputs TRUE if the input is the name of a user-defined procedure or a library procedure.

name must be a word.

Example SHOW DEFINEDP "forward false

DEFINE "ABC [[a b] [PRINT :a] [PRINT :b]] SHOW DEFINEDP "ABC true NAMEP

Synopsis NAMEP name NAME? name

Description Outputs TRUE if the input is the name of a variable. Outputs FALSE, otherwise.

name must be a word.

Example DEFINE "ABC [[a b] [PRINT :a] [PRINT :b]] MAKE "xyz 1 SHOW NAMEP "ABC false

SHOW NAMEP "xyz true MACROP

Synopsis MACROP name MACRO? name

Description Outputs TRUE if the input is the name of a user-defined macro or a library macro. Outputs FALSE, otherwise.

name must be a word.

Example SHOW MACROP "ABC false

.DEFMACRO "ABC [[a b] [PRINT :a] [PRINT :b]] SHOW MACROP "ABC true

179 Workspace Management

PROPLISTP

Synopsis PROPLISTP name PROPLIST? name

Description Outputs TRUE if the input is the name of a property list, outputs FALSE otherwise.

The name input must be a word.

Example SHOW PROPLISTP "Helium false

PPROP "Helium "Symbol "He PPROP "Helium "AtomicNumber 2 SHOW PROPLISTP "Helium true Workspace Queries CONTENTS ...... 180 PROCEDURES ...... 181 NAMES ...... 181 PLISTS ...... 181 NAMELIST ...... 181 PLLIST ...... 182 BURIED ...... 182 STEPPED ...... 182 TRACED ...... 182

Most workspace query procedures output a "contents list", which can be used as input to many Workspace Inspection and Workspace Control procedures. All procedures whose input is indicated as "contentslist" accept any of the following:

• A single word (taken as a procedure name)

• A list of words (taken as procedure names)

• A list of two lists (taken as procedure names and variable names, respectively)

• A list of three lists (taken as procedure names, variable names, and property list names, respectively) CONTENTS

Synopsis CONTENTS

Description Outputs a contents list consisting of three lists containing names of defined procedures, variables, and property lists, respectively. This list includes all unburied named items in the workspace.

Example TO MYPROGRAM END MAKE "name 1 PPROP "properties "property 1 SHOW CONTENTS [[myprogram] [name] [properties]]

180 Workspace Management

PROCEDURES

Synopsis PROCEDURES

Description Outputs a contents list consisting of all unburied user-defined procedures in the workspace.

Example TO FOO END

TO BAR END

SHOW PROCEDURES [bar foo] NAMES

Synopsis NAMES

Description Outputs a contents list consisting of an empty procedure list (indicating no procedure names) followed by a list of all unburied variable names in the workspace.

Example MAKE "foo 1 MAKE "bar 2 SHOW NAMES [[] [bar foo]] PLISTS

Synopsis PLISTS

Description Outputs a contents list, which is a list of three lists. The first two lists are empty, indicating that no procedure names or variable names are returned. The third list is a list of the names of all unburied property lists in the workspace.

Example PPROP "properties "property 1 SHOW PLISTS [[] [] [properties]] NAMELIST

Synopsis NAMELIST varname NAMELIST varnamelist

Description Outputs a contents list consisting of the empty list followed by a list of the name or names given as input. This is useful in conjunction with workspace control procedures that require a contents list as input. These named variables do not have to exist.

Example SHOW NAMELIST [foo bar] [[] [foo bar]]

SHOW NAMELIST "abc

181 Workspace Management

[[] [abc]] PLLIST

Synopsis PLLIST plistname PLLIST plistnamelist

Description Outputs a contents list consisting of two empty lists followed by a list of the name or names given as input. The third sublist of a contents list is taken to mean the names of property lists. This is useful in conjunction with workspace control procedures that require a contents list as input.

Example SHOW PLLIST [foo bar] [[] [] [foo bar]]

SHOW PLLIST "abc [[] [] [abc]] BURIED

Synopsis BURIED

Description Outputs a contents list consisting of three lists, respectively containing the names of all buried procedures, variables, and property lists in the workspace.

Example SHOW BURIED [[] [caseignoredp] []] POTS SHOW BURIED [[pots] [caseignoredp] []] STEPPED

Synopsis STEPPED

Description Outputs a contents list consisting of the list of stepped procedures followed by two empty lists.

Example TO MYFORWARD FORWARD 10 END

SHOW STEPPED [[] [] []] STEP "MYFORWARD SHOW STEPPED [[MYFORWARD] [] []]

See Also STEP TRACED

Synopsis TRACED

Description Outputs a contents list consisting of the list of traced items.

182 Workspace Management

Example TO MYFORWARD FORWARD 10 END

SHOW TRACED [[] [] []]

TRACE "MYFORWARD SHOW TRACED [[MYFORWARD] [] []]

See Also TRACE Workspace Inspection PO ...... 183 POALL ...... 183 POPS ...... 184 PONS ...... 184 POPLS ...... 184 PON ...... 185 POPL ...... 185 POT ...... 185 POTS ...... 185

The workspace inspection procedures print the definition of various workspace types to the current write stream. PO

Synopsis PO contentslist

Description Prints the definitions of all procedures, variables, and property lists named in contentslist to the current write stream. See the Workspace Queries section for an explaination of the formats of contentslist.

PO throws an error if it is asked to print out a procedure or variable name that is not in the workspace. However, it is not an error to ask PO to print out the contents of a property list that is not in the workspace. This is consistent with how GPROP behaves when asked to get a non-existent property.

PO stands for "Print Out".

Example TO xxx print "Hello ; comment end

PO "xxx TO xxx print "Hello ; comment END POALL

Synopsis POALL

183 Workspace Management

Description Prints all unburied definitions in the workspace to the current write stream. POALL abbreviates PO CONTENTS.

Example TO xxx print "Hello ; comment end

POALL TO xxx print "Hello ; comment END POPS

Synopsis POPS

Description Prints the definitions of all unburied procedures in the workspace to the current write stream. POPS abbreviates PO PROCEDURES.

Example MAKE "var 1

TO xxx print "Hello ; comment end

POPS TO xxx print "Hello ; comment END PONS

Synopsis PONS

Description Prints the definitions of all unburied variables in the workspace to the current write stream. PONS abbreviates PO NAMES.

Example MAKE "var 1

TO xxx print "Hello ; comment end

PONS Make "var 1 POPLS

Synopsis POPLS

Description Prints the contents of all unburied property lists in the workspace to the current write stream. POPLS abbreviates PO PLISTS.

Example PPROP "plist1 "p1 1 POPLS Pprop "plist1 "p1 1

184 Workspace Management

PON

Synopsis PON varname PON varlistname

Description Prints the definitions of the named variable(s) to the current write stream. PON abbreviates PO NAMELIST.

Example MAKE "foo 1 MAKE "bar 2 PON [foo bar] Make "foo 1 Make "bar 2 POPL

Synopsis POPL plname POPL plnamelist

Description Prints the contents of the named property lists(s) to the current write stream. POPL abbreviates PO PLLIST.

POPL treats all non-existent property lists as empty property lists. This is consistent with how GPROP behaves when asked to get a non-existent property.

Example PPROP "plist1 "p1 1 POPL [plist1 plist2] Pprop "plist1 "p1 1 POT

Synopsis POT contentslist

Description Prints the title lines of the named procedures, the definitions of the named variables, and the contents of the named property lists to the current write stream. For property lists, the entire list is shown on one line instead of as a series of PPROP instructions as in PO.

Example PPROP "plist1 "p1 1 PPROP "plist1 "p2 2 DEFINE "ABC [[a b] [PRINT :a] [PRINT :b]] MAKE "var 32

POT [[ABC] [var] [plist1]] to ABC :a :b Make "var 32 Plist "plist1 = [p2 2 p1 1]

POT PROCEDURES to ABC :a :b POTS

Synopsis POTS

185 Workspace Management

Description Prints the title lines of all unburied procedures in the workspace to the current write stream. POTS abbreviates POT PROCEDURES.

Example DEFINE "ABC [[a b] [PRINT :a] [PRINT :b]] POTS to abc :a :b Workspace Control ERASE ...... 186 ERALL ...... 187 ERPS ...... 187 ERNS ...... 188 ERPLS ...... 188 ERN ...... 188 ERPL ...... 189 BURY ...... 189 BURYALL ...... 190 BURYNAME ...... 190 UNBURY ...... 190 UNBURYALL ...... 191 UNBURYNAME ...... 191 TRACE ...... 192 UNTRACE ...... 192 STEP ...... 193 UNSTEP ...... 194 EDIT ...... 194 EDALL ...... 194 EDALLBTN ...... 195 EDPS ...... 198 EDNS ...... 199 EDPLS ...... 199 EDN ...... 200 EDPL ...... 200 SAVE ...... 200 SAVEL ...... 201 LOAD ...... 201

The workspace control procedures manipulate workspace "things" (procedures, variables, and property lists). You can use these procedures to erase, bury, unbury, and edit other procedures.

If a thing is erased, it is completely removed from the workspace. It is no longer usable or callable.

If a thing is buried, it is not included in the contents list output by CONTENTS, PROCEDURES, NAMES, or PLISTS, but is included in the list output by BURIED. By implication, buried things are not printed by POALL or saved by SAVE. However, buried things are still usable; a buried procedure can still be called and a buried variable can still be used.

Typically, items are buried to keep them from cluttering up the workspace. For example, all Logolib procedures bury themselves after they are called so that they don't show up when you run EDALL.

Buried things can be completely restored to the workspace by unburying them (for example, with UNBURY). ERASE

186 Workspace Management

Synopsis ERASE contentslist ER contentslist

Description Erases the procedures, variables, and property lists named in contentslist. Once erased, the named things cannot be called or referenced. Primitive procedures are not erased unless the variable REDEFP has the value TRUE.

ERASE does not throw an error if it is asked to erase a procedure, variable, or property list that is not in the workspace. However, ERASE does throw an error when it is asked to erase a primitive when REDEFP either has not been set, or is FALSE.

See the Workspace Queries section for an explanation of the formats of contentslist.

Example TO FOO PRINT "hello END

FOO hello ERASE "FOO FOO I don't know how to FOO ERALL

Synopsis ERALL (ERALL showwarning)

Description Erases all unburied procedures, variables, and property lists from the workspace.

By default, ERALL warns you about what you are about to do. ERALL has an optional input that controls if this warning should be displayed. If you pass in FALSE, the warning is suppressed.

(ERALL "false) is equivalent to ERASE CONTENTS.

Example TO FOO END

TO BAR END

SHOW PROCEDURES [bar foo] (ERALL "false) SHOW PROCEDURES [] ERPS

Synopsis ERPS

187 Workspace Management

Description Erases all unburied procedures from the workspace. ERPS abbreviates ERASE PROCEDURES.

Example TO FOO END

TO BAR END

SHOW PROCEDURES [bar foo] ERPS SHOW PROCEDURES [] ERNS

Synopsis ERNS

Description Erases all unburied variables from the workspace. ERNS abbreviates ERASE NAMES.

Example MAKE "foo 1 MAKE "bar 2 PONS Make "bar 2 Make "foo 1 ERNS PONS ERPLS

Synopsis ERPLS

Description Erases all unburied property lists from the workspace. ERPLS abbreviates ERASE PLISTS.

Example PPROP "plist1 "p1 1 PPROP "plist2 "p2 2 POPLS Pprop "plist1 "p1 1 Pprop "plist2 "p2 1 ERPLS POPLS ERN

Synopsis ERN varname ERN varnamelist

Description Erases the variable(s) named in the input from the workspace. ERN abbreviates ERASE NAMELIST.

Example MAKE "foo 1 MAKE "bar 2 PONS

188 Workspace Management

Make "bar 2 Make "foo 1 ERN [foo] PONS Make "bar 2 ERPL

Synopsis ERPL plname ERPL plnamelist

Description Erases the property lists named in the input from the workspace. ERPL abbreviates ERASE PLLIST.

Example PPROP "plist1 "p1 1 PPROP "plist2 "p2 2 POPLS Pprop "plist1 "p1 1 Pprop "plist2 "p2 1 ERPL [plist2] POPLS Pprop "plist1 "p1 1 BURY

Synopsis BURY contentslist

Description Buries the procedures, variables, and property lists named in the contentslist input. A "thing" that is buried is not included in the lists output by CONTENTS, PROCEDURES, NAMES, or PLISTS, but is included in the list output by BURIED. By implication, buried things are not printed by POALL or saved by SAVE.

BURY does not throw an error if it is asked to bury a procedure, variable, or property list that is not in the workspace, but doing so has no effect. BURY also does not throw an error if asked to bury a primitive, but this also has no effect.

See the Workspace Queries section for an explanation of the contentslist input.

Example TO FOO PRINT [I am Foo] END

TO BAR PRINT [I am Bar] END

POTS TO BAR TO FOO BURY [[FOO] [] []] POTS TO BAR FOO

189 Workspace Management

I am Foo BURYALL

Synopsis BURYALL

Description Buries all procedures, variables, and property lists in the workspace. BURYALL abbreviates BURY CONTENTS.

Example TO FOO PRINT [I am Foo] END

TO BAR PRINT [I am Bar] END

POTS TO BAR TO FOO BURYALL POTS FOO I am Foo BAR I am Bar BURYNAME

Synopsis BURYNAME varname BURYNAME varnamelist

Description Buries the variable(s) named in the input. BURYNAME abbreviates BURY NAMELIST.

Example MAKE "foo [I am Foo] MAKE "bar [I am Bar] PONS Make "bar [I am Bar] Make "foo [I am Foo] BURYNAME [foo] PONS Make "bar [I am Bar] SHOW :foo [I am Foo] SHOW :bar [I am Bar] UNBURY

Synopsis UNBURY contentslist

Description Unburies the procedures, variables, and property lists named in the input. That is, the named items are returned to view in CONTENTS and similar procedures.

190 Workspace Management

UNBURY does not throw an error if it is asked to unbury a procedure, variable, or property list that is not buried, but doing so has no effect.

See the Workspace Queries section for an explanation of the contentslist input.

Example MAKE "foo [I am Foo] MAKE "bar [I am Bar] PONS Make "bar [I am Bar] Make "foo [I am Foo] BURYNAME [foo] PONS Make "bar [I am Bar] UNBURY [ [] [foo] [] ] PONS Make "bar [I am Bar] Make "foo [I am Foo] UNBURYALL

Synopsis UNBURYALL

Description Unburies all procedures, variables, and property lists in the workspace. UNBURYALL abbreviates UNBURY CONTENTS.

Example MAKE "foo [I am Foo] MAKE "bar [I am Bar] PONS Make "bar [I am Bar] Make "foo [I am Foo] BURYNAME [foo] PONS Make "bar [I am Bar] UNBURYALL PONS Make "bar [I am Bar] Make "foo [I am Foo] UNBURYNAME

Synopsis UNBURYNAME varname UNBURYNAME varnamelist

Description Unburies the variable(s) named in the input. UNBURYNAME abbreviates UNBURY NAMELIST.

Example MAKE "foo [I am Foo] MAKE "bar [I am Bar] PONS Make "bar [I am Bar] Make "foo [I am Foo] BURYNAME [foo] PONS

191 Workspace Management

Make "bar [I am Bar] UNBURYNAME [foo] PONS Make "bar [I am Bar] Make "foo [I am Foo] TRACE

Synopsis TRACE contentslist

Description Marks the named items for tracing. A message is printed whenever a traced procedure is invoked, giving the actual input values, and whenever a traced procedure runs STOP or OUTPUT. A message is printed whenever a new value is assigned to a traced variable using MAKE. A message is printed whenever a new property is given to a traced property list using PPROP.

TRACE does not throw an error if it is asked to trace a procedure, variable, or property list that is not in the workspace, but doing so has no effect. TRACE also does not throw an error if asked to trace a primitive, but this also has no effect.

See the Workspace Queries section for an explanation of the contentslist input.

Example TO MYPRINT :a PRINT :a END

MYPRINT "Hello Hello

TRACE "MYPRINT MYPRINT "Hello ( MYPRINT "Hello ) Hello UNTRACE "MYPRINT MYPRINT "Hello Hello

See Also UNTRACE The Trace Button Workspace Queries UNTRACE

Synopsis UNTRACE contentslist

Description Turns off tracing for the named items.

UNTRACE does not throw an error if it is asked to untrace a procedure, variable, or property list that is not being traced, but doing so has no effect.

Example TO MYPRINT :a PRINT :a END

192 Workspace Management

MYPRINT "Hello Hello

TRACE "MYPRINT MYPRINT "Hello ( MYPRINT "Hello ) Hello UNTRACE "MYPRINT MYPRINT "Hello Hello

See Also TRACE The Trace Button STEP

Synopsis STEP contentslist

Description Marks the items in the contents list for stepping.

Whenever a stepped procedure is invoked, each instruction line in the procedure body is displayed in a dialog box before being executed and FMSLogo waits for the user to press the OK button before continuing. The line is truncated according to the current values of PRINTWIDTHLIMIT and PRINTDEPTHLIMIT.

Whenever a stepped variable is "shadowed", a message to this effect is printed to the commander's Output/Command-Recall box. A variable is shadowed whenever a variable of the same name is created with the LOCAL command or when a procedure is invoked that has an input with the same name. If the variable was shadowed by LOCAL, then the instruction line that caused the shadowing is printed after the message. This instruction line is truncated according to the current values of PRINTWIDTHLIMIT and PRINTDEPTHLIMIT.

STEP has no effect on property lists.

STEP does not throw an error if it is asked to step a procedure or variable that is not in the workspace, but doing so has no effect. STEP also does not throw an error if asked to step a primitive, but this also has no effect.

See the Workspace Queries section for an explanation of the contentslist input.

You can step all procedures and variables with the Step Button.

Example TO MYPROGRAM FORWARD 10 RIGHT 90 FORWARD 20 LEFT 90 END

STEP "MYPROGRAM MYPROGRAM

193 Workspace Management

Each line of MYPROGRAM is displayed and waits for OK to continue to next line. UNSTEP "MYPROGRAM MYPROGRAM

See Also UNSTEP Workspace Queries UNSTEP

Synopsis UNSTEP contentslist

Description Turns off stepping for the items in a contents list.

UNSTEP does not throw an error if it is asked to unstep a procedure or variable is not stepped, but doing so has no effect.

Example TO MYPROGRAM FORWARD 10 RIGHT 90 FORWARD 20 LEFT 90 END

MYPROGRAM STEP "MYPROGRAM Each line of MYPROGRAM is displayed and waits for OK to continue to next line. UNSTEP "MYPROGRAM MYPROGRAM

See Also STEP The Step Button EDIT

Synopsis EDIT contentslist ED contentslist

Description Opens the definitions of the named item(s) in the editor.

See the Workspace Queries section for an explanation of the contentslist input.

Example TO MYPROGRAM PRINT "Hrllo END

MYPROGRAM Hrllo EDIT "MYPROGRAM change Hrllo to Hello and exit editor MYPROGRAM Hello EDALL

Synopsis EDALL

194 Workspace Management

Description Opens all definitions in the workspace in the editor.

EDALL abbreviates EDIT CONTENTS.

Example TO MYPROGRAM PRINT :myvariable END

MAKE "myvariable "Hrllo MYPROGRAM Hrllo EDALL change Hrllo to Hello and exit editor MYPROGRAM Hello EDALLBTN

Synopsis EDALLBTN

Description Opens all definitions in the workspace in the editor, just like EDALL.

EDALLBTN is a library procedure that exists to enable you to change what happens when you press the Commander's Edall Button. By redefining it, you can make the Edall Button open the workspace in an external editor, change it to open a specific file, or replace the workspace editor with your own user interface created with WINDOWCREATE.

Example The following example shows how to change the Edall button to open a specific file instead of the entire workspace.

TO EDITFILE ; EDITFILE is a simple procedure for editing (and re-editing) ; an external file using FMSLogo's editor.

; See if the file to edit already been designated. IF NOT NAMEP "editfile.filetoedit [ ; The file to edit has not been designated. ; As the user to select one. ; ; Note that we use a "save" variant of the file picker ; to be able to select a file that doesn't exist. MAKE "editfile.filetoedit DIALOGFILESAVE "*.lgo IF EQUALP [] :editfile.filetoedit [ ; The user cancelled the selection. ERASE NAMELIST "editfile.filetoedit STOP ]

; Bury the filename so that it doesn't pollute the workspace. BURY NAMELIST "editfile.filetoedit ]

; If an editor is already open for this file, then ; activate it and give it focus.

195 Workspace Management

WINDOWSET :editfile.filetoedit 9 SETFOCUS :editfile.filetoedit

IF NOTEQUALP GETFOCUS :editfile.filetoedit [ ; No editor session for this file was found. ; Open the file in the FMSLogo editor.

; When the file is saved, LOAD it into the workspace. ; ; If we used [ LOAD :editfile.filetoedit ], the file might ; fail to load if :editfile.filetoedit were erased ; or modified while the editor was open. Therefore, we ; create an instruction list that has the value of ; :editfile.filetoedit as a word literal, instead of the ; relying on the variable's name. ; ; Unfortunately, file names may contain special characters ; which must be backslashed to be preserved. The MAP adds a ; backslash to any character which needs it, as described in ; the documentation of BACKSLAHEDP. QUOTED creates the word ; literal. ; WINDOWFILEEDIT :editfile.filetoedit (LIST "LOAD QUOTED MAP [ IFELSE MEMBERP ? "| \n()[]{}\|+-*/=<>":;\\~?| [ WORD "\\ ? ][ ? ] ] :editfile.filetoedit) ] END

TO EDITNEWFILE ; EDITNEWFILE is like EDITFILE, except that it always prompts ; for the file to edit. EDITFILE will subsequently open the ; newly selected file each time it's run without prompting. ; ; EDITDIFFERENTFILE would be a better name, since the file isn't ; created, but that's harder to type.

ERASE NAMELIST "editfile.filetoedit EDITFILE END

TO EDALLBTN ; When using EDITFILE to open a file, EDALL has confusing behavior ; because it doesn't save the changes back to the file and includes things ; in the workspace which don't come from the file. To avoid accidentally ; editing the workspace, redefine the Edall button to use EDITFILE. EDITFILE END

196 Workspace Management

The next example shows how to change the Edall button to show a simple procedure picker.

TO EDALLBTN ; Override the "Edall" button with a procedure picker.

WINDOWCREATE "main "procedurepicker [Select a procedure] 200 200 230 255 [] COMBOBOXCREATE "procedurepicker "procedurepicker.proclist 2 2 180 240

BUTTONCREATE "procedurepicker "procedurepicker.edit [Edit] 184 2 40 18 [ IF NOT EMPTYP COMBOBOXGETTEXT "procedurepicker.proclist [ EDIT COMBOBOXGETTEXT "procedurepicker.proclist WINDOWDELETE "procedurepicker ] ]

BUTTONCREATE "procedurepicker "procedurepicker.editall [Edit All] 184 22 40 18 [ EDIT PROCEDURES WINDOWDELETE "procedurepicker ]

BUTTONCREATE "procedurepicker "procedurepicker.cancel [Cancel] 184 220 40 18 [ WINDOWDELETE "procedurepicker ]

; Populate the listbox with the name of all procedures. FOREACH PROCEDURES [ COMBOBOXADDSTRING "procedurepicker.proclist ? ] COMBOBOXSETTEXT "procedurepicker.proclist [] ; clear selection END BURY "EDALLBTN

The last example shows how to change the Edall button to open the workspace in an external editor. In this case it uses Microsoft Wordpad, which is among the worst possible choices for editing Logo programs.

TO GETTEMPPATH ; Calls the win32 function GetTempPathW. ; Outputs the temporary path as a word. ; Outputs [] on error.

LOCAL [rval temppath size buffer codepoint]

DLLLOAD "kernel32.dll

MAKE "rval (DLLCALL [L GetTempPathW B 261 L 261] "kernel32.dll) IFELSE EQUALP 0 ITEM 1 :rval [ MAKE "temppath [] ; error ][ ; Convert from WCHAR* to a Logo word. MAKE "size ITEM 1 :rval MAKE "buffer ITEM 2 :rval

MAKE "temppath "|| REPEAT :size [ ; Determine the code point of the REPCOUNTth character.

197 Workspace Management

MAKE "codepoint (SUM ASCII ITEM (2*REPCOUNT-1) :buffer ; low byte comes first LSHIFT ASCII ITEM (2*REPCOUNT) :buffer 8) ; high byte comes second

; Append the REPCOUNTth character to the value. MAKE "temppath WORD :temppath CHAR :codepoint ] ]

(DLLFREE "kernel32.dll) OUTPUT :temppath END BURY "GETTEMPPATH

TO EDALLBTN LOCALMAKE "editor "|C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe| LOCALMAKE "file WORD GETTEMPPATH "\\tmp.lgo

BURY [[] [editor file]] ; hide local variables from SAVE SAVE :file

FOREVER [ IF NOT (SHELL (LIST (WORD "" :editor "") (WORD "" :file "") ) "TRUE) [ ; The program returned an error code. ERASEFILE :file STOP ]

; Try to load the new file. CATCH "ERROR [ LOAD :file ] LOCALMAKE "error ERROR IF EQUALP :error [] [ ; Successfully loaded the new file. ERASEFILE :file STOP ]

PRINT [There was an error in the file:] PRINT ITEM 2 :error PRINT (SENTENCE [On the line:] ITEM 4 :error) ] END BURY "EDALLBTN EDPS

Synopsis EDPS

Description Opens all unburied procedures in the editor.

EDPS abbreviates EDIT PROCEDURES.

Example TO MYPROGRAM1 PRINT "Hrllo

198 Workspace Management

END

TO MYPROGRAM2 PRINT "Byr END

MYPROGRAM1 Hrllo MYPROGRAM2 Byr EDPS change Hrllo to Hello, change Byr to Bye and exit editor MYPROGRAM1 Hello MYPROGRAM2 Bye EDNS

Synopsis EDNS

Description Opens all unburied variables in the editor.

EDNS abbreviates EDIT NAMES.

Example TO MYPROGRAM PRINT :myvariable END

MAKE "myvariable "Hrllo MYPROGRAM Hrllo EDNS change Hrllo to Hello and exit editor MYPROGRAM Hello EDPLS

Synopsis EDPLS

Description Opens all unburied property lists in the Editor.

EDPLS abbreviates EDIT PLISTS.

Example PPROP "plist 1 "one PPROP "plist 2 "one SHOW GPROP "plist 2 one EDPLS change "one" to "two" and exit editor SHOW GPROP "plist 2 two

199 Workspace Management

EDN

Synopsis EDN varname EDN varnamelist

Description Opens all named variables in the editor.

EDN abbreviates EDIT NAMELIST.

Example TO MYPROGRAM PRINT :myvariable END

MAKE "myvariable "Hrllo MYPROGRAM Hrllo EDN [myvariable] change Hrllo to Hello and exit editor MYPROGRAM Hello EDPL

Synopsis EDPL varname EDPL varnamelist

Description Opens all named property lists in the Editor.

EDPL abbreviates EDIT PLLIST.

Example PPROP "plist 1 "one PPROP "plist 2 "one SHOW GPROP "plist 2 one EDPL [plist] change "one" to "two" and exit editor SHOW GPROP "plist 2 two SAVE

Synopsis SAVE filename

Description Saves the definitions of all unburied procedures, variables, and property lists in a file named filename.

SAVE is equivalent to:

TO SAVE :filename LOCAL "oldwriter MAKE "oldwriter WRITER OPENWRITE :filename SETWRITE :filename POALL SETWRITE :oldwriter

200 Workspace Management

CLOSE :filename END

Example TO MYPROGRAM1 PRINT "Hello1 END

TO MYPROGRAM2 PRINT "Hello2 END

POTS TO MYPROGRAM1 TO MYPROGRAM2

SAVE "myprograms.lgo ERALL POTS LOAD "myprograms.lgo POTS TO MYPROGRAM1 TO MYPROGRAM2 SAVEL

Synopsis SAVEL contentslist filename

Description Saves the definitions of the procedures, variables, and property lists specified by contentslist to a file named filename.

SAVEL stands for "save list".

Example TO MYPROGRAM1 PRINT "Hello1 END

TO MYPROGRAM2 PRINT "Hello2 END

POTS TO MYPROGRAM1 TO MYPROGRAM2

SAVEL [[MYPROGRAM1] [] []] "myprogram.lgo ERALL POTS LOAD "myprogram.lgo POTS TO MYPROGRAM1 LOAD

Synopsis LOAD filename

201 Workspace Management

Description Reads instructions from the file named filename and runs them. The file can include procedure definitions with TO, and these are accepted even if a procedure by the same name already exists. If the file assigns a list value to a variable named STARTUP, then that list is RUN as an instruction list after the file is loaded.

It is important to understand that the file is executed, not copied, into the workspace:

• If Logo sees a TO instruction, then it defines that procedure (the instructions between the TO and END are not immediately run, but instead become the body of the procedure).

• If Logo sees a MAKE instruction, then it makes that name.

• If Logo sees instructions that are outside of a procedure definition, then it runs those instructions in the order seen.

Example TO MYPROGRAM1 PRINT "Hello1 END

TO MYPROGRAM2 PRINT "Hello2 END

POTS TO MYPROGRAM1 TO MYPROGRAM2

SAVE "myprograms.lgo ERALL POTS LOAD "myprograms.lgo POTS TO MYPROGRAM1 TO MYPROGRAM2 Debug Commands

NODES ...... 202 STATUS ...... 203 NOSTATUS ...... 203 NODES

Synopsis NODES

Description Outputs a list of two numbers. The first is the number of nodes of memory currently in use. The second is the maximum number of nodes that have been in use at any time since the last invocation of NODES.

A node is a small block of computer memory used by Logo. Each number uses one node. Each non-numeric word uses one node, plus some non-node

202 Workspace Management

memory for the characters in the word. Each array takes one node, plus some non-node memory, as well as the memory required by its members. Each list requires one node per member, as well as the memory within the members.

NODES is useful it you want to ensure that your program isn't inadvertantly keeping references on a large number of NODEs that would cause FMSLogo's memory usage to grow and grow.

Example ; See what the current node usage is. SHOW NODES [5559 5582]

; Make a variable that uses a lot of nodes. MAKE "biglist ISEQ 1 100000 SHOW NODES [206102 1506144]

; Erase the variable to free the nodes. ERN "biglist SHOW NODES [6267 206283] STATUS

Synopsis STATUS

Description Displays the popup status window. This command has the same effect as pressing the Status Button.

Example STATUS NOSTATUS

See Also The Status Button NOSTATUS NOSTATUS

Synopsis NOSTATUS

Description Closes the popup status window, if it is open. This command has the same effect as pressing the Status Button when it is depressed.

Example STATUS NOSTATUS

See Also The Status Button STATUS

203 Chapter 12. Control Structures

Control Commands ...... 205 RUN ...... 206 RUNRESULT ...... 206 REPEAT ...... 206 REPCOUNT ...... 206 IF ...... 207 IFELSE ...... 207 TEST ...... 208 IFTRUE ...... 208 IFFALSE ...... 209 TRUE ...... 209 FALSE ...... 209 STOP ...... 210 OUTPUT ...... 210 CATCH ...... 210 THROW ...... 211 ERROR ...... 212 PAUSE ...... 213 CONTINUE ...... 213 YIELD ...... 214 NOYIELD ...... 214 EVENTCHECK ...... 215 SETCURSORWAIT ...... 216 SETCURSORNOWAIT ...... 216 HALT ...... 216 WAIT ...... 217 SETTIMER ...... 217 CLEARTIMER ...... 217 BYE ...... 217 .MAYBEOUTPUT ...... 218 IGNORE ...... 218 ` ...... 218 FOR ...... 219 FOREVER ...... 220 DO.WHILE ...... 220 WHILE ...... 221 DO.UNTIL ...... 221 UNTIL ...... 222 Template-Based Iteration ...... 222 Explicit-Slot Templates ...... 223 Named-Procedure Templates ...... 223 Named-Slot Templates ...... 223 APPLY ...... 223 INVOKE ...... 224 FOREACH ...... 224 MAP ...... 225 MAP.SE ...... 225 FILTER ...... 226 FIND ...... 226 REDUCE ...... 226 CROSSMAP ...... 227

204 Control Structures

CASCADE ...... 228 CASCADE.2 ...... 229 TRANSFER ...... 229 ISEQ ...... 229 RSEQ ...... 230 # ...... 230 ? ...... 231

Logo has many facilities for controlling which instructions get executed next. Taken together, these facilities are commonly called "control flow", because they control the "flow" of execution.

In the following descriptions, an "instruction list" input may be a list or a word. If it's a word, it is parsed into list form before it is run. Thus, RUN READWORD or RUN READLIST work. The former is slightly preferable because it allows for a continued line (with ~) that includes a comment (with ;) on the first line.

Pay attention to the difference between an "operation" and a "command". An operation is a procedure that outputs a value. A command is a procedure that does NOT output a value. Most procedures are either one or the other, but some are both. Control Commands

RUN ...... 206 RUNRESULT ...... 206 REPEAT ...... 206 REPCOUNT ...... 206 IF ...... 207 IFELSE ...... 207 TEST ...... 208 IFTRUE ...... 208 IFFALSE ...... 209 TRUE ...... 209 FALSE ...... 209 STOP ...... 210 OUTPUT ...... 210 CATCH ...... 210 THROW ...... 211 ERROR ...... 212 PAUSE ...... 213 CONTINUE ...... 213 YIELD ...... 214 NOYIELD ...... 214 EVENTCHECK ...... 215 SETCURSORWAIT ...... 216 SETCURSORNOWAIT ...... 216 HALT ...... 216 WAIT ...... 217 SETTIMER ...... 217 CLEARTIMER ...... 217 BYE ...... 217 .MAYBEOUTPUT ...... 218 IGNORE ...... 218 ` ...... 218 FOR ...... 219 FOREVER ...... 220

205 Control Structures

DO.WHILE ...... 220 WHILE ...... 221 DO.UNTIL ...... 221 UNTIL ...... 222 RUN

Synopsis RUN instructionlist

Description Runs the instructions in instructionlist; outputs if the list contains an expression that outputs.

Example MAKE "thingstodo [PRINT "Hello] RUN :thingstodo Hello RUNRESULT

Synopsis RUNRESULT instructionlist

Description Runs the instructions in instructionlist. RUNRESULT outputs the empty list if those instructions produce no output. Otherwise, it outputs a list whose only member is the output from running the input instructionlist. This is useful for inventing command-or-operation control structures:

LOCAL "result MAKE "result RUNRESULT [something] IF EMPTYP :result [STOP] OUTPUT FIRST :result

Example MAKE "thingstodo [FIRST [1 2 3]] MAKE "answer RUNRESULT :thingstodo SHOW :answer [1] REPEAT

Synopsis REPEAT count instructionlist

Description Runs the instructions in instructionlist repeatedly, count times.

The number of times which instructionlist has been run can be determined with REPCOUNT.

Example REPEAT 3 [PRINT (LIST "This "is "iteration REPCOUNT)] This is iteration 1 This is iteration 2 This is iteration 3

See Also FOREVER REPCOUNT

Synopsis REPCOUNT

206 Control Structures

Description Outputs the number of the current repetition of a REPEAT command's instruction list. That is, it outputs 1 the first time the instruction list is run, outputs 2 the second time, and so on. REPCOUNT outputs -1 when it is run outside the context of a FOREVER or REPEAT command's instruction list.

If two REPEAT commands are nested, REPCOUNT outputs the repeat count of the innermost REPEAT.

Example REPEAT 3 [PRINT (LIST "This "is "iteration REPCOUNT)] This is iteration 1 This is iteration 2 This is iteration 3 IF

Synopsis IF condition true.instructionlist (IF condition true.instructionlist false.instructionlist)

Description Command or operation where:

• If condition evaluates to TRUE, then IF runs true.instructionlist.

• If condition evalutes to FALSE, then IF does nothing.

• If given a false.instructionlist input, IF acts like IFELSE.

• It is an error if condition does not evaluate to either TRUE or FALSE.

For compatibility with earlier versions of Logo, if an IF instruction is not enclosed in parentheses, but the first thing on the instruction line after the second input expression is a literal list (i.e., a list in square brackets), the IF is treated as if it were IFELSE, but a warning message is given. If this aberrant IF appears in a procedure body, the warning is given only the first time the procedure is invoked in each Logo session.

Example ; single instruction list IF 1=1 [PRINT [Yes it is true]] Yes it is true

; two instruction lists TO MAX :a :b OUTPUT (IF :a > :b [:a] [:b]) END

SHOW MAX 1 2 2 IFELSE

Synopsis IFELSE condition true.instructionlist false.instructionlist

Description Command or operation where:

• If condition evaluates to TRUE, then IFELSE runs true.instructionlist.

207 Control Structures

• If condition evalutes to FALSE, then IFELSE runs false.instructionlist.

• It is an error if condition does not evaluate to either TRUE or FALSE.

Example ; simple examples IFELSE 1=1 [PRINT [Yes it is true]] [PRINT [No it is false]] Yes it is true

IFELSE 1=0 [PRINT [Yes it is true]] [PRINT [No it is false]] No it is false

; example where IFELSE outputs a value TO MAX :a :b OUTPUT IFELSE :a > :b [:a] [:b] END

SHOW MAX 1 2 2 TEST

Synopsis TEST condition

Description TEST remembers its input condition, which must be TRUE or FALSE, so that it be used later by IFTRUE or IFFALSE instructions. The effect of TEST is local to the procedure in which it is used; any corresponding IFTRUE or IFFALSE must be in the same procedure or a subprocedure.

Example TO MYTEST :arg TEST 1 = :arg PRINT [Do this] PRINT [Do that] IFTRUE [PRINT [arg was the number one]] IFFALSE [PRINT [arg was NOT the number one]] END

MYTEST 1 Do this Do that arg was the number one IFTRUE

Synopsis IFTRUE instructionlist IFT instructionlist

Description Runs instructionlist if the most recent TEST instruction had a TRUE input. Does nothing, otherwise. The TEST must have been in the same procedure or a superprocedure.

Example TO MYTEST :arg TEST 1 = :arg PRINT [Do this]

208 Control Structures

PRINT [Do that] IFTRUE [PRINT [arg was the number one]] IFFALSE [PRINT [arg was NOT the number one]] END

MYTEST 1 Do this Do that arg was the number one IFFALSE

Synopsis IFFALSE instructionlist IFF instructionlist

Description Runs instructionlist if the most recent TEST instruction had a FALSE input. Does nothing, otherwise. The TEST must have been in the same procedure or a superprocedure.

Example TO MYTEST :arg TEST 1 = :arg PRINT [Do this] PRINT [Do that] IFTRUE [PRINT [arg was the number one]] IFFALSE [PRINT [arg was NOT the number one]] END

MYTEST 0 Do this Do that arg was NOT the number one TRUE

Synopsis (special form)

TRUE

Description This is a special word to indicate a positive condition. TRUE is a reserved value, not a procedure nor a variable.

Example SHOW 1=1 true

IF "TRUE [PRINT [TRUE is always true]] TRUE is always true FALSE

Synopsis (special form)

FALSE

Description This is a special word to indicate a negative condition. FALSE is a reserved value, not a procedure nor a variable.

209 Control Structures

Example SHOW 1=0 false

IFELSE "FALSE [PRINT [We cannot get here]] [PRINT [FALSE is always false]] FALSE is always false STOP

Synopsis STOP

Description Ends the running of the procedure in which it appears. Control is returned to the context in which that procedure was invoked. The stopped procedure does not output a value.

Example TO MYPROGRAM :arg PRINT [Before Stop] IF 1=:arg [STOP] PRINT [After Stop] END

MYPROGRAM 1 Before Stop

MYPROGRAM 2 Before Stop After Stop OUTPUT

Synopsis OUTPUT value OP value

Description Ends the running of the procedure in which it appears. That procedure outputs value to the context in which it was invoked. Don't be confused: OUTPUT itself is a command, but the procedure that invokes OUTPUT is an operation.

The value input may be any Logo thing (word, list, array, etc.).

Example TO MYPROGRAM OUTPUT [This is the output] END

SHOW MYPROGRAM [This is the output] CATCH

Synopsis CATCH tag instructionlist

Description Command or operation that runs its instructionlist input and outputs whatever instructionlist outputs. If instructionlist runs a THROW instruction with a tag equal to the tag input (case-insensitive comparison), then the running of instructionlist is immediately terminated. In this case, CATCH outputs if a value input is given to THROW.

210 Control Structures

The tag input must be a word. If tag is the word ERROR, then any error condition that arises during the running of instructionlist has the effect of THROW "ERROR instead of printing an error message and returning to toplevel. In this case, CATCH does not output a value. Also, during the running of instructionlist, the variable ERRACT is temporarily unbound. (If there is an error while ERRACT has a value, that value is taken as an instruction list to be run after printing the error message. Typically the value of ERRACT, if any, is the list [PAUSE].)

Example TO MYPROGRAM2 PRINT [Before throw] THROW "tag1 PRINT [We never get here because we THROW back] END

TO MYPROGRAM1 CATCH "tag1 [MYPROGRAM2] PRINT [I'm back] END

MYPROGRAM1 Before throw I'm back THROW

Synopsis THROW tag (THROW tag value) (THROW "ERROR errortext) (THROW "ERROR 4 badvalue)

Description Ends the running of a CATCH instruction's instructionlist input. THROW must be used within the scope of a CATCH instruction that has a tag equal to tag. If THROW is given a value input, then CATCH outputs value. If THROW is not given a value input, then the corresponding CATCH does not output a value.

The tag input must be a word.

THROW "SYSTEM causes FMSLogo to immediately exit.

THROW "TOPLEVEL terminates all running procedures and interactive pauses, and returns control to the toplevel instruction prompt. This has the same effect as pressing the Halt Button.

THROW "ERROR can be used to generate an error condition. If the error is not caught, it prints a message (Throw "Error) with the usual indication of where the error (in this case the THROW) occurred. If tag equals "ERROR and an errortext input is given, then errortext is used as the text of the error message instead of the standard message. In this case, the location indicated for the error is not the location of the THROW, but the location where the procedure containing the THROW was invoked. This allows user-defined procedures to generate error messages as if they were primitives. If tag equals "ERROR and the second input is 4 (the error code for bad input) and a third

211 Control Structures

input exists, then a "bad input" error is thrown and the third input is used as the value of the bad input.

Note that when THROW "ERROR is used, the corresponding CATCH "ERROR, if any, does not output a value because the second input to THROW is treated as an error message, not an output.

Example The following example shows how to use THROW to change the control flow:

TO MYPROGRAM2 PRINT [Before throw] (THROW "tag1 [We need to get back]) PRINT [We never get here because we THROW back] END

TO MYPROGRAM1 SHOW CATCH "tag1 [MYPROGRAM2] PRINT [I'm back] END

MYPROGRAM1 Before throw [We need to get back] I'm back

The following example shows how to check for bad input errors:

TO COORDINATES :x :y IF NOT NUMBERP :x [ (THROW "ERROR 4 :x) ] IF NOT NUMBERP :y [ (THROW "ERROR 4 :y) ] OUTPUT (WORD "|(| :x "|, | :y "|)| ) END

SHOW COORDINATES 1 2 (1, 2)

SHOW COORDINATES [1] [2] COORDINATES doesn't like [1] as input ERROR

Synopsis ERROR

Description Outputs a list describing the error just caught, if any. If no error was caught since the last use of ERROR, then ERROR outputs the empty list. The error list contains four members: an integer code corresponding to the type of error, the text of the error message, the name of the procedure in which the error occurred, and the instruction line on which the error occurred.

The meaning of the first item in the list is explained in the section on Error Codes.

Example TO MYPROGRAM FORWARD 1000 END

212 Control Structures

FENCE CATCH "ERROR [MYPROGRAM] SHOW ERROR [3 turtle out of bounds MYPROGRAM [FORWARD 1000]] SHOW ERROR [] PAUSE

Synopsis PAUSE

Description Command or operation that enters an interactive pause. The user is prompted for instructions with a dialog box that includes the name of the procedure in which PAUSE was invoked. Local variables of that procedure are available during the pause. If the pause is ended by a CONTINUE instruction, then PAUSE outputs whatever the input to CONTINUE was.

If the variable ERRACT exists and an error condition occurs, then the contents of that variable are run as an instruction list. Typically ERRACT is given the value [PAUSE] so that an interactive pause mode is entered in the event of an error. This allows the user to check values of local variables at the time of the error.

Example TO MYPROGRAM REPEAT 180 [RIGHT 2 IF 90=REPCOUNT [PAUSE]] PRINT "Done END

MYPROGRAM Pausing...MYPROGRAM

Enter SHOW HEADING in Pause Mode dialog box and hit OK.

180

Enter CONTINUE in Pause Box and hit OK.

Done CONTINUE

Synopsis CONTINUE value CO value (CONTINUE) (CO)

Description Ends the current interactive pause, returning to the context of the PAUSE invocation that began it. If CONTINUE is given an input, that value is used as the output from the PAUSE. If not, the PAUSE does not output.

Exceptionally, the CONTINUE command can be used without its default input and without parentheses provided that nothing follows it on the instruction line.

Example TO MYPROGRAM

213 Control Structures

REPEAT 180 [RIGHT 2 IF 90=REPCOUNT [PAUSE]] PRINT "Done END

MYPROGRAM Pausing...MYPROGRAM

Enter SHOW HEADING in Pause Mode dialog box and hit OK. 180

Enter CONTINUE in Pause Box and hit OK. Done YIELD

Synopsis YIELD

Description YIELD tells FMSLogo that it's okay to interrupt running Logo code in order to process windows messages, such as keyboard input, mouse clicks, or notifications to repaint the screen. The default state is to yield.

See the NOYIELD command for an explaination of what "yielding" means.

See Also EVENTCHECK NOYIELD

Synopsis NOYIELD

Description NOYIELD tells FMSLogo not to interrupt running Logo instructions to process windows messages, such as keyboard input, mouse clicks, or notifications to repaint the screen. When FMSLogo is in NOYIELD mode, it is unresponsive while running Logo instructions and ignores important user interactions such as pressing on the Halt Button. FMSLogo may appear to lock up until the Logo code finishes or it runs YIELD.

The default mode is to yield, but KEYBOARDON, MOUSEON, and some SETTIMER event callbacks are run in NOYIELD mode.

The notion of not yielding was historically more significant when Windows was a cooperative multi-tasking operating system and applications had complete control of the CPU until they opted to yield to other applications. Once an application had yielded, it would have to wait until all other applications had yielded before it could run again, and there was no way of knowing how long that would take. As such, to guarantee good performance, applications would not yield until they had run out of work to do. Nowadays, Windows gives all applications a fair amount of CPU time, so NOYIELD only prevents FMSLogo from interrupting itself. These interruptions are generally desireable, which makes it difficult to use NOYIELD well. Nonetheless, NOYIELD is available because FMSLogo runs faster in some cases if it cannot be interrupted.

Example You can achieve the proper balance between performance and responsiveness for your programs by understanding the examples given below. Let's say that

214 Control Structures

you have nested loops in your program and that most of the real work is done in the inner loop.

Case 1: User in control for 10,000 operations, lower performance:

YIELD REPEAT 100 [ REPEAT 100 [ ; (work to be done) ] ]

Case 2: User out of control for 10,000 operations, good performance:

NOYIELD REPEAT 100 [ REPEAT 100 [ ; (work to be done) ] ]

Case 3: User out of control for 100 operations, still good performance:

REPEAT 100 [ NOYIELD REPEAT 100 [ ; (work to be done) ] YIELD ]

See Also EVENTCHECK EVENTCHECK

Synopsis EVENTCHECK

Description The EVENTCHECK command is like calling YIELD immediately followed by NOYIELD. It checks to see if any events are waiting to be processed. Some commands that input "callbacks" run them in a no-yield state. If the callback code is short and quick you won't see any problems. But if it's long the user will notice that they lose control during this period. If you sprinkle a few EVENTCHECK instructions around, then the user will not lose control for such a "long" period of time.

This command can be used as an alternative to placing YIELD and NOYIELD commands around computationally intensive loops. You can wrap the whole procedure in a NOYIELD/YIELD pair then you can call EVENTCHECK in strategic locations in your loops.

Example MOUSEON [REPEAT 72 [REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 5]] [] [] [] [] Click the mouse in FMSLogo Screen. Note that while it is drawing you cannot HALT it, because mouse callbacks do not yield.

MOUSEON [REPEAT 72 [REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 5 EVENTCHECK]] [] [] [] []

215 Control Structures

Click the mouse in FMSLogo Screen. Note that while it is drawing you can now HALT SETCURSORWAIT

Synopsis SETCURSORWAIT

Description SETCURSORWAIT sets the cursor to the familiar hourglass shape. Its purpose is to indicate two things. First, it indicates that the current operation may take some time. Second, it indicates the user does not have control until the operation completes. This command only works when not yielding. Once FMSLogo is set to yield, the appropriate (non-hourglass) cursor is used on the next event involving the cursor (like moving the mouse). This means that you must run NOYIELD before each SETCURSORWAIT. If you decide to YIELD momentarily during a computation you must run SETCURSORWAIT again. In other words, if you wish to use SETCURSORWAIT it should always be paired up with a NOYIELD (just before it).

Example REPEAT 100 [ NOYIELD SETCURSORWAIT REPEAT 100 [ ; (work to be done) ] SETCURSORNOWAIT YIELD ] SETCURSORNOWAIT

Synopsis SETCURSORNOWAIT

Description SETCURSORNOWAIT changes the cursor to the familiar arrow shape. This should be just before a call to YIELD.

Once FMSLogo is set to yield, the appropriate (non-hourglass) cursor is used on the next event involving the cursor (like moving the mouse), regardless of whether you call SETCURSORNOWAIT. However, calling SETCURSORNOWAIT shows the arrow cursor without waiting for the next event.

Example REPEAT 100 [ NOYIELD SETCURSORWAIT REPEAT 100 [ ; (work to be done) ] SETCURSORNOWAIT YIELD ] HALT

Synopsis HALT

216 Control Structures

Description Immediately stops FMSLogo from processing any further commands and returns control to the commander. It is the same as pressing the Halt Button.

Example FOREVER [FORWARD REPCOUNT RIGHT 91 SETPENCOLOR REPCOUNT] Type "HALT" in the commander's input box and press the Execute button. Stopping... WAIT

Synopsis WAIT delay

Description Delays further execution for about delay 1/60ths of a second. This also yields to other processes running on your system.

Example WAIT 600 ; ten seconds SETTIMER

Synopsis SETTIMER id delay callback

Description Sets up a timer identified by id (a number from 1-31) to call the instructions in callback in delay milliseconds. It continues to "fire" every delay milliseconds until you invoke CLEARTIMER with the same id.

You can clear the timer at any time with CLEARTIMER. In particular, you can clear the timer in the callback instructions to create a one-shot timer event. You can also create a timer at any time, including in the callback instructions. Halting clears all timers.

Timers with id values from 1-16 run their callbacks in NOYIELD mode, which means they are not interrupted by user interaction and the screen isn't repainted if it becomes occulded when the callback is running. Timers with id values from 17-31 run their callbacks in the normal, interruptable mode.

Each timer id can have different values for callback.

Example SETTIMER 17 200 [SETPENCOLOR (LIST RANDOM 256 RANDOM 256 RANDOM 256)] FMSLogo is ready to run more instructions and the timer changes the pen color randomly every 200 milliseconds. REPEAT 72 [REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 5] CLEARTIMER 17 CLEARTIMER

Synopsis CLEARTIMER id

Description Clears a timer that was scheduled by SETTIMER and identified by id (1-31).

Example SETTIMER 1 200 [SETPENCOLOR (LIST RANDOM 256 RANDOM 256 RANDOM 256)] FMSLogo is ready to run new instructions and the timer changes the pen color randomly every 200 milliseconds. REPEAT 72 [REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 5] CLEARTIMER 1 BYE

217 Control Structures

Synopsis BYE

Description Exits FMSLogo.

Example BYE .MAYBEOUTPUT

Synopsis (special form)

.MAYBEOUTPUT value

Description Works like OUTPUT except that the expression that provides the input value might not output a value, in which case the effect is like STOP. This is intended for use in control structure definitions, for cases in which you don't know whether some expression produces a value.

.MAYBEOUTPUT is an alternative to RUNRESULT. It's fast and easy to use, at the cost of being an exception to FMSLogo's evaluation rules. (Ordinarily, it should be an error if the expression that's supposed to provide an input to something doesn't have a value.)

Example TO INVOKE :procedure [:inputs] 2 .MAYBEOUTPUT APPLY :procedure :inputs END

(INVOKE "PRINT "a "b "c) a b c

PRINT (INVOKE "WORD "a "b "c) abc IGNORE

Synopsis IGNORE input

Description Does nothing with its input. This is useful when an expression is evaluated for a side effect and its actual output is unimportant.

Example TO MYPROGRAM :arg PRINT :arg OUTPUT COUNT :arg END

MYPROGRAM "Hello Hello I don't know what to do with 5 IGNORE MYPROGRAM "Hello Hello `

Synopsis ` list

218 Control Structures

Description Outputs a list equal to its input but with certain substitutions.

If a member of the input list is the word , (comma) then the following member should be an instruction list that produces an output when run. That output value replaces the comma and the instruction list. This is called substitution.

If a member of the input list is the word ,@ (comma atsign) then the following member should be an instruction list that outputs a list when run. The members of that list replace the ,@ and the instruction list. This is called splicing.

A word starting with , or ,@ is treated as if the rest of the word were a one- word list. For example, ,:foo is equivalent to ,[:foo].

A word starting with ", (quote comma) is replaced with a word beginning with " followed by the result of running the substitution on what comes after the comma. If what comes after the comma is a list, only the first word in the list is used in the substitution.

A word starting with :, (colon comma) is replaced with a word beginning with : followed by the result of running the substitution on what comes after the comma. If what comes after the comma is a list, only the first word in the list is used in the substitution.

Backquotes can be nested. Substitution is only done for commas when they appear at the same depth as the backquote in which they are found. See the second and third example below.

Example SHOW `[foo baz ,[BUTFIRST [a b c]] garply ,@[BUTFIRST [a b c]]] [foo baz [b c] garply b c]

SHOW `[a `[b ,[1+2] ,[foo ,[1+3] d] e] f] [a ` [b , [1+2] , [foo 4 d] e] f]

MAKE "name1 "x MAKE "name2 "y SHOW `[a `[b ,:,:name1 ,",:name2 d] e] [a ` [b , [:x] , ["y] d] e] FOR

Synopsis FOR controllist instructionlist

Description FOR is a flexible tool for iteration.

The controllist input controls how the iteration occurs. It must be a list containing either three or four members. In order, they are:

1. A word, which is used as the name of a "control variable". The control variable is local to the procedure.

2. A word or list that is evaluated to determine a number, the "starting value" of the variable.

3. A word or list that is evaluated to determine a number, the "limit value" of the variable. 219 Control Structures

4. An optional word or list that is evaluated to determine the "step size". If the fourth member is missing, the step size is 1 or -1 depending on whether the limit value is greater than or less than the starting value, respectively.

The instructionlist input dictates what FOR should do on each iteration. The effect of FOR is to run instructionlist repeatedly, assigning a new value to the "control variable" on each iteration. First the "starting value" is assigned to the control variable. Then the control value is compared to the "limit value". FOR is complete when the sign of (current - limit) is the same as the sign of the "step size".

If no "step size" is provided, the instructionlist is always run at least once. An explicit step size can lead to a zero-trip FOR, (for example, FOR [I 1 0 1] [...]). Otherwise, instructionlist is run, then the control variable is incremented by the step size and FOR returns to the comparison step.

In many cases, a FOR instruction can be rewritten to use REPEAT and REPCOUNT, instead.

Example FOR [I 2 7 1.5] [PRINT :I] 2 3.5 5 6.5 FOREVER

Synopsis FOREVER instructionlist

Description Runs instructionlist repeatedly, forever.

Example FOREVER [PRINT "|Wake me when you are done.|] Wake me when you are done. Wake me when you are done. Wake me when you are done. Wake me when you are done. Wake me when you are done. Wake me when you are done. ...

See Also REPEAT DO.WHILE

Synopsis DO.WHILE instructionlist conditionlist

Description Repeatedly evaluates the instructionlist as long as the evaluated conditionlist remains TRUE. DO.WHILE evaluates instructionlist before evaluating conditionlist, so instructionlist is always run at least once. The conditionlist input must contain an expression that evalautes to either TRUE or FALSE.

The fact that the conditionlist input is a list may be misleading, because it should contain exactly one expression. It is only a list because the contents

220 Control Structures

of a list are not evaluated by default. Instead, they must be explicitly evaluated with RUN. This allows Logo to reevaluate conditionlist after each iteration, rather than only evaluating it once.

Example MAKE "i 0 DO.WHILE [MAKE "I :i+1 PRINT :i] [:i<3] 1 2 3 WHILE

Synopsis WHILE conditionlist instructionlist

Description Repeatedly evaluates the instructionlist as long as the evaluated conditionlist remains TRUE. WHILE evaluates conditionlist before instructionlist, so instructionlist may not be run at all. The conditionlist input must contain an expression that evalautes to either TRUE or FALSE.

The fact that the conditionlist input is a list may be misleading, because it should contain exactly one expression. It is only a list because the contents of a list are not evaluated by default. Instead, they must be explicitly evaluated with RUN. This allows Logo to reevaluate conditionlist after each iteration, rather than only evaluating it once.

Example MAKE "i 0 WHILE [:i<3] [MAKE "i :i+1 PRINT :i] 1 2 3 DO.UNTIL

Synopsis DO.UNTIL instructionlist conditionlist

Description Repeatedly evaluates the instructionlist as long as the evaluated conditionlist remains FALSE. DO.UNTIL evaluates instructionlist before evaluating conditionlist, so instructionlist is always run at least once. The conditionlist input must contain an expression that evalautes to either TRUE or FALSE.

The fact that the conditionlist input is a list may be misleading, because it should contain exactly one expression. It is only a list because the contents of a list are not evaluated by default. Instead, they must be explicitly evaluated with RUN. This allows Logo to reevaluate conditionlist after each iteration, rather than only evaluating it once.

Example MAKE "i 0 DO.UNTIL [MAKE "i :i+1 PRINT :i] [:i>3] 1 2 3 4

221 Control Structures

UNTIL

Synopsis UNTIL conditionlist instructionlist

Description Repeatedly evaluates the instructionlist as long as the evaluated conditionlist remains FALSE. UNTIL evaluates conditionlist before instructionlist, so instructionlist may not be run at all. The conditionlist input must contain an expression that evalautes to either TRUE or FALSE.

The fact that the conditionlist input is a list may be misleading, because it should contain exactly one expression. It is only a list because the contents of a list are not evaluated by default. Instead, they must be explicitly evaluated with RUN. This allows Logo to reevaluate conditionlist after each iteration, rather than only evaluating it once.

Example MAKE "i 0 UNTIL [:i>3] [MAKE "i :i+1 PRINT :i] 1 2 3 4 Template-Based Iteration

Explicit-Slot Templates ...... 223 Named-Procedure Templates ...... 223 Named-Slot Templates ...... 223 APPLY ...... 223 INVOKE ...... 224 FOREACH ...... 224 MAP ...... 225 MAP.SE ...... 225 FILTER ...... 226 FIND ...... 226 REDUCE ...... 226 CROSSMAP ...... 227 CASCADE ...... 228 CASCADE.2 ...... 229 TRANSFER ...... 229 ISEQ ...... 229 RSEQ ...... 230 # ...... 230 ? ...... 231

This section describes iteration tools that are based on the idea of a "template". This is a generalization of an instruction list or an expression list in which "slots" are provided for the tool to insert varying data. Three different forms of template can be used: explicit-slot templates, named-procedure templates, and named-slot templates.

These iteration tools are extended versions of the ones in Appendix B of the book Computer Science Logo Style, Volume 3: Advanced Topics by Brian Harvey [MIT Press, 1987]. The extensions are primarily to allow for variable numbers of inputs.

222 Control Structures

Explicit-Slot Templates

The most commonly used form of template is the "explicit-slot" form, which is sometimes called the "question mark" form.

Example:

SHOW MAP [? * ?] [2 3 4 5] [4 9 16 25]

In this example, MAP evaluates the template [? * ?] repeatedly, with each of the members of the data list [2 3 4 5] substituted in turn for the question marks. The same value was used for every question mark in a given evaluation. Some tools allow for more than one datum to be substituted in parallel; in these cases the slots are indicated by ?1 for the first datum, ?2 for the second, and so on.

Example:

SHOW (MAP [(WORD ?1 ?2 ?1)] [a b c] [d e f]) [ada beb cfc]

If the template wishes to compute the datum number, the form (? 1) is equivalent to ?1, so (? ?1) means the datum whose number is given in datum number 1. Some tools allow additional slot designations, as shown in the individual descriptions. Named-Procedure Templates

The second form of template is the "named-procedure" form. If the template is a word rather than a list, it is taken as the name of a procedure. That procedure must accept a number of inputs equal to the number of parallel data slots provided by the tool; the procedure is applied to all the available data in order. That is, if data ?1 through ?3 are available, the template "PROC is equivalent to [PROC ?1 ?2 ?3].

Example:

SHOW (MAP "WORD [a b c] [d e f]) [ad be cf]

TO DOTPRODUCT :a :b ; vector dot product OUTPUT APPLY "sum (MAP "product :a :b) END Named-Slot Templates

The third form of template is "named-slot" or "lambda" form. This form is indicated by a template list containing more than one item, whose first item is itself a list. The first item is taken as a list of names; local variables are created with those names and given the available data in order as their values. The number of names must equal the number of available data. This form is needed when one iteration tool is used within the template list of another, and the ? notation would be ambiguous in the inner template.

Example:

TO MATRIXMULTIPLY :m1 :m2 [:tm2 TRANSPOSE :m2] OUTPUT MAP [[row] MAP [[col] DOTPRODUCT :row :col] :tm2] :m1 END APPLY

223 Control Structures

Synopsis APPLY template inputlist

Description Runs the template, filling its slots with the members of inputlist. The number of members in inputlist must be an acceptable number of slots for template. It is illegal to apply the primitive TO as a template, but anything else is okay. APPLY outputs what template outputs, if anything.

APPLY is similar to INVOKE except that APPLY's inputs are provided as a list rather than as separate expressions.

Example SHOW APPLY "SUM [1 2 3] 6 INVOKE

Synopsis INVOKE template input (INVOKE template input1 input2 ...)

Description Runs the template, filling its slots with the remaining input(s). The number of inputs must be an acceptable number of slots for template. It is illegal to use the primitive TO as a template, but anything else is okay. INVOKE outputs what template outputs, if anything.

INVOKE is similar to APPLY except that INVOKE's inputs are provided as separate expressions rather than in a list.

Example SHOW (INVOKE "SUM 1 2 3) 6 FOREACH

Synopsis FOREACH datalist templatelist (FOREACH datalist1 datalist2 ... templatelist)

Description Command that evaluates the templatelist repeatedly, once for each item in datalist. If more than one data list is given, each of them must be the same length. If the data inputs are words, then the template is evaluated once for each character.

In a template, the symbol ?REST represents the portion of the data input to the right of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then ?REST would be replaced by [C D E]. If multiple parallel slots are used, then (?REST 1) goes with ?1, etc.

In a template, the symbol # represents the position in the data input of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then # would be replaced by 2.

Example FOREACH [a b c d] [PRINT (SENTENCE "index # "value ? "rest ?REST)] index 1 value a rest b c d index 2 value b rest c d index 3 value c rest d index 4 value d rest

224 Control Structures

MAP

Synopsis MAP templatelist data (MAP templatelist data1 data2 ...)

Description Outputs a word or list, depending on the type of the data input, of the same length as that data input. (If more than one data input are given, the output is of the same type as data1.) Each item of the output is the result of evaluating the templatelist, filling the slots with the corresponding item(s) of the data input(s). (All data inputs must be the same length.) In the case of a word output, the results of the template evaluation must be words, and they are concatenated with WORD.

In a template, the symbol ?REST represents the portion of the data input to the right of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then ?REST would be replaced by [C D E]. If multiple parallel slots are used, then (?REST 1) goes with ?1, etc.

In a template, the symbol # represents the position in the data input of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then # would be replaced by 2.

Example SHOW MAP [2 * ?] [1 2 3 4 5 6] [2 4 6 8 10 12]

SHOW (MAP "LIST [a b c] [d e f]) [[a d] [b e] [c f]] MAP.SE

Synopsis MAP.SE templatelist data (MAP.SE templatelist data1 data2 ...)

Description Outputs a list formed by evaluating templatelist repeatedly and concatenating the results using SENTENCE. That is, the members of the output are the members of the results of the evaluations. The output list might, therefore, be of a different length from that of the data input(s). (If the result of an evaluation is the empty list, it contributes nothing to the final output.) The data inputs may be words or lists.

In a template, the symbol ?REST represents the portion of the data input to the right of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then ?REST would be replaced by [C D E]. If multiple parallel slots are used, then (?REST 1) goes with ?1, etc.

In a template, the symbol # represents the position in the data input of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then # would be replaced by 2.

Example SHOW (MAP.SE "LIST [a b c] [d e f]) [a d b e c f]

225 Control Structures

FILTER

Synopsis FILTER conditiontemplate data

Description Outputs a word or list, depending on the type of the data input, containing a subset of the members (for a list) or characters (for a word) of the input. The conditiontemplate input is evaluated once for each member of the data, and it must produce a TRUE or FALSE value. If the value is TRUE, then the corresponding member is included in the output. Otherwise, it is omitted.

In a template, the symbol ?REST represents the portion of the data input to the right of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then ?REST would be replaced by [C D E].

In a template, the symbol # represents the position in the data input of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then # would be replaced by 2.

Example TO VOWELP :letter OUTPUT MEMBERP :letter "aeiou END

PRINT FILTER "VOWELP "elephant eea FIND

Synopsis FIND conditiontemplate data

Description Outputs the first item of the data input for which the value produced by evaluating conditiontemplate with that item in its slot is TRUE. If there is no such item, then FIND outputs the empty list.

In a template, the symbol ?REST represents the portion of the data input to the right of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then ?REST would be replaced by [C D E].

In a template, the symbol # represents the position in the data input of the member currently being used as the ? slot-filler. For example, if the data input is [A B C D E] and the template is being evaluated with ? replaced by B, then # would be replaced by 2.

Example TO NEGATIVEP :number OUTPUT :number < 0 END

SHOW FIND "NEGATIVEP [2 4 3 0] [] SHOW FIND "NEGATIVEP [2 1 0 -3 -6] -3 REDUCE

226 Control Structures

Synopsis REDUCE template data

Description Outputs the result of applying the template to accumulate the items of the data input, two items at a time.

The template input must be a two-slot procedure. Typically, template is the name of an associative operation, like "SUM.

If the data input has only one item (member in a list or character in a word), REDUCE outputs that item. Otherwise, template is first applied with ?1 filled with the next-to-last item and ?2 with the last item. Then, if there are more items, the template is applied with ?1 filled with the next item to the left and ?2 with the result from the previous evaluation. This process continues until all items have been used.

The data input must not be empty. It must be either a list or a word (not an array).

If template is the name of a procedure that is capable of accepting arbitrarily many inputs, it is more efficient to use APPLY instead of REDUCE. REDUCE is good for associative procedures that have been written to accept exactly two inputs.

Example TO MAX :a :b OUTPUT IFELSE :a > :b [:a] [:b] END

PRINT REDUCE "MAX [2 3 8 7 9 0] 9

Alternatively, REDUCE can be used to write MAX as a procedure that accepts any number of inputs, as SUM does:

TO MAX [:inputs] 2 IF EMPTYP :inputs [(THROW "error [not enough inputs to max])] OUTPUT REDUCE [IFELSE ?1 > ?2 [?1] [?2]] :inputs END

PRINT (MAX 2 3 8 7 9 0) 9 CROSSMAP

Synopsis CROSSMAP template data (CROSSMAP template data1 data2 ...)

Description Outputs a list containing the results of template evaluations. Each data list contributes to a slot in the template; the number of slots is equal to the number of data list inputs. As a special case, if only one data list input is given, that list is taken as a list of data lists, and each of its members contributes values to a slot.

CROSSMAP differs from MAP in that, instead of taking members from the data inputs in parallel, CROSSMAP takes all possible combinations of members of data inputs, which need not be the same length.

227 Control Structures

For compatibility with program listings in Brian Harvey's textbook series "Computer Science Logo Style", FMSLogo's CROSSMAP templates may use the notation :1 instead of ?1 to indicate slots.

Example SHOW (CROSSMAP [WORD ?1 ?2] [a b c] [1 2 3 4]) [a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 c4] CASCADE

Synopsis CASCADE endtest template startvalue (CASCADE endtest template1 startvalue1 template2 startvalue2 ...) (CASCADE endtest template1 startvalue1 template2 startvalue2 ... finaltemplate)

Description Outputs the result of applying a template (or several templates, see the section entitled Template-Based Iteration) repeatedly, with a given value filling the slot the first time, and the result of each application filling the slot for the following application.

In the simplest case, CASCADE has three inputs. The template is a one- slot expression template. That template is evaluated some number of times (perhaps zero). On the first evaluation, the slot is filled with the startvalue input; on subsequent evaluations, the slot is filled with the result of the previous evaluation. The number of evaluations is determined by the endtest input. This can be either a nonnegative integer, in which case the template is evaluated that many times, or a predicate expression template, in which case it is evaluated (with the same slot filler that is used for the evaluation of the second input) repeatedly, and the CASCADE evaluation continues as long as the predicate value is FALSE. (In other words, the predicate template indicates the condition for stopping.)

If the template is evaluated zero times, CASCADE outputs startvalue. Otherwise, CASCADE outputs the value produced by the last template evaluation.

CASCADE templates may include the symbol # to represent the number of times the template has been evaluated. This slot is filled with 1 for the first evaluation, 2 for the second, and so on.

Example SHOW CASCADE 5 [LPUT # ?] [] [1 2 3 4 5]

SHOW CASCADE [VOWELP FIRST ?] [BUTFIRST ?] "spring ing

SHOW CASCADE 5 [# * ?] 1 120

Several cascaded results can be computed in parallel by providing additional template-startvalue pairs as inputs to CASCADE. In this case, all templates (including the endtest template, if used) are multi-slot, with the number of slots equal to the number of pairs of inputs. In each round of evaluations, ?2 represents the result of evaluating the second template in the previous round. If the total number of inputs (including the first endtest input) is odd, then the output from CASCADE is the final value of the first

228 Control Structures

template. If the total number of inputs is even, then the last input is a template that is evaluated once, after the end test is satisfied, to determine the output from CASCADE.

TO FIBONACCI :n OUTPUT (CASCADE :n [?1 + ?2] 1 [?1] 0) END

TO PIGLATIN :word OUTPUT (CASCADE [VOWELP FIRST ?] [WORD BUTFIRST ? FIRST ?] :word [WORD ? "ay]) END CASCADE.2

Synopsis CASCADE.2 endtest template1 startvalue1 template2 startvalue2

Description Outputs the result of invoking CASCADE with the same inputs. The only difference is that the default number of inputs is five instead of three.

Example TO FIBONACCI :n OUTPUT CASCADE.2 :n [?1 + ?2] 1 [?1] 0 END TRANSFER

Synopsis TRANSFER endtest template inbasket

Description Outputs the result of repeated evaluation of the template input. The template is evaluated once for each member of the list inbasket . TRANSFER maintains an "out basket" that is initially the empty list. After each evaluation of the template, the resulting value becomes the new "out basket". When all input has been processed, TRANSFER outputs the "out basket".

In the template, the symbol ?IN represents the current item from inbasket; the symbol ?OUT represents the entire current "out basket". Other slot symbols should not be used.

If the endtest input is the empty list, evaluation continues until all inbasket members have been used. Otherwise, the endtest input must be a predicate expression template, and evaluation continues until either that template's value is TRUE or inbasket is used up.

Example For each word in the last input, if that word is already part of the result, forget it; if not, append that word to the result so far. The result is initially empty.

SHOW TRANSFER [] [IFELSE MEMBERP ?IN ?OUT [?OUT] [LPUT ?IN ?OUT]] [A B C B D E F B C G] [A B C D E F G] ISEQ

Synopsis ISEQ from to

229 Control Structures

Description Outputs a consecutive ordered list of integers starting with from and ending with to. If from is greater than to, then ISEQ outputs a sequence that counts backwards.

The name ISEQ is short for "Integer SEQuence".

Example SHOW ISEQ 3 7 [3 4 5 6 7]

SHOW ISEQ 7 3 [7 6 5 4 3]

See Also RSEQ RSEQ

Synopsis RSEQ from to count

Description Outputs an ordered list of count equally spaced rational numbers starting with from and ending with to. If from is greater than to, then RSEQ outputs a sequence that counts backwards.

The name RSEQ is short for "Rational number SEQuenece".

Example SHOW RSEQ 3 5 9 [3 3.25 3.5 3.75 4 4.25 4.5 4.75 5]

SHOW RSEQ 3 5 5 [3 3.5 4 4.5 5]

See Also ISEQ #

Synopsis #

Description Outputs the number of the current iteration. The meaning of # depends on the context from which it is run and its full meaning is documented in the procedures which provide this context. In general, it is usable from contexts that iterate over a list of values and it outputs the position of the current value (1 for the first value, 2 for the second, etc.).

# has no meaning outside of an iteration context.

Example The following example shows how to use # within the context of FILTER to extract the first three characters of a word.

SHOW FILTER [# <= 3] "abcdefg abc

The next example shows how to use # as a shorthand for REPCOUNT.

REPEAT 5 [ SHOW # ] 1 2 3

230 Control Structures

4 5

See Also CASCADE FIND FOREACH MAP MAP.SE REPEAT ?

Synopsis ? ?input_index (? input_index)

Description Outputs the value of the current iteration. The meaning of ? depends on the context from which it is run and its full meaning is documented in the procedures which provide this context. It is typically usable from contexts that iterate over a list of values and it outputs current value.

To support iteration contexts where each iteration has multiple values, ? accepts an optional input which selects the value of the current iteration to output. The index of the value to select typically follows the ? without any space in between, for example as ?2, but it can also be given as a parenthesized expression (? 2). The latter form is necessary when the index of the value to select is not known in advance (for example, if the index is stored in a variable).

? is a short for ?1, which is a short for (? 1). This is true even for simple iteration contexts where each iteration has only one value.

APPLY enables the use of ?. Below you can see ? at work in its simplest form. This should give you an idea of how to use APPLY to write your own procedures which can input caller-supplied templates that support ?.

SHOW APPLY [?1] [a b c] a SHOW APPLY [?2] [a b c] b SHOW APPLY [?3] [a b c] c

? has no meaning outside of a context which is designed specifically for its use.

Example The following example shows how to use ? within the context of FILTER to remove consonants from a word.

SHOW FILTER [MEMBERP ? "aeiou] "elephant eea

The next example shows an iteration context where each iteration has multiple values to select. It creates a single list by concatenating the corresponding members of two lists.

SHOW (MAP [WORD ?1 ?2] [a b c] [x y z])

231 Control Structures

[ax by cz]

See Also CASCADE CASCADE.2 CROSSMAP FIND FOREACH MAP MAP.SE

232 Chapter 13. Macro Commands

.MACRO ...... 233 .DEFMACRO ...... 235 MACROEXPAND ...... 235 .MACRO

Synopsis (special form)

.MACRO procname :input1 :input2 ...

Description A macro is a special kind of procedure whose output is evaluated as instructions in the context of the macro's caller. .MACRO is like TO except that the new procedure becomes a macro.

Macros are useful for inventing new control structures comparable to REPEAT, IF, and so on. Such control structures can almost, but not quite, be duplicated by ordinary procedures. For example, here is an ordinary procedure version of REPEAT:

TO MY.REPEAT :num :instructions IF :num=0 [STOP] RUN :instructions MY.REPEAT :num-1 :instructions END

This version works fine for most purposes, for example

MY.REPEAT 5 [PRINT "hello]

But it doesn't work if the instructions to be run include OUTPUT, STOP, or LOCAL. For example, consider this procedure:

TO EXAMPLE PRINT [Guess my secret word. You get three guesses.] REPEAT 3 [IF READWORD = "secret [PRINT "Right! STOP]] PRINT [Sorry, the word was "secret"!] END

This procedure works as written, but if MY.REPEAT were used instead of REPEAT, it wouldn't work because the STOP would stop MY.REPEAT instead of stopping EXAMPLE as desired.

The solution is to make MY.REPEAT a macro. Instead of carrying out the computation, a macro must output a list containing instructions. The contents of that list are evaluated as if they appeared in place of the call to the macro. Here's a macro version of REPEAT:

.MACRO MY.REPEAT :num :instructions IF :num=0 [OUTPUT []] OUTPUT SENTENCE :instructions (LIST "MY.REPEAT :num-1 :instructions) END

233 Macro Commands

Every macro is an operation; all macros always output something. Even in the base case, MY.REPEAT outputs an empty instruction list.

To see how the MY.REPEAT macro works, let's take the example

MY.REPEAT 5 [PRINT "hello]

For this example, FMSLogo first runs MY.REPEAT as a normal procedure. MY.REPEAT outputs the following instruction list:

[PRINT "hello MY.REPEAT 4 [PRINT "hello]]

Then, because MY.REPEAT is a macro, FMSLogo immediately runs this instruction list. This prints "hello" once and invokes another repetition.

The technique just shown, although fairly easy to understand, is too slow because each repetition constructs an instruction list for evaluation. Another approach is to make MY.REPEAT a macro that works just like the non-macro version unless the instructions to be repeated includes OUTPUT or STOP:

.MACRO MY.REPEAT :num :instructions CATCH "repeat.catchtag [OUTPUT REPEAT.DONE RUNRESULT [REPEAT1 :num :instructions]] OUTPUT [] END

TO REPEAT1 :num :instructions IF :num=0 [THROW "repeat.catchtag] RUN :instructions .MAYBEOUTPUT REPEAT1 :num-1 :instructions END

TO REPEAT.DONE :repeat.result IF EMPTYP :repeat.result [OUTPUT [STOP]] OUTPUT LIST "OUTPUT QUOTED FIRST :repeat.result END

If the instructions do not include STOP or OUTPUT, then REPEAT1 reaches its base case and invokes THROW. As a result, MY.REPEAT's last instruction line outputs the empty list, so the second evaluation of the macro does nothing. But if a STOP or OUTPUT happens, then REPEAT.DONE outputs a STOP or OUTPUT instruction that is re-run in the caller's context.

The macro-defining commands have names starting with a dot because macros are an advanced feature of Logo. It's easy to get in trouble by defining a macro that doesn't terminate, or by failing to construct the instruction list properly.

LISP users should note that Logo macros are not special forms. That is, the inputs to the macro are evaluated normally, as they would be for any other procedure. It's only the output from the macro that's handled unusually.

Here's how you can implement LOCALMAKE with .MACRO:

.MACRO MY.LOCALMAKE :name :value OUTPUT (LIST "LOCAL WORD "" :name

234 Macro Commands

"APPLY ""MAKE (LIST :name :value) ) END

It's used this way:

TO TRY MY.LOCALMAKE "myvar "hello PRINT :myvar END

MY.LOCALMAKE outputs the list:

[LOCAL "myvar APPLY "MAKE [myvar hello]]

MY.LOCALMAKE uses APPLY to avoid deciding whether the second input to MAKE requires a quotation mark before it. In this case it would—MAKE "myvar "hello—but the quotation mark would be wrong if the value were a list.

It's often convenient to use the ` operation to construct the instruction list:

.MACRO MY.LOCALMAKE :name :value OUTPUT `[LOCAL ,[WORD "" :name] APPLY "MAKE [,[:name] ,[:value]]] END

On the other hand, ` is slow, since it's tree-recursive and written in Logo. .DEFMACRO

Synopsis .DEFMACRO procname text

Description .DEFMACRO is like DEFINE with the same exceptions as .MACRO.

See DEFINE and .MACRO for more details. MACROEXPAND

Synopsis MACROEXPAND macrocall

Description Operation that inputs Logo expression (macrocall) that invokes a macro and outputs the Logo expression into which the macro would translate the input expression.

The macrocall input must be a list that begins with the name of a macro.

Example SHOW MACROEXPAND [LOCALMAKE "pi 3.14159] [local "pi apply "make [pi 3.14159]]

235 Chapter 14. Error Processing Error Codes ...... 236

If an error occurs, Logo takes the following steps. First, if there is an available variable named ERRACT, Logo takes its value as an instruction list and runs the instructions. The operation ERROR may be used within the instructions (once) to examine the error condition. If the instruction list invokes PAUSE, the error message is printed before the pause happens. Certain errors are "recoverable"; for one of those errors, if the instruction list outputs a value, that value is used in place of the expression that caused the error. (If ERRACT invokes PAUSE and the user then invokes CONTINUE with an input, that input becomes the output from PAUSE and therefore the output from the ERRACT instruction list.)

It is possible for an ERRACT instruction list to produce an inappropriate value or no value where one is needed. As a result, the same error condition could recur forever.

During the running of the ERRACT instruction list, the value of ERRACT is ignored, so that an error in the ERRACT instruction list does not cause a loop. In particular, an error during a pause does not cause a pause-within-a-pause.

If ERRACT has no value, Logo handles the error by generating an internal THROW "ERROR. If this THROW is not caught by a CATCH "ERROR in the user program, it is eventually caught either by the toplevel instruction loop or by a pause loop, which prints the error message. An invocation of CATCH "ERROR takes precedence over ERRACT.

If a floating point overflow occurs during an arithmetic operation, or a two-input mathematical function (like POWER) is invoked with an illegal combination of inputs, the "doesn't like" message refers to the second operand, but should be taken as meaning the combination. Error Codes

When an error happens, you can use the ERROR operation to figure out what went wrong. ERROR outputs a list whose items describe the error. The first item is a numeric code for the type of error that occurred. The second item is a human-readable message that explains the error.

Some messages may have two different codes depending on whether the error is recoverable (that is, if a substitute value can be provided through the ERRACT mechanism).

Some messages are warnings rather than errors; these can not be caught.

The conditions which generate error code 0 and error code 34 so bad that Logo exits immediately. These also cannot be caught.

The numeric error codes and their corresponding human-readable messages are given in the table below.

Error Code Error Message 0 Fatal internal error (can't be caught) 1 Out of memory 2 Stack Overflow 3 Turtle out of bounds 4 PROC doesn't like DATUM as input (not recoverable) 5 PROC didn't output to PROC 6 Not enough inputs to PROC

236 Error Processing

Error Code Error Message 7 PROC doesn't like DATUM as input (recoverable) 8 Too much inside ( )'s 9 I don't know what to do with DATUM 10 ')' not found 11 VAR has no value 12 Unexpected ')' 13 I don't know how to PROC (recoverable) 14 Can't find catch tag for THROWTAG 15 PROC is already defined 16 Stopped 17 Already dribbling 18 File system error 19 Assuming you mean IFELSE, not IF (warning only) 20 VAR shadowed by local in procedure call (warning only) 21 User-initiated THROW "Error 22 PROC is a primitive 23 Can't use TO inside a procedure 24 I don't know how to PROC (not recoverable) 25 IFTRUE/IFFALSE without TEST 26 Unexpected ']' 27 Unexpected '}' 28 Couldn't initialize graphics 29 Macro returned VALUE instead of a list 30 I don't know what to do with VALUE 31 Can only use STOP or OUTPUT inside a procedure 32 APPLY doesn't like DATUM as input. 33 END inside multi-line instruction 34 Out of memory (can't be caught) 1001 WINDOW already exists 1002 WINDOW does not exist 1101 DLL load failed 1102 DLL is not loaded 1103 Not all Type/Data inputs are paired 1104 Invalid data type input 1105 Invalid output type 1106 Function not found

237 Error Processing

Error Code Error Message 1201 Problem Reading GIF, check memory and diskspace 1202 Problem Generating GIF, check memory and diskspace 1211 Could not open .bmp 1212 Unable to create Windows 3.0 bitmap 1213 Could not write .bmp 1214 Not a Windows 3.0 bitmap 1300 MIDI Error 1301 MIDI Error: Already open 1302 MIDI Error: Invalid MIDI device 1303 MIDI Error: Not open 1401 Timer not found 1500 Invalid state for instruction 1600 MCI Error: MESSAGE 1700 Network Error: MESSAGE 1701 netstartup has already been run 1702 The network subsystem has not been started 1703 netconnecton has already been run 1704 netaccepton has already been run 1801 Could not open port 1802 Could not flush port 1803 Could not build dcb on port 1804 Could not set port 1805 Port is already open 1806 Port is not open 1901 Cut failed, possibly not enough memory 1902 Nothing to paste 1903 BitMap Index out of range 1904 BitMap at Index must be initialized with a bitmap 2001 PROC cannot be run on PROC because it has a special form

238 Chapter 15. Special Variables

CASEIGNOREDP ...... 239 ERRACT ...... 239 PRINTDEPTHLIMIT ...... 239 PRINTWIDTHLIMIT ...... 240 REDEFP ...... 240 STARTUP ...... 241

Some of FMSLogo's behavior can be controlled with special variables. The special variables follow the normal scoping rules, so a procedure can locally set one of them to limit the scope of its effect. Initially, no variables exist except CASEIGNOREDP, which is TRUE and buried. CASEIGNOREDP

Synopsis CASEIGNOREDP

Description Normally, lower-case and upper-case letters are considered equal by EQUALP, BEFOREP , MEMBERP , etc. However, if a variable named CASEIGNOREDP exists and its value is not TRUE, then those predicates consider lower-case and upper-case letters to be distinct (that is, not equal).

Example MAKE "CASEIGNOREDP "FALSE SHOW EQUALP "a "A false

MAKE "CASEIGNOREDP "TRUE SHOW EQUALP "a "A true ERRACT

Synopsis ERRACT

Description ERRACT is an instructionlist that is run whenever an error is thrown and there is no CATCH tag for "ERROR. ERRACT typically has the value [PAUSE] to allow interactive debugging.

Some errors may be recoverable if ERRACT can fix the problem. For example, many bad input errors (such as running FORWARD [1]) are recoverable. If a bad input error causes ERRACT to be run, then the output of ERRACT is used instead of the bad input that caused the error. If ERRACT outputs another datum of bad input, then it is run again to fix the new problem.

Example FORWARD [1] FORWARD doesn't like [1] as input

MAKE "ERRACT [PRINT [Doing replacement] 100] FORWARD [1] Doing replacement PRINTDEPTHLIMIT

239 Special Variables

Synopsis PRINTDEPTHLIMIT

Description PRINTDEPTHLIMIT is a special variable. If its value is a nonnegative integer, then FMSLogo treats its value as maximum depth of a sublist (or subarray) structure that is printed by PRINT, etc.

Example PRINT [[1 [2 [3 [4 [5]]]]]] [1 [2 [3 [4 [5]]]]]]

MAKE "PRINTDEPTHLIMIT 4 PRINT [[1 [2 [3 [4 [5]]]]]] [1 [2 [3 [...... ]]]] PRINTWIDTHLIMIT

Synopsis PRINTWIDTHLIMIT

Description PRINTWIDTHLIMIT is a special variable. If its value is a nonnegative integer, then FMSLogo treats its value as the maximum number of items in any one list (or array) that is printed by PRINT, etc. FMSLogo also treats its value as the limit of how many characters in a word are printed, although at least 10 characters of every word is printed, regardless of PRINTWIDTHLIMIT's value.

Example PRINT [1 2 3 4 5 6] 1 2 3 4 5 6

MAKE "PRINTWIDTHLIMIT 4 PRINT [1 2 3 4 5 6] 1 2 3 4 ...

PRINT "1234567890abcdefg 1234567890abcdefg

MAKE "PRINTWIDTHLIMIT 12 PRINT "1234567890abcdefg 1234567890ab...

MAKE "PRINTWIDTHLIMIT 2 PRINT "1234567890abcdefg 1234567890... REDEFP

Synopsis REDEFP

Description If TRUE, allows primitives to be erased (see ERASE) or redefined (see COPYDEF).

Example ERASE "FORWARD FORWARD is a primitive

MAKE "REDEFP "TRUE ERASE "FORWARD

240 Special Variables

FORWARD 100 I don't know how to FORWARD STARTUP

Synopsis STARTUP

Description If assigned a list value in a file that is loaded by LOAD, that value is run as an instruction list after the loading.

Example TO MYPROGRAM PRINT "Hello END

MAKE "STARTUP [MYPROGRAM] SAVE "myprogram.lgo myprog.lgo

ERALL LOAD "myprogram.lgo Hello

241 Chapter 16. Help Commands

HELP ...... 242 WINHELP ...... 242

You can access FMSLogo's manual and system documentation through Logo commands. HELP

Synopsis HELP HELP keyword

Description Opens the FMSLogo manual. HELP has two forms: with and without a keyword input. When no keyword is given, FMSLogo opens the FMSLogo manual to the table of contents. When a keyword is given, FMSLogo searches the FMSLogo manual for the section on keyword. You may enter the full keyword or a partial keyword.

Example Open to the "introduction" section:

HELP "introduction

Open the description of the ERASE command:

HELP "erase WINHELP

Synopsis WINHELP filename (WINHELP filename keyword)

Description WINHELP has two forms: with and without a keyword input. When no keyword is given, FMSLogo opens the Windows help on filename to the table of contents. When a keyword is given, FMSLogo searches the Windows help for the section on keyword within the given help file. You must enter the full keyword.

The WinHelp file format has been deprecated by Microsoft. Therefore, this command is deprecated in FMSLogo.

Example Open the winhelp file for notepad.exe:

WINHELP "c:\\windows\\help\\notepad.hlp

See Also HELP

242 Chapter 17. Environment Commands

LOGOVERSION ...... 243 MACHINE ...... 243 SHELL ...... 245

FMSLogo provides a set of commands that enable you to better interact with the computing environment in which FMSLogo runs. These commands can help you interface with computing elements outside of FMSLogo, such as the underlying operating system or the display. LOGOVERSION

Synopsis LOGOVERSION

Description Outputs a four item list that describes the version of Logo which you are using. The first item is the name of the application (FMSLogo). The second item is the version of FMSLogo. The third item is the operating system on which you are running. The fourth item is an integer that represents the locale for which FMSLogo was built. The meaning of this integer is given in the following table.

Locale Identifier Locale Name 1031 German 1032 Greek 1033 English 1034 Spanish 1036 French 1040 Italian 1045 Polish 1049 Russian 1050 Croatian 2052 Simplified Chinese 2070 Portuguese

LOGOVERSION is provided so that you can write portable Logo programs that run on different versions of Logo. By knowing what version of Logo you are using, your program can take best advantage of what each version offers you.

LOGOVERSION is supported by other Logo environments, including aUCBLogo and Elica.

More items may be added to the list in future releases, so you should use ITEM to get the fourth value, instead of LAST.

Example SHOW LOGOVERSION [FMSLogo 8.1.0 Windows 1033] MACHINE

243 Environment Commands

Synopsis MACHINE

Description Outputs a list that describes the characteristics of the machine. The list has the following format:

[IsWindows Wordsize DrawingSurfaceWidth DrawingSurfaceHeight IsPaletteEnable WindowsVersionMajor WindowsVersionMinor WorkingAreaWidth WorkingAreaHeight DesktopWidth DesktopHeight OuterWindowWidth OuterWindowHeight InnerWindowWidth InnerWindowHeight]

Where the meaning of each member is given by the table below.

Item Name Meaning 1 IsWindows 1, if this is Microsoft Windows. 0, otherwise. 2 Wordsize The number of bits in a machine word. If the version of FMSLogo was compiled for a 32- bit machine, this is 32 even when running on a 64-bit Windows. 3 DrawingSurfaceWidth The width of the drawing surface within the FMSLogo screen window, in pixels. 4 DrawingSurfaceHeight The height of the drawing surface within the FMSLogo screen window, in pixels. 5 IsPaletteEnabled 0, always (FMSLogo does not support displays that use palettes). 6 WindowsVersionMajor The major version of Windows. 7 WindowsVersionMinor The minor version of Windows. 8 WorkingAreaWidth The width of the part of the desktop that is not obscured by the taskbar, in pixels. 9 WorkingAreaHeight The height of the part of the desktop that is not obscured by the taskbar, in pixels. 10 DesktopWidth The width of the whole desktop, in pixels. 11 DesktopHeight The height of the whole desktop, in pixels.

244 Environment Commands

Item Name Meaning 12 OuterWindowWidth The width of the FMSLogo screen window, in pixels. This includes the window frame, the vertical scollbar, etc. 13 OuterWindowHeight The height of the FMSLogo screen window, in pixels. This includes the window frame, the title bar, the menu bar, the horizontal scrollbar, etc. If the commander window is docked, this also includes the thickness of the splitter and the commander. 14 InnerWindowWidth The width of the client area of the FMSLogo screen window, in pixels. This only includes the visible portion of the drawing surface, not the window frame, scrollbar, etc. 15 InnerWindowHeight The height of the client area of the FMSLogo screen window, in pixels. This only includes the visible portion of the drawing surface, not the window frame, scrollbar, etc.

Example SHOW MACHINE [1 32 1000 1000 0 5 1 1280 772 1280 800 1035 594 1027 251] SHELL

Synopsis SHELL command (SHELL command wait)

Description Runs an input string as a shell command. Outputs TRUE if the command was executed, FALSE otherwise. If the command is a literal list in the instruction line, and if you want a backslash character sent to the shell, you must use \\ to get the backslash through Logo's reader intact.

The optional wait input controls whether FMSLogo waits for command to finish running before it runs the next instruction. If present, wait must be

245 Environment Commands

either TRUE or FALSE. When no wait input is given, SHELL does not wait for the command to finish.

If your command contains spaces in the file path to the executable, it's a good idea to put double-quotes around it, or else you may end up running the wrong program. For example, if a file named c:\Program.exe exists, then the following instruction runs c:\Program.exe with the command- line parameter Files\Audacity\audacity.exe:

SHOW SHELL [c:\\Program Files\\Audacity\\audacity.exe]

However, the following instruction always runs audacity.exe, regardless of whether c:\Program.exe exists:

SHOW SHELL [\"c:\\Program Files\\Audacity\\audacity.exe\"]

Example SHOW SHELL [notepad c:\\test.txt] true

SHOW SHELL [unknown-app c:\\test.txt] false

246 Chapter 18. Directory Commands

DIR ...... 247 FILES ...... 247 DIRECTORIES ...... 247 CHDIR ...... 248 POPDIR ...... 248 MKDIR ...... 248 RMDIR ...... 248 DIR

Synopsis DIR

Description Prints out files and directories in the current directory. It prints out the FILES list and DIRECTORIES list.

Example DIR File fmslogo.exe File LICENSE.TXT File logohelp.chm File README.TXT File startup.logoscript File turtle.bmp File uninstall.exe Directory . Directory .. Directory Examples Directory logolib FILES

Synopsis FILES

Description Outputs a list of the names of each file in the current working directory. The file names are sorted alphabetically.

Example SHOW FILES [fmslogo.exe LICENSE.TXT logohelp.chm README.TXT startup.logoscript turtle.bmp uninstall.exe]

See Also DIRECTORIES DIRECTORIES

Synopsis DIRECTORIES

Description Outputs a list of the names of each directory in the current working directory.

The directory names are sorted alphabetically, except that the special entries "." and ".." always appear first, if present.

Example SHOW DIRECTORIES [. .. Examples logolib]

247 Directory Commands

See Also FILES CHDIR

Synopsis CHDIR directoryname

Description Changes the current working directory to directoryname, just like the DOS command CHDIR (cd). The directoryname input must be a word. You can use DIR to list both files and directories.

Example CHDIR "Examples Changed to "C:\Program Files\FMSLogo\Examples"

POPDIR Changed to "C:\Program Files\FMSLogo"

See Also POPDIR MKDIR POPDIR

Synopsis POPDIR

Description Pops you up (1 level) out of a directory. It is equivalent to:

CHDIR "..

Example CHDIR "Examples Changed to "C:\Program Files\FMSLogo\Examples"

POPDIR Changed to "C:\Program Files\FMSLogo"

See Also CHDIR MKDIR MKDIR

Synopsis MKDIR directoryname

Description Makes (creates) a directory and then changes (CHDIR) into it. The directoryname input must be a word (the name of the directory you want to make). You can use the DIR command to list the files and directories in the current directory. You can go back into the parent directory with POPDIR.

Example MKDIR "junk Now in newly created directory "junk"

POPDIR Changed to "C:\Program Files\FMSLogo" RMDIR

248 Directory Commands

Synopsis RMDIR directoryname

Description Removes (deletes) a directory named directoryname. The directoryname input must be a word (a name of an existing directory). You cannot remove a directory if it is your working directory. You cannot remove a directory that contains files or other directories (both FILES and DIRECTORIES must output the empty list when it is your working directory).

Example MKDIR "junk Now in newly created directory "junk"

POPDIR Changed to "C:\Program Files\FMSLogo"

RMDIR "junk Removed directory "junk"

See Also MKDIR

249 Chapter 19. Windows Commands

Window Commands ...... 251 WINDOWCREATE ...... 251 WINDOWDELETE ...... 252 WINDOWENABLE ...... 252 Dialog Commands ...... 253 DIALOGCREATE ...... 253 DIALOGDELETE ...... 253 DIALOGENABLE ...... 254 Listbox Commands ...... 254 LISTBOXCREATE ...... 254 LISTBOXDELETE ...... 255 LISTBOXENABLE ...... 255 LISTBOXGETSELECT ...... 256 LISTBOXADDSTRING ...... 256 LISTBOXDELETESTRING ...... 257 Combobox Commands ...... 257 COMBOBOXCREATE ...... 257 COMBOBOXDELETE ...... 258 COMBOBOXENABLE ...... 258 COMBOBOXGETTEXT ...... 259 COMBOBOXSETTEXT ...... 259 COMBOBOXADDSTRING ...... 259 COMBOBOXDELETESTRING ...... 260 Scrollbar Commands ...... 260 SCROLLBARCREATE ...... 261 SCROLLBARDELETE ...... 262 SCROLLBARENABLE ...... 262 SCROLLBARSET ...... 263 SCROLLBARGET ...... 263 Button Commands ...... 264 BUTTONCREATE ...... 264 BUTTONDELETE ...... 265 BUTTONENABLE ...... 265 BUTTONUPDATE ...... 265 Static Commands ...... 266 STATICCREATE ...... 266 STATICDELETE ...... 267 STATICUPDATE ...... 267 Group Box Commands ...... 267 GROUPBOXCREATE ...... 267 GROUPBOXDELETE ...... 268 Checkbox Commands ...... 268 CHECKBOXCREATE ...... 269 CHECKBOXDELETE ...... 270 CHECKBOXENABLE ...... 270 CHECKBOXSET ...... 270 CHECKBOXGET ...... 271 Radio Button Commands ...... 271 RADIOBUTTONCREATE ...... 271 RADIOBUTTONDELETE ...... 273 RADIOBUTTONENABLE ...... 273

250 Windows Commands

RADIOBUTTONSET ...... 273 RADIOBUTTONGET ...... 274 Debug Commands ...... 274 DEBUGWINDOWS ...... 274 Modal vs. Modeless Windows ...... 275 MESSAGEBOX ...... 275 YESNOBOX ...... 275 SELECTBOX ...... 276 QUESTIONBOX ...... 276 DIALOGFILEOPEN ...... 277 DIALOGFILESAVE ...... 277 WINDOWFILEEDIT ...... 278 Example Code for Constructing a Window ...... 278

This chapter describes how to create Graphical User Interfaces (GUIs) in FMSLogo.

The term "window" is very broad and includes simple windows, push buttons, dialog boxes, list boxes, combo boxes, scroll bars, buttons, static text, group boxes, checkboxes, and radio buttons. Using these elementary units, you can build up complex GUIs. Each window maintains a parent-child relationship with the windows that are placed on it. The way you program GUIs is modeled after how they are displayed, you create each individual sub-window and set up the parent-child relationships.

Each time a window is created, you must specify the parent that "owns" the window. You must also specify a "name" so that the new window may be referenced by other instructions. Most other commands use this name to identify the Window or control you wish to communicate with. When a parent window is deleted, its "child" Windows and controls are also deleted.

When controls are in windows, the coordinates used by all the Windows procedures are in Windows coordinate system (not the turtle coordinate system). That is the Y axis is upside down (positive numbers are down). Likewise, the origin is not the middle of the screen, it is the upper left hand corner of the window. Furthermore, the position and size are given in "dialog units", which are proportional to the size of the font that is being used. This ensures that the dialog boxes have a consistent layout, regardless of the font size.

When controls are on the FMSLogo screen window the coordinates are in the turtle coordinate system. Window Commands

WINDOWCREATE ...... 251 WINDOWDELETE ...... 252 WINDOWENABLE ...... 252

Windows are one of two types of basic "canvas" types. A window has a title bar, a frame, and a grey client area upon which other window controls can be placed. Unlike dialogs, windows are modeless, which means that FMSLogo continues to run instructions while the window is displayed. WINDOWCREATE

Synopsis WINDOWCREATE parent name title xpos ypos width height setup

Description Creates a window. A window is used as the framework to which you add other window objects or controls (sometimes called widgets). You can add things such as buttons, scrollbars, listboxes, etc. to the window. The window

251 Windows Commands

is modeless, which means that WINDOWCREATE stops before the window is destroyed. See Modal vs. Modeless for more details.

The parent input is the name of the window that owns the new window. If this is the first window you are creating, use "main as the parent input.

The name input identifies the new window (perhaps as the parent of another future window or control) and must be a unique word.

The title input specifies the title, or caption, of the new window.

The xpos input is the X coordinate where the upper-left corner of the new window is placed.

The ypos input is the Y coordinate where the upper-left corner of the new window is placed.

The width input is the width of the new window, in dialog units.

The height input is the height of the new window, in dialog units.

The setup input is an instruction list to run when the window is created. The most common use of the setup input is create and add child controls to the window. You may give the empty list for this input and add controls later.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] BUTTONCREATE "mywindow "mybutton "PUSH 25 25 25 25 [PRINT "pushed] WINDOWDELETE "mywindow WINDOWDELETE

Synopsis WINDOWDELETE name

Description Deletes (closes) the window whose name is name . All child window and controls are also deleted. If no window with the given name exists, then all windows and all controls which were created by FMSLogo are deleted.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] BUTTONCREATE "mywindow "mybutton "PUSH 25 25 25 25 [PRINT "pushed] WINDOWDELETE "mywindow WINDOWENABLE

Synopsis WINDOWENABLE name state

Description Enables or disables the window identified by name. If state equals TRUE, then the window is enabled. If state equals FALSE, then the window is disabled.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] BUTTONCREATE "mywindow "mybutton "PUSH 25 25 25 25 [print "pushed] WINDOWENABLE "mywindow "False The window is now disabled WINDOWENABLE "mywindow "True The window is now enabled WINDOWDELETE "mywindow

252 Windows Commands

Dialog Commands

DIALOGCREATE ...... 253 DIALOGDELETE ...... 253 DIALOGENABLE ...... 254

Dialogs are one of two types of basic "canvas" types. A dialog has a title bar, a frame, and a grey client area upon which other window controls can be placed. Unlike windows, dialogs are modal, which means that FMSLogo does not run any instructions until the dialog is closed. Because of this, dialogs are used to present the user with a question that must be answered before the program can continue. DIALOGCREATE

Synopsis DIALOGCREATE parent name title xpos ypos width height setup

Description Creates a window that is suitable for use as a dialog box. A dialog window is used as the framework to which you add other window objects or controls (sometimes called widgets). You can add things such as buttons, scrollbars, listboxes, etc. to the dialog. This command is similar to WINDOWCREATE except that it does not stop until the dialog is closed (see Modal vs. Modeless).

The parent input is the name of the window that owns the new dialog. If this is the first window you are creating, use "main as the parent input.

The name input identifies the new dialog (perhaps as the parent of another future window or control) and must be a unique word.

The title input specifies the title, or caption, of the new dialog.

The xpos input is the X coordinate where the upper-left corner of the new dialog is placed.

The ypos input is the Y coordinate where the upper-left corner of the new dialog is placed.

The width input is the width of the new dialog, in dialog units.

The height input is the height of the new dialog, in dialog units.

The setup input is an instruction list to run when the dialog is created. You should create and add child controls in the setup instruction list because DIALOGCREATE does not stop until the dialog is closed. Be sure to add at least one button that calls DIALOGDELETE on this window, such as OK, End, Close, or Cancel.

Example TO MYSETUP BUTTONCREATE "mydialog "myok "OK 25 25 50 25 [DIALOGDELETE "mydialog] END

DIALOGCREATE "main "mydialog "mytitle 0 0 100 75 [MYSETUP] DIALOGDELETE

Synopsis DIALOGDELETE name

253 Windows Commands

Description Deletes (closes) the dialog whose name is name. All child window and controls are also deleted.

Example TO MYSETUP BUTTONCREATE "mydialog "myok "OK 25 25 50 50 [DIALOGDELETE "mydialog] END

DIALOGCREATE "main "mydialog "mytitle 0 0 100 100 [MYSETUP] DIALOGENABLE

Synopsis DIALOGENABLE name state

Description Enables or disables the dialog identified by name. If state equals TRUE, then the window is enabled. If state equals FALSE, then the window is disabled.

Be careful when using DIALOGENABLE to disable a dialog. Because DIALOGCREATE doesn't stop until the dialog closes, if you disable the dialog box, the user may not be able to close the dialog, which means FMSLogo may get stuck waiting forever.

Example TO MYSETUP BUTTONCREATE "mydialog "mydisable "Disable 25 25 50 20 [DIALOGENABLE "mydialog "false] BUTTONCREATE "mydialog "myok "OK 25 50 50 20 [DIALOGDELETE "mydialog] END

DIALOGCREATE "main "mydialog "mytitle 0 0 100 100 [MYSETUP] Clicking the "Disable" button causes FMSLogo to lock up Listbox Commands

LISTBOXCREATE ...... 254 LISTBOXDELETE ...... 255 LISTBOXENABLE ...... 255 LISTBOXGETSELECT ...... 256 LISTBOXADDSTRING ...... 256 LISTBOXDELETESTRING ...... 257

Listboxes are a type of control that presents the user with a predetermined choice of items. The items are represented as text and displayed vertically, one per line. LISTBOXCREATE

Synopsis LISTBOXCREATE parent name xpos ypos width height

Description Creates a listbox control. A listbox control shows the user a set of items and lets them select one of them.

The parent input is the name of the window that owns the new listbox. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

The name input identifies the new listbox and must be a unique word.

254 Windows Commands

The xpos input is the X coordinate where the upper-left corner of the new listbox is placed.

The ypos input is the Y coordinate where the upper-left corner of the new listbox is placed.

The width input is the width of the new listbox.

The height input is the height of the new listbox.

If the parent of the listbox is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

Example Create a listbox in a new window:

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] LISTBOXCREATE "mywindow "mylist 25 25 50 50

; Delete the parent window and its listbox control. WINDOWDELETE "mywindow

Create a listbox on the FMSLogo screen window:

LISTBOXCREATE "main "mylist 25 25 100 100

; Delete all windows. WINDOWDELETE "main LISTBOXDELETE

Synopsis LISTBOXDELETE name

Description Deletes (closes) the listbox whose name is name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] LISTBOXCREATE "mywindow "mylist 25 25 50 50 LISTBOXADDSTRING "mylist [Triangle] LISTBOXADDSTRING "mylist [Square] LISTBOXDELETE "mylist WINDOWDELETE "mywindow LISTBOXENABLE

Synopsis LISTBOXENABLE name state

Description Enables or disables the listbox identified by name. If state equals TRUE, then the listbox is enabled. If state equals FALSE, then the listbox is disabled.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] LISTBOXCREATE "mywindow "mylist 25 25 50 50 LISTBOXADDSTRING "mylist [Triangle]

255 Windows Commands

LISTBOXADDSTRING "mylist [Square] LISTBOXENABLE "mylist "FALSE

The listbox is now disabled

LISTBOXENABLE "mylist "TRUE LISTBOXDELETE "mylist WINDOWDELETE "mywindow LISTBOXGETSELECT

Synopsis LISTBOXGETSELECT name

Description Outputs the selected item within the listbox that is identified by name. The output is a list, as if the text of the currently selected row were parsed by PARSE. If nothing is selected, then LISTBOXGETSELECT outputs the empty list.

Example TO DODRAW CLEARSCREEN IF EQUALP [Triangle] LISTBOXGETSELECT "mylist [REPEAT 3 [FORWARD 100 RIGHT 120]] IF EQUALP [Square] LISTBOXGETSELECT "mylist [REPEAT 4 [FORWARD 100 RIGHT 90]] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] LISTBOXCREATE "mywindow "mylist 25 0 50 50 LISTBOXADDSTRING "mylist [Triangle] LISTBOXADDSTRING "mylist [Square] BUTTONCREATE "mywindow "mydraw "Draw 25 50 50 25 [DODRAW]

Select an item from the listbox and then click the Draw button.

WINDOWDELETE "mywindow LISTBOXADDSTRING

Synopsis LISTBOXADDSTRING name item

Description Adds item to the listbox that is identified by name.

Example TO DODRAW CLEARSCREEN IF EQUALP [Triangle] LISTBOXGETSELECT "mylist [REPEAT 3 [FORWARD 100 RIGHT 120]] IF EQUALP [Square] LISTBOXGETSELECT "mylist [REPEAT 4 [FORWARD 100 RIGHT 90]] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] LISTBOXCREATE "mywindow "mylist 25 0 50 50 LISTBOXADDSTRING "mylist [Triangle] LISTBOXADDSTRING "mylist [Square] BUTTONCREATE "mywindow "mydraw "Draw 25 50 50 25 [DODRAW]

Select an item from the listbox and then click the Draw button.

256 Windows Commands

WINDOWDELETE "mywindow LISTBOXDELETESTRING

Synopsis LISTBOXDELETESTRING name index

Description Deletes the item at index from the listbox that is identified by name.

Listbox items are zero-indexed, which means that the first item in the listbox is at index 0, the second is at index 1, etc.

If there are index items or fewer in the listbox, then the instruction does nothing. This is not considered an error.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] LISTBOXCREATE "mywindow "mylist 25 0 50 50 LISTBOXADDSTRING "mylist [Triangle] LISTBOXADDSTRING "mylist [Square] LISTBOXADDSTRING "mylist [Hexagon] LISTBOXDELETESTRING "mylist 1 WINDOWDELETE "mywindow Combobox Commands

COMBOBOXCREATE ...... 257 COMBOBOXDELETE ...... 258 COMBOBOXENABLE ...... 258 COMBOBOXGETTEXT ...... 259 COMBOBOXSETTEXT ...... 259 COMBOBOXADDSTRING ...... 259 COMBOBOXDELETESTRING ...... 260

Comboboxes are a type of control that presents the user with a predetermined choice of items as well as a free-form text input. The items are represented as text and displayed vertically, one per line.

Comboboxes get their name by being a combination of a listbox control and an edit control.

Comboboxes can also be used to create a pure edit control by setting the height such that the listbox is hidden. COMBOBOXCREATE

Synopsis COMBOBOXCREATE parent name xpos ypos width height

Description Creates a combobox control. A combobox control gives the user a selection of items and allows them to enter a selection not listed. A combobox is two controls in one: a listbox control and an edit control.

If you wish to create an edit control (a combobox without a listbox) set the height to a size in which the listbox doesn't fit.

The parent input is the name of the window that owns the new combobox. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

257 Windows Commands

The name input identifies the new combobox and must be a unique word.

The xpos input is the X coordinate where the upper-left corner of the new combobox is placed.

The ypos input is the Y coordinate where the upper-left corner of the new combobox is placed.

The width input is the width of the new combobox.

The height input is the height of the new combobox.

If the parent of the combobox is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

Example Create a combobox in a new window:

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] COMBOBOXCREATE "mywindow "mycombo 25 25 50 50

; Delete the window and its combobox. WINDOWDELETE "mywindow

Create a combobox on the FMSLogo screen window:

COMBOBOXCREATE "main "mycombo 25 25 100 100

; Delete all windows. WINDOWDELETE "main COMBOBOXDELETE

Synopsis COMBOBOXDELETE name

Description Deletes (closes) the combobox that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] COMBOBOXCREATE "mywindow "mycombo 25 25 50 50 COMBOBOXDELETE "mycombo WINDOWDELETE "mywindow COMBOBOXENABLE

Synopsis COMBOBOXENABLE name state

Description Enables or disables the combobox identified by name. If state equals TRUE, then the combobox is enabled. If state equals FALSE, then the combobox is disabled.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] COMBOBOXCREATE "mywindow "mycombo 25 0 50 50 COMBOBOXADDSTRING "mycombo [3]

258 Windows Commands

COMBOBOXADDSTRING "mycombo [4] COMBOBOXADDSTRING "mycombo [5] COMBOBOXADDSTRING "mycombo [6] COMBOBOXSETTEXT "mycombo [3] COMBOBOXENABLE "mycombo "False

The combobox is now disabled

COMBOBOXENABLE "mycombo "True WINDOWDELETE "mywindow COMBOBOXGETTEXT

Synopsis COMBOBOXGETTEXT name

Description Outputs the text within the edit control portion of the combobox that is identified by name. This may be a selected item within the listbox portion, or it may be something the user typed into the edit portion. The output is a list, as if parsed by PARSE.

Example TO DODRAW CLEARSCREEN MAKE "sides FIRST COMBOBOXGETTEXT "mycombo REPEAT :sides [FORWARD 50 RIGHT 360/:sides] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] COMBOBOXCREATE "mywindow "mycombo 25 0 50 50 COMBOBOXADDSTRING "mycombo [3] COMBOBOXADDSTRING "mycombo [4] COMBOBOXADDSTRING "mycombo [5] COMBOBOXADDSTRING "mycombo [6] BUTTONCREATE "mywindow "mydraw "Draw 25 50 50 25 [DODRAW] Select or enter number of sides from combobox and then click the Draw button WINDOWDELETE "mywindow COMBOBOXSETTEXT

Synopsis COMBOBOXSETTEXT name text

Description Sets the contents of the edit control portion of the combobox that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] COMBOBOXCREATE "mywindow "mycombo 25 0 50 50 COMBOBOXADDSTRING "mycombo [3] COMBOBOXADDSTRING "mycombo [4] COMBOBOXADDSTRING "mycombo [5] COMBOBOXADDSTRING "mycombo [6] COMBOBOXSETTEXT "mycombo [3] WINDOWDELETE "mywindow COMBOBOXADDSTRING

259 Windows Commands

Synopsis COMBOBOXADDSTRING name item

Description Appends item to the listbox portion of the combobox that is identified by name.

Example TO DODRAW CLEARSCREEN MAKE "sides FIRST COMBOBOXGETTEXT "mycombo REPEAT :sides [FORWARD 50 RIGHT 360/:sides] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] COMBOBOXCREATE "mywindow "mycombo 25 0 50 50 COMBOBOXADDSTRING "mycombo [3] COMBOBOXADDSTRING "mycombo [4] COMBOBOXADDSTRING "mycombo [5] COMBOBOXADDSTRING "mycombo [6] BUTTONCREATE "mywindow "mydraw "Draw 25 50 50 25 [DODRAW] Select or enter number of sides from combobox and then click the Draw button WINDOWDELETE "mywindow COMBOBOXDELETESTRING

Synopsis COMBOBOXDELETESTRING name index

Description Deletes the item at index from the listbox portion of a combobox that is identified by name.

Combobox items are zero-indexed, which means that the first item in the combobox is at index 0, the second is at index 1, etc.

If there are index items or fewer in the combobox, then the instruction does nothing. This is not considered an error.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] COMBOBOXCREATE "mywindow "mycombo 25 0 50 50 COMBOBOXADDSTRING "mycombo [3] COMBOBOXADDSTRING "mycombo [4] COMBOBOXADDSTRING "mycombo [5] COMBOBOXADDSTRING "mycombo [6] COMBOBOXDELETESTRING "mycombo 1 WINDOWDELETE "mywindow Scrollbar Commands

SCROLLBARCREATE ...... 261 SCROLLBARDELETE ...... 262 SCROLLBARENABLE ...... 262 SCROLLBARSET ...... 263 SCROLLBARGET ...... 263

Scrollbars let the user select a value by sliding a "scoller" along a bar that represents a range of possible values. For example, if you wanted the user to enter a number from 1 to 100, you could use a scrollbar.

260 Windows Commands

In many GUI frameworks, scrollbars are used to fit a large window into a small space by displaying only a small portion of the window and allowing the user to scroll which portion is visible. However, that is NOT the kind of scrollbar that FMSLogo lets you create; the scrollbars that you create with FMSLogo are often associated with a "slider" control. SCROLLBARCREATE

Synopsis SCROLLBARCREATE parent name xpos ypos width height callback

Description Creates a scrollbar control. Scrollbar controls let the user select a value by sliding a "scroller" along a bar that represents a range of possible values. The position of the scrollbar is often linked to a static control that displays the scrollbar's current position, but this is not required.

When a scrollbar is first created, it has a range from 0 to 100 and an initial position of 0. You can change the range and position with SCROLLBARSET.

The orientation (vertical or horizontal) of the scrollbar is determined by the longest dimension. That is, if width > height, then the scrollbar is horizontal. Otherwise, the scrollbar is vertical.

The parent input is the name of the window that owns the new scrollbar. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

The name input identifies the new scrollbar and must be a unique word.

The xpos input is the X coordinate where the upper-left corner of the new scrollbar is placed.

The ypos input is the Y coordinate where the upper-left corner of the new scrollbar is placed.

The width input is the width of the new scrollbar. If the height input is greater than or equal to the width input, then the scrollbar is vertical and the system's default scrollbar width is used instead of the width input.

The height input is the height of the new scrollbar. If the height input is less than the width input, then the scrollbar is horizonal and the system's default scrollbar height is used instead of the height input.

The callback input is an instruction list that is run whenever the position of the scrollbar changes. One common use for the callback input is to inform the user of what value has been selected.

If the parent of the scrollbar is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

Example Create a scrollbar in a new window:

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] SCROLLBARCREATE "mywindow "myscroll 25 25 50 0 [SETHEADING SCROLLBARGET "myscroll] SCROLLBARSET "myscroll 0 360 0 Move the scrollbar and observe what happens to the turtle.

261 Windows Commands

WINDOWDELETE "mywindow

Create a scrollbar on FMSLogo screen window:

SCROLLBARCREATE "main "myscroll 25 25 100 0 [SETHEADING SCROLLBARGET "myscroll] SCROLLBARSET "myscroll 0 360 0 Move the scrollbar and observe what happens to the turtle. SCROLLBARDELETE "myscroll SCROLLBARDELETE

Synopsis SCROLLBARDELETE name

Description Deletes (closes) the scrollbar that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] SCROLLBARCREATE "mywindow "myscroll 25 25 50 0 [] SCROLLBARDELETE "myscroll WINDOWDELETE "mywindow SCROLLBARENABLE

Synopsis SCROLLBARENABLE name state

Description Enables or disables the scrollbar identified by name. If state equals TRUE, then the scrollbar is enabled. If state equals FALSE, then the scrollbar is disabled.

When a scrollbar is disabled, the position of the scrollbar is hidden. If you want the user to be able to see the position of a scrollbar, but not be able to change it, then use an enabled scrollbar and make the scrollbar's callback reset the position back to the correct value. This pattern is shown in the second example, below.

Example Disabling a scrollbar:

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] SCROLLBARCREATE "mywindow "myscroll 25 25 50 0 [] SCROLLBARENABLE "myscroll "False

The scrollbar is now disabled.

SCROLLBARENABLE "myscroll "True WINDOWDELETE "mywindow

Creating a read-only scrollbar:

TO SCROLLBARCALLBACK ; Whenever the user changes the scrollbar's position, ; change it back to the correct value, which is held ; in :ScrollbarValue. ; ; In order to avoid an infinite loop, only change the ; value if it's different from what we would set it to.

262 Windows Commands

IF NOT EQUALP :ScrollbarValue SCROLLBARGET "myscroll [ SCROLLBARSET "myscroll 0 360 :ScrollbarValue ] END

TO SCROLLBARUPDATE :NewValue ; Call this whenever you want to update the value. MAKE "ScrollbarValue :NewValue SCROLLBARCALLBACK END

; Create a window with a read-only scrollbar. WINDOWCREATE "main "mywindow [Read Only Scrollbar Example] 0 0 100 30 [] SCROLLBARCREATE "mywindow "myscroll 5 5 90 0 [ SCROLLBARCALLBACK ]

; Set initial value. SCROLLBARUPDATE 50

Try to change the scrollbar's position with the mouse. It snaps back to the value which is set by SCROLLBARUPDATE in SCROLLBARCALLBACK.

; Programmatically change the value. SCROLLBARUPDATE 100

; Delete the window when you're done. WINDOWDELETE "mywindow

SCROLLBARSET

Synopsis SCROLLBARSET name min max position

Description Set the range and current position of the scrollbar control that is identified by name. You can invoke SCROLLBARSET multiple times on the same scrollbar.

The min input is the minimum value representable by the scrollbar. This must be an integer.

The max input is the maximum value representable by the scrollbar. This must be an integer that is greater than or equal to min.

The position input is the current value of the scrollbar. This must be an integer. If position is not between min and max, then the scrollbar's position is set to either min or max, whichever is closer.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] SCROLLBARCREATE "mywindow "myscroll 25 25 50 0 [SETHEADING SCROLLBARGET "myscroll] SCROLLBARSET "myscroll 0 360 0 Move the scrollbar and observe what happens to the turtle. WINDOWDELETE "mywindow SCROLLBARGET

263 Windows Commands

Synopsis SCROLLBARGET name

Description Output the current position of the scrollbar control that is identified by name. The output is within the range specified by SCROLLBARSET.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] SCROLLBARCREATE "mywindow "myscroll 25 25 50 0 [SETHEADING SCROLLBARGET "myscroll] SCROLLBARSET "myscroll 0 360 0 Move the scrollbar and observe what happens to the turtle. WINDOWDELETE "mywindow Button Commands

BUTTONCREATE ...... 264 BUTTONDELETE ...... 265 BUTTONENABLE ...... 265 BUTTONUPDATE ...... 265

Buttons let the user choose when an event happens. The only function of a button is to run an instruction list when it is pressed. BUTTONCREATE

Synopsis BUTTONCREATE parent name label xpos ypos width height callback

Description Creates a button control. A button control lets the user trigger events. The only function of the button control is to run the callback instruction list when it is pressed.

The parent input is the name of the window that owns the new button. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

The name input identifies the new button and must be a unique word.

The label input is a word to write on the button.

The xpos input is the X coordinate where the upper-left corner of the new button is placed.

The ypos input is the Y coordinate where the upper-left corner of the new button is placed.

The width input is the width of the new button.

The height input is the height of the new button.

The callback input is an instruction list that is run whenever the user clicks on the button.

If the parent of the button is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

264 Windows Commands

Example Create buttons in a new window:

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] BUTTONCREATE "mywindow "myleft "Left 25 25 25 25 [FORWARD 2 LEFT 1] BUTTONCREATE "mywindow "myright "Right 50 25 25 25 [FORWARD 2 RIGHT 1] Click left or right repeatedly and watch the turtle. WINDOWDELETE "mywindow

Create buttons on the FMSLogo screen window:

BUTTONCREATE "main "myleft "Left 50 50 50 25 [FORWARD 2 LEFT 1] BUTTONCREATE "main "myright "Right 100 50 50 25 [FORWARD 2 RIGHT 1] Click left or right repeatedly and watch the turtle. WINDOWDELETE "main

See Also BUTTONUPDATE BUTTONENABLE BUTTONDELETE BUTTONDELETE

Synopsis BUTTONDELETE name

Description Deletes (closes) the button that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] BUTTONCREATE "mywindow "mybutton "PUSH 25 25 25 25 [PRINT "pushed] BUTTONDELETE "mybutton WINDOWDELETE "mywindow BUTTONENABLE

Synopsis BUTTONENABLE name state

Description Enables or disables the button identified by name. If state equals TRUE, then the button is enabled. If state equals FALSE, then the button is disabled.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] BUTTONCREATE "mywindow "mybutton "PUSH 25 25 25 25 [PRINT "pushed] BUTTONENABLE "mybutton "False

The button is now disabled

BUTTONENABLE "mybutton "True WINDOWDELETE "mywindow BUTTONUPDATE

Synopsis BUTTONUPDATE name text

Description Replaces the text on the button identified by name with text.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] MAKE "Pushed 0

265 Windows Commands

BUTTONCREATE "mywindow "mybutton :Pushed 25 25 25 25 [MAKE "Pushed :Pushed + 1 BUTTONUPDATE "mybutton :Pushed] Push the button a few times. BUTTONDELETE "mybutton WINDOWDELETE "mywindow Static Commands

STATICCREATE ...... 266 STATICDELETE ...... 267 STATICUPDATE ...... 267

Static controls are simply a way of displaying text. Static controls are called "static" because the user can't interact with them. However, you can update the text, so the term "static" is somewhat misleading. STATICCREATE

Synopsis STATICCREATE parent name text xpos ypos width height

Description Creates a static text control. A static control is used to simply display text. The term "static control" is somewhat misleading because the text displayed by a static control can be dynamically updated by STATICUPDATE.

The parent input is the name of the window that owns the new static control. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

The name input identifies the new static control and must be a unique word.

The text input is a word that is written on the static control. If there is more text than can fit within the width of the static control on a single line, then the text is word-wrapped.

The xpos input is the X coordinate where the upper-left corner of the new static control is placed.

The ypos input is the Y coordinate where the upper-left corner of the new static control is placed.

The width input is the width of the new static control.

The height input is the height of the new static control.

If the parent of the static control is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

Example Creating a static control on a new window:

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] STATICCREATE "mywindow "mystatic [Heading=0] 25 25 50 25 REPEAT 72 [RIGHT 5 STATICUPDATE "mystatic SENTENCE [Heading=] HEADING WAIT 60]

Watch the text change as the turtle rotates.

266 Windows Commands

WINDOWDELETE "mywindow

Creating a static control on the FMSLogo screen window:

STATICCREATE "main "mystatic [Heading=0] 25 25 100 50 REPEAT 72 [RIGHT 5 STATICUPDATE "mystatic SENTENCE [Heading=] HEADING WAIT 60]

Watch the text change as the turtle rotates.

WINDOWDELETE "main STATICDELETE

Synopsis STATICDELETE name

Description Deletes (closes) the static control that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] STATICCREATE "mywindow "mystatic [This is Static] 25 25 50 25 STATICDELETE "mystatic WINDOWDELETE "mywindow STATICUPDATE

Synopsis STATICUPDATE name text

Description Replaces the text of the static control identified by name with text. If there is more text than can fit within the width of the static control on a single line, then the text is word-wrapped.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] STATICCREATE "mywindow "mystatic [Heading=0] 25 25 50 25 REPEAT 72 [RIGHT 5 STATICUPDATE "mystatic SENTENCE [Heading=] HEADING WAIT 60] WINDOWDELETE "mywindow Group Box Commands

GROUPBOXCREATE ...... 267 GROUPBOXDELETE ...... 268

A group box control is used to group radio button controls and checkbox controls both graphically and logically. Radio buttons and checkboxes must belong to a group box. Note that radio buttons and checkboxes which are placed in a group box still use the parent's origin NOT the group box's origin. GROUPBOXCREATE

Synopsis GROUPBOXCREATE parent name xpos ypos width height

Description Create a group box control. A group box control is a unique control compared with the other controls because all it does is group radio buttons (see RADIOBUTTONCREATE) and checkboxes (see CHECKBOXCREATE ) both graphically and logically. Radio buttons and checkboxes must belong to a group box control.

267 Windows Commands

The parent input is the name of the window that owns the new group box control. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

The name input identifies the new group box control and must be a unique word.

The xpos input is the X coordinate where the upper-left corner of the new group box control is placed.

The ypos input is the Y coordinate where the upper-left corner of the new group box control is placed.

The width input is the width of the new group box control.

The height input is the height of the new group box control.

If the parent of the group box is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

Example TO CHECKONTHINGS IFELSE CHECKBOXGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 40 CHECKBOXCREATE "mywindow "mygroupbox "myhideturtle [Hide Turtle] 20 20 60 20 BUTTONCREATE "mywindow "mybutton "Go 40 50 25 25 [CHECKONTHINGS]

Clicking on the Go button shows or hides the turtle, depending on whether the checkbox is checked.

; Delete the window and all of its child controls. WINDOWDELETE "mywindow GROUPBOXDELETE

Synopsis GROUPBOXDELETE name

Description Deletes (closes) the group box control that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 40 GROUPBOXDELETE "mygroupbox WINDOWDELETE "mywindow Checkbox Commands

CHECKBOXCREATE ...... 269 CHECKBOXDELETE ...... 270 CHECKBOXENABLE ...... 270 CHECKBOXSET ...... 270

268 Windows Commands

CHECKBOXGET ...... 271

Checkbox controls are used to ask the user yes/no questions. A checkbox control has two components: a checkbox and a text label that indicates what putting a check in the checkbox means.

For multiple choice questions, use radio button control. CHECKBOXCREATE

Synopsis CHECKBOXCREATE parent group name label xpos ypos width height

Description Creates a checkbox control. A checkbox control is used to give the user a selection between True and False. A checkbox must be associated with a groupbox control (see GROUPBOXCREATE).

The parent input is the name of the window that owns the new checkbox. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

The group input is the name of the group box control to associate with the new checkbox control.

The name input identifies the new checkbox and must be a unique word.

The label input is a word to write next to the checkbox.

The xpos input is the X coordinate where the upper-left corner of the new checkbox is placed.

The ypos input is the Y coordinate where the upper-left corner of the new checkbox is placed.

The width input is the width of the new checkbox.

The height input is the height of the new checkbox.

If the parent of the checkbox is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

Example Create a checkbox in a new window:

TO CHECKONTHINGS IFELSE CHECKBOXGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 40 CHECKBOXCREATE "mywindow "mygroupbox "myhideturtle [Hide Turtle] 20 20 60 20 BUTTONCREATE "mywindow "mybutton "Go 40 50 25 25 [CHECKONTHINGS]

Clicking on the Go button shows or hides the turtle, depending on whether the checkbox is checked.

WINDOWDELETE "mywindow

269 Windows Commands

Create a checkbox on the FMSLogo screen window:

TO CHECKONTHINGS IFELSE CHECKBOXGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

GROUPBOXCREATE "main "mygroupbox 110 90 140 60 CHECKBOXCREATE "main "mygroupbox "myhideturtle [Hide Turtle] 120 80 120 40 BUTTONCREATE "main "mybutton "Go 160 20 50 50 [CHECKONTHINGS]

Clicking on the Go button shows or hides the turtle, depending on whether the checkbox is checked.

WINDOWDELETE "main CHECKBOXDELETE

Synopsis CHECKBOXDELETE name

Description Deletes (closes) the checkbox that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 40 CHECKBOXCREATE "mywindow "mygroupbox "mycheckbox [Check Me] 20 20 60 20 CHECKBOXDELETE "mycheckbox WINDOWDELETE "mywindow CHECKBOXENABLE

Synopsis CHECKBOXENABLE name state

Description Enables or disables the checkbox identified by name. If state equals TRUE, then the checkbox is enabled. If state equals FALSE, then the checkbox is disabled.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 40 CHECKBOXCREATE "mywindow "mygroupbox "mycheckbox [Check Me] 20 20 60 20 CHECKBOXENABLE "mycheckbox "False

The checkbox is now disabled

CHECKBOXENABLE "mycheckbox "True WINDOWDELETE "mywindow CHECKBOXSET

Synopsis CHECKBOXSET name state

Description Sets the state of the checkbox that is identified by name to state. state must be either True (checked) or False (unchecked).

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 40

270 Windows Commands

CHECKBOXCREATE "mywindow "mygroupbox "mycheckbox [Check Me] 20 20 60 20 CHECKBOXSET "mycheckbox "true CHECKBOXSET "mycheckbox "false WINDOWDELETE "mywindow CHECKBOXGET

Synopsis CHECKBOXGET name

Description Outputs the state (True or False) of the checkbox that is identified by name.

Example TO CHECKONTHINGS IFELSE CHECKBOXGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 40 CHECKBOXCREATE "mywindow "mygroupbox "myhideturtle [Hide Turtle] 20 20 60 20 BUTTONCREATE "mywindow "mybutton "Go 40 50 25 25 [CHECKONTHINGS] WINDOWDELETE "mywindow Radio Button Commands

RADIOBUTTONCREATE ...... 271 RADIOBUTTONDELETE ...... 273 RADIOBUTTONENABLE ...... 273 RADIOBUTTONSET ...... 273 RADIOBUTTONGET ...... 274

Radio buttons controls are used to ask the user a multiple choice question. Each radio button two components: a round button and a text label that indicates what pressing the button means.

Radio buttons are grouped using a groupbox control. When the user presses a radio button, it is selected and all other radio buttons in the group are unselected. As a result, only one item in the group may be selected at any time.

For yes/no questions, a checkbox control may be more intuitive.

The term "radio button" comes from car radios that have mechanical preset buttons. When you press one of these real radio buttons, it gets pushed in, the tuner changes to your selection, and all other buttons pop out. RADIOBUTTONCREATE

Synopsis RADIOBUTTONCREATE parent group name label xpos ypos width height

Description Creates a radio button control. A radio button control is used to give the user a selection of a two state (TRUE or FALSE) item. But along with this is a restriction that only one radio button within a group box can be set to TRUE at any given time. A radio button must be associated with a group box control (see GROUPBOXCREATE).

The parent input is the name of the window that owns the new radio button. If no window or dialog with that name exists, then the FMSLogo screen window is used as the parent.

271 Windows Commands

The group input is the name of the group box control to associate with the new radio button control. All radio buttons within the same group box must be created one after another, without creating any other controls on the same parent in between.

The name input identifies the new radio button and must be a unique word.

The label input is a word that is written next to the radio button.

The xpos input is the X coordinate where the upper-left corner of the new radio button is placed.

The ypos input is the Y coordinate where the upper-left corner of the new radio button is placed.

The width input is the width of the new radio button.

The height input is the height of the new radio button.

If the parent of the radio button is the FMSLogo screen window, then the xpos, ypos, width, and height inputs are all given in turtle coordinates. Otherwise, they are given in "dialog units", the origin is the upper-left corner of the parent, and Y values increase as you move down the screen.

Example Create radio buttons in a new window:

TO CHECKONTHINGS IFELSE RADIOBUTTONGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 5 80 60 RADIOBUTTONCREATE "mywindow "mygroupbox "myhideturtle [Hide Turtle] 20 15 60 20 RADIOBUTTONCREATE "mywindow "mygroupbox "myshowturtle [Show Turtle] 20 35 60 20 RADIOBUTTONSET "myhideturtle "true RADIOBUTTONSET "myshowturtle "false BUTTONCREATE "mywindow "mybutton "Go 40 70 25 15 [CHECKONTHINGS]

; Delete the window and all of its child controls. WINDOWDELETE "mywindow

Create a radio button on the FMSLogo screen window:

TO CHECKONTHINGS IFELSE RADIOBUTTONGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

GROUPBOXCREATE "main "mygroupbox 110 130 140 100 RADIOBUTTONCREATE "main "mygroupbox "myhideturtle [Hide Turtle] 120 120 120 40 RADIOBUTTONCREATE "main "mygroupbox "myshowturtle [Show Turtle] 120 80 120 40 RADIOBUTTONSET "myhideturtle "true RADIOBUTTONSET "myshowturtle "false BUTTONCREATE "main "mybutton "Go 160 20 50 50 [CHECKONTHINGS]

; Delete all windows.

272 Windows Commands

WINDOWDELETE "main

See Also RADIOBUTTONDELETE RADIOBUTTONGET RADIOBUTTONSET RADIOBUTTONENABLE RADIOBUTTONDELETE

Synopsis RADIOBUTTONDELETE name

Description Deletes (closes) the radio button that is identified by name.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 60 RADIOBUTTONCREATE "mywindow "mygroupbox "myradiobutton [Switch Me] 20 20 60 20 RADIOBUTTONDELETE "myradiobutton WINDOWDELETE "mywindow RADIOBUTTONENABLE

Synopsis RADIOBUTTONENABLE name state

Description Enables or disables the radio button identified by name. If state equals TRUE, then the radio button is enabled. If state equals FALSE, then the radio button is disabled.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 60 RADIOBUTTONCREATE "mywindow "mygroupbox "myradiobutton [Switch Me] 20 20 60 20 RADIOBUTTONENABLE "myradiobutton "False

The radio button is now disabled

RADIOBUTTONENABLE "myradiobutton "True WINDOWDELETE "mywindow RADIOBUTTONSET

Synopsis RADIOBUTTONSET name state

Description Sets the state of the radio button that is identified by name to state. state must be either TRUE (pressed) or FALSE (unpressed).

Even though the user can only set one radio button in a group to TRUE at any given time, RADIOBUTTONSET can violate this constraint. If you use this command to set a radio button to TRUE, you should also set all the other radio buttons within the group box to FALSE.

Example TO CHECKONTHINGS IFELSE RADIOBUTTONGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

273 Windows Commands

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 60 RADIOBUTTONCREATE "mywindow "mygroupbox "myhideturtle [Hide Turtle] 20 20 60 20 RADIOBUTTONCREATE "mywindow "mygroupbox "myshowturtle [Show Turtle] 20 40 60 20 RADIOBUTTONSET "myhideturtle "true RADIOBUTTONSET "myshowturtle "false BUTTONCREATE "mywindow "mybutton "Go 40 70 25 20 [CHECKONTHINGS] WINDOWDELETE "mywindow RADIOBUTTONGET

Synopsis RADIOBUTTONGET name

Description Outputs the state (TRUE or FALSE) of the radio button that is identified by name.

Example TO CHECKONTHINGS IFELSE RADIOBUTTONGET "myhideturtle [HIDETURTLE] [SHOWTURTLE] END

WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] GROUPBOXCREATE "mywindow "mygroupbox 10 10 80 60 RADIOBUTTONCREATE "mywindow "mygroupbox "myhideturtle [Hide Turtle] 20 20 60 20 RADIOBUTTONCREATE "mywindow "mygroupbox "myshowturtle [Show Turtle] 20 40 60 20 RADIOBUTTONSET "myhideturtle "TRUE RADIOBUTTONSET "myshowturtle "FALSE BUTTONCREATE "mywindow "mybutton "Go 40 70 25 20 [CHECKONTHINGS] WINDOWDELETE "mywindow Debug Commands

DEBUGWINDOWS ...... 274 DEBUGWINDOWS

Synopsis DEBUGWINDOWS (DEBUGWINDOWS name)

Description Prints the tree (hierarchy of parent-child relationships) of a window. For each window that is printed, both the window type and name are printed.

If a name input is given, then DEBUGWINDOWS prints the hierarchy of the window that is identified by name. If no name input is given, all windows and controls are printed.

Example WINDOWCREATE "main "mywindow "mytitle 0 0 100 100 [] LISTBOXCREATE "mywindow "mylist 25 0 50 50 BUTTONCREATE "mywindow "mydraw "Draw 25 50 50 25 [Print "Click] DEBUGWINDOWS Window mywindow Button mydraw ListBox mylist

274 Windows Commands

WINDOWDELETE "mywindow Modal vs. Modeless Windows

MESSAGEBOX ...... 275 YESNOBOX ...... 275 SELECTBOX ...... 276 QUESTIONBOX ...... 276 DIALOGFILEOPEN ...... 277 DIALOGFILESAVE ...... 277 WINDOWFILEEDIT ...... 278

Windows programming supports two types of windows: Modal and Modeless. The modal windows (DIALOGCREATE) are similar to a non-windows programming model where the application is in control. In midstream of processing you, as the programmer, decide to prompt the user for information (that is, READLIST). Processing is halted and other components of the application are inaccessible until the user supplies the requested information. For example, prompting the user for a file name when trying to open a document is Modal.

When an application uses a modeless window (WINDOWCREATE), the user is in control. For example, the commander in FMSLogo is modeless. The program is generally idle and reacts when the user triggers an event (such as pushing a button).

Modal windows should be avoided where possible because users prefer to be in control of their applications, rather than being forced to answer a question before the application will do anything else.

FMSLogo has some predefined modal dialog boxes that you can use in your Logo programs. MESSAGEBOX

Synopsis MESSAGEBOX title message

Description Displays a dialog box with title in the title bar and message as the message. The dialog has an "OK" and a "Cancel" button. Processing does not continue until the user clicks one of these buttons. The commander window is also disabled until messagebox is dismissed. If the user presses "OK", then processing continues. If the user presses "Cancel", then processing is halted, as if by the HALT command.

Both the title and message inputs must be lists or words.

The message input is truncated according to the current values of PRINTWIDTHLIMIT and PRINTDEPTHLIMIT. The message box is automatically sized to fit message. The message is not word-wrapped, so if you have a long message, you may want to put in some line breaks.

Example MESSAGEBOX [This is the title] [This is the message. Press OK.]

See Also QUESTIONBOX SELECTBOX YESNOBOX

Synopsis YESNOBOX title question

275 Windows Commands

Description Displays a dialog box with title in the title bar and question as the message. The dialog also has "Yes", "No", and "Cancel" buttons. FMSLogo does not evaluate any further instructions until the user clicks one of these buttons. The commander window is also disabled until dialog is dismissed. If the user presses "Yes", then YESNOBOX outputs the TRUE and instruction evaluation continues. If the user presses "No", then YESNOBOX outputs the FALSE and instruction evaluation continues. If the user presses "Cancel", then instruction evaluation is halted, as if by the HALT command.

Both the title and question inputs should be either lists or words. For list inputs, the contents of the list is used, not the list, itself. The inputs are truncated according to the current values of PRINTWIDTHLIMIT and PRINTDEPTHLIMIT.

The yes/no box is automatically sized to fit question. The question is not word-wrapped, so if you have a long question, you may want to put in some line breaks.

Example SHOW YESNOBOX [Question] [Do you like Logo?] true SELECTBOX

Synopsis SELECTBOX title choicelist

Description Displays a dialog box with title as the title bar and choicelist as a list of choices. The dialog also has an "OK" and a "Cancel" button. FMSLogo does not evaluate any further instructions until the user clicks one of these buttons. The commander window is also disabled until dialog is dismissed. If the user presses "OK", then SELECTBOX outputs the index of the selected item (1 for first item, 2 for the second item, etc.) and instruction evaluation continues. If the user presses "Cancel", then instruction evaluation is halted, as if by the HALT command.

Both the title and choicelist inputs must be lists.

Example SHOW SELECTBOX [Choose Color] [Red Green Blue] Select green and hit OK 2

SHOW SELECTBOX [Which are colors] [[Red Green Blue] [One Two Three] None] Select "Red Green Blue" and hit OK 1

See Also MESSAGEBOX QUESTIONBOX QUESTIONBOX

Synopsis QUESTIONBOX title question

Description Displays a dialog box with title in the title bar, question as the message, and an edit control for text input. The dialog box also has "OK" and "Cancel" buttons. Processing does not continue until the user clicks one of these buttons. The commander window is also disabled until dialog is dismissed. If the user

276 Windows Commands

presses "OK", then QUESTIONBOX outputs the text in the edit control as a list. If the user presses "Cancel", then processing is halted, as if by the HALT command.

Both the title and question inputs may be lists or words. The question input is truncated according to the current values of PRINTWIDTHLIMIT and PRINTDEPTHLIMIT.

The question box is automatically sized to fit question. The question is not word-wrapped, so if you have a long question, you may want to put in some line breaks.

Example SHOW QUESTIONBOX [Question] [Do you like Logo?] [Yes, I do.]

See Also MESSAGEBOX SELECTBOX DIALOGFILEOPEN

Synopsis DIALOGFILEOPEN filename

Description Displays a standard "Open" windows dialog box. It does NOT open a file; it just allows the user to select the desired file using a Graphical User Interface. The filename input is used to set the defaults of name, directory and/or extension. The output is the fully-specified file name that the user selected. If the user presses "Cancel", then DIALOGFILEOPEN outputs the empty list ([]).

The filename input must be a word that specifies the directory to start in, the default filename, and/or extension of the filename. Wildcard characters ("*") are permitted as the filename or extension.

Example SHOW DIALOGFILEOPEN "|c:\\Program Files\\FMSLogo\\Examples\\Windows\\*.lgo| The dialog box shows all files ending in ".lgo" in the specified directory. c:\Program Files\FMSLogo\Examples\Windows\Visual.lgo DIALOGFILESAVE

Synopsis DIALOGFILESAVE filename

Description Displays a standard "Save As" windows dialog box. It does NOT save a file; it just allows the user to select the desired file using a Graphical User Interface. The filename input is used to set the defaults of name, directory and/or extension. The output is the full path name of the file that the user selected. If the user presses "Cancel", then DIALOGFILESAVE outputs the empty list ([]).

The filename input must be a word that specifies the directory to start in, the default filename, and/or extension of the filename. Wildcard characters ("*") are permitted as the filename or extension.

Example SHOW DIALOGFILESAVE "|c:\\Program Files\\FMSLogo\\Examples\\Windows\\*.lgo| The dialog box shows all files ending in ".lgo" in the specified directory. c:\Program Files\FMSLogo\Examples\Windows\Visual.lgo

277 Windows Commands

WINDOWFILEEDIT

Synopsis WINDOWFILEEDIT filename callback

Description Opens the editor on the file with the given filename. When the contents of the file is saved, it is saved to the file, not the workspace. The callback instruction list is run when the user closes the editor.

Example Simple example

WINDOWFILEEDIT "|c:\\Program Files\\FMSLogo\\logolib\\demo| [PRINT "Done]

Let the user select the file to edit

WINDOWFILEEDIT DIALOGFILEOPEN "|c:\\Program Files\\FMSLogo\\logolib\\*| [PRINT "Done] Example Code for Constructing a Window

Below is a code listing that constructs a simple window that draws some polygons on the screen. Unlike a traditional program, the logic does not start at the beginning and run line-by-line until it reaches the end. Instead, the logic is broken into small chunks and is executed in response to "events" such as mouse clicks.

The example can create both a modal and a modeless window. If it uses a modeless window, then SETUP can be called after WINDOWCREATE stops. If it uses a modal window, then SETUP is called during the DIALOGCREATE because DIALOGCREATE does not stop until the window is closed.

TO WIN ; For modeless example use this line WINDOWCREATE "root "d1 [Draw Pictures] 0 0 150 110 [] SETUP ; Create main window

; For modal example use this line ; DIALOGCREATE "root "d1 [Draw Pictures] 0 0 150 110 [SETUP] ; Create main window END

TO SETUP STATICCREATE "d1 "st4 [Select Shape] 5 10 50 10 ; Label the List box

LISTBOXCREATE "d1 "l1 5 25 80 40 ; Create List box with 3 Items owned by d1 LISTBOXADDSTRING "l1 "Square LISTBOXADDSTRING "l1 "Triangle LISTBOXADDSTRING "l1 "Hexagon

STATICCREATE "d1 "st11 [Red] 100 10 40 10 ; Label the scrollbar

SCROLLBARCREATE "d1 "s1 100 25 10 50 [MYRED] ; Create scroll bar, call MYRED when clicked SCROLLBARSET "s1 1 255 125 MYRED ; Init

BUTTONCREATE "d1 "b1 "End 5 80 40 10 [MYEND] ; Create button to call myend BUTTONCREATE "d1 "b3 "Clear 55 80 35 10 [CLEARSCREEN] ; Create button to clear screen BUTTONCREATE "d1 "b2 "Draw 100 80 35 10 [DRAWTHING] ; Create button to call drawthing

END

; run this procedure when the "Draw" button pushed

278 Windows Commands

TO DRAWTHING SETPENCOLOR (LIST SCROLLBARGET "s1 0 0) ; Ask scrollbar what to setpencolor to

; Draw appropriate shape according to the listbox

IF EQUALP [Hexagon] LISTBOXGETSELECT "l1 [REPEAT 6 [FORWARD 100 RIGHT 60]] IF EQUALP [Square] LISTBOXGETSELECT "l1 [REPEAT 4 [FORWARD 100 RIGHT 90]] IF EQUALP [Triangle] LISTBOXGETSELECT "l1 [REPEAT 3 [FORWARD 100 RIGHT 120]] END

; run this procedure when the "End" button is pushed TO MYEND ; For modeless example use this WINDOWDELETE "d1

; For modal example use this ; DIALOGDELETE "d1 END

; run this procedure when red scroll bar is adjusted TO MYRED STATICUPDATE "st11 SENTENCE [Red] SCROLLBARGET "s1 ; Update static label of position END

279 Chapter 20. Bitmap Commands

BITCUT ...... 280 BITCOPY ...... 281 BITPASTE ...... 281 BITPASTETOINDEX ...... 281 BITFIT ...... 282 SETBITINDEX ...... 283 BITINDEX ...... 284 SETBITMODE ...... 284 BITMODE ...... 285 BITBLOCK ...... 285 BITLOAD ...... 286 BITSAVE ...... 286 BITSIZE ...... 287 BITLOADSIZE ...... 287 GIFLOAD ...... 287 GIFSAVE ...... 287 GIFSIZE ...... 289 SETACTIVEAREA ...... 289 ACTIVEAREA ...... 289

This chapter describes procedures which enable you to manipulate sub-images within the primary image. BITCUT

Synopsis BITCUT width height

Description Cuts out part of the image and stores it in memory (or the clipboard, if BITINDEX is 0). Anytime later, you can use BITPASTE to "paste" it back into the image. FMSLogo cuts a rectangle starting at the turtle's position with a width of width pixels and a height of height pixels.

The rectangle that is cut is always taken horizontally and vertically, regardless of the turtle's heading.

BITCUT may appear to be off by 1 pixel in width and height when you use it, but it is not. This can be explained with an example. If you draw a square with REPEAT 4 [FORWARD 2 RIGHT 90], then the square is 3 pixels high, not 2. This is because of how FMSLogo draws images. In short, FMSLogo draws an imaginary line going down the center of each pixel. If a pixel is intersected (hit), then it is lit up. The distance from the center of the pixels representing the top of the square to the center of the pixels on the bottom of the square is 2 pixels. However, because FMSLogo can't turn on half a pixel, it turns on the entire pixel, which adds a half pixel to each side of the square, making the square 3x3 pixels in size. Bitmaps sizes are not taken from "center pixel to center pixel" like lines, they are whole pixel to whole pixel (inclusive).

Example SETPENSIZE [2 2] REPEAT 72 [CIRCLE2 100 SETPENCOLOR (LIST REPCOUNT*3 0 0) RIGHT 5] PENUP SETXY -50 -50

280 Bitmap Commands

BITCUT 100 100 CLEARSCREEN PENUP REPEAT 36 [FORWARD 150 BITPASTE BACK 150 RIGHT 10]

See Also SETBITINDEX BITCOPY

Synopsis BITCOPY width height

Description Copies part of the image and stores it in memory (or the clipboard, if BITINDEX is 0). Anytime later, you can use BITPASTE to "paste" it into the image. FMSLogo copies a rectangle starting at the turtle's position with a width of width pixels and a height of height pixels.

The rectangle that is copied is always taken horizontally and vertically, regardless of the turtle's heading.

Example SETPENSIZE [2 2] REPEAT 72 [CIRCLE2 100 SETPENCOLOR (LIST REPCOUNT*3 0 0) RIGHT 5] PENUP SETXY -50 -50 BITCOPY 100 100 CLEARSCREEN PENUP REPEAT 36 [FORWARD 150 BITPASTE BACK 150 RIGHT 10]

See Also SETBITINDEX BITPASTE

Synopsis BITPASTE

Description Pastes the image that was BITCUT into the bitmap index specified by BITINDEX. If BITINDEX is 0, then BITPASTE pastes the contents of the clipboard. The bitmap is pasted to the location of the turtle, with the turtle being the lower-left corner.

Example SETPENSIZE [2 2] REPEAT 72 [CIRCLE2 100 SETPENCOLOR (LIST REPCOUNT*3 0 0) RIGHT 5] PENUP SETXY -50 -50 BITCUT 100 100 CLEARSCREEN PENUP REPEAT 36 [FORWARD 150 BITPASTE BACK 150 RIGHT 10]

See Also SETBITINDEX SETBITMODE BITPASTETOINDEX

281 Bitmap Commands

Synopsis BITPASTETOINDEX index x y

Description Pastes the entire image that was "cut" with BITCUT to the x, y coordinate of the bitmap at the index input. Don't confuse the indices here; the index input specifies the index to paste to, whereas SETBITINDEX specifies the index to copy from.

The x and y inputs specify the coordinates on the destination bitmap where the lower-left corner of the source bitmap is pasted.

This command is useful for producing flicker-free animation. For example, let's say you have a ball rolling across a background. You have to erase the ball, put the background back, and draw the ball in its new position. The problem is that the user momentarily sees a screen with no ball after you erase it, but before you draw it in its new position. This is called "flicker". However, if you create the entire animation frame in memory (by using BITPASTETOINDEX) and BITPASTE each frame to the screen in a single instruction, then the user doesn't see any flicker.

Note that the destination index must already have an image to paste to.

Example ; Draw a red block 100x100 in Bitmap Buffer 1 SETBITINDEX 1 SETFLOODCOLOR [255 0 0] BITBLOCK 100 100 BITCOPY 100 100

; Draw a green block 50x50 in Bitmap Buffer 2 CLEARSCREEN SETBITINDEX 2 SETFLOODCOLOR [0 255 0] BITBLOCK 50 50 BITCOPY 50 50

; Reserve 100x100 space in Bitmap Buffer 3 CLEARSCREEN SETBITINDEX 3 BITCOPY 100 100

; Copy 1 to 3 SETBITINDEX 1 BITPASTETOINDEX 3 0 0

; Copy 2 to 3 SETBITINDEX 2 BITPASTETOINDEX 3 25 25

; Paste 3 to Screen SETBITINDEX 3 BITPASTE

See Also SETBITMODE BITFIT

282 Bitmap Commands

Synopsis BITFIT width height

Description Resizes (or "fits") the currently "cut" (BITCUT or BITCOPY) image into the specified dimensions. Anytime later, you can "paste" (BITPASTE) it back into the image. FMSLogo fits the "cut" image to a width of the width pixels and a height of the height pixels. The original "cut" image is replaced by this newly "fit" image.

BITFIT can permanently "scale" your image, whereas ZOOM only temporarily views it at a different scale.

Example SETPENSIZE [2 2] REPEAT 72 [CIRCLE2 100 SETPENCOLOR (LIST REPCOUNT*3 0 0) RIGHT 5] PENUP SETXY -50 -50 BITCUT 100 100 CLEARSCREEN BITPASTE CLEARSCREEN BITFIT 200 100 BITPASTE SETBITINDEX

Synopsis SETBITINDEX index

Description Sets the current bitmap cut buffer according to index. The index input must be a number from 0 to 1023. Its purpose is to allow multiple images to be stored in memory ready for quick pasting when doing animation.

The index of 0 is the default and also has the behavior of using the clipboard as the cut buffer. That is if you "cut" an image in an application like Microsoft Paint, then you can paste it directly in FMSLogo. The reverse is also true, if "cut" an image in FMSLogo it is available applications like Microsoft Paint.

Use BITINDEX to obtain the current setting.

Example ; Set a triangle at index 0. CLEARSCREEN SETBITINDEX 0 REPEAT 3 [FORWARD 50 RIGHT 120] BITCUT 100 100

; Set a square at index 1. CLEARSCREEN SETBITINDEX 1 REPEAT 4 [FORWARD 50 RIGHT 90] BITCUT 100 100

; Paste the bitmaps along two concentric circles. CLEARSCREEN SETBITMODE 3 PENUP HIDETURTLE

283 Bitmap Commands

REPEAT 72 [FORWARD 50 BITPASTE BACK 50 RIGHT 5] SETBITINDEX 0 REPEAT 72 [FORWARD 100 BITPASTE BACK 100 RIGHT 5] PENDOWN BITINDEX

Synopsis BITINDEX

Description Outputs current bitmap index, as set by SETBITINDEX. The default index is 0.

Example SETBITINDEX 99 SHOW BITINDEX 99 SETBITMODE

Synopsis SETBITMODE mode

Description Sets the current bitmap mode according to mode. The mode input must be a number from 1 to 9. The meaning of each value is given by the following table:

Mode Meaning 1 Take copy of memory then copy to screen 2 Take copy of memory OR with copy of screen then copy to screen 3 Take copy of memory AND with copy of screen then copy to screen 4 Take copy of memory XOR with copy of screen then copy to screen 5 Take copy of memory AND with invert of screen then copy to screen 6 Take invert of memory then copy to screen 7 Take copy of memory OR with copy of screen then invert to screen 8 Take invert of memory OR with copy of screen then copy to screen 9 Take invert of screen then copy to screen

The purpose of SETBITMODE is to allow images to be pasted using different methods. Sometimes you want the background erased and sometimes not. Sometimes you wish to invert the image before pasting it and sometimes not.

Use BITMODE to obtain the current setting.

Example ; Fill the screen with white

284 Bitmap Commands

SETSCREENCOLOR [255 255 255]

; Draw a circle and fill it with red PENDOWN CIRCLE 50 SETFLOODCOLOR [255 0 0] FILL

; Copy the red circle to the clipboard PENUP SETXY -50 -50 BITCOPY 101 101

; Fill the screen with yellow SETSCREENCOLOR [255 255 0]

; Paste by simply copying the image onto the background SETBITMODE 1 BITPASTE ; Notice how the white background still exists

; Fill the screen with yellow SETSCREENCOLOR [255 255 0]

; Now, paste by AND-ing the image onto the background SETBITMODE 3 BITPASTE ; Notice the white background disappeared BITMODE

Synopsis BITMODE

Description Outputs the current bitmap mode set by SETBITMODE.

Example ; save and restore the bitmode MAKE "savemode BITMODE SETBITMODE 8 SHOW BITMODE 8 SETBITMODE :savemode SHOW BITMODE 1 BITBLOCK

Synopsis BITBLOCK width height

Description Draws an opaque block (rectangle) of the given dimensions such that the turtle's current position is at the lower-lefthand corner of the block. The color of the block is the value of FLOODCOLOR. The rectangle is always draw with the width going horizontally and the height going vertically, regardless of the turtle's orientation.

285 Bitmap Commands

Example SETFLOODCOLOR 2 BITBLOCK 200 100

SETFLOODCOLOR 3 BITBLOCK 100 50 BITLOAD

Synopsis BITLOAD filename

Description Loads the bitmap specified by the filename input. The filename input must be a word that is the name of valid bitmap file.

If the picture is small enough, it is pasted onto the screen such that its lower left corner is at the turtle's current position. Otherwise, the picture is positioned in the upper left corner of the screen. The picture is always pasted right- side-up with the bottom running horizontally and the sides running vertically, regardless of the turtle's orientation.

BITLOAD is equivalent to selecting the Bitmap - Load menu option.

Example BITLOAD "c:\\windows\\forest.bmp

See Also BITSAVE BITSAVE

Synopsis BITSAVE filename (BITSAVE filename maxcolordepth)

Description Saves a picture (bitmap image) of your work on the computer's disk. It also allows you to add more work to an existing piece of work. The dimensions of the picture are determined by ACTIVEAREA.

Remember that if your image was generated with a Logo program you really don't need to save it as an image unless you want to use the image in another application such as Microsoft Paint or as a wallpaper.

The filename input must be a word that is the name of the bitmap file to save.

The maxcolordepth input is total number of colors in the bitmap in bits per pixel. That is, 1 = 2 colors, 4 = 16 colors, 8 = 256 colors, and 24 = 16.7 million colors. The default value is 24.

The format of the saved image is known as a Microsoft Windows Bitmap (BMP). You can use these files with other applications such as Microsoft Paint. Note that these files can be big and may take a long time to read or write on slow machines.

Example REPEAT 72 [CIRCLE2 100 RIGHT 5] BITSAVE "myfile.bmp CLEARSCREEN BITLOAD "myfile.bmp

286 Bitmap Commands

BITSIZE

Synopsis BITSIZE

Description Output the width and height of the bitmap specified by the current BITINDEX. The output is a two-member list of the form [width height]. BITSIZE outputs [0 0] if no bitmap is loaded.

Example SHOW BITSIZE [0 0]

BITCOPY 100 200 SHOW BITSIZE [100 200] BITLOADSIZE

Synopsis BITLOADSIZE filename

Description Output the width and height of the bitmap that is specified by the filename input. The filename input must be a word that is the name of valid bitmap file.

The output is a two-member list of the form [width height].

Example SHOW BITLOADSIZE "c:\\windows\\forest.bmp [256 256] GIFLOAD

Synopsis GIFLOAD filename

Description Loads the GIF picture (compressed bitmap image) specified by the filename input. The filename input must be a word that is the name of valid GIF file.

If the picture is small enough, it is pasted onto the screen such that its lower left corner is at the turtle's current position. Otherwise, the picture is positioned in the upper left corner of the screen. The picture is always pasted right- side-up with the bottom running horizontally and the sides running vertically, regardless of the turtle's orientation.

GIFLOAD is equivalent to selecting the Bitmap - Load menu option.

Example GIFLOAD "mypicture.gif

See Also GIFSAVE GIFSAVE

Synopsis GIFSAVE filename (GIFSAVE filename delay append loop) (GIFSAVE filename delay append loop maxcolor)

287 Bitmap Commands

(GIFSAVE filename delay append loop maxcolor transcolorvector)

Description Save a picture of your work as a GIF (pronounced "jif") image so that it can be used on Web pages or Email. The dimensions of the picture are determined by ACTIVEAREA. GIFSAVE saves the picture in a format called GIF (Graphics Interchange Format) that was created by CompuServe. The format was popular on the Web for several reasons. First, it is a compressed format and takes less time to transmit than uncompressed formats. Second, it supports "interlacing", which makes the image partially viewable as it's being transmitted (it starts off blurry and comes into focus). Third, it supports animation. Animated GIFs allow multiple images in one file with specified delays between the images. The filename input must be a word that is the name of the file to which the GIF is written. If a file by this name already exists, it is ovewritten. When four or more inputs are given, you can save a GIF animation frame (series of compressed bitmap images). The delay input specifies how many hundredths of a second to display the frame. The append input specifies whether to start a new animation or append a new frame to an existing animation. This should be either "TRUE or "FALSE. The loop input specifies how many times the animation should loop (the default of -1 = no loop, 0 = loop forever, n = loop n times). You can specify the maximum color depth with the optional maxcolor input. The choices are 1 (2 colors), 4 (16 colors), or 8 (256 colors) bits per pixel (8 being the default). If your image does not use many colors you can reduce the size of the GIF file produced significantly by using this option. The optional transcolorvector input takes the form [red green blue] and specifies the color of the pixels which are transparent in the saved image. If this input is not specified then no pixels are transparent. Example A single image (no animation): REPEAT 72 [REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 5] GIFSAVE "myfile.gif CLEARSCREEN GIFLOAD "myfile.gif

GIF animation: CLEARSCREEN SETACTIVEAREA [-150 -150 150 150]

; Flag to indicate we do not append the first frame MAKE "append "FALSE REPEAT 36 [ REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 10 ; Save a frame (no delay and loop forever) (GIFSAVE "myfile.gif 0 :append 0) MAKE "append "TRUE ]

288 Bitmap Commands

Open the file myfile.gif with your Web browser (for example, Firefox or Internet Explorer).

See Also GIFLOAD ACTIVEAREA GIFSIZE

Synopsis GIFSIZE filename

Description Output the width and height of the GIF file that is specified by the filename input. The filename input must be a word that is the name of valid GIF file.

The output is a two-member list of the form [width height].

Example SHOW GIFSIZE "myfile.gif [256 256] SETACTIVEAREA

Synopsis SETACTIVEAREA area

Description Sets the active area for printing and saving pictures. The area input must be a list of the form: [XLow YLow XHigh YHigh]. All members must be integers.

You can achieve the same effect by using Bitmap - Active Area from the menu.

Example BITBLOCK 100 100 SETACTIVEAREA [0 0 50 50] BITSAVE "myfile.bmp CLEARSCREEN BITLOAD "myfile.bmp

See how only the part of the rectangle that was within the active area is restored.

See Also ACTIVEAREA ACTIVEAREA

Synopsis ACTIVEAREA

Description Outputs the current active area, as set by SETACTIVEAREA.

The active area is output as a list of the form: [XLow YLow XHigh YHigh]. All members are integers.

Example SETACTIVEAREA [-10 -10 10 10] SHOW ACTIVEAREA [-10 -10 10 10]

289 Chapter 21. Networking Commands

Networking Tools (Outside of FMSLogo) ...... 290 NETSTARTUP ...... 292 NETSHUTDOWN ...... 292 NETACCEPTON ...... 292 NETACCEPTOFF ...... 293 NETACCEPTRECEIVEVALUE ...... 293 NETACCEPTSENDVALUE ...... 294 NETCONNECTON ...... 295 NETCONNECTOFF ...... 296 NETCONNECTSENDVALUE ...... 296 NETCONNECTRECEIVEVALUE ...... 297

Networking allows FMSLogo to communicate with the rest of the world. FMSLogo uses TCP/IP sockets, the same technology upon which the Internet is built. So if you have an Internet connection, then your friend can be in England, you can be in Canada, and you can use FMSLogo to draw on each other's screen or build games that you play together.

FMSLogo can send data to and receive data from instances of FMSLogo which are running on other computers. The NETCONNECT family of commands is used to initiate connections to other computers. The NETACCEPT family of commands is used to accept connections from other computers. You can have at most two connections, the one you initiated and the one you accepted. You can send and receive data on either type of connection. Networking Tools (Outside of FMSLogo)

In order to use networking within FMSLogo, it is helpful to understand the networking tools that the rest of the world uses.

DNS (Domain Name Service). TCP/IP identifies machines using cryptic IP addresses that look something like "21.100.200.5" (four numbers, each less than 256, separated by dots). These numbers have no intrinsic meaning and are hard for people remember, so machines may also be given names. DNS is a network service for "resolving" easy-to-remember names to hard-to-remember IP addresses. If you try to connect to a machine using its easy-to-remember DNS name, the software you use (including FMSLogo) uses DNS to resolve the name to an IP address before creating the connection.

For example, a Web browser can download FMSLogo from a machine named "sourceforge.net". The Web browser needs to use DNS to resolve this name to an IP address before it can create a TCP/IP socket to download FMSLogo. So the Web browser first asks its DNS server for the IP address of "sourceforge.net". The DNS server might reply with something like "216.34.181.60". Once the Web browser knows the IP address for sourceforge.net, it can create the connection and start downloading FMSLogo.

By convention, there's a special range of IP addresses that means "whatever machine I'm on". This range includes the IP address "127.0.0.1". There's also a special host name "localhost" that resolves to "127.0.0.1". If you are writing both the client and the server programs, it's usually easiest to develop the program on one machine and use "localhost" as the remote machine name. Later, you can run the client and server on different machines and connect across the network using the machine's real name.

PING. Ping is a simple command-line program that is used to test network connectivity. To use it, start a Windows command prompt and type

PING remotemachine

290 Networking Commands where remotemachine is the name or IP address of the machine you'd like to test connectivity to. PING reports if it can reach that machine and how long it takes to do so. If PING cannot reach the remote machine, then no other networking software, including the FMSLogo Networking commands will be able to connect to it. If PING fails with the name, but succeeds with the IP address, then there is probably something wrong with DNS or the name.

Ports and Service Names. A single machine may offer multiple networking services, such as TELNET, FTP, HTTP, or POPMAIL. One of these services can be provided by FMSLogo. TCP requires that each of these services be assigned a unique "TCP port", which is number from 1 to 65535. For example, the TCP port 80 is usually reserved for HTTP, so if you connect to a machine on TCP port 80, you are likely connecting to that machine's HTTP service.

When using NETACCEPTON to create your own service, you must also choose which TCP port to assign to your service. You should choose one that is not reserved for some other service. In general, picking one above 1024 is recommended.

TELNET. Similar to how PING can be used to determine if you can connect to a machine, TELNET can be used to determine if you can connect to a particular service on a machine. To use it, open a Windows command prompt and run

TELNET remotemachine remoteport where remotemachine is the DNS name or IP address of the remote machine and remoteport is the TCP port number of service that you want to connect to.

If you can PING a machine, but cannot use TELNET to connect to its port, then it may mean that the machine is not listening on that port (that is, it's not providing the service at this time), or that a firewall is blocking connections on the port.

Network Router. Nowadays, it is rare to connect a computer directly to the Internet. Instead, most networks have a router that is directly connected to the Internet and the other machines are connected to it. These routers typically perform multiple services, including DNS, DHCP (assignment of IP addresses), Firewall (blocking network connections), and network address translation (maintaining a different "internal" IP addresses that all appear as the same IP address to the rest of the Internet).

In general, when Windows boots up, it tries to get an IP address using DHCP. Your network router (acting as a DHCP server) assigns it an IP address and (acting as a DNS server) uses the computer name for the IP address. You can determine your machine's name by starting a command prompt and running

ECHO %COMPUTERNAME%

You can determine your machine's IP address by starting a command prompt and running ipconfig

Firewalls. The Internet can be dangerous, as there are people connected to the Internet who want to attack your computer. Firewalls make the Internet safer by blocking connections. In addition to blocking unwanted connections from attackers, firewalls may block connections from friendly FMSLogo machines, making it impossible for FMSLogo to connect through them. Not only does your network router act as a firewall, but each Windows machine may have its own "personal" firewall.

If you cannot use TELNET to connect to a port on the remote machine, then a firewall may be blocking the connection. To resolve the problem, you must configure all intermediate firewalls to allow these connections. It is not safe to solve such a problem by disabling the firewall completely. Instead, it's worth learning how to allow connections on specific ports, as needed.

291 Networking Commands

Packet Sniffer. Even if you are able to connect to the remote machines, it's sometimes helpful to see the exact data is being transmitted or received. For this, the tool-of-choice is a packet sniffer. A packet sniffer can show you everything that your network adapter sends or receives, including what FMSLogo is sending or receiving. There's a good free packet sniffer called Wireshark. To enable Wireshark to capture network traffic sent from a machine to itself may additionally require a tool called "RawCap". NETSTARTUP

Synopsis NETSTARTUP (NETSTARTUP synchronous_dns)

Description Turns on networking in FMSLogo. This must be called before any other network commands will work.

If the synchronous_dns input is not given, FMSLogo uses asynchronous DNS. You may optionally call NETSTARTUP with the synchronous_dns input as 0 (asynchronous) or 1 (synchronous). Synchronous DNS makes FMSLogo unresponsive during a network name lookup. Support for synchronous DNS was added to work around "Host not Found" errors with Trumpet WinSock in the early 1990s. It should not be needed today.

Example NETSTARTUP NETSHUTDOWN NETSHUTDOWN

Synopsis NETSHUTDOWN

Description Turns off networking in FMSLogo. No network procedure in FMSLogo will work until you call NETSTARTUP again.

Example NETSTARTUP NETSHUTDOWN NETACCEPTON

Synopsis NETACCEPTON localport sendready receiveready

Description Listens for and accepts new network connections on TCP port localport. When data are received from the remote host, FMSLogo runs the receiveready instruction list. When you send data with NETACCEPTSENDVALUE it might output FALSE (meaning that it's not ready to send). If this happens you won't be able to send more data until FMSLogo runs the sendready instruction list again.

To stop accepting connections, run NETACCEPTOFF.

NETACCEPTON outputs TRUE if the operation was successful. Otherwise, it outputs FALSE.

The localport input is the local TCP port on which to listen for new connections. It must be an integer between 1 and 65535. The port must not already be in use by some other service on the machine. It is recommended that you use ports numbers greater than 1024.

292 Networking Commands

The sendready input is an instruction list (a list of instructions or a procedure name) that is run multiple times: 1. When FMSLogo successfully invokes listen. 2. When a client connects to FMSLogo. 3. When FMSLogo is ready to send data to the client. 4. When a second client connects to FMSLogo. 5. When FMSLogo is ready to send data to the second client. 6. And so on for each new client...

FMSLogo also runs the sendready instruction list when it is ready to send after an earlier call to NETACCEPTSENDVALUE failed.

The receiveready input is an instruction list (a list of instructions or a procedure name) which FMSLogo runs it whenever it receives data from the client. To obtain the data received, run NETACCEPTRECEIVEVALUE from the receiveready instruction list.

Example NETSTARTUP ; Start up the network

; Wait for someone to connect to you on port 5124 SHOW NETACCEPTON 5124 [PRINT [Ready to send]] [PRINT [Ready to receive]] true Ready to send

NETACCEPTOFF NETSHUTDOWN NETACCEPTOFF

Synopsis NETACCEPTOFF

Description Stops accepting incoming connections.

Example NETSTARTUP ; Start up the network

; Wait for someone to connect to you on local port 5124 SHOW NETACCEPTON 5124 [PRINT [Ready to send]] [PRINT [Ready to receive]] true Ready to send

NETACCEPTOFF NETSHUTDOWN NETACCEPTRECEIVEVALUE

Synopsis NETACCEPTRECEIVEVALUE

Description Outputs the value of the last network data received on the connection created with NETACCEPTON. The output is a list, as if parsed by PARSE.

The network data is interpreted as characters encoded in the system default Windows code page of the host operating system. As a result, it may not be

293 Networking Commands

possible to receive data from an instance of FMSLogo that is running on an operating system which is configured for a different language than yours.

It is best to call this procedure in your receiveready callback code of your NETACCEPTON instruction. If you don't, then the data is discarded the next time receiveready is run.

FMSLogo does not guarantee that the remote machine that sent the data is friendly. It is therefore a good practice to make sure that the data looks correct before using it. For example, if you want to accept turtle commands from a remote machine, its bad to simply RUN all data that you receive, as the data could include a SHELL command that installs malware. Instead, your program should verify that the data it received is a well-formed turtle command before running it.

Example This example sets up both a client and server. The client (connector) sends data to the server (accepter).

NETSTARTUP ; Start up the network

; Wait for someone to connect to you on local port 5124 SHOW NETACCEPTON 5124 [] [PRINT NETACCEPTRECEIVEVALUE] true

; Connect to local machine on port 5124 ; If you want to run this portion on a different computer, then replace ; the "localhost with the name of the other computer. SHOW NETCONNECTON "localhost 5124 [PRINT [Ok to Send Again]] [] true

WAIT 100 ; Wait little for connection to establish Ok to Send Again Ok to Send Again Ok to Send Again SHOW NETCONNECTSENDVALUE [Hello thanks for taking my call] ; Send some data true

WAIT 100 ; Wait a little before we shut things down Hello thanks for taking my call

NETCONNECTOFF NETACCEPTOFF NETSHUTDOWN NETACCEPTSENDVALUE

Synopsis NETACCEPTSENDVALUE data

Description Sends data out the accept socket.

The data input may be a word, a list, or an array. The data are sent as if printed by PRINT, without the final newline. The network payload is encoded according to the system default Windows code page of the host operating system, followed by a 0 byte.

294 Networking Commands

NETACCEPTSENDVALUE outputs TRUE if data were successfully queued to be sent. Otherwise, it outputs FALSE (meaning that it's not ready to send). If it outputs FALSE, you must wait until the sendready input list of NETACCEPTON is run before sending on it again.

Example This example sets up a client and server on the same machine. The server (accepter) sends data to whomever connected.

NETSTARTUP ; Start up the network

; Wait for someone to connect to you on local port 5124 SHOW NETACCEPTON 5124 [PRINT [Ok to Send Again]] [] true Ok to Send Again

; Connect to the local machine on port 5124. ; If you want to run this portion on a different computer, then replace ; the "localhost with the name of the other computer. SHOW NETCONNECTON "localhost 5124 [] [PRINT NETCONNECTRECEIVEVALUE] true

WAIT 100 ; Wait little for connection to establish Ok to Send Again Ok to Send Again

SHOW NETACCEPTSENDVALUE [Who are you that called me] ; Send some data true

WAIT 100 ; Wait a little before we shut things down Who are you that called me

NETCONNECTOFF NETACCEPTOFF NETSHUTDOWN NETCONNECTON

Synopsis NETCONNECTON remotemachinename remoteport sendready receiveready

Description Initiates a connection over the network to the TCP port remoteport on remotemachinename. To turn off the connection call NETCONNECTOFF. To obtain the data received call NETCONNECTRECEIVEVALUE in your receiveready instruction list. When you actually send data with NETCONNECTSENDVALUE it might output FALSE (meaning that it's not ready to send). If this happens you must wait until the sendready callback code is run before trying to send the data again.

NETCONNECTON outputs TRUE if the operation was successful. Otherwise, it outputs FALSE.

The remotemachinename input is a DNS host name or an IP address. It can be a list or a word.

295 Networking Commands

The remoteport input is an integer that is used to identify which remote TCP port to connect to.

The sendready input is an instruction list (a list of instructions or a procedure name) to run when data is ready to send again. The first time sendready is run is when FMSLogo successfully invokes the connection request. The second time sendready is run is when FMSLogo actually connects to the remote machine. The third time sendready is run is when FMSLogo is ready to send on the connection. After that, sendready is run when FMSLogo is ready to send after an earlier call to NETCONNECTSENDVALUE failed.

The receiveready input is an instruction list (a list of instructions or a procedure name) to run when data are available. It is run whenever data is received and is ready to be read.

Example This example assumes that a machine named "remotemachinename" is listening on port 5124.

NETSTARTUP ; Start up the network SHOW NETCONNECTON "remotemachinename 5124 [PRINT [ready to send again]] [PRINT [I have something]] true

NETCONNECTOFF NETSHUTDOWN NETCONNECTOFF

Synopsis NETCONNECTOFF

Description Shuts down a connection that was created with NETCONNECTON. After running this command, NETCONNECTSENDVALUE and NETCONNECTRECEIVEVALUE no longer work.

Example The following example assumes that there is a machine named "remotemachinename" that is listening on port 5124.

NETSTARTUP ; Start up the network SHOW NETCONNECTON "remotemachinename 5124 [PRINT [ready to send again]] [PRINT [I have something]] true

NETCONNECTOFF NETSHUTDOWN NETCONNECTSENDVALUE

Synopsis NETCONNECTSENDVALUE data

Description Sends data out the connection that was created with NETCONNECTON.

The data input may be a word, a list, or an array. The data are sent as if printed by PRINT, without the final newline. The network payload is encoded according to the system default Windows code page of the host operating system, followed by a 0 byte.

296 Networking Commands

NETCONNECTSENDVALUE outputs TRUE if the data were successfully queued to be sent. Otherwise, it outputs FALSE (meaning that it's not ready to send). If it outputs FALSE, you must wait until the sendready callback procedure of NETCONNECTON is run and then try sending the data again.

Example The following example sets up both a client and a server. The client (connector) sends data to the server (accepter).

NETSTARTUP ; Start up the network

; Wait for someone to connect to you on port 5124 SHOW NETACCEPTON 5124 [] [PRINT NETACCEPTRECEIVEVALUE] true

; Connect to local machine on port 5124 ; If you want to run this portion on a different computer, then replace ; the "localhost with the name of the other computer. SHOW NETCONNECTON "localhost 5124 [PRINT [Ok to Send Again]] [] true

WAIT 100 ; Wait a little to establish the connection Ok to Send Again Ok to Send Again Ok to Send Again

SHOW NETCONNECTSENDVALUE [Hello thanks for taking my call] ; Send some data true

WAIT 100 ; Wait a little before we shut things down Hello thanks for taking my call

NETCONNECTOFF NETACCEPTOFF NETSHUTDOWN NETCONNECTRECEIVEVALUE

Synopsis NETCONNECTRECEIVEVALUE

Description Outputs the value of the last network data received on the connection that was created with NETCONNECTON. The output is a list, as if parsed by PARSE.

The network data is interpreted as characters encoded in the system default Windows code page of the host operating system. As a result, it may not be possible to receive data from an instance of FMSLogo that is running on an operating system which is configured for a different language than yours.

It is best to call this procedure in your receiveready callback code of your NETCONNECTON command. If you don't, then the data is discarded the next time receiveready is run.

Example The following example sets up both a client and server. The server (accepter) sends data to the client (connector).

297 Networking Commands

NETSTARTUP ; Start up the network

; Wait for someone to connect to you on port 5124 SHOW NETACCEPTON 5124 [PRINT [Ok to Send Again]] [] true Ok to Send Again

; Connect to local machine on port 5124 ; If you want to run this portion on a different computer, then replace ; the "localhost with the name of the other computer. SHOW NETCONNECTON "localhost 5124 [] [PRINT NETCONNECTRECEIVEVALUE] true

WAIT 100 ; Wait a little to establish the connection Ok to Send Again Ok to Send Again

SHOW NETACCEPTSENDVALUE [Who are you that called me] ; Send some data true

WAIT 100 ; Wait a little before we shut things down Who are you that called me

NETCONNECTOFF NETACCEPTOFF NETSHUTDOWN

298 Chapter 22. Multimedia Commands

MIDI Commands ...... 299 MIDIOPEN ...... 299 MIDICLOSE ...... 300 MIDIMESSAGE ...... 300 MIDI Table ...... 301 MIDI Instrument ...... 302 Sound Wave Commands ...... 306 PLAYWAVE ...... 306 Sound Commands ...... 307 SOUNDON ...... 307 SOUNDOFF ...... 307 TONE ...... 308 SOUND ...... 308 Media Control Commands ...... 308 The Media Control Interface ...... 308 MCI ...... 313

The multimedia commands in FMSLogo manipulate multimedia devices such as CD players, sound cards, and MIDI devices. MIDI Commands

MIDIOPEN ...... 299 MIDICLOSE ...... 300 MIDIMESSAGE ...... 300 MIDI Table ...... 301 MIDI Instrument ...... 302

FMSLogo supports three commands that allow you to create and play MIDI (Musical Instrument Digital Interface) music. MIDIOPEN

Synopsis MIDIOPEN (MIDIOPEN id)

Description Opens the MIDI device and accesses it through a MIDI device driver. The device driver chosen depends on several things. When no inputs are given, MIDIOPEN attempts to use the MIDI-MAPPER. When an id input is given, MIDIOPEN lets you choose any available MIDI driver available on your system. The id input can be any integer from 0 to 1 less than number of MIDI drivers available. To determine which id maps to which driver try several MIDIOPEN commands with increasing id inputs. MIDIOPEN outputs the name of the driver being used.

On success, MIDIOPEN outputs a list of words that represents the name of the driver being used.

MIDI allows you to generate sound on your sound card. You must install the appropriate drivers under Windows for your sound card to work. Most sound cards come with a MIDI player which reads MIDI messages from a file and

299 Multimedia Commands

passes them to the MIDI driver. If you have a working MIDI player under Windows then FMSLogo should work, too.

MIDI commands in FMSLogo does not use MIDI files (.MID or .MDI). Instead you build up sequences of MIDI messages and send them directly to the MIDI device. Note that you can play MIDI files using the MCI command. FMSLogo is not a MIDI sequencer. You can think of MIDI commands in FMSLogo as a programmable keyboard. It just so happens that the link between your programmable keyboard (MIDI commands) and your Speaker is MIDI.

Example PRINT MIDIOPEN [MIDI Mapper] MIDICLOSE

See Also MIDIMESSAGE MIDICLOSE MIDICLOSE

Synopsis MIDICLOSE

Description Closes the MIDI device that was opened with MIDIOPEN.

Example PRINT MIDIOPEN [MIDI Mapper] MIDICLOSE MIDIMESSAGE

Synopsis MIDIMESSAGE message

Description Sends a MIDI message to the MIDI sequencer. You must call MIDIOPEN before using this command.

The message input must be a list. It has three forms: the short form, the long form and the System Exclusive form.

The Short Form. The short form of message has three integer members: [status data1 data2]. The first integer is known as the "status byte", but it can also be thought of as a "command byte", since it specifies what should be done. data1 and data2 are both required, even if the message requires only 1 (just use 0).

The Long Form. The long form of message is similar to the short form, but it contains many short-form triples. It has the form [status data1 data2 status data1 data2 ...].

The System Exclusive Form. The system exclusive form is a list that starts with 240 (0xF0 in hexadecimal). It can then be followed by any number of data bytes. It has the form [240 data1 data2 ...]

The meaning of the midi messages are given in the MIDI Table.

This documentation does not attempt to teach you MIDI, but it contains enough information to get you started. For more information you may be interested in

300 Multimedia Commands

reading a book on MIDI such as: "MIDI Basics" by Akira Otsuka and Akihiko Nakajima.

Example PRINT MIDIOPEN [MIDI Mapper] MIDIMESSAGE (LIST 192+13 56 0 192+13 56 0) listen to tone MIDIMESSAGE (LIST 144+13 100 100) MIDICLOSE MIDI Table

This table defines some messages that are legal for MIDIMESSAGE.

Command Name Status Byte Data Byte 1 Data Byte 2 Note Off 128 + Channel 0-127 Pitch 0-127 Velocity Note On 144 + Channel 0-127 Pitch 0-127 Velocity Poly Pressure 160 + Channel 0-127 Pitch 0-127 Pressure Control Change 176 + Channel 0 Undefined 0-127 MSB Control Change 176 + Channel 1 Modulation Wheel 0-127 MSB Control Change 176 + Channel 2 Breath Controller 0-127 MSB Control Change 176 + Channel 3 After Touch 0-127 MSB Control Change 176 + Channel 4 Foot Controller 0-127 MSB Control Change 176 + Channel 5 Portamento Time 0-127 MSB Control Change 176 + Channel 6 Data Entry 0-127 MSB Control Change 176 + Channel 7 Main Volume 0-127 MSB Control Change 176 + Channel 8-31 Undefined 0-127 MSB Control Change 176 + Channel 32-63 LSB of 0-31 0-127 MSB Control Change 176 + Channel 64 Damper Pedal 0:off 127:on Control Change 176 + Channel 65 Portamento 0:off 127:on Control Change 176 + Channel 66 Sostenuto 0:off 127:on Control Change 176 + Channel 67 Soft Pedal 0:off 127:on Control Change 176 + Channel 68-92 Undefined 0:off 127:on Control Change 176 + Channel 93 Chorus 0:off 127:on Control Change 176 + Channel 94 Celeste 0:off 127:on Control Change 176 + Channel 95 Phaser 0:off 127:on Control Change 176 + Channel 96 Data Entry + 1 0:off 127:on Control Change 176 + Channel 97 Data Entry - 1 0:off 127:on Control Change 176 + Channel 98-121 Undefined 0:off 127:on Control Change 176 + Channel 122 Local Control 0-127 Control Change 176 + Channel 123 All Notes Off 0 Control Change 176 + Channel 124 Omni Mode off 0-15 Control Change 176 + Channel 125 Omni Mode on 0

301 Multimedia Commands

Command Name Status Byte Data Byte 1 Data Byte 2 Control Change 176 + Channel 126 Mono on/Poly off 0 Control Change 176 + Channel 127 Poly on/Mono off 0 Program Change 192 + Channel 0-127 Program Not used Channel Pressure 208 + Channel 0-127 Pressure Not used Pitch Wheel 224 + Channel 0-127 LSB 0-127 MSB System Exclusive 240 0-127 Id Code Any number of bytes Undefined 241 Not used Not used Song Position 242 0-127 LSB 0-127 MSB Song Select 243 0-127 Song Not used Undefined 244 Not used Not used Undefined 245 Not used Not used Tune Request 246 Not used Not used End of Exclusive 247 Not used Not used Timing Clock 248 Not used Not used Undefined 249 Not used Not used Start 250 Not used Not used Continue 251 Not used Not used Stop 252 Not used Not used Undefined 253 Not used Not used Active Sensing 254 Not used Not used System Reset 255 Not used Not used MIDI Instrument

This table defines the mapping between instrument numbers and instruments. Number Class Instrument 0 Piano Acoustic Grand Piano 1 Piano Bright Acoustic Piano 2 Piano Electric Grand Piano 3 Piano Honky-tonk Piano 4 Piano Rhodes Piano 5 Piano Chorused Piano 6 Piano Harpsichord 7 Piano Clavinet 8 Chromatic Percussion Celesta 9 Chromatic Percussion Glockenspiel 10 Chromatic Percussion Music box 11 Chromatic Percussion Vibraphone 12 Chromatic Percussion Marimba

302 Multimedia Commands

Number Class Instrument 13 Chromatic Percussion Xylophone 14 Chromatic Percussion Tubular Bells 15 Chromatic Percussion Dulcimer 16 Organ Hammond Organ 17 Organ Percussive Organ 18 Organ Rock Organ 19 Organ Church Organ 20 Organ Reed Organ 21 Organ Accordion 22 Organ Harmonica 23 Organ Tango Accordion 24 Guitar Acoustic Guitar (nylon) 25 Guitar Acoustic Guitar (steel) 26 Guitar Electric Guitar (jazz) 27 Guitar Electric Guitar (clean) 28 Guitar Electric Guitar (muted) 29 Guitar Overdriven Guitar 30 Guitar Distortion Guitar 31 Guitar Guitar Harmonics 32 Bass Acoustic Bass 33 Bass Electric Bass (finger) 34 Bass Electric Bass (pick) 35 Bass Fretless Bass 36 Bass Slap Bass 1 37 Bass Slap Bass 2 38 Bass Synth Bass 1 39 Bass Synth Bass 2 40 Strings Violin 41 Strings Viola 42 Strings Cello 43 Strings Contrabass 44 Strings Tremolo Strings 45 Strings Pizzicato Strings 46 Strings Orchestral Harp 47 Strings Timpani 48 Ensemble String Ensemble 1 49 Ensemble String Ensemble 2 50 Ensemble Synth Strings 1

303 Multimedia Commands

Number Class Instrument 51 Ensemble Synth Strings 2 52 Ensemble Choir Aahs 53 Ensemble Voice Oohs 54 Ensemble Synth Voice 55 Ensemble Orchestra Hit 56 Brass Trumpet 57 Brass Trombone 58 Brass Tuba 59 Brass Muted Trumpet 60 Brass French Horn 61 Brass Brass Section 62 Brass Synth Brass 1 63 Brass Synth Brass 2 64 Reed Soprano Sax 65 Reed Alto Sax 66 Reed Tenor Sax 67 Reed Baritone Sax 68 Reed Oboe 69 Reed English Horn 70 Reed Bassoon 71 Reed Clarinet 72 Pipe Piccolo 73 Pipe Flute 74 Pipe Recorder 75 Pipe Pan Flute 76 Pipe Bottle Blow 77 Pipe Shakuhachi 78 Pipe Whistle 79 Pipe Ocarina 80 Synth Lead Lead 1 (square) 81 Synth Lead Lead 2 (sawtooth) 82 Synth Lead Lead 3 (calliope lead) 83 Synth Lead Lead 4 (chiffer lead) 84 Synth Lead Lead 5 (charang) 85 Synth Lead Lead 6 (voice) 86 Synth Lead Lead 7 (fifths) 87 Synth Lead Lead 8 (brass + lead) 88 Synth Pad Pad 1 (new age)

304 Multimedia Commands

Number Class Instrument 89 Synth Pad Pad 2 (warm) 90 Synth Pad Pad 3 (polysynth) 91 Synth Pad Pad 4 (choir) 92 Synth Pad Pad 5 (bowed) 93 Synth Pad Pad 6 (metallic) 94 Synth Pad Pad 7 (halo) 95 Synth Pad Pad 8 (sweep) 96 Synth Effects FX 1 (rain) 97 Synth Effects FX 2 (soundtrack) 98 Synth Effects FX 3 (crystal) 99 Synth Effects FX 4 (atmosphere) 100 Synth Effects FX 5 (brightness) 101 Synth Effects FX 6 (goblins) 102 Synth Effects FX 7 (echoes) 103 Synth Effects FX 8 (sci-fi) 104 Ethnic Sitar 105 Ethnic Banjo 106 Ethnic Shamisen 107 Ethnic Koto 108 Ethnic Kalimba 109 Ethnic Bagpipe 110 Ethnic Fiddle 111 Ethnic Shana 112 Percussive Tinkle Bell 113 Percussive Agogo 114 Percussive Steel Drums 115 Percussive Woodblock 116 Percussive Taiko Drum 117 Percussive Melodic Tom 118 Percussive Synth Drum 119 Percussive Reverse Cymbal 120 Sound Effects Guitar Fret Noise 121 Sound Effects Breath Noise 122 Sound Effects Seashore 123 Sound Effects Bird Tweet 124 Sound Effects Telephone Ring 125 Sound Effects Helicopter 126 Sound Effects Applause

305 Multimedia Commands

Number Class Instrument 127 Sound Effects Gunshot MIDI Glossary

Channel A channel is a number from 0-15 which corresponds to channels 1-16.

Pitch A pitch is a number from 0-127 and corresponds to a note on the instrument.

Velocity A velocity is a number from 0-127 and corresponds to how fast the key (or string) is pressed or released (most terminology is in reference to keyboards). 0 means is released.

Pressure A pressure is a number from 0-127 and corresponds to the characteristics of how the key is hit.

Program A program is a number from 0-127 and corresponds to the instrument to use. See the MIDI Instrument table.

MSB Most Significant Bits.

LSB Least Significant Bits.

Id Code Manufacturer's Id Code. Used to enter System Exclusive Mode which is specific to the manufacturer of the device.

Song A song is a rhythm machine. Sound Wave Commands

PLAYWAVE ...... 306 PLAYWAVE

Synopsis PLAYWAVE wavefile flags

Description Plays a wave file.

The wavefile input is a filename of a WAVE file. It may either be a word or a list of words. If wavefile is the empty word or the empty list, then FMSLogo stops any wave files that it is currently playing. If the file named by wavefile does not exist or is an invalid wave file, then the instruction does nothing.

The flags input is an integer that describes how the sound should be played. The meaning is given by the following table:

Flag Behavior 0 Synchronous does not stop until completed. 1 Asynchronous returns immediately while sound is still playing.

306 Multimedia Commands

Flag Behavior 2 Don't use the default sound if the specified one cannot be found. 4 In memory sound (not supported). 8 Continue to loop the sound until another PLAYWAVE instruction is run. 16 Don't stop an already playing sound.

These flags can be combined by adding them together.

Example ; loop the tada sound. PLAYWAVE "c:\\windows\\tada.wav 1+8

; wait two seconds WAIT 120

; stop the sound PLAYWAVE [] 0 Sound Commands

SOUNDON ...... 307 SOUNDOFF ...... 307 TONE ...... 308 SOUND ...... 308 SOUNDON

Synopsis SOUNDON frequency

Description Starts playing a sound on the PC speaker. The sound remains playing until you call SOUNDOFF.

The frequency input is the frequency of the sound you want to hear. The larger the frequency the higher the pitch.

SOUNDON does not work on Windows NT or Windows XP because it uses OUTPORT.

Example SOUNDON 1000 SOUNDOFF SOUNDOFF

Synopsis SOUNDOFF

Description Shutoff a sound turned on by SOUNDON.

SOUNDOFF does not work on Windows NT or Windows XP because it uses OUTPORT.

307 Multimedia Commands

Example SOUNDON 1000 SOUNDOFF TONE

Synopsis TONE frequency duration

Description Plays a tone on the PC speaker.

The frequency input must be a number and is measured in hertz (cycles per second). The larger the frequency the higher the pitch.

The duration input must be a number and is measured in milliseconds. The larger the duration the longer the tone plays for.

FMSLogo cannot respond to user control while it plays a tone.

Example TONE 1000 200

REPEAT 50 [ TONE REPCOUNT * 10 50 ] SOUND

Synopsis SOUND soundlist

Description Plays a sequence of tones on the PC speaker.

The soundlist input must be a list of pairs. Each pair specifies a frequency (in hertz) and duration (in milliseconds). The larger the frequency the higher the pitch. The larger the duration the longer the sound plays for.

FMSLogo is unresponsive to user control while it plays a sound vector.

Example Play a single frequency/duration pair:

SOUND [1000 200]

Play a sequence of descending tones [500 100 490 100 ... 10 100]:

MAKE "zing [] REPEAT 50 [ MAKE "zing FPUT REPCOUNT*10 FPUT 100 :zing ] SOUND :zing Media Control Commands

The Media Control Interface ...... 308 MCI ...... 313 The Media Control Interface

The Media Control Interface (MCI) is a facility provided by the operating system that provides programs with device-independent capabilities for controlling audio and visual peripherials. FMSLogo gives your Logo programs full access to this powerful facility through the MCI command.

308 Multimedia Commands

MCI is too rich and too complex to fully document here. Instead, we give a brief overview of the core MCI concepts and examine some sample procedures for performing common tasks. For a complete reference on MCI, search for "Media Control Interface" on https://docs.microsoft.com. As you read through the official reference manual, keep in mind that FMSLogo programs access MCI through its "command string" interface, not its "command message" interface. MCI Overview

All uses of the MCI follow the same pattern: you open a device, you run some commands, then you close the device when you're done. Each of these commands must be followed by a device name. Many commands take additional parameters that can follow the device name, which further qualify what the command should do. These parameters may be given in any order. For example, the play command starts playing a device at its current position. It takes optional from and to parameters, which specify where it should start and stop playing, as in:

MCI [play cdaudio from 2 to 3]

which tells the Media Control Interface to play track 2 of an audio CD and to stop when it gets to track 3.

Commands may accept different parameters based on the device type. For example, play on a cdaudio device only accepts to and from parameters. In contrast, play on an animation device (a movie) additionally accepts fast, slow, reverse, scan, and speed parameters.

Some parameters only need to be present to have an effect. These parameters are more commonly called "flags". Other parameters require one or more values, which must directly follow the parameter name. For example, in the play command below, the slow flag just needs to be present, but the from parameter must be followed by a position value.

MCI [play animation slow from 5]

All commands are asynchronous, unless otherwise specified. This means that FMSLogo runs the command immediately, but doesn't wait for the command to finish before running the next Logo instruction. In general, this is what you want. However, all commands optionally accept a wait flag, which instructs FMSLogo to wait until the command has finished before running the next instruction. During this time, FMSLogo will be unresponsive, so use this flag with caution. If you specify wait and then realize that you don't want to wait anymore, you can press Ctrl+Break to stop waiting.

If you don't want to wait for a command to finish, but would like to be notified when it does, you can specify the notify flag. In this case, you must also specify an instruction list as the second input to MCI. The following code uses the notify flag to print out a message when a CD audio track stops playing.

(MCI [play cdaudio from 2 to 3 notify] [PRINT [Track 2 has finished playing]]) Example: Playing a Track from a CD

The following procedure uses the Media Control Interface to play the first track on an audio CD.

TO PLAY.TRACK.1 IGNORE MCI [open cdaudio] MCI [set cdaudio time format tmsf] MCI [play cdaudio from 1 to 2] WAIT 3600 MCI [stop cdaudio] MCI [close cdaudio] END

309 Multimedia Commands

Let's take a closer look at each instruction in the example above.

The procedure first opens the "cdaudio" device by issuing an open command. This "open" has nothing to do with physically opening the CD tray, it is required before the cdaudio device will accept any other commands. Unlike most other commands, the open command outputs a value on success. Since Logo programs must do something with every value that is output, we simply IGNORE it.

The set command is used to specify the time format as "tmsf", which stands for "track:minute:second:frame".

The play command is used to start playing from one time to another. The track plays asynchronously, which means that FMSLogo doesn't wait for the track to finish playing before running the next instruction. If you wanted to wait until the track was done before moving on to the next instruction, you could add the wait flag to the end of the MCI instruction, as in:

MCI [play cdaudio from 1 to 2 wait]

Since we're using TMFS format, the to and from numbers are taken to be in tracks. TMFS values are given in tt:mm:ss:ff format, so if we wanted to play the first fifteen seconds of track 1, we could do that with the following instruction.

MCI [play cdaudio from 1 to 1:00:15]

Also note that it is not necessary to specify an end time for the play command. If you wanted to play the entire CD, you could do so with:

MCI [play cdaudio from 1]

The WAIT instruction just waits for 60 seconds. This has nothing to do with MCI, it just gives you some time to listen to the CD.

The stop command is used to stop the CD from playing.

The close command is used to tell the Media Control Interface that you are done with the cdaudio device. Example: Playing a Waveform File

The following procedure uses the Media Control Interface to play part of a waveform file.

TO PLAY.WAVEFORM IGNORE MCI [open c:\\windows\\media\\ding.wav type waveaudio alias ding] MCI [set ding time format samples] MCI [play ding from 0 to 5000] WAIT 120 MCI [close ding] END

Let's take a closer look at each instruction in the example above.

The procedure first opens "c:\windows\media\ding.wav" by issuing an open command. We use the alias parameter so that we can refer to this media entity as ding instead of always using the full path to ding.wav. Unlike most other commands, the open command outputs a value on success. Since Logo programs must do something with every value that is output, we simply IGNORE it.

The set command is used to specify the time format as "samples". A sample is the smallest unit of sound within a given waveform file.

310 Multimedia Commands

The play command is used to start playing from one time to another. The waveform plays asynchronously, which means that FMSLogo doesn't wait for the audio clip to finish playing before running the next instruction. If you wanted to wait until the track was done before moving on to the next instruction, you could add wait to the end of the MCI instruction, as in

MCI [play ding from 0 to 5000 wait]

It is not necessary to specify an end time for the play command. If you wanted to play the entire waveform, you could do so with:

MCI [play ding from 0]

The WAIT instruction just waits for two seconds. This has nothing to do with MCI, it just gives you some time to listen to your waveform.

The close command is used to tell the Media Control Interface that you are done with the waveform file. Example: Record a Waveform File

The following procedure uses the Media Control Interface to record an audio file.

TO RECORD.WAVEFORM IGNORE MCI [open new type waveaudio alias mysong] MCI [record mysong] WAIT 300 MCI [stop mysong] MCI [save mysong mysong.wav] MCI [close mysong] END

Let's take a closer look at each instruction in the example above.

The procedure first opens the waveaudio device by issuing an open command. The new flag tells MCI that the waveaudio device should be opened for recording, not playback. The alias parameter is required when using the new flag. In this case, it gives the recording session the name "mysong" so that future instructions can refer to it. Unlike most other commands, the open command outputs a value on success. Since Logo programs must do something with every value that is output, we simply IGNORE it.

The record command is used to start recording on the microphone.

The WAIT instruction just waits for five seconds. This has nothing to do with MCI, it just gives you some time to record your audio clip.

The stop command turns the microphone off and stops recording from it.

The save command copies all of the recorded audio data to a file named mysong.wav. Keep in mind that all MCI commands are run asynchronously, which means that FMSLogo may start running other Logo instructions before the file has been fully written. To make sure that FMSLogo waits until the file is 100% written, you can add the wait flag, like this:

MCI [save mysong mysong.wav wait]

Once the mysong.wav has been saved, it can be played with most other audio programs. It can also be played with FMSLogo by using the PLAYWAVE command or other MCI instructions.

The close command is used to tell the Media Control Interface that you are done with the microphone.

311 Multimedia Commands

Example: Playing a Video File

The following procedure uses the Media Control Interface to play a video file.

TO PLAY.AVI IGNORE MCI [open c:\\windows\\clock.avi alias clock] MCI [play clock] WAIT 120 MCI [pause clock] WAIT 120 MCI [resume clock] WAIT 720 MCI [close clock] END

Let's take a closer look at each instruction in the example above.

The procedure first opens "c:\windows\clock.avi" by issuing an open command. We use the alias parameter so that we can refer to this media entity as clock instead of always using the full path to clock.avi. Unlike most other commands, the open command outputs a value on success. Since Logo programs must do something with every value that is output, we simply IGNORE it.

The play command is used to start playing from one time to another. The video plays asynchronously, which means that FMSLogo doesn't wait for the video to finish playing before running the next instruction. If you wanted to wait until the video was done before moving on to the next instruction, you could add wait to the end of the MCI instruction, as in:

MCI [play clock wait]

The WAIT instructions just waits for some amount of time. They have nothing to do with MCI, they just gives you some time to see the result of the previous MCI command.

The pause and resume commands are used to pause and unpause the video.

The close command is used to tell the Media Control Interface that you are done with the video file. This closes the window in which the video was playing. Example: Playing a MIDI File

The following procedure uses the Media Control Interface to play a MIDI file.

TO PLAY.MIDI IGNORE MCI [open c:\\windows\\media\\flourish.mid type sequencer alias flourish] MCI [play flourish] WAIT 600 MCI [stop flourish] MCI [close flourish] END

Let's take a closer look at each instruction in the example above.

The procedure first opens the MIDI file "c:\windows\media\flourish.mid" by issuing an open command. The type parameter is set to sequencer, which is the device name for the MIDI sequencer. We use the alias parameter so that we can refer to this media entity as flourish instead of always using the full path to flourish.mid. Unlike most other commands, the open command outputs a value on success. Since Logo programs must do something with every value that is output, we simply IGNORE it.

312 Multimedia Commands

The play command is used to start playing the MIDI file. The music plays asynchronously, which means that FMSLogo doesn't wait for the music to finish playing before running the next instruction.

The WAIT instructions just waits for ten seconds. This has nothing to do with MCI, it just gives you some time to listen to the music before it is stopped.

The stop command stops the song from playing.

The close command is used to tell the Media Control Interface that you are done with the MIDI file. MCI

Synopsis MCI mci-command-list (MCI mci-command-list callback)

Description MCI lets you write Logo procedures to manipulate multimedia devices. With it, you can link sounds to the steps of drawing a picture. You can narrate your own slide show. You can even ask your user questions in your own voice. The MCI interface is very powerful. It opens the door to letting Logo control any multimedia device, including sound cards, CD players, movies, and more.

Depending on the command, MCI may (or may not) output a status that indicates if the command was successful.

The mci-command-list input must be a list. The format of the list is described in the section entitled The Media Control Interface.

The MCI allows you to start a device and optionally "wait" for it to finish or to have it "notify" you when it has finished by running the callback input. The callback input is an instruction list that is run when the MCI command completes if you use the "notify" option. The "notify" mechanism allows you, for example, to play a wave file and be notified when it has completed so that you can start another immediately without sitting and "waiting" for it.

Example TO SOUNDIT PRINT MCI [open c:\\windows\\tada.wav type waveaudio alias wa1] PRINT MCI [open c:\\windows\\ding.wav type waveaudio alias wa2] MCI [seek wa1 to start] MCI [play wa1 wait]

REPEAT 2 [ MCI [seek wa2 to start] MCI [play wa2 wait] ]

MCI [close wa1] MCI [close wa2] END

313 Glossary

Array A primitive data type that is an ordered set of zero or more things. For example, {123 abc} is an array with two members. Arrays are similar to lists, except you can easily change the items within an array, but you can't easily create a new array that is everything after a specified item. That is, SETITEM works, but BUTFIRST doesn't. In general, procedures which operate on large arrays are faster than equivalent procedures which operate on large lists.

Command A procedure that does not output a value.

Color Vector A list of three numbers that represents the magnitude of red, green, and blue that are associated with a particular color. The numbers within the list must be integers from 0 to 255, inclusive. Wherever a colorvector is accepted as input, you may also supply a color index.

Contents List A list of three lists, which respectively contains the names of all procedures, variables, and property lists within a workspace. Contents lists are sometimes abbreviated by omitting the list of things that are irrelevant in a particular context. For example, [[SQUARE TRIANGLE] [myvar] [myplist]] is a contents list for a workspace that contains two procedures (SQUARE and TRIANGLE), a variable (myvar), and a property list (myplist). If you were only interested in the variables, then the contents list could be abbreviated to [[] [myvar]]. Note that you can't remove a list that comes before the one you're interested in, so the list of procedure names still appears, even though it is empty. You can remove a list that comes after the one you're interested in, so the list of property lists is omitted.

Drawing Surface The area on which the turtle can draw. This may be larger or smaller than the screen window, depending on how large the window is. By default, this is 1000 x 1000 turtle steps.

Element An item of an array that is indexed based on the physical layout in memory, instead of by its origin. For example, in the array {a b c}@0, b is the first item, but the second element.

Form A series of tokens that is syntactically correct for evaluation in Logo.

Expression A series of tokens that, when RUN, produces a value. This include operations with all of its inputs, as well constant expressions like 3 or "foo.

Instruction A series of tokens that that, when RUN, produces no value. Generally, this is a command with all of its inputs.

Item An indexed thing that is contained within a word, a list, or an array. For example, the third item of "abcd is "c. Items are usually called members when their location within a word or list is unimportant.

List A primitive data type that is an ordered sequence of zero or more things. For example, [123 abc] is a list with two members.

Instruction List A list of words that are intended to be RUN by some other command. These should be well-formed expressions or instructions, depending on if the procedure that runs the instructionlist expects an output or not.

314 Glossary

Member A thing that is contained within a word or list. For example "c is a member of "abcd. Members are usually called items when their location within a word or list is signficiant.

Operation A procedure that outputs a value.

Procedure A named collection of instructions that peforms some task. Procedures that output a value are called operations. Procedures that don't output a value are called commands.

Run The process of evaluating one or more instructions or expressions and performing all of the side effects associated with them.

Special Form A series of tokens that is syntactically correct for evaluation in Logo, but whose meaning is determined by a special rule rather than by the default rule of running it as an instruction or expression.

Word A primivite data type that is a sequence of characters. This includes constants, like "foo and numbers, like 3.14.

315