image

REALbasic Book Afterthoughts

 
 

These are errata, desiderata, updata, and miscellaneous shmata connected with the first edition of my REALbasic book. These are all made superfluous by the advent of the second edition. But if you’re still using the first edition and REALbasic 2.1.2, you might find this page helpful.

I’d like to thank the many people who have written in with errors and suggestions, including (in absolutely no order whatever) Joe Huber, Tony Rich, James Wilson (three gold stars), Joe Brown (several more gold stars), Kem Tekinay, Bernd Froehlich, Bob Urschel, Dave Fultz, Bob Stern, Fabian Lidman, Mark Stubbs, Donald Siano, George Bate, Andrew Who Is Nice to Bears, Charles Yeomans, and probably others whose names I’m sorry I’ve omitted.

p. 3
First sentence (wow, only one sentence and already it’s a mistake), change it to: “This chapter introduces the REALbasic workspace, also known as the IDE (for integrated development environment; see the Preface, What REALbasic Is Like).”
p. 31
Last example, showing use of Return in a function: Sub and End Sub should be Function and End Function.
p. 41
Third example: comment symbols omitted. The second and fourth lines should read:
// ... [what to do if condition1 is true] ...
// ... [what to do if condition2 is true] ...
p. 49
“Except, of course … zero-based.” I would prefer that this sentence be in parentheses.
p. 50
Third example, second line: it would be clearer if the line ended with a comment, // error.
p. 65
Second paragraph of the new section; completely replace the paragraph (up to the footnote) with the following: In order to study the Code Editor of a class, we need to make a class. To do so, you choose File -> New Class, unless the class is to be a window class, in which case you choose File -> New Window. However, there is no need to do this right now; issues of class creation are the subject of Chapter 4, and it just so happens that even an empty project provides us with one excellent example of a class ready-made - the Window1 window class. So you might wish to open the Window1 Code Editor at this point, to help you follow the discussion. (And the footnote then follows as now.)
p. 75
Last line (the end of the code example), there should be a space in the string before “buttons.”
p. 79
4th para, last sentence, second word, “each”, first letter: wrong font.
p. 84
2nd para, fourth word should be pushButton1(1).
p. 91
The discussion of passing an object parameter by reference is not as compelling as it might be, because it isn’t clear why a function would want to repoint an object. It might be better to show the function initializing the object. This came up in a real situation for me the other day; I have a nil Picture instance and I want to send it off to a function to initialize it with NewPicture (because the function knows the right width and height), and you can’t do that without ByRef.
p. 92
Change all references to “garbage collection” to “reference counting”, to get Joe Strout off our backs. Also, I should have added a clear warning about circular references at the end of the section.
p. 93
Last sentence: it is just possible that there is now a better workaround, namely to test whether the window’s macWindowPtr is zero. I have not studied this extensively yet.
p. 95
Third paragraph: after saying how to create a new class, I should insert a sentence saying that if the new class is to be a window class, you choose File -> New Window instead, and perhaps something pointing out in advance that for purposes of this chapter window classes are a bit exceptional, since they cannot be subclassed.
p. 122
End of page: The section on Constructors and Destructors fails to explain how inheritance is deal with. The rule is that when an object is instantiated, REALbasic looks up the hierarchy for a constructor - that is, it looks in the class of the object being instantiated, then in its superclass, then in its superclass, and so on. As soon as it finds a constructor, it executes it, and that’s all; it does not, for example, then execute the constructor of the superclass of the class where it found the constructor (though of course the constructor that it does execute can call its superclass’s constructor explicitly).
p. 127
In a future edition I’d like to have a subsection on pointer-to-function at this point. The question of how to do this comes up fairly often (i.e. call a function which isn’t specified until runtime). This might also make a more compelling example of how to use class interfaces.
p. 127
Another thing to talk about here is how to get around the limitations on ByRef by using an object as a carrier. For example, let’s say you’ve got a Picture object stored as a property, and you want to pass a reference to it to a function that will initialize it with NewPicture. You can’t do this without ByRef, but you can’t use ByRef because a property is not a local. The solution is to make the property a PicturePtr object - an object with one property which is the Picture. You can pass the object in the ordinary way, and receiving function can now do whatever it likes to the Picture. In short, wrapping an object around a thing is the most general way to make a pointer to that thing.
p. 127
Fifth paragraph, replace “Finally” with “Further”, and add a new ending to this paragraph: “Finally, an array wrapper class solves the problem of the unusual status of arrays in REALbasic, that they are neither a class nor a datatype; for example, you cannot declare an array of array, but you can declare an array of a class that wraps an array.”
p. 130
It would have been nice at this point to insert a Hash class example that uses the string array wrapper class just developed. This would have illustrated its value for making arrays of arrays (see previous item). A simple hash based on the sum of the ascii values of the first and last characters of the string would do for illustrative purposes. This has been corrected in the downloadable book examples.
p. 131
In a future edition I’d like to add some more example classes. A map class would be very nice, and could be used to illustrate the use of a varPtr class as a way of returning a reference (to a value of arbitrary type); I have one sitting around.
p. 142
First footnote, the domain name of the first URL is misspelled (should be “wanadoo”).
p. 143
Users are occasionally stumped by the fact that the TextEncodingConverter’s input buffer is only 1024 characters long. This fact should be mentioned explicitly, and an example given showing how to break a long conversion into shorter segments.
p. 147
A subsection on Errors should be inserted. Numeric operations can yield errors - for example, you can divide by zero, or take the square root of a negative - and you are not notified; you must test explicitly. Franco Vaccari has pointed out to me that testing whether d=d will reveal in most cases whether d is an error, and is very fast. However, this doesn’t catch the divide-by-zero case. The most general test, though slower, is to coerce to a string and check against the various possible error strings, such as “INF”, “NAN”, and so forth. (Ideally, perhaps REALbasic should throw an exception the moment a numeric error occurs.)
p. 149
Before the second paragraph, insert a paragraph pointing out that comparison between variants always fails, and providing the proper technique (assign one of them to a scalar first).
p. 150
At the end of the Variants section, add a paragraph something like this:

