Jun 97 - Newton Q and A
Volume Number: 13
Issue Number: 6
Column Tag: develop
Newton Q&A: Ask the Llama
by Apple Developer Technical Support Group
Q: I'm probably missing something obvious, but when I try to use an
asynchronous output call in some situations, I get an exception, while
synchronous calls seem to work fine. For instance, this code fails
consistently with bus errors:
endpoint:output(headerCache,
nil,
{async: true,
form: 'string,
completionScript: func(ep, options, result)
self:SendData(endpoint, qfCursor)});
On the other hand, this code works fine:
endpoint:output(headerCache, nil, nil);
self:SendData(endpoint, qfCursor);
I'd really prefer to use asynchronous calls, but I keep running into problems. Do you
have any suggestions?
A: The key thing you're missing is that self (that is, the receiver) is not what you
expect in your asynchronous callback. In your first example, you pass a completion
frame as the third argument of the Output message. It's this frame that will be self
(that is, that will be the context of the completionScript). This means that you send
the sendData message to that completion frame.
What you probably want is to send the message to the ep argument passed to the
completionScript. This will be the endpoint to which you sent the Output message. In
general, you will have set this endpoint to have a _parent slot that points to your
application. Assuming that the sendData method is in either the endpoint or your
application, you would modify the body of the completionScript to be
ep:sendData(endpoint, qfCursor);
The same restrictions apply for Input and Option calls as well.
______________________________
Q: I have a pop-up view that has an icon with some text, and I'd like
the user to be able to edit the icon. I call MakeShape on the icon and
draw it into a bitmap. I then have an interface for the user to modify
the icon. The problem occurs when I try to display the modified icon in
the pop-up. It either doesn't show up, has incorrect bounds, or throws
an exception. Before I modify the icon, it looks like something that
would be returned by GetPictAsBits:
{data: , bounds: {0,0,15,15}, }
Once I call MakeShape on the icon, it looks like this:
{class: bitmap, bounds: ,
The pop-up chokes on this when I try to display it. First it threw an
exception because it was expecting a frame instead of a binary object in
the bounds frame. So I called SetBounds to set the bounds frame to
{0,0,15,15}. This enabled the pop-up to open, but the icon wasn't in
the right place. Fiddling with the bounds frame didn't seem to help. So
I'm guessing that the next problem is that I have pixels instead of bits
in the data slot. I tried calling SetClass on the slot to change it from
pixels to bits. That actually didn't throw an exception, but the length is
still different and it didn't look right. How can I get my shape or bitmap
back into a form that the pop-up will be happy with?
A: The basic problem is that the binary object used by MakeShape to represent the
picture (that is, ) is not the same as that used in the bitmap structure (). You have a couple of choices. Since the formats are
documented, you can write some code to convert the object returned by MakeShape into
a NewtonScript bitmap object. The other option, which seems more complex but is
probably easier to implement, is to use the MakeShape representation only for your
icon editor. Let the user modify the MakeShape representation, but keep track of the
changes and use them to modify the bitmap. So, while the user is editing the icon, there
will be two data objects: the original icon representation using the bitmap data
structure and the MakeShape representation that the user sees and modifies. As the
user changes the MakeShape object, your code is also modifying the bitmap object.
As a related side note, you can use DrawIntoBitmap to get the bits that represent the
shape.
______________________________
Q: In an application I'm building, I want to keep a serial
communication session open with a GPS unit 24 hours a day, unattended
by the user. Both the MessagePad and the GPS unit are powered by the
car. The GPS unit sends out data approximately every two seconds. I'm
using the "Basic Serial" Newton DTS sample code as the starting point.
The communications code in the application works fine except that
occasionally I get a -18003 exception, which results in a
kMessage_BufferOverrun message. I've tried turning on
useSoftFlowControl and useHardFlowControl in the
kCMOInputFlowControlParms parameter frame inside the
MBuildConfigOptions method, but that doesn't seem to help.
Can you explain when/why this exception is raised? Can I safely ignore
the exception by revising the MNotifyError method? What can I do to
prevent the occurrence of the exception in the first place?
A: A -18003 error can indicate several things, including bad parity or a framing
error. Usually it indicates that the Newton's UART (SCC chip) buffer has overrun. You
can just ignore this error, repost the input specification, and go on your merry way.
To repost the input specification, call the endpoint's SetInputSpec with the relevant
input specification. Before reposting the input specification, you may also want to
flush the communication tools buffers using the serial discard data option
(kCMOSerialDiscard) and flush the NewtonScript buffer with FlushInput. Regardless
of whether you flush, you will have lost some data in the process, although for most
GPS applications that should be fine. You may also want to try increasing the size of the
serial input buffer; this might give you just enough time to process all the data.
A better solution would be to have the GPS receiver support some type of flow control,
though this will depend on the manufacturer of the unit.
______________________________
Q: I have a view with a protoKeyboard button. The input lines within
the view all take numeric input, and when the user double-taps, the
numeric keypad pops up. But the keyboard button brings up the full
QWERTY keyboard instead. How can I make the button open the numeric
keypad?
A: The keyboard button is behaving correctly. If you don't specify which keyboard to
open, it will always open the global alphanumeric keyboard. There are two ways you
can get the behavior you want:
• Override the 'defaultKeyboard slot in your protoKeyboardButton. This slot
contains the keyboard that you want to use. In this case you want the symbol
'numericKeyboard, which specifies the default numeric keyboard.
• Override the buttonClickScript in the protoKeyboardButton. You can use
the OpenKeypadFor function and specify your input line as the view. This will
usually do the right thing since calling OpenKeypadFor has just about the same
effect as the user's double-tapping in an input line.
______________________________
Q: I noticed that the NTK project preferences dialog lets you compress
your application. How much slower will the application run if I do this?
A: Unfortunately, there's no simple answer to this question. The speed of execution
depends on a number of factors, including how many times the system has to
uncompress pages from your application into a cache and how full the system heap is.
The best way to find out is to try your application with the three different compression
options: none, compressed, or faster compression. Make sure that you perform your
tests a number of times and under different memory-loading conditions. If your
application will be doing communications, that's a good thing to test. You can also use
HeapShow (which comes with NTK) to fill the system and NewtonScript heaps to
simulate low-memory conditions.