Archives
 
 
 
  Special
 
 
 
  About Us
 
 
 

Newsletter
Free E-mail Newsletter from BYTE.com

 
    
           
Visit the home page Browse the four-year online archive Download platform-neutral CPU/FPU benchmarks Find information for advertisers, authors, vendors, subscribers Request free information on products written about or advertised in BYTE Submit a press release, or scan recent announcements Talk with BYTE's staff and readers about products and technologies

ArticlesEnhancing Netscape with Plug-Ins


March 1997 / Core Technologies / Enhancing Netscape with Plug-Ins

How to write code that interacts with Netscape while extending its capabilities.

Andrew Taylor and Raymond GA Côté

In this article we present a short excursion into the Macintosh LiveConnect plug-in software development kit (SDK) for Netscape Navigator 3.0. We modify the sample applications provided in the SDK, connect a third-party graphics library from Snowbound Software, and point out a few pitfalls for the unwary. The final result is a plug-in that allows you to display PCX files on the Mac and perform the simple manipulations of rotating and resizing images.

Your First Plug-In

The Netscape plug-in SDK is available free of charge from the Netscape Web site at http://home.netscape.com/comprod/development_partners/plugin_api/index.html . It contains projects for Mac, Windows, and Unix machines.

The SDK is simple to use and quick to implement, but, unfortunately, it's the source of some maddeningly obscure problems. All the SDK sample projects were built using Metrowerks CodeWarrior release 9. We made all modifications to the MacShell.cpp file, which is one of the source files in the project.

Navigator presents data to a plug-in in one of two formats: stream and file. The stream data type allows the plug-in to operate on data as it's downloaded from the network. The file data type indicates that the plug-in wants to see the entire file before processing. The imaging library we use prefers to process com plete files, so we'll concentrate on that method.

Modifying the MacTemplate project code is simple and obvious. The steps are outlined below.

First, declare an image-handle variable ( fImgHandle ) for storing the decompressed image. Second, initialize this new variable by setting it to -1 during the call to NPP_New . Third, clean up the memory by releasing any allocated memory during NPP_Destroy .

In the fourth step, add the following line to NPP_NewStream to inform Navigator you want a file, not a stream:

*stype = NP_ASFILEONLY; // we are file-oriented

Step five is where all the difficult work comes in. In the call NPP_StreamAsFile , add the lines shown in the first section of the table "Code Gallery" to decompress and display the image. When the Web page references a uniform resource locator (URL) on a remote Web page, Navigator first downloads the image into a temporary file and then hands you the name of the temp orary file. Navigator automatically deletes this image file when it's no longer needed.

In the final step, change the DoDraw call to display the image. Navigator provides several things: a pointer to the graphics port for display, the origin within the port, and the height and width of the image. The Snowbound library scales the image to fit within that viewing area.

Then you build the project. The resulting shared library (for PowerPC) or code resource (for 680x0) is ready to test.

The plug-in resulting from the preceding six modifications displays a PCX image directly in a Web page. But the image may look rather strange. The reason for this took a little while for us to discover and was the subject of our first lesson about plug-ins.

Mixed Lessons

Lesson one: Never trust the state of the world. Implementing a simple image-decompression/image-display plug-in took three calls and just minutes. Unfortunately, the displayed colors bore little resemb lance to the way that the Snowbound library usually displays the image.

It turns out that Netscape changes the window's foreground and background colors. Adding a call to save the GrafPort settings, forcing them to known values, and then restoring the original settings when done solves this problem.

Lesson Two: Use minimal code to paint. Your plug-in might receive an update event multiple times when you think one would be sufficient. Just make sure you don't do a lot of calculations in your paint routine. Simply updating the display from an off-screen bit map is probably optimal.

Lesson Three: When debugging, debug the right code. Debugging a plug-in (in our case, a PowerPC plug-in) is fairly simple. Just follow the steps below.

  • Quit Netscape Navigator. This is very important. You can spend a remarkable amount of time debugging the wrong version of the plug-in because Navigator cached the previous version.
  • Drag an alias of your pl ug-in into the Netscape Plug-Ins directory.
  • Set up your debugger to break on the NPP_Initialize call.
  • Launch Navigator and open a Hypertext Markup Language (HTML) page, which exercises your plug-in.

JavaScript Makes It Live

Adding a new display ability to Navigator is useful, but the combined power of JavaScript, Java, and plug-ins provides the ability to also interact with the plug-in directly on the Web page.