Variants are especially useful in method declarations. If a method takes a variant parameter, it can called in the expectation that it will take a parameter of some particular type, and that expectation will be met. If a method returns a variant, it can be called in the expectation that it will return some particular type, and that expectation will be met. For example, in the cArray class developed in Example 4-1, if you change every occurrence of “string” to “variant”, the class still works (except for sorting), and the test routine still works (except for sorting). The difference is that now if you write a different test routine which treats cArray as an array of integers instead of an array of strings, it works too! Instead of writing one wrapper class for an array of strings and another wrapper class for an array of integers, a single wrapper class for an array of variants can be used for both. Thus, variants are a labor-saving device for the programmer, because they make classes more reusable. This is roughly comparable to the use of templates in C++.
p. 152
References to the trick of setting the totalSeconds property to itself can all be deleted; the bug has been fixed.
p. 157
The last sentence of the last paragraph, and the example, can be deleted; Insert and Append now work properly on Color arrays.
p. 159
Middle of the page: on Windows, gathering up Byte values from an original Long will yield the same results in the opposite order, because of the endian difference. It is useful to have on a hand a utility routine (I call mine TwiddleBytes) that reverses the order of two or four bytes of a memoryblock on Windows; that way, you can call the routine in situations like this, between writing as a Long and gathering up as Byte, and the Byte indexes will come out the same on both platforms. In general this is a Mac book, but it was wrong of me to have omitted this important information.
p. 161
Last example, third line: introduce a subsequent line
mm = newMemoryBlock(len(s)+2)
p. 162
The section “Being Careful” can be deleted. The warning about not locking down memory can be moved to the start of the section, and the warning about not writing off the end of a memoryblock is no longer needed, because REALbasic now does bounds checking to ensure that this won’t happen.
p. 162
Both code examples, $FF should be &hFF.
p. 168
Some readers wrongly assume that semaphores / critical sections imply that when a thread encounters code to which the door is barred (a critical section which another thread already occupies, or a semaphore which it cannot signal because another thread has already done so), it will enter that code the instant such entry is possible (as soon as the other thread leaves the critical section or releases the semaphore). This is not true, of course, and the next-to-last paragraph on this page says as much, but I think an additional sentence might stress this point, and perhaps I could even add a version of the Racing ProgressBars example rewritten to use a dispatch mechanism to ensure that each bar progresses in turn. This might take advantage of the ThreadID property, which needs mentioning anyhow.
p. 181
Figure 6-3: the diagram would be clearer if the event handlers being triggered were labelled at each stage. So, the first four stages (the top row) might be labelled (from left to right) EnableMenu, EnableMenuItems, EnableMenuItems, EnableMenuItems; and the second four stages (the bottom row) might be labelled (from right to left) ItemName, ItemName, ItemName, Action.
p. 182
It would really help the discussion at this point if I were to introduce a section Static Menus and just went through the complete motions of creating a menu item and implementing its functionality. The About item of the Apple menu would be a good choice.
p. 182
End of the page: There’s a bug in REALbasic where invisible menu items, unless enabled, can screw up the enabling of subsequent menu items. I implicitly use the workaround in the example at the bottom of the page (enabling the item whether it is visible or not), but I should comment explicitly on this point (unless, of course, the bug gets fixed).
p. 218
Turkey at the end of the page: delete the turkey. This was fixed at last (2.1a24).
p. 219
The next-to-last paragraph may need to be modified slightly to take account of the new behavior where the Language popup’s Default item actually changes to tell you what the Default Language setting is. Also, Version Info now appears as Package Info.
p. 223
Example (freeheap): the example is not working helpfully and will have to be altered. The Apple event will have to be replaced with a Toolbox call; I believe that something along the following lines should suffice:
dim total, contig as memoryBlock
dim dummy as integer
total = newMemoryBlock(4)
contig = newMemoryBlock(4)
dummy = interfacelib.purgespace(total, contig)
p. 225
At the end of the next-to-last paragraph is the place to mention the RBVersion and RBVersionString constants.
p. 226
First sentence, “built-in global booleans”: add “or a boolean constant defined in a module”. It had not occurred to me, at the time I wrote this sentence, that there would be reason to use conditional compilation based on a programmer-defined constant, since every situation where one would wish to do this would be covered equally well by a normal condition. I still feel this way (the overhead in an application of even large quantities of unexecuted code cannot be much), but that is no reason to be inaccurate.
p. 242
First example: I ought to point out explicitly here that implicit instantiation works just as well. That is, the line could have been written:
i = saveChanges.init(self)
p. 262
In the RGBSurface discussion, there’s a new feature: change “32” to “32 or 16”, and add: “other Picture instances have a nil RGBSurface” (and delete the turkey; the bug has been fixed).
p. 266
What I say about the pen height and width being expressed down and to the right of the coordinates you give, is true for DrawRect and DrawPolygon, but not for DrawOval and DrawRoundRect, which express their pen height and width inwards. In other words, the contrast is not, as my words imply, between the Draw- commands and the Fill- commands, but between DrawRect / DrawPolygon on the one hand, and everything else on the other.
p. 287
Second and third examples: in the first two lines of each, delete “canvas1.”. (JLeft and JTop are window properties, not canvas1 properties; it isn’t until the end of this page that we rewrite using a Canvas subclass, so that they become canvas1 properties.)
p. 289
Second and third examples: if the refreshRect line is changed to
canvas1.refreshrect 0,0,0,0
the example still works. The reason apparently is that as long as you ask for something to be refreshed, the new material scrolling in will automatically be refreshed in addition, in accordance with the clipping rule mentioned on p. 286. This is cool because it means there’s a way even in this situation to let REALbasic do the math as to what needs refreshing.
p. 297
Last paragraph, “Figure 11-20”: should be “Figure 11-21”.
p. 340
Code example, 11th line, change “theeend” to “theend”.
p. 342
First code example, 2 lines from the end (“theField…”), the line needs to be tabbed one more to the right.
p. 392
The second footnote can probably be deleted: the crash is said to have been fixed.
p. 412
First body paragraph, “we don’t the StaticTexts”: insert “want” before “the”.
p. 414
Second footnote: change the URL (for Rolf Heller’s CharKeyCode XFCN) to http://mirror.apple.com/mirrors/info-mac/dev/card/key-xfcns-20.hqx. The URL was right, but has expired.
p. 425
Last paragraph: delete the paragraph. The leak has at last been fixed (2.1a26). Also, there is now a new way to overcome the watch, namely the disableAutoWaitCursor pragma; however, it is very oddly implemented (it is really a global compilation constant, not a pragma at all), so it may not suit everyone’s needs, and this section remains valuable.
p. 432
The “Bad FolderItem” bug has been fixed (starting in 2.1a28)! Trying to create one will result in a nil FolderItem, which is easy to check for. This also obviates the need for the workaround described on p. 441.
p. 434
The GetTemporaryFolderItem function needs to be mentioned here (in a sentence or two at the end of the 7th paragraph).
p. 442
It turns out that the trick of yielding time may not be necessary here. According to Steve LoBasso, it isn’t the file system that’s playing us false; it’s REALbasic itself, which has cached information about the folder it created, and has not updated that information while creating the three files inside it. To get it to do so, it suffices to reassert the identification of the folderitem f. Thus, the code should go like this:
dim b as binarystream
dim f as folderitem
f = desktopfolder.child(testingtesting)
f.createasfolder
b = f.child(one).createbinaryfile(text)
b.close
b = f.child(two).createbinaryfile(text)
b.close
b = f.child(three).createbinaryfile(text)
b.close
f = desktopfolder.child(testingtesting)
msgbox str(f.count)
The msgbox gets the right answer, and there is no need to step out to a timer after all.
p. 444
This might be ultimately the place to talk about the MacVRefNum and MacDirID properties of a FolderItem.
p. 445
Third paragraph: the paragraph is unnecessarily coy about how to resolve an alias; I should have thought this was obvious, but reader comments suggest that it is not. The technique has been elegantly summarized by Chad McQuinn as follows:
if f.alias then
  f = f.parent.child(f.name)
