Issue 3-18, May 6, 1998

Be Engineering Insights: Proper Printing

By Benoît Schillings

I thought that since the Print feature now actually prints, I'd use this newsletter article to provide a good reference example of how to implement printing in your application—so here it is.

status_t MyView::PageSetup()
  status_t  result = B_ERROR;

// It is a good idea to give the print job a meaningful
// name, since this is what the user will see in the spool
// control (or the spool folder), so try to name it after
// the document being printed.

  BPrintJob  printJob(this->DocumentName());

// If mPrintSettings is NULL, it means that this document
// was never printed, so we need to set up the Settings of
// the BPrintJob using a new empty message. Otherwise you
// would reuse the settings saved with the document so that
// the user does not have to reset all the settings each
// time he wants to open and print.

  if (mPrintSettings != NULL)
    printJob.SetSettings(new BMessage(mPrintSettings));

// Call ConfigPage, this allows the user to change the
// current PageSettings and will validate the content of the
// settings if the printer has changed.

  result = printJob.ConfigPage();

  if (result == B_NO_ERROR) {

// We have new settings, so we can delete the old local copy
// and extract the new one out of the print job.

    delete (mPrintSettings);
    mPrintSettings = printJob.Settings();

// You may want to save those new settings somewhere in the
// current document, so that they are remembered from one
// session to another.


  return (result);


void MyView::Print()
  BPrintJob printJob(this->DocumentName());

// If we do not have any settings, this probably means that
// the user is trying to print without having done a
// PageSetup first. In that case we want to get a PageSetup
// dialog to show up before printing.
// Note that if mPrintSettings is not NULL, this could also
// mean that a PageSetup setting from a previous printing
// session was reloaded from the document.

  if (mPrintSettings == NULL) {
    if (PageSetup() != B_NO_ERROR)
    printJob.SetSettings(new BMessage(mPrintSettings));

// ConfigJob will show the user a dialog which allows him
// to specify which pages to print, the number of copies,
// the printing quality etc.

  if (printJob.ConfigJob() == B_NO_ERROR) {
    int32  curPage = 1;
    int32  first_page;
    int32  last_page;
    int32  pages_in_document;
    BRect  pageRect = printJob.PrintableRect();
    BRect  curPageRect = pageRect;

// Let's find out how many pages we have in the document.

    pages_in_document = (this->TotalVerticalSize() +
      (pageRect.Height() - 1)) / pageRect.Height();

// Find out how many pages the user wants to print
// this time.

    first_page = printJob.FirstPage();
    last_page = printJob.LastPage();

// Be certain to clip the last page value against the
// document size. It looks pretty bad to the customer when
// you try to output MAXINT pages on her printer!

    if (last_page > pages_in_document)
      last_page = pages_in_document;

// Let's start the job for real,
// BeginJob actually creates the spool file!


// Now, for all the pages, let's image the page and add it
// to the current job.

    for (curPage = first_page;
         curPage <= last_page; curPage++) {

// Let's compute a rectangle which encloses the part of the
// view describing page "curPage"

      curPageRect.OffsetTo(0, curPage * pageRect.Height());

// Let's render the current view with this curPageRect.
// Note that we want that part of the view to be set on the
// page at position 0,0

      printJob.DrawView(this, curPageRect, BPoint(0.0, 0.0));

// And let's add this new page to the job.


// Check for errors/user interrupt/nuclear war
// alert/disk full

      if (!printJob.CanContinue())
        goto catastrophic_exit;




Spreading The Word II

By Dave Johnson

Spreading the Word II—another in my series of articles about making MONEY developing applications for the BeOS.

Visit Be and PC User Groups!

Developers—have you shown your application(s) to any user groups yet? User groups are one of the best ways to spread the word about your product.

Demonstrating your product to a user group accomplishes several desirable goals:

  • You are informing users of your product's existence (and after the demo they inform others).

  • You are showing them how it works and how they would use it.

  • You are learning from your potential customers what they want to know. Often the question and answer period after your demonstration is the most important part of your visit.

When visiting a user group, bring you own computer with everything set up and ready to go. You probably won't need a monitor, but ask ahead of time just in case. Now I'll remind you of the obvious: once you set a date, make sure you arrive with your demo well-prepared, machine fully tricked out, goodies to give away, and so on. Bring one or more copies of your product for a raffle. If you only sell online let them know that you'll send the product to the winner(s). If you're demonstrating to a PC user group instead of a Be user group let us know and we'll try to provide some things, like T-shirts and copies of BeOS to raffle, to help you out.

There are now over 100 Be User Groups (BUGs) and they are eager to see your products. They would be more than happy to arrange a meeting to show a Be app. You can find them on the web at:

Send them a note asking if you can be added to their schedule. If you want more specific information about specific groups, contact

Don't limit yourself to Be user groups! PC user groups are not necessarily Windows user groups and the BeOS runs on PCs. Everyone with a Pentium is ultimately a potential customer for your BeOS application, so it's a GREAT idea to look PC user groups and arrange to show them your product. The BeOS runs on Intel architecture, which means that there are a huge number of potential customers out there right now—but they don't know about you yet! You can bring the news about the BeOS to these groups by showing your product.

Here are some links to lists of PC user groups to check out:

One more thing—remember my article on sending press releases? It's also a good idea to send them to Be and PC user groups.

Support BeOS-Related Web Sites

It's helpful to become familiar with the various BeOS-related web sites. Check them out! Contact the people in charge and find out how to send them news, articles, review copies, etc. A relationship with a news site is a relationship with its readers.

Tip: Advertise! You get exposure and the web site gets support if you place a banner ad on the web site!

Check the BeOS-related web sites below:

Be Leading Edge:
BeOS Central:
Be Happy:
Let It...Be:
Be Dope
Be News Now:
BeOS for Intel:
Plan Be:
Time to Be:
Be Different (Spanish):

For Shareware Authors

Here's something I've been meaning to bring up for a while: Shareware authors—consider selling your product as a commercial application instead of shareware. Selling your product commercially through BeDepot offers all the advantages of shareware with fewer disadvantages. Make your product available at low cost, a "no-brainer" price, and you won't believe how many you'll sell! The revenue can finance the next version, maybe even enable you to quit your day job.

One of the main reasons for making a product available as shareware has been the difficulty of collecting payment, especially using credit cards. BeDepot <> collects payments for you, and even accepts credit cards. You just sit back and get checks.

Another typical reason for selling as shareware has been the difficulty of delivering the product once it is ordered. You either have to print manuals and boxes and duplicate disks, or send a large file (or ship a package) when you get the order. BeDepot delivers the product electronically for you.

So once again, I urge you to use BeDepot instead of trying to make money through shareware. You'll make more, with less hassle.

Visit Be newsgroups at*

Another place to gather and spread information is on newsgroups. Check the Be newsgroups located at*. It isn't good manners to just show up and advertise (except at, if you follow their rules), but there is a lot to gain from being active on these newsgroups. You can help people with their questions and also get information from a wide variety of sources. Newsgroups are read by a lot of people, even if they are not actively posting, so being active helps you and your products become known.

Developers' Workshop: Forget-Me-Nots

By Stephen Beaulieu

Greetings! As it turns out, I am back in the hot seat again much sooner than anticipated. With Doug on vacation and my wedding swiftly approaching, we belatedly discovered a need to rearrange the order of the DTS Newsletter writing. So, you get me again now, and then will be hippo-free until late June or early July.

Along with rearranging Newsletter duties, the DTS team also sat down to more clearly parcel out responsibilities for sections of the BeOS. These "areas of expertise" loosely define where we should be focussing our individual efforts for investigating bugs, answering developer questions, writing sample code and so on. I was lucky enough to inherit many of the lower-level Kits, including: the Kernel, Mail, Network, Storage, and Support Kits, rounded off with developer tools and add-ons.

This week I am going to talk about some of the things that we forget to talk about every now and then. I'll start with two "forgotten functions" from my areas: cast_as() and snooze_until().


Take a look sometime inside of support/ClassInfo.h. You will see some useful macros there that probably do not see the light of day as much as they should, at least if outside engineers are anything like we are. The cast_as() macro is the most important of these functions (although the others can certainly be useful.)

There are some places in the BeOS where void *s are thrown about with great abandon. Those that leap readily to mind include dealing with items from BLists and arguments for thread entry functions. It is very tempting to simply use C-style casts to deal with these pointers, but this is not smart. (And before we go farther I will admit to being dumb in all of my sample code until now, look for updates in the near future to correct this.) Let me give you a concrete example of how this could be problematic.

Assume that you have a BList that is (supposedly) full of BRect pointers. You want to look at these pointers and find one that contains a given BPoint. You would have a loop whose inner core looked like this:

BRect *rect = (BRect *) list.ItemAt(index);
if (rect->Contains(point)) {
  /* do something cool */

This is all fine and dandy if the item at index is actually a BRect. The result if the item is not a BRect is undefined (and probably most undesirable).

But there is a way to make sure that this slice of evil never occurs. Change the inner loop to something like this:

void *item = NULL;
BRect rect = NULL;

item = list.ItemAt(index);
rect = cast_as(item, BRect);
if (!rect) {
  printf("we don't have a rect here!\n");
  return B_ERROR;
/* we are safe and know that rect is indeed a BRect*/
if (rect->Contains(point)) {
  /* do something cool */

Now, in an ideal world you wouldn't end up with a situation where you have chosen the wrong BList to look through, or where you haven't accidentally added the wrong pointer to the right BList. But these things have been known to happen!

Another, and perhaps more common, use for the cast_as() macro is found when playing in the Interface Kit. There are many functions that simply return a generic BView*. Whenever these need to be cast to a more specific class using the cast_as() macro will prove much safer than a blind C-style cast.


A new thread control function was added to the Kernel Kit in Release 3 that deserves mention. snooze_until() allows a thread to block until a certain time is reached. This is exciting, of course, but how does snooze_until() differ from it's older sibling snooze()?

The most obvious way is that snooze_until() supports defining a time to awaken based on a named time base. In Release 3 the only time base supported is the B_SYSTEM_TIMEBASE, which simply deals with the system time. In the future we will support other time bases so snooze_until() could be used to block until a given frame of video is ready or until the next MIDI event needs to be sent.

The other major difference (and the only one of real use now) is that snooze_until() has been designed to be more accurate than snooze(). This accuracy comes in large part from the possibilities of being rescheduled between calls. Take the following example where you want to snooze for 25 milliseconds in between some printf() calls.

printf("let's print!\n");
printf("let's print again!\n");

In the best of all worlds there would only be the 25 millisecond interval between the calls. But in the worst case your thread could be rescheduled right after the first printf(), and when next rescheduled would immediately block for the 25 milliseconds, and then would be rescheduled after the snooze(). With a thread rescheduling latency of 1 -2 milliseconds, this could mean that you could sleep for a handful of milliseconds extra.

You could rewrite this code using snooze_until() and your worst case scenario would look a little better.

bigtime_t now = system_time();
printf("let's print!\n");
snooze_until(now + 25000);
printf("let's print again!\n");

This will base the wake-up time on the original "now" time, rather than the time that the snooze() function was called, and should be better.

There are currently some caveats, however. The difference in performance between snooze_until() and snooze() is generally not noticeable unless running within a real-time thread or if the amount of time to snooze is very small. In general, it doesn't make any sense to try and snooze for less than 1 millisecond, because interrupts are only looked at every millisecond. However, when snooze_until() is called and the amount of time left until the wake-up time is very small, it will return rather than have the thread rescheduled. This makes tight timing loops more accurate (assuming you have a need for such a tight loop anyway).

And as mentioned, this really only makes a huge difference when dealing with a real-time thread. If you are not dealing with a real-time thread there is no guarantee that you will run when you are ready. If higher priority threads are ready to run, they will go first, regardless of which type of nap you took. Even when dealing with a real-time thread, you must still be aware that there are latencies involved, on the order of 2-3 milliseconds max, and 1 millisecond on average, so timing loops will never be precisely accurate.


One last forgotten item. In the mad rush to get Release 3 out the door, we forgot to also release the GNU Public License code that used in the BeOS. We are rectifying this lapse in memory now.

We use GPL code for malloc, termcap and crypt. This are directly linked into the kernel, libroot, telnet, telnetd, top, and zbeos (the BeOS Intel bootloader). We have a single downloadable archive called gnu_x86.tar.gz that contains makefiles, the GNU source code, and object files that allow you to rebuild these components.

We also use GPL code for our 3Com 3C905 Ethernet drivers. This code comes from Linux and the source is available in an archive called linux_ether.tar.gz.

The other GNU tools used by the BeOS are included in the /optional directory of the Release 3 CD.

The packages are complete and allow you to rebuild the GNU code and relink to produce the final binaries. Unfortunately if you make modifications (or used modified versions) we can't offer support if you run into problems.

We thank you all for your patience and friendly reminders to make these packages available. Be is a strong supporter of "free" software, and we will continue to do our best to comply with the license requirements of the code included in the BeOS.

Just For Fun

By Jean-Louis Gassée

In late March this year, we held our first developer conference that focused on the Intel platform. Now we are preparing for our first trade show with a similar focus, but a much bigger audience. This is PC Expo, in New York City, opening June 16th at the Jacob Javits Convention Center.

As we learned from inflicting our inexperience on BeOS enthusiasts who ordered the Release 3 for Intel product, we are likely to find that nothing we've done so far can fully prepare us for an event like PC Expo. We've been to MacWorld trade shows, a couple of Comdexes—the first in the PowerPC pavilion, the second generously hosted by our Umax friends -- we've been to NAB, with the Adamation booth this time, but never as "ourselves" to a PC Expo.

I'm sure we'll undergo more humbling and comical experiences which will be reported here—at least the admissible ones. Still, since we released the Intel version of our BeOS, we've learned a few lessons we plan to bring with us to our "coming out" at PC Expo.

First, we've verified there is demand for our product. I'm not trying to be funny or attempting to brag. Consider this: We mostly gave away the PowerPC version of the BeOS, on CDs bundled with magazines and as a free download version. This was a good way to spread the news and to bootstrap an installed base for Be developers. However, we learned we weren't learning much from this distribution method.

As some companies have found, the free software habit is hard to kick. Shareholders get nervous and the intended audiences—developers and customers—experience mixed emotions. It feels good at first, but will it last? And, in any event, giving away your product makes it hard to get a feel for the demand out there.

For those reasons, there is no free BeOS for Intel. So far, customers have been kind, putting up with our fledgling e-commerce system, overtaxed voice mail, and learn-as-you-go bumbling. Returns are very few and, while demand has settled down from its early peak, we enjoy a modest daily current of business from the US, Europe, and Japan. No strutting in the end zone, but we are a little ahead of our (conservative) goals for this year.

Second, we have to re-emphasize the "geeks-only" status of our product. We're not ready for the mainstream. Installation isn't for normal people, there are still too few applications (though this is changing), and we support only a limited range of hardware devices. This also is changing, but we will never cover the immense range of configurations Windows does.

To help people through the labyrinth of hardware compatibility, we hope to offer a Windows application for download soon. Once in your system, it would test your hardware and return one of three answers: yes; not sure, please allow us to upload the test results to galactic headquarters; or, no, sorry, we're not worthy of your hardware.

Meanwhile, we're not sitting still. We plan to offer a very minimalist VGA grey scale driver for Release 3.1. If the BeOS CD does not contain a driver for your graphics card, this driver will still let you boot on (almost) any display adapter, install the BeOS, and look for the right driver on our Web site or other related ones. In addition, as we are doing with our friends at UMI and the "Ming Specials" listed on our Web site, we'll work with system vendors to identify "BeOS Ready" systems.

Third, I just mentioned Release 3.1. It is exactly what the numbering convention implies: rolling up bug fixes, adding more drivers (including the basic VGA install capability mentioned above). PC Expo gives us a good deadline to beat for that release. I tend to like "dot" releases. They solidify the previous "major" version, they fix more bugs than they create—unlike the "big" releases—and they instill confidence in developers and customers.

Fourth, since we introduced the BeOS for Intel Architecture PCs, we've learned we have to keep working hard at differentiating our work from IBM's futile attempt to position OS/2 as "Better DOS than DOS, better Windows than Windows." Once the audience realizes we mean it when we acknowledge Windows as the immensely successful general-purpose reference OS, it becomes much easier to position the BeOS as a complementary specialized OS for video and audio applications.

The stealth success of Linux as a specialized OS, a Unix clone coexisting peacefully with Windows, helps demonstrate the validity of the general purpose vs. specialized concept. We also find that our non-religious, non-Microsoft-bashing posture is appreciated. Others do the bashing very well; we'd like to stay focused on all the things we have to do for customers and developers.

Speaking of which, and this is the last item on my list for today, PC Expo will give all of us an opportunity to show applications, sell some product, display work in progress, show promising prototypes, and, in general, demonstrate momentum on the application side.

For us on the release side, a trade show is effective persuasion for getting developers to bring their work to the next stage, especially when moving PowerPC code to the Intel side. We'll have demo stations set up, so if you'd like to show your work, please let us know. With the "geeks only" positioning clearly established, we'll enjoy the right subset of PC Expo visitors.

BeDevTalk Summary

BeDevTalk is an unmonitored discussion group in which technical information is shared by Be developers and interested parties. In this column, we summarize some of the active threads, listed by their subject lines as they appear, verbatim, in the mail.

To subscribe to BeDevTalk, visit the mailing list page on our web site:


Subject: BFS Filesystem, Viruses and anything else I can dream up


Can the Be filesystem become fragmented? Is there any way to check for fragmentation, or to defragment?


Yes, fragmentation is possible, but, according to Dominic Giampaolo...

In practice BFS seems quite resilient against fragmentation. I recently ran some diagnostics on some systems around here that have been in constant use for 6 months or more... Over 98% of the files on all three machines were stored in one or two contiguous runs of disk blocks.

Tyler Riti wonders whether defragmenting is worth it: 30 minutes of defragging to gain a few milliseconds of seek time. Furthermore, does defragmenting actually buy you back those milliseconds? Of course it does, says the conventional wisdom; but multi-threading confounds the issue. If two or more programs are hitting different files at the same time, then the contiguity of the files isn't necessarily a help, and can actually be a hindrance (since the order in which the blocks are hit isn't necessarily sorted).

Subject: Crossdevelopment with BeIDE

The BeIDE puts object files in a directory that's always named "(Objects)". If you zip and move your project directory between PPC and Intel, you clobber the destination object files. Can anybody think of an automated way to avoid this?

Thorbjorn Jemander (and others) suggested creating a directory structure that separates the projects from the source:


The project and "(Objects)" directory live in the respective architecture directories, and the source code lives in the "source" directory. The projects would include the common sources, but wouldn't step on each other's object files.

Most folks liked the solution, although it isn't perfect: If you change the set of source files, you have to update both projects (for example).

Subject: html indexing tool?

Scripting talk with all the usual snakes and ladders: Python, Perl, Frontier, etc.

The usefulness of Be API-specific components (BMessage, BPath, etc.) as scripting candidates was clarified. Some of our readers debated whether an object database (as used by some scripting environments) is necessary: Is the BFS fast enough to use directories as tables and files as records?

Other topics: How should data types (int16, int32, et. al.) be represented within a script message? Is string representation too slow? W.G.J. Langeveld thinks strings are plenty fast enough, given the context:

Well sure, strings aren't all that speedy. They're not horrible either, compared to the time to interpret the instruction (which is a string anyway) and the task switch time to send the message. How many numbers will a typical message contain? If you think the answer is more than 10, then I think we have different ideas of what scripting is supposed to accomplish.

How should different data types be presented to the user? Need the user know the difference between int32 and int64 (for example)? Chris Herborth suggested that the scripting interface follow the API. Some readers objected on the grounds that this would be too complex for users. Mr. Herborth responded:

“I'm going to exactly mirror the API, then start working on making a simplified API for people doing common tasks. By having everything there at the start, I'm enabling anyone to come up with:

  1. a correct application scripting message :-)

  2. the ability to make a simplified API”

The attitude of "smarter doesn't mean harder" didn't appease all of our readers. It was generally agreed that a scripting language's first requirement is that it be easy to use; it mustn't require knowledge of implementation details such as BMessage format or data byte-length. Some folks are concerned that a "robust" language will cut corners when it comes to hiding details.

A grass-roots, module-by-module, Frontier-like project was proposed by Jake "Jake Hamby" Hamby.

Subject: Math performance on Release 3 Intel

Peter Enzerink wants to know why the floating point benchmarks run slower in BeOS Release 3 than on Windows 95. There were no direct answers, but a number of subthreads:

  • How much does compiler optimization affect performance? No clear answer, but most of our listeners seem to think that you shouldn't expect more than a 10% speed up.

  • Does a higher thread priority mean a faster app? No—you should never try to improve overall app speed by increasing thread priorities. If you have a real-time stream, then use a real-time priority; but goosing all threads in an effort to (A) get more performance out of the system or (B) play beat-your-neighbor is (A) ill-conceived and futile, and (B) exhibits a pathetic insecurity and mean spirit.

  • Can you really use MSVC to compile BeOS code (as a listener implied)? It's been done; Jon Watte suggests...

    1. Write speed-critical section in C only.

    2. Transfer needed header files to Windows NT

    3. Compile C files with MSVC

    4. Transfer .OBJ files to BeOS, renaming them .o

    5. Compile C++ files with mwcc

    6. Link it all together to an app

Note that this is an unsupported phenomenon.

Subject: Idea ?! ?

Are "gestural" input systems useful? Listener Chaut liked the sound of the Windows app that lets you...

"...draw a 'W' (at the scale you want) with your mouse and it launches Word ..."

Would this be just a weekend hack, or is this an example of (notoriously difficult) OCR in sheep's clothing? (Yes it is, no it isn't, went the debate.)

A number of listeners wrote in to second the call for more BeOS input devices (stylus pads and the like), but some of us just couldn't take the

Subject seriously and will be spending the evening in our rooms. Mike Manzano:

I've got it! How about just a button that, when you press on it, pops up a menu with a list of things you can launch in it!

And Ingmar Krusch:

It would be easy to write an app that recognizes gestures from QuickCam pictures. So if you make a funny face, it connects N+ to

Subject: Running a thread on a processor


How do you assign a thread to a specific processor (on an MP system)?


You can't—and you really don't want to. If you want to select an algorithm based on the number of processors, do so (the get_system_info() function will help you here), but don't try to outguess the system when it comes to scheduling cycles.



If a window accepts first click, shouldn't the initial click make the window active?


Nope. The easiest way to activate the window is to tell the view that gets the click to do it.

Subject: alive or dead?


How can you test (programmatically) to see if an app is *really* alive? (Or, as Ingmar Krusch colorfully put it: “I want to know if it quacks when I feed it.”)


Call BRoster::IsRunning()

Objection: This only returns the presence of the app in BRoster's roster of apps—it doesn't actually check to see if the app is alive.


Call get_thread_info(), snooze, and then re-call and check for activity.

Objection: It's theoretically possible for an app to be completely inactive and so appear dead.


Look for the presence of a debugger nub thread in the team.

Objection: What if some other (or future) debugger doesn't spawn a recognizable nub?

Subject: BeFS: difference between PPC and x86 filesystem?

Is there a difference between the PPC and Intel versions of BFS that would prevent a user from reading the PPC CD on a PC running BeOS?

THE BE LINE: (From Dominic Giampaolo) We do not currently support reading PPC versions of BFS under Intel (nor the other way around). The layout of the file system is the same on both platforms, only the endianess is different.

Support for reading opposite-endian file systems is planned for a future release although I'm not sure when it will make it in.

Subject: mimetypes questions

In a subthread of the mimetypes topic, flavors of zip were discussed:

  • gzip: Good compression, particularly on multiple small files (since it compresses the lot of them as a single stream), but it doesn't preserve Be attributes. Also, since gzip produces a stream, damage is difficult to correct.

  • zip: zip archives files individually so its compression isn't as good as gzip (although the difference isn't overwhelming), but damage repair is easier. Also, zip preserves Be attributes; this feature tilts the scales in many cases.

  • bzip2: Best compression, although, again, there's not a huge difference. If you absolutely have to squish out that last 10% of trapped air, then use bzip2; otherwise, don't worry about it. And bzip2 (according to Trey Boudreau) isn't protected by patent lawyers (as bzip is).

Creative Commons License
Legal Notice
This work is licensed under a Creative Commons Attribution-Non commercial-No Derivative Works 3.0 License.