haiku-website/static/legacy-docs/benewsletter/Issue4-32.html

427 lines
33 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Be Newsletters - Volume 4: 1999</title><link rel="stylesheet" href="be_newsletter.css" type="text/css" media="all" /><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="./images/favicon.ico" /><!--[if IE]>
<link rel="stylesheet" type="text/css" href="be_newsletter_ie.css" />
<![endif]--><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><link rel="start" href="index.html" title="Be Newsletters" /><link rel="up" href="volume4.html" title="Volume 4: 1999" /><link rel="prev" href="Issue4-31.html" title="Issue 4-31, August 4, 1999" /><link rel="next" href="Issue4-33.html" title="Issue 4-33, August 18, 1999" /></head><body><div id="header"><div id="headerT"><div id="headerTL"><a accesskey="p" href="Issue4-31.html" title="Issue 4-31, August 4, 1999"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a accesskey="u" href="volume4.html" title="Volume 4: 1999"><img src="./images/navigation/up.png" alt="Up" /></a> <a accesskey="n" href="Issue4-33.html" title="Issue 4-33, August 18, 1999"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="headerTR"><div id="navigpeople"><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div><div class="navigboxed" id="naviglang" title="English">en</div></div><div id="headerTC">Be Newsletters - Volume 4: 1999</div></div><div id="headerB">Prev: <a href="Issue4-31.html">Issue 4-31, August 4, 1999</a>  Up: <a href="volume4.html">Volume 4: 1999</a>  Next: <a href="Issue4-33.html">Issue 4-33, August 18, 1999</a></div><hr /></div><div class="article"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Issue4-32"></a>Issue 4-32, August 11, 1999</h2></div></div></div><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Engineering4-32"></a>Be Engineering Insights:<br />
I. Making Your BLoopers More Responsive<br />
II. Gamma Correction
</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Jean-Baptiste</span> <span class="surname">Queru</span></span></div></div></div><p>
Some of my fellow engineers tell me that I'm lucky to have so many ideas
for my newsletter articles. They couldn't be more wrong. Having to choose
between two ideas is much harder (at least for me) than having to find
one idea. After whittling a pile of ideas down to just two, I couldn't
choose between them, so I'm using both for this article.
</p><p>
You can find the source for them here:
ftp://ftp.be.com/pub/samples/graphics/gamma.zip
</p><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id807993"></a>Part I: Responsive BLoopers</h3></div></div></div><p>
Something that BeOS developers must keep in mind when programming their
user interface is that users don't like interfaces to feel slow or
sluggish. One key to interface responsiveness is to let the <code class="classname">BLooper</code> run
freely and process messages. To achieve this goal, you must make sure
that your program doesn't spend too much time sitting in the various
virtual functions that the <code class="classname">BLooper</code> will call
in its <code class="classname">BHandler</code>s. The sample
code for this article shows two techniques that should cover a reasonable
number of common cases.
</p><div class="sect3"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id808022"></a>Use Asynchronous Controls</h4></div></div></div><p>
In older versions of BeOS, the only way to track the mouse to dynamically
change a control was to repeatedly call <code class="methodname">GetMouse()</code> in a loop. The BeBook
mistakenly suggested doing this in <code class="methodname">MouseMoved()</code>, which would prevent the
BLooper from processing message as long as the mouse button was held
down, which could be a very long time. The correct way to do this was to
poll in a separate thread, a tricky thing to set up and to tear down
without deadlocking.
</p><p>
Fortunately, R4 added an elegant way to solve the problem: the view event
mask, which lets you create asynchronous controls. Since this has already
been explained in other Newsletter articles, I won't say much about it,
but you can look at the sample code to see one of those beasts in action.
For more information,
</p><p>
see: <a class="xref" href="Issue3-45.html#Engineering3-45" title="Be Engineering Insights: That BeOS is one baaad mother-[Shut your mouth!] ...just talking 'bout BeOS">Be Engineering Insights: That BeOS is one baaad mother-[Shut your mouth!]
...just talking 'bout BeOS</a><br />
and<br />
<a class="xref" href="Issue3-46.html#Engineering3-46" title="Be Engineering Insights: The Kitchen Sink">Be Engineering Insights: The Kitchen Sink</a>
</p></div><div class="sect3"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id808073"></a>Use Other Threads to Do the Actual Work</h4></div></div></div><p>
We're now reaching the heart of the problem. The naive way to implement
real time user feedback with asynchronous controls is to redraw the
display each time <code class="methodname">MouseMoved()</code> is called.
Change the <code class="code">#if</code> in the sample
code to see what happens in that case. This is not what a user wants to
see, and it gets worse as the processing time gets longer. A temporary
solution might be to eliminate some of the <code class="constant">B_MOUSE_MOVED</code> messages by hand
in the <code class="classname">BMessageQueue</code> before they're dispatched; this only works if the
processing stays reasonably short and if the <code class="classname">BLooper</code>
is a <code class="classname">BWindow</code>.
</p><p>
A more general solution is to have another thread do the work for the
<code class="classname">BLooper</code>, so the <code class="classname">BLooper</code>
can continue processing messages (e.g., update
messages) as they come along. Since setting up and tearing down threads
can be painful, and can easily create deadlocks and other race
conditions, I've encapsulated all that work in two classes—called
<code class="classname">SignalSender</code> and <code class="classname">SignalCatcher</code> --
that I hope will be reasonably easy to
use. Those classes are an example of how easy it is to create your own
synchronization classes, and you might even find them useful in their
current state.
</p></div></div><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id808143"></a>Part II: Gamma correction.</h3></div></div></div><p>
The sample code is not only interesting because of the programming
techniques it uses, but also because of what it does. This small program
is actually intended to calibrate a gamma correction system and to use
this system to draw anti-aliased lines.
</p><p>
Gamma is a very simple process. The intensity of light created by a CRT
is a nonlinear function of its input voltage. Gamma is a parameter that
represents this nonlinearity, and gamma correction is the process of
compensating for this nonlinearity. Surprisingly, this nonlinearity is
the same for all CRTs: the intensity of light produced by the CRT is
proportional to the input voltage raised to the power 2.5. You can thus
repeat after me: "Gamma is 2.5."
</p><p>
There are, however, many components between the framebuffer (or, more
precisely, the DAC) and the CRT's input: various amplifiers, filters,
brighness/contrast controls. Overall, those components scale and offset
the signal between the DAC and the CRT.
</p><p>
All the math is done in a <code class="classname">GammaCorrect</code> class, so you don't have to know
exactly how it works if you don't want to.
</p><p>
The patterns displayed by the program are these:
</p><ul class="itemizedlist"><li><p>
In the top-left corner, a median blend of black and white (note that
I'm using lines, because some monitors, although expensive, have some
limitations that make other patterns yield incorrect results).
</p></li><li><p>
In the top-right corner, a plain gray that you can select using the
control in the bottom of the screen and that you must try to adjust to
the brightness of the black and white pattern.
</p></li><li><p>
In the bottom-left corner, a system of high-frequency ripples that
show some circular moire patterns if the gamma correction is not
properly calibrated.
</p></li><li><p>
In the bottom-right corner, some gamma-corrected anti-aliased lines,
compared to the standard lines.
</p></li></ul><p>
Right now, nothing is done by the OS, and everything has to be done by
the applications. This will probably change in a future release, but this
sample code shows how to use some gamma correction without any OS support.
</p><p>
If you want to know more about how it really works, here's the beginning
of an explanation. If we call <code class="literal">f</code> the value for a pixel in the
framebuffer and <code class="literal">l</code> the lightness on the screen for this pixel, we can
write that <code class="literal">l</code> is proportional to
<code class="literal">(f+e)^2.5</code>. Since it's more convenient to
use values between 0 and 1, we'll renormalize <code class="literal">l</code> in that range with to
renormalization factors that we'll call <code class="literal">a</code> and
<code class="literal">b</code>, so that <code class="literal">l=a*l'+b</code> (<code class="literal">l'</code> is
the normalized version of <code class="literal">l</code>). We can finally write that
<code class="literal">f=((l'-b)/a)^0.4-e</code>, where <code class="literal">f</code> will
vary between 0 and 1 when <code class="literal">l'</code> varies
between 0 and 1.
</p><p>
The sample code will compute <code class="literal">a</code>, <code class="literal">b</code>,
and <code class="literal">e</code> from another value <code class="literal">m</code> that I call
the "mid-light" value; i.e., the gray level that is as light as a median
blend of black and white. With ideal monitor settings, <code class="literal">m</code> should be
approximately 3/4, so that we get <code class="literal">a=1</code>, <code class="literal">b=0</code>
and <code class="literal">e=0</code>.
</p></div><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id808327"></a>Part III: Conclusion</h3></div></div></div><p>
I hope this article casts some light on a few useful programming tricks.
Please send your feedback to jbq@be.com
</p></div></div><hr class="pagebreak" /><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Engineering4-32-2"></a>Be Engineering Insights: Common ioctls and Error codes for Drivers</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Arve</span> <span class="surname">Hjønnevåg</span></span></div></div></div><p>
If you look in the file <code class="filename">be/drivers/Drivers.h</code>
in your system headers,
you'll find a list of Be-defined opcodes for ioctls. A driver may choose
to implement any of these, but all implemented ioctls need to behave as
defined by us. Some ioctls are required for certain types of devices.
Let's go through the opcodes defined for Release 4.5.
</p><p>
<code class="constant">B_GET_DRIVER_FOR_DEVICE</code>, <code class="constant">B_GET_PARTITION_INFO</code>,
and <code class="constant">B_SET_PARTITION</code> are
implemented in devfs. You should not implement any of these.
</p><p>
<code class="constant">B_GET_DEVICE_SIZE</code> and <code class="constant">B_SET_DEVICE_SIZE</code>
are obsolete calls that operate
on 32-bit numbers.
</p><p>
<code class="constant">B_SET_NONBLOCKING_IO</code> and <code class="constant">B_SET_BLOCKING_IO</code>, are used to change a file
descriptor to blocking or nonblocking mode. Devices where a read or write
operation depends on other events to complete should implement these. The
driver also sets the mode on open according to the <code class="constant">O_NONBLOCK</code> flag.
</p><p>
<code class="constant">B_GET_READ_STATUS</code> and <code class="constant">B_GET_WRITE_STATUS</code>
are used, in blocking IO mode,
to determine if a following read or write will block. A pointer to a bool
is passed as the argument, and the driver writes set the value to false
if the operation will block, and true if not.
</p><p>
<code class="constant">B_GET_GEOMETRY</code> is used to get information about a disk device. All
drivers that publish their device under /dev/disk/ should implement this.
The argument to this call is a pointer to the following structure:
</p><pre class="programlisting c">
typedef struct {
<span class="type">uint32</span> <code class="varname">bytes_per_sector</code>; <span class="comment">/* sector size in bytes */</span>
<span class="type">uint32</span> <code class="varname">sectors_per_track</code>; <span class="comment">/* # sectors per track */</span>
<span class="type">uint32</span> <code class="varname">cylinder_count</code>; <span class="comment">/* # cylinders */</span>
<span class="type">uint32</span> <code class="varname">head_count</code>; <span class="comment">/* # heads */</span>
<span class="type">uchar</span> <code class="varname">device_type</code>; <span class="comment">/* type */</span>
<span class="type">bool</span> <code class="varname">removable</code>; <span class="comment">/* non-zero if removable */</span>
<span class="type">bool</span> <code class="varname">read_only</code>; <span class="comment">/* non-zero if read only */</span>
<span class="type">bool</span> <code class="varname">write_once</code>; <span class="comment">/* non-zero if write-once */</span>
} <span class="type">device_geometry</span>;
</pre><p>
For block devices, bytes per sector should match the block size of the
physical device. A file system mounted on your device will not try to
read partial blocks. Most devices do not expose accurate information
about the relation of cylinders, heads, and sectors, but the number of
usable blocks in the device should match sectors per track*cylinder
count*head count.
</p><p>
When using this call to determine the size of a device, make sure to use
64-bit precision for the calculation.
</p><pre class="programlisting c">
<span class="type">device_geometry</span> <code class="varname">g</code>;
<span class="type">off_t</span> <code class="varname">devsize</code>;
if(<code class="function">ioctl</code>(<code class="varname">devfd</code>, <code class="constant">B_GET_GEOMETRY</code>, &amp;<code class="varname">g</code>) &gt;= 0) {
<code class="varname">devsize</code> = (<span class="type">off_t</span>)<code class="varname">g</code>.<code class="varname">bytes_per_sector</code> *
(<span class="type">off_t</span>)<code class="varname">g</code>.<code class="varname">sectors_per_track</code> *
(<span class="type">off_t</span>)<code class="varname">g</code>.<code class="varname">cylinder_count</code> * (<span class="type">off_t</span>)<code class="varname">g</code>.<code class="varname">head_count</code>;
}
</pre><p>
The device type field indicates the type of the device. The most common
values here are <code class="constant">B_DISK</code> for hard drives and
<code class="constant">B_CD</code> for CD-ROMs.
</p><p>
If the media in the device is removable, the removable field should be
true. Some devices support media of different size and block size. If
there is no media in the drive, report a size and block size of 0.
</p><p>
The read only field is set if the driver knows that the media is not
writeable. Some devices may not be able to determine this, so make sure
your application deals with write operations failing.
</p><p>
write_once should normally be set to false.
</p><p>
<code class="constant">B_GET_BIOS_GEOMETRY</code>, <code class="constant">B_GET_BIOS_DRIVE_ID</code>: On the x86 platform, hard
drives can be accessed though the bios at boot time and from other
operating systems. <code class="constant">B_GET_BIOS_GEOMETRY</code> will fill in the same structure as
<code class="constant">B_GET_GEOMETRY</code>, but sectors per track, cylinder count, and head count
need to match the numbers used by the bios. This information is needed to
create a partition table that the bios can use. <code class="constant">B_GET_BIOS_DRIVE_ID</code> will
return the drive number the bios uses for this drive. This information is
needed when adding a disk to the boot menu.
</p><p>
<code class="constant">B_FORMAT_DEVICE</code> is used to format the media in the device. If your device
needs to prepare the media before it can be read and written to,
implement <code class="constant">B_FORMAT_DEVICE</code>.
</p><p>
<code class="constant">B_GET_ICON</code> allows a device to have a custom icon. Currently, our disk
drivers have the Be disk and CD-ROM icons built in, but we will provide a
simple way to specify standard icons in the future.
</p><p>
<code class="constant">B_EJECT_DEVICE</code> and <code class="constant">B_LOAD_MEDIA</code> are used to eject or load media.
</p><p>
B GET MEDIA STATUS is used to determine the state of the media in the
drive. This is described in detail in my article "Removable Media"
&lt;http://www-classic.be.com/aboutbe/benewsletter/volume
II/Issue44.html#Insight&gt;.
</p><p>
<code class="constant">B_SET_UNINTERRUPTABLE_IO</code> and
<code class="constant">B_SET_INTERRUPTABLE_IO</code> change how the driver
responds to signals. By default a driver should return to user space as
soon as possible when it receives <code class="constant">SIGINT</code>. A driver can use the
<code class="constant">B_CAN_INTERRUPT</code> flag when acquiring semaphores and can abort its operation if
<code class="constant">B_INTERRUPTED</code> is returned. However, when using the file system cache, a
read or write operation may carry data that doesn't belong to the current
thread. The file system uses <code class="constant">B_SET_UNINTERRUPTABLE_IO</code> to tell the driver
not to abort any operations. <code class="constant">B_SET_INTERRUPTABLE_IO</code> restores the default
state. A disk driver that wants to abort IO operations on signals needs
to implement these ioctls.
</p><p>
<code class="constant">B_FLUSH_DRIVE_CACHE</code> needs to be implemented by disk drivers if the device
has a write cache. If the device has a write cache, either a software
cache or hardware cache, a call to <code class="constant">B_FLUSH_DRIVE_CACHE</code> should not return
until all data in the cache has been written to the media.
</p><p>
If an opcode is not supported by your driver, return <code class="constant">B_DEV_INVALID_IOCTL</code>.
This will cause the ioctl call to return -1 with errno set to
<code class="constant">B_DEV_INVALID_IOCTL</code>. For all opcodes above you
should return <code class="constant">B_OK</code> or <code class="constant">B_NO_ERROR</code>
if the operation was successful. If the operation failed you need to
return an error. In the file be/support/Errors.h under your system
headers, you'll find error codes for a variety of error conditions. You
should try to pick the error code that best describes why the operation
failed. Let's look at the most common cases for drivers.
</p><p>
If you don't know why an operation failed, return <code class="constant">B_ERROR</code>.
</p><p>
If an operation failed because you could not allocate memory, return
<code class="constant">B_NO_MEMORY</code>.
</p><p>
If an IO operation fails, return <code class="constant">B_IO_ERROR</code>, or if your device has
additional information you can return more specific errors such as
<code class="constant">B_DEV_NO_MEDIA</code>, <code class="constant">B_DEV_UNREADABLE</code>,
<code class="constant">B_DEV_FORMAT_ERROR</code>, <code class="constant">B_DEV_TIMEOUT</code>,
<code class="constant">B_DEV_RECALIBRATE_ERROR</code>, <code class="constant">B_DEV_SEEK_ERROR</code>,
<code class="constant">B_DEV_READ_ERROR</code>, <code class="constant">B_DEV_WRITE_ERROR</code>,
<code class="constant">B_DEV_NOT_READY</code>, and <code class="constant">B_READ_ONLY_DEVICE</code>.
</p><p>
If someone tries to write to a read-only device or to write-protected
media, return <code class="constant">B_READ_ONLY_DEVICE</code>.
</p><p>
For devices with removable media it's also important that
<code class="constant">B_DEV_NO_MEDIA</code>
and <code class="constant">B_DEV_MEDIA_CHANGED</code> are returned when appropriate. Once opened, read
and write operations should fail with <code class="constant">B_DEV_MEDIA_CHANGED</code> if the media
changes. See the article "<a class="xref" href="Issue3-44.html#Engineering3-44" title="Be Engineering Insights: Removable Media">Be Engineering Insights: Removable Media</a>" for more info on how this
should be implemented.
</p></div><hr class="pagebreak" /><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="DevWorkshop4-32"></a>Developers' Workshop: What's Going On in Documentation Land?</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Ken</span> <span class="surname">McDonald</span></span></div></div></div><p>
Recently, the DTS oraA long time ago, in an office far, far away (or at least, on the other
side of the building), I wrote a newsletter article about making and
using menus in BeOS GUI applications. One of the goals of that article
was to see how people responded to a more tutorial style of
documentation--something that didn't necessarily go into every last,
cotton-pickin' finicky little detail, but that did provide the basic
information necessary to use a class or classes in your program, in a
compact, easy -to-read form.
</p><p>
We were rather surprised at the number of responses generated by that
article, almost all of them positive. Well, it's been a while, and other
things came up of course, but now we're back in the tutorial game. In
fact, there will hopefully be quite a few more tutorial style documents
coming down the pipe in the future.
</p><p>
In light of this (and due to the fact that I didn't have the time or the
imagination to do anything else), it seemed apropos to do a sequel to my
previous newsletter tutorial. Think of this one as "Looking for Tutorial
Feedback II: Nightmare on BView Street". The first writeup in this new
tutorial series will be about the BView class, and the first part of this
writeup is a short, very high-level introduction located here:
</p><p>
&lt;http://www-classic.be.com/aboutbe/benewsletter/volume_III/resources/articl
e.htm l&gt;
</p><p>
I hope the technical content is useful, but the main purpose of
presenting this here is to elicit comments from you, the reader. We
expect to put quite a bit of effort into this series (hopefully resulting
in a complete tutorial for programming the BeOS), and given this, it
makes sense to develop a format which will make the information as useful
as possible. For example, one of the things I've done in the tutorial is
to include a sidebar on the left, giving easy access to the section and
subsection headings within the document. Is this a good idea? Can you
suggest other features which might be better, or complementary? As the
series progresses, I will be locked in to a certain format and approach,
in order to maintain consistency--but right now, the sky is the limit.
(Well, subject to resource constraints, of course :-) ) So suggest away!
</p><p>
And, of course, please make comments on the writing style and content
also. If nothing else, please tell me:
</p><div class="orderedlist"><ol><li><p>
What I'm doing right in the tutorial.
</p></li><li><p>
What I'm doing wrong.
</p></li><li><p>
What most needs to be covered by this sort of documentation.
</p></li></ol></div><p>
You can email directly to me, ken@be.com. (Nope, you don't get my home
phone number :-) ). If you could begin the subject line of any feedback
with the words "TUTORIAL COMMENTS", it would let me use the cool indexing
features of the Be file system to keep responses nicely sorted.
</p></div><hr class="pagebreak" /><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BitByBit4-32"></a>Bit By Bit: Introducing <span class="application">Rephrase</span></h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Stephen</span> <span class="surname">Beaulieu</span></span></div></div></div><p>
Our application-building exercise begins with <span class="application"><span class="application">Rephrase</span></span>,
a <code class="classname">BTextView</code> based
text-processing application. Over the next few months, I'll add features
in each installment, and explain the BeOS coding philosophy behind them.
</p><p>
You'll find the first version of <span class="application">Rephrase</span> at
</p><p>
&lt;ftp://ftp.be.com/pub/samples/tutorials/rephrase/rephrase0.1d1.zip&gt;
</p><div class="blockquote"><blockquote class="blockquote"><p>
<span class="application">Rephrase</span> 0.1d1<br />
New Features:<br />
Edit text within the window.
Drag and drop for open and save.
About box.
</p></blockquote></div><p>
This limited version of <span class="application">Rephrase</span> is essentially an application wrapped
around a standard <code class="classname">BTextView</code>. It
has a <code class="classname">BApplication</code> and a <code class="classname">BWindow</code> for the
text view to live in. There is an About window, with a basic set of menu
items in the main window to bring up the about window, quit the
application, and edit the text.
</p><p>
The application's real functionality (limited as it is) comes from the
<code class="classname">BTextView</code>. It lets you cut, copy, paste, and select the text. It even
provides limited file i/o through inherent drag and drop capabilites:
select text and drag it to the Tracker to save a text clipping, or drag a
file to the view to paste in its contents.
</p><p>
Although it has only 164 lines of code (many of them blank or comments),
the application is surprisingly functional. With the addition of
resizing, scrollbars and real open and save capabilities, <span class="application">Rephrase</span> could
even be useful.
</p><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id809190"></a>Programming Concepts</h3></div></div></div><p>
BeOS uses a system of messaging to manage most aspects of communication
and event handling. <code class="classname">BLooper</code>s run an event loop in a thread that receives
incoming messages and dispatches them to associated <code class="classname">BHandler</code>s to be acted
on.
</p><p>
<code class="classname">BApplication</code> provides a connection to the Application Server, which
enables the messaging system for the app. It also serves as the main
looper for interapplication communication and application global
services, such as displaying an About window. A global pointer to the
<code class="classname">BApplication</code> object (<code class="varname">be_app</code>),
is available throughout the application.
</p><p>
<code class="classname">BWindow</code>s and <code class="classname">BView</code>s
are the specialized loopers and handlers for managing
the graphical user interface. When visible, a <code class="classname">BWindow</code> represents an area
on screen. A <code class="classname">BWindow</code> maintains a hierarchy of
<code class="classname">BView</code>s that draw in and
handle messages for sections of that area. User interaction generates
messages that are delivered to the window, which passes them to the
<code class="classname">BView</code>s to handle as appropriate.
</p><p>
For example, when you select a menu item in <span class="application">Rephrase</span>, a message is sent
to the <code class="classname">BMenuItem</code>'s target. The menu item's window is the default target.
However, the menu item can be told to send its message elsewhere. For
instance, when "About <span class="application">Rephrase</span>" is selected from the File menu, a message
is sent to the <code class="classname">BApplication</code>. All the menu items in the Edit menu send
their messages to the <code class="classname">BTextView</code>.
</p></div><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id809293"></a>Implementation Details</h3></div></div></div><div class="orderedlist"><ol><li><p>
In <code class="function">main()</code>, create the application on the stack, call
<code class="methodname">Run()</code> and
return after run completes.
</p></li><li><p>
Don't hard-code your interface details. Some views resize
themselves to match their contents. Menus, for example, resize to
match the size of the characters in their font. After you create and
add the menu, determine its size and use that information to place the
rest of your views. Change the size of your font in the Menu
preferences panel, run <span class="application">Rephrase</span> and see.
</p></li><li><p>
Do not delete a <code class="classname">BLooper</code>. Send it a
<code class="constant">B_QUIT_REQUESTED</code> message
instead. This calls its <code class="methodname">QuitRequested()</code> hook function, and if that
returns <code class="constant">true</code>, will call the <code class="methodname">Quit()</code> function which tears down the
looper.
</p></li><li><p>
Windows own their child views and will properly delete them when
destroyed. Only delete a view if you have already called <code class="methodname">RemoveChild()</code>
to remove it from its parent.
</p></li><li><p>
Invokers own their model messages and will properly delete them
when destroyed.
</p></li><li><p>
When an app's last window is asked to quit, it should request the
app to quit as well. If not, the application may hang around in the
Deskbar with no windows.
</p></li></ol></div></div><p>
Next week: Opening a file.
</p></div></div><div id="footer"><hr /><div id="footerT">Prev: <a href="Issue4-31.html">Issue 4-31, August 4, 1999</a>  Up: <a href="volume4.html">Volume 4: 1999</a>  Next: <a href="Issue4-33.html">Issue 4-33, August 18, 1999</a> </div><div id="footerB"><div id="footerBL"><a href="Issue4-31.html" title="Issue 4-31, August 4, 1999"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a href="volume4.html" title="Volume 4: 1999"><img src="./images/navigation/up.png" alt="Up" /></a> <a href="Issue4-33.html" title="Issue 4-33, August 18, 1999"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="footerBR"><div><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div></div><div id="footerBC"><a href="http://www.access-company.com/home.html" title="ACCESS Co."><img alt="Access Company" src="./images/access_logo.png" /></a></div></div></div><div id="licenseFooter"><div id="licenseFooterBL"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" title="Creative Commons License"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc-nd/3.0/88x31.png" /></a></div><div id="licenseFooterBR"><a href="./LegalNotice.html">Legal Notice</a></div><div id="licenseFooterBC"><span id="licenseText">This work is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative
Commons Attribution-Non commercial-No Derivative Works 3.0 License</a>.</span></div></div></body></html>