466 lines
35 KiB
HTML
466 lines
35 KiB
HTML
<?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 2: 1997</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="volume2.html" title="Volume 2: 1997" /><link rel="prev" href="Issue2-20.html" title="Issue 2-20, May 21, 1997" /><link rel="next" href="Issue2-22.html" title="Issue 2-22, June 4, 1997" /></head><body><div id="header"><div id="headerT"><div id="headerTL"><a accesskey="p" href="Issue2-20.html" title="Issue 2-20, May 21, 1997"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a accesskey="u" href="volume2.html" title="Volume 2: 1997"><img src="./images/navigation/up.png" alt="Up" /></a> <a accesskey="n" href="Issue2-22.html" title="Issue 2-22, June 4, 1997"><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 2: 1997</div></div><div id="headerB">Prev: <a href="Issue2-20.html">Issue 2-20, May 21, 1997</a> Up: <a href="volume2.html">Volume 2: 1997</a> Next: <a href="Issue2-22.html">Issue 2-22, June 4, 1997</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="Issue2-21"></a>Issue 2-21, May 28, 1997</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="Engineering2-21"></a>Be Engineering Insights: BScreens and Puppy Paws</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Scott</span> <span class="surname">Bronson</span></span></div></div></div><p>
|
||
The beauty and sensibility of a final result often belies the time and
|
||
effort that went into creating it. Good dancers appear to have been born
|
||
moving effortlessly. An attractive, well-dressed human being likely
|
||
didn't wake up looking quite so polished. Everything we see, from the
|
||
most majestic landscape to the least significant spore, required a period
|
||
of growth. Whatever the refinement of the result, this means that
|
||
everything went through periods of lankiness and growing pains. Puppy
|
||
paws appear far too big for the legs they're mounted on. A baby's head
|
||
dwarfs its tiny body. When growing, dependencies require that some parts
|
||
grow faster and be in place sooner than others. A browse through the DR9
|
||
Advanced Access header files will hint at things to come, like multiple
|
||
displays. The header file Screen.h describes the new API for applications
|
||
to obtain information about screens in a remarkably dynamic multiple
|
||
screen environment.
|
||
</p><p>
|
||
Imagine a full multitasking operating system that will allow displays to
|
||
come and go at will. Let's say the user is done at the office (imagine!)
|
||
and—without restarting—unplugs his BeOS notebook from his 17"
|
||
monitor, tucks it under his arm, and takes it home. Without any help, the
|
||
OS notices that the 17" CRT is gone and the 14" built-in LCD display
|
||
should be the new main screen. In a flurry of windows moving and
|
||
updating, everything in the system shifts to the new configuration with
|
||
no surprises for the user.
|
||
</p><p>
|
||
Certainly a nice image. But not without a few minor problems to solve.
|
||
For instance, how does a program refer to specific screens when they can
|
||
appear and disappear at will? It cannot use a pointer, as it is hard to
|
||
tell when the pointer is invalid, and the consequences for misuse are
|
||
dire. Neither can it use a "GetNthScreen" call, as the screen indexes
|
||
will change when screens are added and removed (when monitor 1 is
|
||
removed, monitor 2 becomes monitor 1, monitor 3 becomes monitor 2, and so
|
||
on).
|
||
</p><p>
|
||
The solution is the screen_id, a unique, opaque 32-bit identifier,
|
||
representing a screen attached to the computer. When a screen is
|
||
disconnected, its <span class="type">screen_id</span> falls into permanent disuse. When it is
|
||
reconnected, it is assigned a new ID. Because screen_ids are meant to be
|
||
lightweight, they are not persistent across boots. A solution involving
|
||
far more than 32 bits will be developed later to persistently identify
|
||
screens.
|
||
</p><p>
|
||
And, now the star of the show. The <code class="classname">BScreen</code> is an extremely lightweight,
|
||
easy to construct class that represents a single screen. <code class="classname">BScreen</code>s are
|
||
meant to be constructed immediately when information is needed, and to
|
||
exist for as short a time as possible. Although construction and
|
||
destruction take insignificant time, some of the calls (such as
|
||
BaseAddress and BytesPerRow) are slower than you might expect because
|
||
they involve a synchronous round-trip AppServer request.
|
||
</p><p>
|
||
To prevent race conditions with the results of the <code class="classname">BScreen</code> functions, the
|
||
display will not change when any <code class="classname">BScreen</code> objects referring to it are in
|
||
existence. The display is locked in the <code class="classname">BScreen</code>'s constructor and freed
|
||
in the destructor so neither the Screen preferences panel nor anybody
|
||
else will be able to change the horizontal or vertical size, bit depth,
|
||
color palette, or anything else that might affect client applications.
|
||
This is why it is extremely important to destroy the <code class="classname">BScreen</code>, allowing
|
||
the display to change again, as soon as possible. A user won't react
|
||
kindly to an application hogging his screen, and when informed which is
|
||
the culprit (it's not hard to figure out who is misusing the <code class="classname">BScreen</code>),
|
||
will remorselessly blow it away.
|
||
</p><pre class="programlisting cpp">
|
||
class <code class="classname">BScreen</code> {
|
||
|
||
<code class="classname">BScreen</code>( <span class="type">screen_id</span> id=<code class="constant">B_MAIN_SCREEN_ID</code> );
|
||
<code class="classname">BScreen</code>( <span class="type"><code class="classname">BWindow</code> *</span><code class="parameter">win</code> );
|
||
~<code class="classname">BScreen</code>();
|
||
</pre><p>
|
||
The best way to construct a <code class="classname">BScreen</code> object is to pass in a window. The
|
||
constructor will return the screen that contains that window (or the
|
||
majority of the window). If you need more flexibility, you can pass the
|
||
ID of the desired screen. Because <code class="classname">BScreen</code>s are meant to be created on the
|
||
stack, the destructor should be called automatically. Manually creating
|
||
and deleting <code class="classname">BScreen</code>s on the heap is a sure recipe for leaks (again,
|
||
likely leading to an irate user and your application's unceremonious
|
||
termination).
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">bool</span> <code class="methodname">IsValid</code>();
|
||
</pre><p>
|
||
When screens can come and go at will, it will be possible for the <code class="classname">BScreen</code>
|
||
constructor to be passed a <span class="type">screen_id</span> which is no longer valid. The
|
||
<code class="classname">BScreen</code> will be constructed anyway, but will refer to the main screen
|
||
instead of the screen you asked for. This is so you don't have to do
|
||
error checking every single time you construct a <code class="classname">BScreen</code>. Accidentally
|
||
using the main screen will prevent crashing, and will generally produce
|
||
acceptable results anyway. IsValid will return false if the <code class="classname">BScreen</code>
|
||
refers to the main screen instead of the screen you asked for.
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">color_space</span> <code class="methodname">ColorSpace</code>();
|
||
<code class="classname">BRect</code> <code class="methodname">Frame</code>();
|
||
<span class="type">screen_id</span> <code class="methodname">ID</code>();
|
||
<span class="type">void*</span> <code class="methodname">BaseAddress</code>();
|
||
<span class="type">uint32</span> <code class="methodname">BytesPerRow</code>();
|
||
<span class="type">status_t</span> <code class="methodname">WaitForRetrace</code>();
|
||
</pre><p>
|
||
These calls are pretty much self-explanatory, except that <code class="methodname">WaitForRetrace</code>
|
||
is temporarily unimplemented (it just returns <code class="constant">B_ERROR</code> right now).
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">uint8</span> <code class="methodname">IndexForColor</code>( <span class="type">rgb_color</span> rgb );
|
||
<span class="type">uint8</span> <code class="methodname">IndexForColor</code>( <span class="type">uint8</span> <code class="parameter">r</code>, <span class="type">uint8</span> <code class="parameter">g</code>, <span class="type">uint8</span> <code class="parameter">b</code>,
|
||
<span class="type">uint8</span> <code class="parameter">a</code>=0 );
|
||
<span class="type">rgb_color</span> <code class="methodname">ColorForIndex</code>( <span class="type">constuint8</span> <code class="parameter">index</code> );
|
||
</pre><p>
|
||
The BeOS has a system color table that applies to every bitmap, every
|
||
8-bit screen, basically everywhere indexed color is used. VRAM is cheap
|
||
enough now that if you need realistic color, it is much easier to simply
|
||
set the display to 32-bit color than to manage and arbitrate the palette
|
||
(even with full OS support). So why not make these calls global? Because
|
||
even though this capability will likely go unused in the BeOS, the
|
||
hardware DOES allow each individual screen to have its own color
|
||
environment.
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">uint8</span> <code class="methodname">InvertIndex</code>( <span class="type">uint8</span> <code class="parameter">index</code> );
|
||
</pre><p>
|
||
Passed a color index, <code class="methodname">InvertIndex</code> returns the index of a suitable
|
||
inverse. It uses the inversion map returned by <code class="code"><code class="methodname">ColorMap</code>()-><code class="varname">inversion_map</code></code>.
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">constcolor_map*</span> <code class="methodname">ColorMap</code>();
|
||
</pre><p>
|
||
<code class="methodname">ColorMap</code>() allows you to save time by doing your own table lookups. Don't
|
||
use the color map after its <code class="classname">BScreen</code> has been destructed. Suitably bad
|
||
things will happen.
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">rgb_color</span> <code class="methodname">DesktopColor</code>();
|
||
<span class="type">void</span> <code class="methodname">SetDesktopColor</code>( <span class="type">rgb_color</span> <code class="parameter">rgb</code>,
|
||
<span class="type">bool</span> <code class="parameter">stick</code>=<code class="constant">true</code> );
|
||
</pre><p>
|
||
These set the screen's desktop color. If stick is <code class="constant">true</code>, then it saves the
|
||
change to disk. If not, then the desktop color change will last only
|
||
until the computer is restarted.
|
||
</p><pre class="programlisting cpp">
|
||
};
|
||
|
||
inline <span class="type">uint8</span> <code class="classname">BScreen</code>::<code class="methodname">IndexForColor</code>( <span class="type">rgb_color</span> <code class="parameter">rgb</code> )
|
||
{ return <code class="methodname">IndexForColor</code>( <code class="parameter">rgb</code>.<code class="varname">red</code>, <code class="parameter">rgb</code>.<code class="varname">green</code>, <code class="parameter">rgb</code>.<code class="varname">blue</code>,
|
||
<code class="parameter">rgb</code>.<code class="varname">alpha</code> ); }
|
||
</pre><p>
|
||
Finally, a pinch of syntactic sugar.
|
||
</p><p>
|
||
Let's see how to use <code class="classname">BScreen</code>. First, a simple example that draws a
|
||
rectangle, colored the inverse of the desktop color, in a view.
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">void</span> <code class="classname">MyView</code>::<code class="methodname">Draw</code>( <code class="classname">BRect</code> <code class="parameter">where</code> )
|
||
{
|
||
<code class="classname">BRect</code> <code class="varname">area</code>( 10, 10, 110, 110 );
|
||
<span class="type">rgb_color</span> <code class="varname">deskcolor</code>;
|
||
|
||
<code class="classname">BScreen</code> <code class="varname">screen</code>( <code class="methodname">Window</code>() );
|
||
|
||
<span class="comment">// Now, the screen containing the majority of the window</span>
|
||
<span class="comment">// has been locked. It will not change while the</span>
|
||
<span class="comment">// function is executing.</span>
|
||
|
||
<code class="varname">deskcolor</code> = <code class="varname">screen</code>.<code class="methodname">DesktopColor</code>();
|
||
if( <code class="varname">screen</code>.<code class="methodname">ColorSpace</code>() == <code class="constant">B_COLOR_8_BIT</code> ) {
|
||
<span class="comment">// do the inversion calculation using indexed colors</span>
|
||
<span class="type">uint8</span> <code class="varname">icol</code> = <code class="varname">screen</code>.<code class="methodname">InvertIndex</code>(
|
||
<code class="varname">screen</code>.<code class="methodname">IndexForColor</code>(<code class="varname">deskcolor</code>) );
|
||
<code class="methodname">SetHighColor</code>( <code class="varname">screen</code>.<code class="methodname">ColorForIndex</code>(<code class="varname">icol</code>) );
|
||
} else {
|
||
<span class="comment">// Invert the rgb_color</span>
|
||
<code class="methodname">SetHighColor</code>( ~<code class="varname">rcol</code>.<code class="varname">red</code>, ~<code class="varname">rcol</code>.<code class="varname">green</code>, ~<code class="varname">rcol</code>.<code class="varname">blue</code> );
|
||
}
|
||
|
||
<code class="methodname">FillRect</code>( <code class="varname">area</code> );
|
||
|
||
<span class="comment">// The screen variable is destroyed, and its display</span>
|
||
<span class="comment">// released and allowed to change again, when this</span>
|
||
<span class="comment">// function returns.</span>
|
||
}
|
||
</pre><p>
|
||
If the screen is currently in 8-bit mode, the inversion calculation is
|
||
done using indexed colors. This is not strictly necessary—inverting
|
||
the rgb_color would provide visually acceptable results—but this is a
|
||
good example of how to manipulate color indexes.
|
||
</p><p>
|
||
Otherwise, if the screen is not in 8-bit-mode, the screen must be in a
|
||
direct mode, and we'll calculate the inverse directly from the color's
|
||
individual components. Finally, the rect is filled in, and the desktop
|
||
color's inverse is on screen.
|
||
</p><p>
|
||
A somewhat more advanced usage of <code class="classname">BScreen</code> (snipped from the Connect
|
||
source code):
|
||
</p><pre class="programlisting cpp">
|
||
<span class="type">void</span> <code class="classname">Border</code>::<code class="methodname">MessageReceived</code>( <span class="type"><code class="classname">BMessage</code> *</span><code class="parameter">m</code>)
|
||
{
|
||
<span class="type">constcolor_map *</span><code class="varname">cm</code> = <code class="classname">BScreen</code>( <code class="methodname">Window</code>( )).<code class="methodname">ColorMap</code>( );
|
||
if (<code class="parameter">m</code>-><code class="varname">what</code> < sizeof(<code class="varname">cm</code>-><code class="varname">color_list</code>)/
|
||
sizeof(<code class="varname">cm</code>-><code class="varname">color_list</code>[0])) {
|
||
<code class="methodname">SetViewColor</code>( <code class="varname">cm</code>-><code class="varname">color_list</code>[<code class="parameter">m</code>-><code class="varname">what</code>]);
|
||
<code class="methodname">Invalidate</code>( );
|
||
}
|
||
}
|
||
</pre><p>
|
||
First, notice that the <code class="classname">BScreen</code> object is anonymous—it was never given
|
||
a name. The rules of construction and destruction still apply, so the
|
||
<code class="classname">BScreen</code> will not be destroyed until the flow of execution leaves the
|
||
enclosing brackets; in this case, when the function returns. Even in the
|
||
worst case, <code class="classname">Border</code>::<code class="methodname">MessageReceived</code> takes a tiny amount of time to
|
||
execute, so this is acceptable. The variable cm will go out of scope when
|
||
the <code class="classname">BScreen</code> is destroyed, so its validity is ensured for the duration of
|
||
the function.
|
||
</p><p>
|
||
The conditional makes sure that the index <code class="code"><code class="varname">m</code>-><code class="varname">what</code></code> falls within the bounds
|
||
of the color table. Then, using a simple table lookup (instead of the
|
||
slightly more expensive <code class="methodname">ColorForIndex</code> call), the appropriate <span class="type">rgb_color</span> is
|
||
passed to <code class="methodname">SetViewColor</code>. Simple, straightforward, and there is no chance
|
||
that the color table will change or disappear until the function returns.
|
||
</p><p>
|
||
<code class="classname">BScreen</code> is not meant to be used to lock the screen (though it can
|
||
certainly be misused to do that for now). A more sensible way to allow
|
||
applications to directly and asynchronously modify screen bits (i.e. DMA)
|
||
is in development.
|
||
</p><p>
|
||
Do you remember get_screen_info and friends from the DR8 InterfaceDefs.h?
|
||
They're still there in the Advanced Access DR9, but they are tiny little
|
||
functions implemented using <code class="classname">BScreen</code>s. They will go away in the full DR9
|
||
release. Use the old API at your peril.
|
||
</p><p>
|
||
So, yes, with <code class="classname">BScreen</code> I've added a tiny bit of lankiness to the DR9 BeOS.
|
||
Lanky not because it's hard to use (at least, I sure tried to make it
|
||
simple), but because significant parts of it are not used today. However,
|
||
just as a dog's legs eventually grow to fit its paws, the BeOS will grow
|
||
to fit its header files, and the result will be lean, fast, and powerful.
|
||
</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="Engineering2-21-2"></a>Be Engineering Insights: Unicode UTF-8</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Don</span> <span class="surname">Larkin</span></span></div></div></div><p>
|
||
You may have heard that DR9 adopts the Unicode Standard for encoding
|
||
characters and, in particular, the UTF-8 transformation of Unicode
|
||
character values. You can read all about UTF-8 in "The Unicode Standard,
|
||
Version 2.0" published by Addison-Wesley, but here's a synopsis for those
|
||
of you that don't have the book.
|
||
</p><p>
|
||
Unicode is a universal encoding scheme for all the characters in the
|
||
major scripts of the world—including, among others, extended Latin,
|
||
Cyrillic, Greek, Devanagiri, Telugu, Hebrew, Arabic, Tibetan, and the
|
||
various character sets used by Chinese, Japanese, and Korean. It assigns
|
||
a unique and unambiguous 16-bit value to each character, making it
|
||
possible for characters from various languages to co-exist in the same
|
||
document. Unicode makes it simpler to write language-aware software
|
||
(though it doesn't solve all the problems). It also makes a wide variety
|
||
of symbols available to an application even if it's not concerned with
|
||
internationalization.
|
||
</p><p>
|
||
Unicode's one disadvantage is that all characters have a width of 16
|
||
bits. Although 16 bits are necessary for a universal encoding and a fixed
|
||
width is important for the standard, there are many contexts in which
|
||
byte-sized characters would be easier to work with and take up less
|
||
memory (besides being more familiar and backwards compatible with
|
||
existing code). UTF-8 is designed to address this problem.
|
||
</p><p>
|
||
UTF-8 stands for "UCS Transformation Format, 8-bit form" (and UCS stands
|
||
for "Universal Multiple-Octet Character Set," another name for Unicode).
|
||
UTF-8 transforms 16-bit Unicode values into a variable number of 8-bit
|
||
units. It takes advantage of the fact that for values less than 0x0080,
|
||
the Unicode character set matches the 7-bit ASCII character set—in
|
||
other words, Unicode adopts the ASCII standard, but encodes each
|
||
character in 16 bits. UTF-8 strips ASCII values back to 8 bits and uses
|
||
two or three bytes to encode Unicode values over 0x007f.
|
||
</p><p>
|
||
The high bit of each UTF-8 byte indicates the role it plays in the
|
||
encoding: If the high bit is 0, the byte stands alone and encodes an
|
||
ASCII value. If the high bit is 1, the byte is part of a multiple-byte
|
||
character representation.
|
||
</p><p>
|
||
In addition, the first byte of a multibyte character indicates how many
|
||
bytes it takes to represent the character: The number of high bits that
|
||
are set to 1 (before a bit is 0) is the number of bytes in the encoding.
|
||
Therefore, the first byte of a multibyte character will always have at
|
||
least two high bits set. The other bytes in a multibyte encoding have
|
||
just one high bit set.
|
||
</p><p>
|
||
To illustrate, here is how UTF-8 arranges the bits in one-, two-, and
|
||
three-byte encodings (where a '0' or '1' indicates a control bit
|
||
specified by the standard and an 'x' is a bit that contributes to the
|
||
character value):
|
||
</p><pre class="screen">
|
||
1: 0 x x x x x x x
|
||
|
||
2: 1 1 0 x x x x x 1 0 x x x x x x
|
||
|
||
3: 1 1 1 0 x x x x 1 0 x x x x x x 1 0 x x x x x x
|
||
</pre><p>
|
||
Note that any 16-bit value can be encoded in three UTF-8 bytes. However,
|
||
UTF-8 discards leading zeroes and always uses the fewest possible number
|
||
of bytes, so it can encode Unicode values less than 0x0080 in a single
|
||
byte and values less than 0x0800 in two bytes.
|
||
</p><p>
|
||
In addition to the codings illustrated above, UTF-8 takes four bytes to
|
||
translate a Unicode "surrogate pair"—two conjoined 16-bit values that
|
||
together encode a character that's not part of the standard. Surrogates
|
||
are extremely rare. See "The Unicode Standard" for details.
|
||
</p><p>
|
||
The UTF-8 encoding scheme has several advantages:
|
||
</p><ul class="itemizedlist"><li><p>
|
||
The single byte that encodes an ASCII value can't be confused with a
|
||
byte that's part of a multiple-byte encoding. You can test a UTF-8 byte
|
||
for an ASCII value without considering its context; if there's a match,
|
||
you can be sure the byte is the ASCII character. UTF-8 is fully
|
||
compatible with ASCII.
|
||
</p></li><li><p>
|
||
The first (or only) byte of a character can't be confused with a byte
|
||
inside a multibyte sequence. It's simple to find where a character
|
||
begins. For example, this macro does the job:
|
||
</p><pre class="programlisting c">
|
||
#define BEGINS_CHAR(<code class="parameter">byte</code>) ((<code class="parameter">byte</code> & 0xc0) != 0x80)
|
||
</pre></li><li><p>
|
||
The string functions in the standard C library—such as,
|
||
<code class="function">strcasecmp()</code>, <code class="function">strcat()</code>,
|
||
and <code class="function">strlen()</code>—can operate on a UTF-8 string.
|
||
</p><p>
|
||
However, it's important to remember that <code class="function">strlen()</code> measures the string
|
||
in bytes, not characters. Some Interface Kit functions, like
|
||
<code class="methodname">GetEscapements()</code> in the <code class="classname">BFont</code> class, ask for a character count;
|
||
<code class="function">strlen()</code> can't provide the answer. Instead, you need to do something
|
||
like this to count the characters in a UTF-8 string:
|
||
</p><pre class="programlisting c">
|
||
<span class="type">int32</span> <code class="varname">count</code> = 0;
|
||
while ( *<code class="varname">p</code> != '\0' ) {
|
||
if ( BEGINS_CHAR(*<code class="varname">p</code>) )
|
||
<code class="varname">count</code>++;
|
||
<code class="varname">p</code>++;
|
||
}
|
||
</pre></li><li><p>
|
||
Also, you should be careful when using the string comparison functions
|
||
to order a set of strings. Unicode tries to be a universal encoding and
|
||
orders characters in a way that's generically correct. However, it may
|
||
not be correct for specific characters for specific languages. (Because
|
||
it follows ASCII, UTF-8 is correct for English.)
|
||
</p></li><li><p>
|
||
For European languages, UTF-8 generally yields more compact data
|
||
representations than would Unicode. Most of the characters in a string
|
||
can be encoded in a single byte. In many other cases, UTF-8 is no less
|
||
compact than Unicode.
|
||
</p></li></ul><p>
|
||
The BeOS assumes UTF-8 encoding in most cases. For example, a <code class="constant">B_KEY_DOWN</code>
|
||
message reports the character that's mapped to the key the user pressed
|
||
as a UTF-8 value. The message has a data array named "byte" with each
|
||
byte of the encoding as a separate item. The bytes are extracted from the
|
||
array and passed as a string to the new version of <code class="methodname">KeyDown()</code>, along with
|
||
the byte count:
|
||
</p><pre class="programlisting cpp">
|
||
virtual <span class="type">void</span> <code class="methodname">KeyDown</code>(<span class="type">const char *</span><code class="parameter">bytes</code>, <span class="type">int32</span> <code class="parameter">numBytes</code>);
|
||
</pre><p>
|
||
You can expect the "bytes" string to always contain at least one byte.
|
||
And, of course, you can test it for any ASCII value without caring that
|
||
it's UTF-8:
|
||
</p><pre class="programlisting cpp">
|
||
if ( <code class="varname">bytes</code>[0] == <code class="constant">B_TAB</code> )
|
||
. . .
|
||
</pre><p>
|
||
Similarly, BeOS objects that display text in the user interface—such
|
||
as window titles and button labels—expect to be passed UTF-8 encoded
|
||
strings, and will pass you a UTF-8 string if you ask for the title or
|
||
label.
|
||
|
||
Although the <code class="classname">BFont</code> class allows other encodings, which you may need to
|
||
use from time to time, the system fonts are stuck with UTF-8. It's
|
||
recommended that you stick with it as well wherever possible.
|
||
</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="News2-21"></a>News From The Front</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">William</span> <span class="surname">Adams</span></span></div></div></div><p>
|
||
What kind of programmer are you? That's what I ask myself on a regular
|
||
basis. Am I motivated by fame, fortune, prestige, or something like a
|
||
desire to change the world?
|
||
</p><p>
|
||
Well, honestly, it's a combination of all of these. I've done the mission
|
||
critical custom app thing to great success, and now I've moved on to more
|
||
interesting things. When I program the BeOS, I'm excited. I mean really.
|
||
Staying up until 4am for that "one more compile" just so you can see
|
||
picture in picture video running on a standard BeOS machine?
|
||
</p><p>
|
||
Well, that's what I did this weekend.
|
||
</p><p>
|
||
ftp://ftp.be.com/pub/dr9/samples/videomania.tgz
|
||
</p><p>
|
||
I don't watch TV that much, but when a TV tuner/video capture card costs
|
||
only $127 at Fry's, how could I possibly resist. The interesting thing
|
||
about the Hauppauge board is that it has a tuner, and composite video
|
||
inputs. You can switch between them on the fly. With two of these boards
|
||
in your machine, you basically have 4 video input sources. This is better
|
||
than my TV at home, and costs a lot less. I'm telling you, if you haven't
|
||
already gone out and bought one of these capture cards yet, now would be
|
||
a good time.
|
||
</p><p>
|
||
The other interesting thing about the Hauppauge board is that it works
|
||
better at full screen rather than smaller. Why is that? DMA my fine
|
||
fellow, DMA. The Hauppauge board, or more accurately the Brooktree Bt848
|
||
video capture chip, does DMA transfers directly into video memory if you
|
||
tell it to. So full screen 60 fields per second 32 bit color looks pretty
|
||
cool, and you don't need high energy machines to achieve this
|
||
performance. When you display at a smaller scale, the Bt848 has to do
|
||
some scaling. This doesn't really slow it down, but the quality isn't as
|
||
good. The beauty of DMA is that the CPU doesn't really get involved. A
|
||
lowly PowerPC 603 66MHz could do the job.
|
||
</p><p>
|
||
The thing that keeps me programming is the leap frog inspiration that
|
||
really cool technology causes. Once you have one of these capture cards,
|
||
you might think of ways to improve your "entertainment system." You might
|
||
add easy access to the web and TV Guide, or you might find it interesting
|
||
to add control of your FireWire-based VCR and CD players. Whatever your
|
||
motivation, there's nothing like getting all excited about driving a
|
||
tractor all over the apps that other poor farmers are still struggling
|
||
with.
|
||
</p><p>
|
||
Judging from our mail and BeDevTalk postings, you're all very active with
|
||
DR9. We're pumping out sample apps as fast as we can, and working on
|
||
documentation. Keep sending us your input as to how we can better serve
|
||
you. Without your efforts, this platform will be a technology looking for
|
||
a solution. Keep up the good work and keep sending in that valuable
|
||
praise and criticism. We in turn will continue to try and provide you
|
||
with the best platform upon which you can dream up your killer apps.
|
||
</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="Gassee2-21"></a>Back From Europe</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-Louis</span> <span class="surname">Gassée</span></span></div></div></div><p>
|
||
I spent a week in the old country, meeting software developers, investors
|
||
and business partners, mostly from France, but also from other parts of
|
||
Europe. We've invested early in Europe, based on a combination of beliefs
|
||
and connections. The connections relate to my checkered past in the
|
||
computer industry over there. I worked in the French as well as the
|
||
European HQ of my alma mater Hewlett-Packard, at Data General, at Exxon
|
||
Office Systems (briefly, quickly recognizing the error) and starting
|
||
Apple France, before fulfilling an old dream and moving to the Silicon
|
||
Valley. As a result, when we started the company, we benefited from a
|
||
hospitable European network. Friends invested in the company and
|
||
introduced us to other investors; we abducted people to California and
|
||
linked up again with associates from earlier lives.
|
||
</p><p>
|
||
In many respects, the company probably wouldn't be around if it weren't
|
||
for our European connections. In 1991, when we started raising money, US
|
||
investors were understandably reluctant. Microsoft was already perceived
|
||
as the invincible juggernaut—the agility came later when they became a
|
||
born-again Internet company. At the time, PDAs, set-top boxes and 3DO
|
||
game consoles were in fashion and we couldn't quite demonstrate our OS
|
||
side by side with older platforms. The "no legacy, no baggage" equation
|
||
was hard to explain.
|
||
</p><p>
|
||
In so called "high-tech" industries, Europe is perceived as having fallen
|
||
behind the US. In several instances, it is even true as in the case of
|
||
the PC business. Companies such as Olivetti or Nixdorf were once industry
|
||
leaders. Their misfortunes haven't dulled European appetites for new
|
||
technology. In many respects "conservative" Europeans are more daring
|
||
than New World players. VCRs, CDs and, more recently, the Macintosh and
|
||
digital cellular telephones enjoyed a better early acceptance in the old
|
||
continent than in the US. (Once the new standards get accepted in the US,
|
||
the market quickly makes up for a late start.)
|
||
</p><p>
|
||
In Be's case, our unconventional proposition found early takers in
|
||
Europe. Some investors were not awed by the Microsoft "Über alles"
|
||
mystique, others saw in us the Silicon Valley connection. One of them
|
||
told us bluntly he'd "never invest in a deal like this based in Europe"...
|
||
</p><p>
|
||
European developers react in a similar fashion. First, in an apparent
|
||
paradox, just like the blunt investor, many local developers would be
|
||
reluctant to bet their time and energy on a European media OS. And,
|
||
second, our evangelism efforts got "traction" earlier in Europe than in
|
||
the US. Does it mean the famous "tractor app" will come from Europe
|
||
rather than the US? It is still too early to tell, but we see another
|
||
positive factor in our European connection. It is even harder to make
|
||
money in the software business in Europe than it is in the US. As a
|
||
result of our use of the Net to market and deliver software, European
|
||
developers see the BeOS as a way to break into the US market unavailable
|
||
with the conventional distribution network. Our goal is to make their
|
||
hopes come true.
|
||
</p></div></div><div id="footer"><hr /><div id="footerT">Prev: <a href="Issue2-20.html">Issue 2-20, May 21, 1997</a> Up: <a href="volume2.html">Volume 2: 1997</a> Next: <a href="Issue2-22.html">Issue 2-22, June 4, 1997</a> </div><div id="footerB"><div id="footerBL"><a href="Issue2-20.html" title="Issue 2-20, May 21, 1997"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a href="volume2.html" title="Volume 2: 1997"><img src="./images/navigation/up.png" alt="Up" /></a> <a href="Issue2-22.html" title="Issue 2-22, June 4, 1997"><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>
|