TweetFollow Us on Twitter

Tools Plus Pro

Volume Number: 15 (1999)
Issue Number: 10
Column Tag: Programming

Tools Plus Pro Libraries + Framework

by Thurman Gillespy III, M.D., Seattle, WA

Mac Programming Fast and Easy


The Tools Plus Pro 5 libraries and (optional) application framework greatly simplify the development of Macintosh applications and plug-ins. Tools Plus provides a high level API that simplifies and consolidates many Mac OS toolbox routines. Tools Plus can be programmed in C, C++, and Pascal, and covers the user interface and event processing components of the Mac Toolbox. Tools Plus replaces the classic Macintosh event loop with an event dispatcher. Tools Plus interface components include windows (including dialogs, floating windows, and a tool bar), cursors, menus, pop-up menus, buttons, scroll bars, sliders, panels, and list boxes. Tools Plus fully supports the Appearance Manager, but even without it, Tools Plus can still develop great-looking applications. Tools Plus supports most of the compilers in common use today.

Tools Plus is developed and distributed by Water's Edge Software, Ontario, Canada. A fully featured evaluation kit (9.4M) and a smaller demo kit (676K) are available online.
Water's Edge Software

How I Use Tools Plus

I've been using Tools Plus since early 1996 for the development of a medical image display program, Dr Razz. The program uses many Tools Plus interface components, including the tool bar, floating windows, sliders, picture buttons, cursor tables, and edit fields. Two great ways to see what Tools Plus can do are to carefully study the Tools Plus Demo App (included in the evaluation and demo kits) to see all the user interface components in action, and also to look at my program to see Tools Plus used to develop a complete Macintosh application.
Dr Razz

The Out of Box Experience

The Tools Plus distribution includes the Tools Plus 680x0 and PPC libraries for C/C++ and Pascal. Separate libraries for applications and plug-ins are included. The 680x0 libraries have both large and small code model versions. Also included is an application framework, actually a stub application outline. Tools Plus supports CodeWarrior (as far back as version 6), CodeWarrior Pro, Symantec C/C++, THINK C, and THINK Pascal, and separate libraries and project files are included for these systems.

Extras include a printed and electronic user manual (in both eDoc and PDF formats) and 11 different tutorial projects that illustrate a particular Tools Plus feature. A demo application (the Tools Plus Demo App) and source code are included that nicely illustrate the Tools Plus event model and user interface components.

Tools Plus also ships with SuperCDEFs, a nice collection of 3D user interface components that you can use to develop a great-looking user interface without the Appearance Manager. SuperCDEFs includes buttons, sliders, tabs, hierarchy triangles, and progress thermometers.

Figure 1.Some of the many SuperCDEFs components.

Also bundled are the Infinity Windoid WDEF, miscellaneous icons, animated cursors, fonts, and other resources.

Figure 2.A floating window created with the Infinity Windoid WDEF.

Tools Plus Professional retails for $249, and includes a one year subscription with three annual updates, as well as a license to include the libraries in your finished product. The subscription also includes e-mail access to the Tools Plus Developer Forum, Water's Edge News, and technical support. Support questions are usually promptly answered. Bug notices are automatically e-mailed to registered developers, which is a very nice service. Tools Plus Lite (680x0 libraries for CodeWarrior only) is available for a limited time for $99. Academic discounts are available. Tools Plus Pro and Tools Plus Lite are available from Water's Edge and DevDepot.

Some Assembly Required

So how do you develop an application or plug-in with Tools Plus? A great place to get started is to use the sample project and the application framework files appropriate for your development system. The application framework is composed of 8 files (and associated headers) that form a basic application shell, with lots of "insert your code here to handle..." comments. The framework is entirely optional, and you can use your own coding style as you see fit.

You can divide project development into the following steps.

  1. develop DLOG, MENU and other resources for user interface
  2. write your application specific initialization routines
  3. all InitToolsPlus with appropriate parameters
  4. write the application event handler
  5. write event handlers for each window type (optional, but highly recommended)
  6. write the event filter (optional, but the recommended method of performing menu updates)
  7. write routines to handle application and window events
  8. link the appropriate Tools Plus library/libraries for your development system
  9. compile and enjoy!

Batteries Not Included

Tools Plus is not a complete application/plug-in development environment, although the libraries handle most of the event processing and user interface aspects of an application or plug-in. There is no support for memory management (except for edit fields), file operations, open/save file dialogs, low-level debug support, or network operations. Support for balloon help is incomplete, and is completely absent for standard algorithms such as linked lists. There is no Tools Plus API support for print operations, but the application framework has useful print starter code. Tools Plus does not come with an interface editor like CodeWarrior Constructor, REALbasic or AppMaker - for serious work you will need Resorcerer from Mathemaesthetics. Tools Plus has basic list box support, but Water's Edge recommends purchasing StoneTable[TM] from StoneTablet Publishing for advanced list box operations. For advanced text handling and display you should consider the popular WASTE text-editing library from Marco Piovanelli, and for file operations you should consider the MoreFiles routines from Jim Luther.


USING The Tools Plus System

The Tools Plus libraries handle events and manage the Tools Plus interface components. To get started, you initialize the libraries, then let them begin processing events.

Press Here To Start

Getting the Tools Plus libraries up and running is easy. Your application's main function may only contain 3 or 4 statements.

TPEventRecord	Event;

void main(void)
	// initialize Tools Plus
	InitToolsPlus(&Event, MyEventHandler, MyEventFilter,...);
	// initialize your data structures, etc.
	// tell Tools Plus to begin processing Mac OS events
	// your clean up code, if any (might be within the event handler)

InitToolsPlus gets the ball rolling, and should be called as soon as possible. It initializes the Tools Plus internal data structures, handles Macintosh startup chores for you, lets you set your event handling routines, and has a number of optional parameters.

The prototype is:

pascal Boolean InitToolsPlus (
			TPEventRecord								*EventPtr,
			const EventHandlerProcPtr		EventHandler,
			const EventFilterProcPtr			EventFilter,
			short											MoreHandles,
			short											MaxWindows,
			short											TEBufferSize,
			long												InitSpec);