end
Also, I’m getting reports of people having occasional trouble with the AppleScript technique for creating an alias. There are third-party plug-ins that can do the job better, but REAL’s failure to include this functionality as part of the language is mystifying; meanwhile, the AppleScript device was always just a workaround, but at least it relies solely upon RB’s native abilities.
p. 459
Fifth body paragraph, “simply send refer”: delete “send”.
p. 465
Second paragraph: straighten the slanted single quote after the second “snd”.
p. 466
I still haven’t experimented with the QTGraphicsExporter class, but I do now have QT4, and this is the place to describe the class, so ultimately that will need doing.
p. 470
First full paragraph, “pointing the file”: insert “to” before “the”.
p. 470
Third code block, the setting of the variable d should be wrapped in an openRealDatabase call.
p. 473
Mention of the DatabaseCursorField’s JPEGValue property, and the corresponding DatabaseRecord’s JPEGColumn property, is deliberately omitted - it’s broken. MacPict and MacPictValue, and even IntegerValue, are said to be broken too!
p. 478
4th bullet paragraph, second line, there should be a hyphen at the end of the line.
p. 488
Third body paragraph, “But no law says that you have do this”: insert “to” before “do”.
p. 490
First and second paragraphs, “EnableDrag” should be “DragRow”. - Also it would be nice if I’d mention (and give the workaround to) the bug with dragging the second row of a ListBox here, but I keep hoping REAL will fix it.
p. 500
Last paragraph: delete the paragraph. This has at last been fixed (2.1a25).
p. 508
Last paragraph: perhaps delete the paragraph, in conjunction with the change on p. 442; it is not, perhaps, necessary after all to step out to a timer to get file actions to catch up with themselves. The technique is still needed on p. 528ff, though; I have not found any other way to get REALbasic to close the file as an EditableMovie and reopen it as a normal Movie.
p. 529
Example: the code should really be modified slightly so as to include the first p in the movie, since it turns out that the qteffectsequence omits it. I’ve done this in the online version.
p. 532
I’m not sure whether this or the previous chapter would be the place to talk about the SoundFormat class. The problem here is that REAL has never documented the class; I know nothing about it.
p. 539f
Starting about version 2.1a29, REALbasic’s SpriteSurface scrolling behavior was changed so that scrolling the background scrolls the sprites (to put it another way, a sprite maintains a consistent coordinate system with respect to the 0,0 position of the background when the surface starts running). This means that the examples must be changed; in order for the Sprite to appear to move diagonally downwards, it must compensate for the scrolling action of the background. My online examples have been altered to reflect this.
p. 552
It has been pointed out to me that James Milne’s MADPlug (see p. 634) can play a MOD file while a SpriteSurface is running. To be sure, I’ve never heard a MOD file that I didn’t regard as hideous; however, I suppose that’s no reason to be silent on the matter. Still, I feel that properly speaking SpriteSurface soundtracks are a problem REALbasic should handle without a plug-in.
pp. 559f
The code developed here does not work on postscript printers. In my online version of this example, I’ve included the Brosius-Ulmenstein modification of the code, but there are still printers for which it doesn’t work. In a better world, I’d do more research on the problem and rewrite this section. In the best of all worlds, REALbasic would include verbs for learning resolutions and choosing one.
Also it would be nice if I would add something about high-resolution printing on Epson printers, since this is much easier than what I describe here: to print at 360 dpi, you just draw into a picture 5 times the size of the nominally 72-dpi printer graphics, and scale down into the graphics with DrawPicture. (And you can learn the user’s resolution setting from bytes 34-5 and 36-7 of the setupString.) Perhaps this would have worked on the StyleWriter too?
pp. 571
Next-to-last code block: Use of the hard-coded IP address 206.74.122.3 is now deprecated; use dict.org instead. The online version of the code for this example has been updated to reflect this change.
pp. 576
First code example: in both the 4th and 16th line, the first closing-parenthesis should be deleted.
p. 600
The URL for EightyRez is now http://www3.shore.net/~gmcgath/EightyRez.html, and it’s now freeware. Accordingly, I’d recommend it over ResEdit, and in a future edition would probably prefer to use it, rather than ResEdit, in this part of the book.

Back

This page prepared August 21, 2012 by Matt Neuburg, phd = matt at tidbits dot com, using RubyFrontier. RubyFrontier is a port, written in the Ruby language, of the Web-site-creation features of UserLand Frontier. Works just like Frontier, but written in Ruby!
Download RubyFrontier from GitHub.