We previously attempted to build a plug-in for Navigator 2.0 that presented the user with buttons and scroll bars for manipulating the displayed image. It worked just fine -- until we scrolled through the browser window. The resulting screen paint was very ugly. Buttons would lose their position, and the scroll pane was never sure where to update itself on the screen.

The solution is to build the direct-manipulation elements from standard HTML elements and use JavaScript to communicate with your plug-in. Go back to the SDK to modify another sam ple project. This time it's the CharFlipper sample code.

Communication between a Web-page user-interface element and a plug-in requires three levels: the JavaScript User Interface component, Java glue , and the plug-in itself. This chain of events is illustrated in the figure "Using JavaScript to Operate a Plug-In" . Each level requires a method (i.e., a function) with the same name. In our example, it's Rotate. This method rotates the displayed image 90 degrees clockwise each time it's called.

We can start at the user-interface level by attaching a JavaScript statement to a simple button that says "Rotate." The JavaScript statement is as follows:

onclick="document.ImageViewer.Rotate();"

JavaScript cannot directly call the plug-in. It must use a simple Java class as its glue. For that purpose, we created a Java class, called ImageViewer.class , which is placed in the Netscape plug-ins folder. This class contains a method definition as f ollows:

public native void Rotate();

It's that simple. The JavaScript calls the method in the Java class, which is defined as native. Java knows to seek out a plug-in with the same name as this class and then call the proper C++ method.

Now we call the C++ plug-in ImageViewer. The Rotate method that Java calls is declared as follows:

void native_ImageViewer_Rotate
   ( JRIEnv* env, struct ImageViewer * self );

The naming convention can get a little long, but it's pretty clear. The env and self parameters are used to obtain access to the object instance. You need to do a standard invocation first, as shown in the second section of the table "Code Gallery."

The interplay of HTML, JavaScript, and custom plug-ins provides a powerful combination of cross-platform presentation and native compiled-code speed. Although Navigator is still a work in progress, version 3.0 provides a strong base upon which useful applications can be built.


Code Gallery

Section 1: Display a graphic

  // The following line calls the Snowbound library to do
  // all the decompression work.
  This->fImgHandle = IMG_decompress_bitmap((char *)fname);
  
  // Display the image.
  if( StartDraw(This->fWindow))
  {
        DoDraw(this);
        EndDraw(This->fWindow);
  }
Section 2: Call the Rotate method
   // get plug-in structure back for this instance.
  NPP instance = (NPP)self->GetPeer(env); 
  // retrieve pointer to the actual instance. 
  ImageViewer *iView = (ImageViewer *)instance->pData;
  // Now able to use object methods and variables.
  // Invoke the rotate method.
  iView->Rotate();




Using JavaScript to Operate a Plug-In

illustration_link (29 Kbytes)

How events flow from JavaScript to a Netscape plug-in.


Andrew Taylor and Raymond GA Côté develop custom cross-platform applications at Appropriate Solutions, Inc. (Peterborough, NH). You can contact them at aetaylor@AppropriateSolutions.com and rgacote@AppropriateSolutions.com , respectively. The Snowbound imaging library can be found at http://www.snowbnd.com .

Up to the Core Technologies section contentsGo to previous article: SearchSend a comment on this articleSubscribe to BYTE or BYTE on CD-ROM  
Flexible C++
Matthew Wilson
My approach to software engineering is far more pragmatic than it is theoretical--and no language better exemplifies this than C++.

more...

BYTE Digest

BYTE Digest editors every month analyze and evaluate the best articles from Information Week, EE Times, Dr. Dobb's Journal, Network Computing, Sys Admin, and dozens of other CMP publications—bringing you critical news and information about wireless communication, computer security, software development, embedded systems, and more!

Find out more

BYTE.com Store

BYTE CD-ROM
NOW, on one CD-ROM, you can instantly access more than 8 years of BYTE.
 
The Best of BYTE Volume 1: Programming Languages
The Best of BYTE
Volume 1: Programming Languages
In this issue of Best of BYTE, we bring together some of the leading programming language designers and implementors...

Copyright © 2005 CMP Media LLC, Privacy Policy, Your California Privacy rights, Terms of Service
Site comments: webmaster@byte.com
SDMG Web Sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, New Architect, SD Expo, SD Magazine, Sys Admin, The Perl Journal, UnixReview.com, Windows Developer Network