InitToolsPlus takes a pointer to a TPEventRecord, the Tools Plus structure that contains the Tools Plus event information. Typically, this variable has global scope. The EventHandler and EventFilter parameters are discussed below. MoreHandles is the number of master handle blocks to allocate at startup. MaxWindows is the maximum number of windows that can be opened at the same time. Tools Plus preallocates window storage (about 300 bytes/window) and is limited to 250 windows at most (far more than any application could reasonably use). TEBufferSize specifies the size of text editing buffers (maintained by Tools Plus) used for cutting, copying, pasting, and storing copies of text for Edit menu Undo/Redo support, and should be between 255 and 32767 bytes.

Spec is the specification parameter that specifies various start up tasks and Tools Plus behavior. There are 19 different parameters available. In my application, I initialize ToolsPlus for 12 master handle blocks, 60 maximum windows, and an edit buffer of 4096 bytes. The specifications I use are initMacToolbox (initialize the Mac toolbox), initUseColor (use Color QuickDraw if available), initUseTEScrap (maintain a local TextEdit scrap), initDontUnloadDeskScrap (don't unload the desk scrap to disk) and initPureAppearanceManager (use Appearance Manager controls if available, resolve certain appearance ambiguities).

InitToolsPlus(&Event, EventHandler, EventFilter,
			12, 60, 4096,
			initMacToolbox + initUseColor +
			initUseTEScrap + initDontUnloadDeskScrap +

InitToolsPlus also flushes the Mac OS event queue, seeds the random number generator and calls MaxApplZone. InitToolsPlus is typical of many Tools Plus routines: highly configurable, and able to handle of lot of the Mac OS "dirty work" for you.

After initializing Tools Plus, perform your application-specific initialization routines. Next, call ProcessEvents to tell Tools Plus to start processing Mac OS events into Tools Plus events. Tools Plus events are then dispatched to your EventHandler and WindowHandler routines (see below).

That's it! After three or four lines of code, your application is running and ready to process events.

The Tools Plus Event Model

After you call ProcessEvents, Tools Plus takes raw Mac OS events, translates them into very high-level Tools Plus events, and dispatches the events to your event handlers. Your event handlers parse the TPEventRecord, and then execute your application-specific code. The Tools Plus event model saves you hundreds of lines of code compared with handling the Mac OS events yourself.

The Tools Plus events are listed in Table 1.

doNothing No event (background processing done here)
doChgWindow User clicked in an inactive window
doRefresh A window has to be refreshed
doGoAway The close box was clicked
doButton Button was clicked
doMenu Menu was selected
doKeyDown A keyboard key was pressed
doAutoKey A keyboard key is auto-repeating
doKeyUp A keyboard key was released
doClickToFocus Mouse clicked in an object that wants the keyboard focus (inactive field, etc.)
doScrollBar Mouse clicked in a scroll bar
doListBox Some sort of List Box activity
doClick Mouse click/drag [1..3]
doPopUpMenu Pop-up menu was selected
doPictButton Picture button activity
doClickControl Mouse clicked in a custom control
doManualEvent Manually processed events
doMoveWindow A window was dragged by user
doGrowWindow A window was "grown" by user
doClickDesk Mouse clicked in the desk top
doZoomWindow Zoom box was clicked by user
doSuspend Appl. suspended (in background)
doResume Appl. resumed (now active appl.)
doChgInField Editing field contents was changed
doPreRefresh Refresh window before T+ objects
doActivate Window was activated
doDeactivate Window was deactivated
doMoveCursor Cursor has entered a new Cursor Zone
doKeyInControl Key stroke was applied to a control
doChgMonitorSettings Monitor settings were changed
doOpenApplication App launched with no open docs
doOpenDocuments Your app should open 1 or more docs
doPrintDocuments Your app should print 1 or more docs
doQuitApplication Your app should quit

Table 1. Tools Plus Events.

In many cases, the Tools Plus event represents the summation of multiple fields in a low-level Mac OS event, which greatly simplifies your code. For example, it might take half a dozen or so steps to process a Mac OS event to determine a mouse click occurred in the close box, but Tool Plus dispatches only one event: doGoAway.

Every application or plug-in has a main event handler.

pascal void EventHandler(Ptr myCustomData);

The address of this event handler is passed as a parameter to InitToolsPlus. Your event handler typically looks like this:

// application event handler
// this handler presumes all window events are handled by window event handlers
pascal void EventHandler(Ptr myCustomData)
	switch (Event.what) {
		case doNothing:
			DoBackgroundProcessing();// do background processing here
		case doChgWindow:
		case doMenu:
		case doManualEvent:
		case doSuspend:
		case doResume:
		case doMoveCursor:
		case doChgMonitorSettings:
		case doKeyDown:
		case doAutoKey:
		case doKeyUp:
		// most applications don't handle keyboard events when no windows are open
		// Apple Events
		case doOpenApplication:
		case doOpenDocuments:
		case doPrintDocuments:
		case doQuitApplication:

After branching to the code that handles the specific Tools Plus event, you often parse the TPEventRecord further for additional information. For example, handling a File/Open menu command might look like this:

// handle menu event
void HandleDoMenu(void)
	switch (Event.Menu) {
		case iFile:
			switch (Event.Menu.Item) {
				case iNew:
				case iOpen:
				case iClose:
				case iPreferences:
				case iQuit:
		case iEdit:
			switch (Event.Menu.Item) {
				case iUndo:
				case iCut:
				case iCopy:
				case iPaste:
				case iClear:

Window Event Handlers

An important feature of Tools Plus is the option to have window-related events sent to a window event handler. I highly recommend you utilize window handlers since they allow you to nicely modularize your window-related code. Typically, different types of windows have separate window event handlers, but windows of the same type will share the same handler. For example, a tool palette floating window would have a separate window handler, while all document windows might share the same handler.

To associate a window event handler with a window, you create a UniversalProcPtr that points to the handler, then call SetWindowEventHandler to make the association. The example below is derived from my Preferences dialog. If there aren't too many dialogs in the program, I prefer to create the dialogs at program startup and keep them hidden until needed. The window event handler won't be called until the window is made visible and begins to receive user interactions.

EventHandlerUPP	prefsDlgEventHandlerUPP;
pascal void SetWindowEventHandler (short Window,
					EventHandlerUPP EventHandler);
pascal EventHandlerUPP NewEventHandlerProc (
			EventHandlerProcPtr userRoutine);

// initialize the Preferences window at app start up, but don’t make visible
void InitPrefsWindow(void)
	// create dialog from DLOG resource
	LoadDialog(kPrefsWindowID, kPrefsWindowResID);
	Init_Prefs_Dialog();	// set button, check boxes, etc per user prefs
	prefsDlgEventHandlerUPP =
	// delete UPP here if not needed anymore
} /* InitPrefsWindow */

//event handler for Preferences dialog
static pascal void PrefsDlgEventHandler(Ptr myData)
	extern TPEventRecord	Event;

	switch (Event.What) {
		case doButton:
			switch (Event.Button.Num) {
				case iSaveButton:
					// record user preference settings
					// no break after case!
				case iCancelButton:
					WindowDisplay(kPrefsWindow, wHide);
				case iUseIC:
					// toggle the ‘Use InternetConfig’ checkbox
				case iUseTempMem:
					// toggle the ‘Use temporary memory’ checkbox
		case doPopUpMenu:

In the example above, when the user selects the Preferences... menu item, the Preferences dialog is made visible with the WindowDisplay function, and the handler begins to receive events. When the Save or Cancel buttons are selected, the window is hidden with the same Tools Plus call.

WindowDisplay(kPrefsWindow, wShow);	// display the dialog
WindowDisplay(kPrefsWindow, wHide);	// hide dialog, don't destroy

Mac OS Events

There are three occasions when you might have to handle raw Mac OS events.

First, Mac OS events not handled by Tools Plus are reported as doManualEvents. For example, Open and Close File dialog update events are sent to the application event filter proc, and are reported as a doManualEvent. The raw Mac OS event is recorded in the Event field of the TPEventRecord.

// code snippet from an application event handler
// note how the Event.message field is recast to a DialogPtr
case doManualEvent:
	if (Event.Event.what==updateEvt && OpenFileDlgIsOpen())

Second, you can preprocess raw Mac OS events before they are handled by Tools Plus in an event filter that is an optional parameter for InitToolsPlus. A common use for this filter is keyboard shortcuts. Here is an example where the Command-Option-Shift-D key combination calls the debugger. The filter should return true (0) if the event has been handled and does not need further processing by Tools Plus, or false (1) if the event should be handled by Tools Plus.

// preprocess Mac OS events before handled by Tools Plus
// call Debugger() if Command-Option-Shift-D keys pressed
pascal Boolean EventFilter(EventRecord *evt)
	switch (evt->what) {
		case keyDown://
			if ( (evt->modifiers & (cmdKey | optionKey | shiftKey))
						&& IsKeyDown(0x02) )	// 0x02 == 'D' key
				return (0);
		return (1);

Finally, you have to process raw Mac OS events in the event filter proc of a CustomGetFile or CustomPutFile dialog.

Apple Events

New to version 5.0 is support for Apple Events. The four required events are now reported as Tools Plus events: doOpenApplication, doOpenDocuments, doPrintDocuments and doQuitApplication. During InitToolsPlus, Tools Plus calls AEInstallEventHandler to install default handlers for the four required Apple Events. If you install your own handler for one or more of these events, your handlers override the Tools Plus defaults. If you install handlers for any other Apple Events, Tools Plus calls the handler for you. If there are no installed handlers for an Apple Event, Tools Plus reports the Apple Event as a doManualEvent.

To determine which files have been sent with the Open or Print Document Apple Events, the CountNumberOfFiles and GetIndexFileFSS routines are provided. Of course, production code will handle any errors when attempting to open a file.

// code snippet from an application event handler
// handle the ‘odoc’ Apple Event
FSSpec	myFSS;

case doOpenDocuments:
	for (i = 1; i <= CountNumberOfFiles(); i++)
		if (GetIndexFileFSS(i, &myFSS))

I found a minor bug with the new Apple Event support. If an Apple Event is handled, the event is still reported as a doManualEvent. Water's Edge has officially reported the bug, and promises a fix in the next release.

Tools Plus Interface Components API

Tools Plus interface components are created with and referenced by an integer reference number. You can use predefined values, or get the next available reference number.

enum	{prefDialogID = 1 };

// create a new window with predefined reference number
WindowOpen(prefDialogID, ...);
WindowDisplay(prefDialogID, wShow);

// create a new window with first free window number
windID = GetFreeWindowNum();
WindowOpen(windID, ...);
WindowDisplay(windID, wShow);

If an invalid reference is passed to a Tools Plus routine, Tools Plus will either safely perform a null operation, or will alert the user that an invalid operation has occurred (Figure 3). With the Mac OS API, using an invalid reference like a menu or window handle usually results in a system crash, or worse.

Figure 3.Tools Plus error message if an invalid parameter is passed to a Tools Plus routine.

Tools Plus also gives you complete control over the appearance of the user interface components, including color, font, visibility, and enabled and disabled status.

Most Tools Plus elements are created by one of four methods:

  • boundaries of the control are passed as separate parameters
  • boundaries are passed in a Rect structure
  • boundaries are derived from a DLOG resource with the same resource ID as the control reference number
  • all element parameters are contained in a MBAR, MENU, WIND, DLOG or CNTL resource

The general form of these four methods is as follows:


As an example, here are the four methods of creating a new button.

// create a button with separate parameters for button coordinates
pascal void NewButton(short Button, short left, short top,
	short right, short bottom, const Str255 Title, long Spec,
	Boolean Enabled, Boolean Selected);

// get button coordinates from Rect structure
pascal void NewButtonRect(short Button, const Rect *Bounds,
	const Str255 Title, long Spec, Boolean Enabled,
	Boolean Selected);

// get button coordinates from DLOG item with same resource number
// as Button parameter
pascal void NewDialogButton(short Button, const Str255 Title,
	long Spec, Boolean Enabled, Boolean Selected);

// get button parameters from CNTL resource
pascal void LoadButton(short Button, short ResID);

If the control is displayed in a window, the reference numbers are local to every window. For example, you can have two check boxes with the same number if they are in different windows.


SuperCDEFs are an excellent collection of high quality, 3D user interface components (Figure 1). There is a neat trick to get a great 3D look with or without the Appearance Manager. Choose the SuperCDEFs appearance that you prefer (there are multiple choices), and then paste the appropriate library into your resource file. Next, change the SuperCDEFs' resource ID to 0. Then, SuperCDEFs will override the default System CDEFs, and you will have a great-looking interface with no additional effort.

Zen and the Art of (Tools Plus) Resource Editing

As noted above, the Tools Plus user interfaces can be designed with resource templates. For example, to create a simple Preferences dialog, design the DLOG resource and dialog control items (DITL resources) in Resorcerer or ResEdit.

Figure 4.DLOG resource in Resorcerer.

Figure 5.DLOG and DITL resources in Resorcerer. Item numbers are shown.

Then the dialog can be created with one line of code, and the check boxes and button are drawn automatically.

// using DLOG resource to create a ‘Preferences’ dialog
enum { PrefWindowID = 1};
enum { PrefWindowResID = 128};
enum {
	iOKButton = 1,

LoadDialog(PrefWindowID, PrefWindowResID);

The buttons and check boxes are referenced by their resource ID number. And, of course, you will have to write the code that loads the user preferences and sets the dialog buttons based on the preference values.

An alternate method of designing your interface with resources is to use CNTL resources. As we'll see in the next section, CNTL resources allow you to have a great-looking interface with or without the Appearance Manager. An example of using CNTL resources is illustrated in the section on pop-up menus below.

If you are designing your interface with resources, you should strongly consider purchasing Resorcerer. Using Resorcerer to design your program interface isn't as elegant as a dedicated interface editor, but it's reasonably close.

Keeping Up Appearances

To develop an interface that looks similar with and without the Appearance Manager, you must use CNTL resources. Each CNTL resource points to a CDEF resource. For each Appearance Manager control you want available without the Appearance Manager, you must link your application with a third-party CDEF or WDEF resource that replicates that control. The SuperCDEFs and Infinity Windoid WDEF resources included with Tools Plus support Appearance Manager equivalents for buttons, sliders, tabs, hierarchy triangles, progress thermometers, and a floating window (Figures. 1 and 2). You must number these third-party resources 128 or higher so they don't conflict with the System resources. Then, have the CNTL resources point to the third-party resources rather than the System resources. Finally, link your project with the Appearance Manager library (AppearanceLib). PPC projects should "weak link" the library to avoid a runtime error if the Appearance Manager is not present.

At runtime, call InitToolsPlus with the initAppearanceManagerSavvy or initPureAppearanceManager specifications. In your startup code, use the UsingAppearanceManager function to determine of the Appearance Manager services are available. If the manager is present, you can substitute the procIDs of the control resources so the Appearance Manager controls are used instead of the 3rd party resources.

if (UsingAppearanceManager()) {
	ReplaceWindowProcID(myToolPaletteProcID, 1985);
	ReplaceControlProcID(myCheckBoxProcID, checkBoxProc);
	ReplaceControlProcID(myRadioButtonProcID, radioButProc);

At this point I must confess that my application looks so good with SuperCDEFs and the Infinity Windoid WDEF that I've not converted my application to fully support the Appearance Manager. Using CNTL resources and substituting procIDs is definitely more work than simply using User Item resources and the NewDialogXXX form of Tools Plus component creation. However, if you want your application to support themes and other advanced Appearance Manager features, then CNTL resources are the way to go.

The Tools Plus User Interface Components

Here are some of the user interface components supported by Tools Plus. Be sure to look at the demo app to get a complete look at the Tools Plus system.


Tools Plus supports all standard window and dialog types, and they can be created from resource templates. I find it convenient to create non-document windows like tool palettes and dialogs during program startup, then simply hide and unhide the windows as needed.

You can get the Mac OS window pointer to the Tools Plus window with the WindowPointer function. I use window pointers to set the windowKind field of the WindowRecord, and to store document related data in the refCon field.

WindowRef	w;
w = WindowPointer(windID);
SetWindowKind(w, kMyDocWindID);
SetWRefCon(w, (long)myDocDataH);

When you are finished with and close a window, Tools Plus releases the window reference for future use, but does not actually free the Tools Plus window data structure.


In Tools Plus, dialogs are simply windows with user interface components. Dialogs can be created as either modal or non-modal. I prefer to create my dialogs in Resorcerer with DLOG/DITL resources, then create the dialog with the LoadDialog function.

Tools Plus also supports dynamic alerts, simple dialogs with only 1 to 3 pushbuttons and static text. The AlertBox function creates the alert and automatically resizes the alert dialog to properly fit the alert text.

The Tool Bar

Tools Plus supports a non-movable tool bar that sits directly beneath the menu bar, much like the CodeWarrior IDE tool bar. However, unlike the CodeWarrior, the tool bar width is always the full width of the screen. Tools Plus automatically hides the tool bar when your application is in the background or if an Open or Close File dialog is opened. Tools Plus also deactivates (dims) the tool bar if a modal dialog is opened.

Figure 6.Tool Bar from the Tools Plus Demo App.

Floating Windows(!)

Hardly a month passes on the comp.sys.mac.programmer newsgroups without someone asking how to support floating windows (Figures. 2 and 7). Tools Plus provides superb, easy-to-implement support for floating windows. Floating windows automatically float above document windows, and are hidden when your application is switched to the background. Floating window behavior is set with the wPalette spec when creating the window. The floating palette appearance is easily achieved using the included Infinity Windoid WDEF resource.

Figure 7.Floating window from the Tools Plus Demo App

Window Levels

The presence of standard windows, floating palettes, the tool bar and modal windows adds a lot complexity to window management. Tools Plus maintains a window level hierarchy that determines which windows are active, and which remain frontmost (Table 2).

Topmost Layer (closest to user)
Modal Windows Modal windows open at the front of this layer
Multiple modal windows can be open simultaneously
Frontmost modal window is only accessible window overriding all others
Tool Bar Always active (only one tool bar can be open)
Inaccessible if a modal window is open
Automatically hidden when your application is suspended
Floating Palettes Floating palettes open at the front of this layer
Always active
Multiple floating palettes can be open simultaneously
Inaccessible if a modal window is open
Automatically hidden when your application is suspended
Standard Windows Standard (modeless, non-tool bar non-floating palette) windows open at the front of this layer
Only the frontmost window in this layer is active
Multiple standard windows can be open simultaneously
When running under System 5 or 6's Finder, desk accessory windows may appear in this layer, providing a tool bar or floating palette is not open
Inaccessible if a modal window is open

Table 2. The Tools Plus window layer model.


Tools Plus provides full support for both pull-down and hierarchical menus. Although there are a variety of routines for creating menus, the easiest method of creating your application menus is to create each MENU resource in your resource editor, tie all of them together with an MBAR resource, and call the LoadMenuBar function in your initialization code. Manipulating menus using Tools Plus is similar to using the Mac OS API, except you use a menu number instead of a MenuHandle.

EnableMenu(kFileMenu, iCloseItem, enabled);
MenuMark(kOptionsMenu, iColor, CheckChar);
RenameItem(kEnhanceMenu, iToolBarItem, "\pShow Tool Bar");
RenameItem(kEnhanceMenu, iToolBarItem, "\pHide Tool Bar");

Tools Plus automatically handles the Edit menu when an editing field is active, including Cut, Copy and Paste operations to and from the Clipboard, and Undo/Redo support for the last edit operation.

Water's Edge recommends that you update the status of your menu items in the event filter when the user clicks the mouse in the menu bar for maximum performance. That way, user actions that result in menu items being enabled, disabled, added, or deleted - such as menu item check marks appearing or disappearing. - won't be performed until just before the user actually sees the menu.

// filter Mac OS events before processing by Tools Plus
// update all menu items when the user clicks in the menu bar
pascal Boolean EventFilter(EventRecord *evt)
	WindowRef	w;	// just a place holder for FindWindow

	switch (evt->what) {
		case mouseDown:
			if (FindWindow(evt->where, &w) == inMenuBar)
	return (1); // Tools Plus should continue to process this event

However, changes to the menu bar should be performed more promptly. For example, when all document windows are closed, the Edit menu is dimmed in many applications. Fortunately, Tools Plus updates the menu bar after an event handler routine finishes whenever the menu bar has been changed with the AppleMenu, Menu, RemoveMenu, or EnableMenu routines.

My major annoyance with Tools Plus menus is the inability to show multiple-key menu item shortcuts in a menu. This shortcoming could be readily fixed by the Mercutio MDEF, but, unfortunately, Tools Plus is not compatible with Mercutio. Water's Edge is investigating the issue, but have not committed to a Mercutio-compatibility release date.

Mercutio MDEF

Pop-Up Menus

Pop-up menus are a great user interface feature that allow a selection from multiple choices in a compact region of a window or dialog. In addition to Mac OS standard pop-up menus, Tools Plus pop-up menus have additional options, including displaying the selected item's icon within the pop-up box, suppressing the pop-up menu's "down arrow", and a "pop down" option where the menu's list opens below the menu body.

Figure 8.Pop-up menus from the Tools Plus Demo App.

I create my pop-up menus with the LoadDialogPopUp function.

LoadDialogPopUp(short MenuNumber, long Spec, short ResID);

MenuNumber is the menu resource ID, which must be 1600 or higher. Tools Plus uses the coordinates of the resource identified by ResID - in Resorcerer, I use a User Item - to draw the pop-up. Spec is the pop-up specification that defines the pop-up appearance and behavior. Options I use include popup3DBody (3D look available in all system versions), popupUseWFont (use window font) and popupIconTitle (use the menu item icon in the pop-up box). Unfortunately, the pop-up menu title is drawn to the left of the user item rectangle, so getting the pop-ups lined up correctly in your window takes a few edit-compile-run cycles.

Water's Edge recommends using CNTL resources as the best method for creating pop-up menus. The manual is a bit sparse on the details, but here are the steps (using Resorcerer):

  • Create and place a new Control item (Item menu) in the window where the pop-up box will be drawn. The menu title will be drawn to the left of the box.
  • Select the item, then choose Get Info from the Item menu. A Control Item dialog will open. Enter the CNTL resource number in the Res. ID edit field. A new CNTL resource will be created if one does not exist.
  • Click the Edit button, and edit the (new) CNTL resource.
  • Change the CDEF Res ID field to 63, which will generate a ProcID of 1008.
  • Change the ‘MENU’ ID field to the number of MENU resource used by the pop-up (must be 16000 or higher).
  • Enter the name of the pop-up menu in the Title field.
  • Set the Style code and Title width fields to 0.

I struggled to get CNTL resources and pop-up menus to work correctly until I discovered two crucial tips:

  1. you must set the Conform 'CNTL' bounds to Control item bounds dialog editor preference (Dialog/Preferences...) in order to synchronize resizing the Control item with the CNTL resource.
  2. Style code and Title width fields must be set to 0 (Resorcerer may choose an inappropriate default). Frankly, CNTL resources are significantly more complicated than using User Item resources with LoadDialogPopUp.


Cursor shapes are easily changed with the CursorShape routine. There are defined constants for the standard cursor shapes: arrowCursor, iBeamCursor, crossCursor, plusCursor, watchCursor. Tools Plus automatically changes the cursor shape when the cursor is over an edit field.

pascal void CursorShape(short Shape);

The watch cursor has special status. When you change the cursor shape to the watch, Tools Plus is alerted that "a lengthy process in underway." If the watch cursor is active, the cursor shape will not be changed automatically by Tools Plus. Most events are filtered and not sent to the application event handler except for Command-period, to allow the user to cancel a lengthy operation.

Cursor Tables and Zones

A powerful feature of Tools Plus cursor management is the ability to define regions where the cursor automatically changes shape. Tools Plus uses cursor tables, which contain one or more cursor zones. When the cursor enters a cursor zone, it changes to the cursor shape defined for that zone (Figure 9). The zones are defined in local window coordinates. Each cursor table has a default cursor that is used if the cursor does not fall within any of the cursor zones. A cursor table is associated with a window by the UseCursorTable routine.

Figure 9.Cursor Zone Example. When the cursor moves inside the cursor zone, the cursor shape changes from an arrow to a plus shape.

I use cursor tables to support cursor shapes for different tools. At program initialization cursor tables are defined, and linked to the cursor resource associated with each tool. However, I don't create a cursor zone for any of the tables. When the tool is selected, UseCursorTable associates the proper table with the image window, and the cursor shape automatically changes to the proper tool when the cursor moves within the window (Figure 10).

// program start up
// establish cursor tables for each tool
// cursor tables
enum {
	SelectionTable = 1,

// resource IDs for cursor shapes
enum {
	GrabberResID = 128,

// set up the cursor tables, associate table with default cursor resource
NewCursorTable(SelectionTable, arrowCursor);
NewCursorTable(GrabberTable, GrabberResID );
NewCursorTable(MagnifyTable, MagnifyResID);
NewCursorTable(PencilTable, PencilResID);
NewCursorTable(PaintBrushTable, BrushResID);

// application event handler
// when a tool is selected, associate the proper cursor table with the image window
// in this example, the Magnify tool is selected
UseCursorTable(FrontImageWindow(), MagnifyTable);

Figure 10.Cursor table example. The magnify tool is selected. Cursor shape is arrow when the cursor is outside of window, and changes to magnify glass when moved over window.

Every Picture (Button) Tells a Story

Some of my favorite Tools Plus features are picture buttons - click-sensitive icons and PICT resources. This versatile control permits a wide range of button types, including pushbuttons, click-sensitive icons, multistage buttons, radio-type buttons and polarized buttons (button value increases or decreases depending on which part of the button is clicked). Picture buttons are an easy method of creating great-looking tool palettes (Figures 6, 7 and 10).

Picture buttons are a bit more complex to set up because of the many different button types and behavior options available. I create my picture buttons with the NewDialogPictButton routine.

pascal void NewDialogPictButton (
		short ButtonID,				// Picture button number
		short BaseID,					// Base image's resource ID
		long Spec,						// Appearance and Behavior spec
		Boolean EnabledFlag,	// "Button is enabled" flag
		Boolean SelectedFlag, // "Button is selected" flag
		short minimum,				// Minimum button value
		short value,					// Initial button value
		short maximum);				// Maximum button value

The button's coordinates are obtained from the dialog item whose number matches the button number, ButtonID. BaseID is the resource number of the icon or PICT resource of the button, and Spec is the behavior and appearance specification. There are 30 different specification parameters for customizing the appearance and behavior of the button.

Tools Plus can support more than one icon or PICT resource for a picture button. For example, the active, inactive, and dimmed states of a button may have a different image, and multistage buttons will of course have a different image for each stage. Tools Plus handles multiple resources for picture buttons by using a resource numbering sequence system to determine which resource is associated with each stage and appearance of the button.

The picture button type I find most useful is a 3D button created with SICN icon resources, which I use for a tool palette on a tool bar window (Figure 10). Tools Plus automatically creates a color, 3D button from the black & white SICN icon. The options I prefer for my tool palette include picbutLockSelect (lock button in selected state until another button selected) and pcitbutSlectLightenSICN3D (lighten and "push in" button when selected).

Field(s) of Dreams

Tools Plus text editing fields are powerful. Tools Plus automatically handles many routine edit field tasks, including field activation/deactivation and low memory protection. Fields can store up to 32k of text each. To save memory or improve performance, you can limit the field text length to a much smaller number, or can have a text handle that automatically resizes as text is entered. Either Pascal or C strings can be used.

When you enter or change the text in an edit field, you are working on a copy of the field text. The changes are not saved to the edit field string until the edit field is deactivated by clicking or tabbing to another field, or closing the dialog with the field. You can optionally be notified when this occurs to perform field validation. Fields can be placed in any window that you create. Tool Plus ensures that only one field - the active field - is active and selected at a time.

Another great feature of Tools Plus is its field filters. Filters allow you to limit what characters can be entered into a field.

pascal short NewFieldFilter(const Str255 Chars,
													long FilterSpec);

NewFieldFilter returns the field reference number. Chars specifies the characters to be included in the field, and Spec allows various text filter options. Filters and length-limited fields are a great help when designing a data entry form.

A problematic aspect of edit field management is validating field contents. You can have Tools Plus notify you when the active edit field is about to be deactivated. If you don't need to validate edit field contents, then you should call InitToolsPlus with the initAutoFocus specification, and Tools Plus will automatically update field contents.

If you don't use the initAutoFocus option, there are two occasions when Tools Plus notifies you when the user is about to deselect an active edit field. First, when the user clicks in an inactive edit field, Tools Plus sends your event handler a doClickToFocus event. The GetEditString function returns a handle to the temporary copy of the active edit field string. If the field string is validated, you save the changes with the SaveFieldString function, and allow the new edit field to be selected with the ClickToFocus function.

// example of field validation
// example is for a form with a name and e-mail edit field
pascal void GetEditString(Str255 EditString);
pascal void ClickToFocus(void);
pascal void SaveFieldString(void);

// window event handler
case doClickToFocus:
	if (MyValidateFieldProc()) {

short MyValidateFieldProc(void)
	Str255	string;
	short	fieldNum = ActiveFieldNumber();
	switch (fieldNum) {
		case nameField:
			if (!IsNameFieldValid(string)) {
				Alert("Invalid name field, please reenter.");
				return false;
		case e-mailField:
			if (!IsValidEmailAddress(string)) {
				Alert("Invalid e-mail address, please reenter.");
				return false;
	return true;

Second, if the user pressed the Tab key to move to the next field (or pressed Shift-Tab to move to the previous field), you use the HaveTabInFocus function to determine if the key press occurred in an active edit field. If the field contents are acceptable, you save the field changes with SaveFieldString (as before), and use TabToFocus to allow the user to tab into the next or previous field.

pascal void HaveTabInFocus(void);

// window event handler
case doKeyDown:
case doAutoKey:
	if (HaveTabInFocus()) {
		if (MyValidateFieldProc()) {

Scroll Bars and Sliders

Tools Plus provides excellent support for managing scroll bars and sliders, a problematic aspect of the pre-Appearance Manager Mac OS API. You can use the default system scroll bar, or you can use third-party CDEFs like those provided in SuperCDEFs. SuperCDEFs has a nice selection of sliders (Fig. 1). Tools Plus also supports "live action" scroll bars, and scroll bars that automatically resize when a window is resized.

When a scroll bar or slider is moved or clicked by the user, a doScrollBar event is reported. The event record also reports which part of the scroll bar or slider was activated. Your event handler will continue to get doScrollBar events as long as the user keeps moving the scroll bar thumb with the mouse.

A better method of handling scroll bar and slider events is to use an action routine which Tools Plus calls for every user interaction with the scroll bar. The action routine is linked to the scroll bar with the SetScrollBarAction routine. Within the routine, you use the GetScrollBarActionInfo routine to determine which scroll bar is active, the parent window of the scroll bar, the part moved or clicked by the user, and whether the mouse is still in the original scroll bar part. Action routines are another method of developing nicely modularized code in Tools Plus.

// prototypes
// Create a UPP to a scroll bar's action routine
pascal ScrollBarActionUPP NewScrollBarActionProc (ScrollBarActionProcPtr userRoutine);
// Set an action routine for a scroll bar
pascal void SetScrollBarAction (short ScrollBar, ScrollBarActionUPP ActionProc);
// Get info about the scroll bar currently calling an action routine
pascal void GetScrollBarActionInfo (short *Window,
									short *ScrollBar,
									short *Part,
									Boolean *InPart);
// create UPP, attach the action proc to the scroll bar
ScrollBarActionUPP MyActionProcUPP;
MyActionProcUPP =
// typical structure of scroll bar action proc
pascal void MyActionProc(void)
	short				scrollBar, part, curVal, windID;
	Boolean			inPart;
	static short	oldVal = 0;
	GetScrollBarActionInfo(&windID, &scrollBar,
											&part, &inPart);
	if (!inPart)
	// get the current value of the scroll bar attached to the action proc
	curVal = GetScrollBarVal(scrollBar);
	switch (part) {
		case (inThumb):
			if (curVal == oldVal)
			// handle in thumb action here
		case (inPageUp):
		case (inUpButton):
			// handle page up action here
		case (inPageDown):
		case (inDownButton):
			// handle page down action here
	oldVal = curVal;

Miscellaneous Stuff


The Tools Plus documentation is excellent. There are overview chapters on setting up and using the libraries, and specific sections for each type of interface element. Both printed and electronic versions (eDoc and PDF) are supplied. There is a nice touch to the electronic documentation I've not seen before - the pages are numbered consecutively from the title page, so that when you select Move to Page... (eDoc) or Go to Page... (PDF), the Table of Contents page numbers and the electronic page numbers are synchronized. I think a few more code examples would be helpful, but there is plenty of code to study in the demo app and in the tutorials.

Whither Carbon?

Water's Edge states that Tools Plus is already highly Carbon compliant, and full Carbon compatibility should not be a problem.


Living with Tools Plus

I've enjoyed working with Tools Plus and Water's Edge Software. The quality of the libraries, the documentation and the technical support is excellent. Tools Plus greatly simplifies the task of developing Mac OS applications and plug-ins, and lets you concentrate on coding your application. I'm impressed with how much of the "dirty work" of Mac OS programming the Tools Plus system handles for you.

I've submitted about half a dozen bugs that have been acknowledged, fixed, and logged in the changes file. Most of the bugs I've encountered have been minor and easy to work around. I find it helpful to knock off a quick mini-application to send to Water's Edge that isolates a particular problem, and with Tools Plus, the application is easy to create!

My two major complaints with Tools Plus are the lack of full support for balloon help (scheduled for Sept. 99 release) and the inability to have multiple-key menu item shortcuts (under investigation, but no release date announced). Some features I'd like to see include Open/Save File dialog support, preference file support, and some examples of how to make your application scriptable.


I strongly recommend the Tools Plus system. But is Tools Plus for you? Here are some points you should consider.

  • What language do you program in? If you are better at programming in C or Pascal than C++, then I'd lean towards Tools Plus. If you are good in BASIC, I'd take a peak at REALbasic. If C++ is what bakes your cookies, then you might be more comfortable with a complete application framework like PowerPlant.
  • Do you have strong beliefs about your coding structure and style? A code generator or application framework will impose its programming worldview upon you, whereas Tools Plus allows you to program in the style that suits you best.
  • What about PowerPlant? PowerPlant is a more complete application development system, but it is significantly more complex to learn than Tools Plus. You will be up and running much faster with Tools Plus, but down the road you will have some programming chores to do on your own that PowerPlant would have handled for you.
  • Are you a Windows programmer new to the Mac? Welcome! The Tools Plus event model resembles the Win32 messaging system, so I think your Windows programming skills will serve you well if you choose the Tools Plus system.

Whatever your choice, good luck on your programming projects.

Thurman Gillespy III ( is an Associate Professor of Radiology at the University of Washington, Seattle, Washington, and practices at both the University of Washington Medical Center and the Puget Sound Veterans Medical Center in Seattle. His research interests include medical image processing and image display. When not programming or occupied with the day job, Thurman is the personal chauffeur for his two teenage daughters.


Community Search:
MacTech Search:

Software Updates via MacUpdate

Macs Fan Control 1.5.14 - Monitor and co...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
VueScan 9.7.96 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
FileMaker Pro 19.6.1 - Quickly build cus...
FileMaker Pro is the tool you use to create a custom app. You also use FileMaker Pro to access your app on a computer. Start by importing data from a spreadsheet or using a built-in Starter app to... Read more
Duet - Use your iPad as an exter...
Duet is the first app that allows you to use your iDevice as an extra display for your Mac using the Lightning or 30-pin cable. Note: This app requires a iOS companion app. Release notes were... Read more
Firefox 107.0.1 - Fast, safe Web browser...
Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
War Thunder - Multiplayer war...
In War Thunder, aircraft, attack helicopters, ground forces and naval ships collaborate in realistic competitive battles. You can choose from over 1,500 vehicles and an extensive variety of combat... Read more
Numbers 12.2.1 - Apple's spreadshee...
With Apple Numbers, sophisticated spreadsheets are just the start. The whole sheet is your canvas. Just add dramatic interactive charts, tables, and images that paint a revealing picture of your data... Read more
DEVONthink Pro 3.8.7 - Knowledge base, i...
DEVONthink is DEVONtechnologies' document and information management solution. It supports a large variety of file formats and stores them in a database enhanced by artificial intelligence (AI). Many... Read more
Drive Genius 6.2.3 - $79.00
Drive Genius features a comprehensive Malware Scan. Automate your malware protection. Protect your investment from any threat. The Malware Scan is part of the automated DrivePulse utility. DrivePulse... Read more
VLC Media Player 3.0.18 - Popular multim...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more

Latest Forum Discussions

See All

TouchArcade Game of the Week: ‘Sling Min...
The world of PC games has always blown my mind because there’s just SO MUCH stuff out there that it’s not uncommon at all for there to be a game that’s well-liked and well-reviewed, and seemingly quite popular with a solid fanbase, and have it be... | Read more »
SwitchArcade Round-Up: Reviews Featuring...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 2nd, 2022. So, today turned out a little quieter than the usual Friday. It was so quiet, in fact, that I decided to pen a few reviews. The Knight Witch, Railbound, and Donut... | Read more »
Blue Archive reveals its latest event st...
Nexon has announced the new update for Blue Archive, under the name of An Unconcealed Heart. Featuring a battle between two academies, the story will follow a group struggling to gain recognition, and will bring three new students to recruit. [... | Read more »
Dead Cells+ Is Out Now on Apple Arcade a...
Following the major update for Dead Cells on iOS and Android a few days ago, Playdigious has brought Dead Cells+ () to Apple Arcade. As an App Store Great, Dead Cells+ includes all prior paid DLC and content updates. It also has exclusive mobile... | Read more »
SwitchArcade Round-Up: ‘Romancing SaGa’,...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 1st, 2022. Wow, December. We’re already at the last month of the year? Phew. I have a lot of work to finish in the next few weeks. As for today, we’ve got a little news, a... | Read more »
‘Railbound’ Update Now Available Adding...
One of our favorite puzzlers released this year is Railbound from Afterburn Games, which hit in early September and earned our Game of the Week recognition for being an absolutely ace logic puzzler. The goal is to place rail pieces down in order to... | Read more »
The Seven Deadly Sins: Grand Cross celeb...
Netmarble Corporation has pulled out all the stops to celebrate the 3 and a half year anniversary of The Seven Deadly Sins: Grand Cross. The Grand Cross 3.5th Year Anniversary the Ultimate One, a rather wordy title, brings with it a brand new... | Read more »
‘Skullgirls Mobile’ Major Update 5.2 Out...
Developer Hidden Variable pushed out a major update for Skullgirls Mobile (Free) a few hours ago. The version 5.2 update brings in Black Dahlia (before the console and PC game), Retakes, XP Treats, free gifts, and more. Since launch, Skullgirls... | Read more »
Out Now: ‘Disgaea 4’, ‘Romancing SaGa: M...
Each and every day new mobile games are hitting the App Store, and so each week we put together a big old list of all the best new releases of the past seven days. Back in the day the App Store would showcase the same games for a week, and then... | Read more »
SwitchArcade Round-Up: ‘Elevator Action...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for November 30th, 2022. We’re finishing up the month on a quiet note, friends. There are five new releases to look at today, with a few notables amongst them. We’ve got summaries for... | Read more »

Price Scanner via

New Holiday Sale: Apple retailers are offerin...
Several Apple retailers lowered prices on 10.9″ iPad Airs overnight to lows of $100 off MSRP starting at $499. Their prices are the lowest available for iPad Airs anywhere this Holiday season right... Read more
New Holiday sale at Amazon: Take $50 off Appl...
Amazon has Apple’s new 10th-generation iPads in stock and on sale, for the first time, for $50 off MSRP starting at only $399. Their discount applies to all models and all colors. With the discount,... Read more
Holiday Sale: Get an 8.3″ Apple iPad mini for...
Sams Club has 10.9″ 64GB iPad minis on Holiday sale for $80-$100 off MSRP through December 7, 2022. With their discount, prices start at $399 — the cheapest price for a new iPad mini from any of the... Read more
Sams Club Holiday December Event sale: Apple...
Apple AirPods Max headphones are on sale at Sams Club for $110 off MSRP ($439) as part of their December Event sale, ending on December 7, 2022, valid for all colors. Sale price for online orders... Read more
Apple’s 10.2″ 64GB 9th-generation iPads are o...
Sams Club has 9th-generation 64GB iPads on Holiday sale for $60 off MSRP through December 7, 2022. With their discount, prices start at $259 — the cheapest price for a new iPad from any of the Apple... Read more
11″ 128GB WiFi M2 iPad Pro on sale for $749,...
B&H Photo has the new 11″ 128GB WiFi M2-powered iPad Pro (in Space Gray or Silver) on Holiday sale for $749 including free 1-2 day shipping to most US addresses. Their price is $50 off MSRP and... Read more
Find the best Holiday sale price on an iPad u...
We’ve updated our iPad Price Trackers with the latest information on the new 10th-generation iPads, M2-powered iPad Pros, M1 iPad Airs, iPad minis, and 9th generation iPads from Apple’s authorized... Read more
Apple retailers are offering $100-$150 Holida...
Apple retailers have posted their most-recent Holiday sale prices on 13″ MacBook Airs. Take up to $150 off MSRP on M2-powered Airs with these sales with prices starting at only $1099. Free shipping... Read more
Holiday Sale: Apple’s 14″ MacBook Pros with M...
B&H Photo is offering $200-$300 discounts on Apple’s 14″ MacBook Pros with M1 Pro CPUs as part of their Holiday 2022 sale, with prices starting at $1799. Free 1-2 day shipping is available to... Read more
Deal Alert! 50% off Apple MagSafe Chargers
AT&T has Apple MagSafe Chargers on sale for 50% off MSRP as part of their Holiday sale. Service is not required to take advantage of these savings. With the discounts, their sale prices are the... Read more

Jobs Board

Support Technician II - *Apple* Support - O...
…problems and acting as a liaison between customers and resolving groups. As an Apple Technical Specialist, you will be supporting many of our popular Apple Read more
*Apple* Electronic Repair Technician - PlanI...
…a highly motivated individual to join our Production Department as an Apple Electronic Repair Technician. The computer repair technician will diagnose, assemble, Read more
Lead Developer - *Apple* tvOS - Rumble (Uni...
…earnings, and positive sentiment About the role: We are looking for a Lead Apple tvOS Developer to join our application engineering team to expand our video centric Read more
Tier 1 Endpoint Engineer - *Apple* - Red Ri...
…Desk on site, at our Client's location, with a focus on support to Apple products. This position will handle technical support requests directly from customers and Read more
Product Manager II - *Apple* - DISH (United...
…you will be doing We seek an ambitious, data-driven thinker to assist the Apple Product Development team as our new Retail Wireless division continues to grow and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.