Pilot Load Thomas Röfer.

BtnLib for PocketC

PocketC by OrbWorks is a small C interpreter for the 3Com PalmPilot, Palm III, and IBM WorkPad. It is quite powerful, but it does not provide the typical user interface elements of the Pilot. Bill Winn introduced a module that realizes simple buttons, but these buttons neither look nor behave the same way as the original Pilot controls. In addition, the module can only be used for a small number of buttons. Otherwise, the application will be very slow.

In contrast, BtnLib is a powerful library that allows to use a large number of buttons with different styles. The buttons can either use texts or bitmaps as labels, they can have various frames, can be grouped to radio buttons, and can function as check boxes. BtnLib has short reaction times, even with a large number of buttons. However, the creation of buttons is slow in BtnLib. Therefore, since version 1.3 of BtnLib, it comes with an additional module called BtnSnap. This module consists of a single function, btnSnap(), that makes a snapshot of the current button configuration and stores it as source code in a memopad file. This source code can be included in the program to allow faster button initialization.

BtnLib was developed using PocketC 1.0b5. On a PalmPilot Personal, it seems that PocketC only allows to allocate up to 6444 bytes. This memory is used for variables (6 bytes for each) and the character data of strings (length+1 bytes for each string). It is also used to allocate a buffer that stores the screen contents before a dialog is displayed and that is used to restore the screen after the dialog is closed. If more than 1788 bytes of data are allocated, this backup mechanism does not work any longer and the screen will remain blank after closing a dialog.

BtnLib uses at least 1282 bytes. For each button, additional space is required, depending on the button's size and the length of the buttons label. Hence, in most programs, the screen must be repainted manually after a dialog was closed. However, BtnLib provides a function for this purpose.

Distribution and Warranty

This library is provided as-is, with no warrenty expressed or implied. This library is free but not in public domain. As source code, it may not be included as part of a compilation on a cd-rom, magnetic tape, or any other storage device without the express written consent of the author. As part of an compiled application, it can be distributed freely. If an application uses BtnLib, this fact should by noted, e.g. in an about dialog.

Version History

Version 1.3
Added a tool for fast button initialization.

Version 1.2
Uses less resources.

Version 1.1
Added support for check boxes and hiding buttons.
Bitmap buttons are now created using the function btnCreateBitmap().
btnSetText() has been renamed to btnSetLabel().

Version 1.0
First release.

Download

Click here to download the library source, the demonstration source listed below, a compiled fast version of the sample, and a description (this page).

Contact

E-mail:
WWW:
roefer@tzi.org
http://www.tzi.org/~roefer

Functions

btnCreate(string label,x,y,width,style)

Creates a new text button and returns its number. Buttons are numbered in sequence of their creation, starting with number 1. Text buttons, bitmap buttons, and check boxes use the same numbering sequence.

label
Contains the text label of the button.
x
The x-coordinate of the left side of the button. This position does not include the frame. If x is set to -1, the button is created on the right side of the previously created one.
y
The y-coordinate of the top side of the button. This position does not include the frame. If y is set to -1, the button uses the y-coordinate of the previously created button.
width
The width of the button without a frame. If width is set to -1, Bill Winn's formula is used to estimate the width from the number of characters in label.
style
The style of the button. style is a sum of several bits:
0x001 - If this bit is set, the button has a solid frame.
0x002 - If this bit is set, the button has a dotted frame.
0x004 - If this bit is set, the frame has rounded corners.
0x020 - If this bit is set, the button is hidden.
0x080 - If this bit is set, the button is a radio button.
0x100 - This bit marks the selected radio button. Only one button can be selected in each group.
0x200 - This bit marks the first radio button in a group, and hence starts a new group.

btnCreateBitmap(string label,x,y,style)

Creates a new bitmap button and returns its number.

label
Contains the bitmap that is used as label.
x
The x-coordinate of the left side of the button. This position does not include the frame. If x is set to -1, the button is created on the right side of the previously created one.
y
The y-coordinate of the top side of the button. This position does not include the frame. If y is set to -1, the button uses the y-coordinate of the previously created button.
style
The style of the button. style is a sum of several bits:
0x001 - If this bit is set, the button has a solid frame.
0x002 - If this bit is set, the button has a dotted frame.
0x004 - If this bit is set, the frame has rounded corners.
0x020 - If this bit is set, the button is hidden.
0x080 - If this bit is set, the button is a radio button.
0x100 - This bit marks the selected radio button. Only one button can be selected in each group.
0x200 - This bit marks the first radio button in a group, and hence starts a new group.

btnCreateCheck(x,y,style)

Creates a new check box and returns its number.

x
The x-coordinate of the left side of the check box. This position does not include the frame. If x is set to -1, the check box is created on the right side of the previously created button.
y
The y-coordinate of the top side of the check box. This position does not include the frame. If y is set to -1, the check box uses the y-coordinate of the previously created button.
style
The style of the check box. style is a sum of several bits:
0x001 - If this bit is set, the check box has an additional solid frame.
0x002 - If this bit is set, the button has an additional dotted frame.
0x004 - If this bit is set, the additional frame has rounded corners.
0x008 - If this bit is set, the check box is checked.
0x020 - If this bit is set, the check box is hidden.
0x080 - If this bit is set, the button is a radio button. Check boxes can be in radio button groups, but they cannot be selected with the pen, similarly to the "ToDo" application. To select a check box in a radio button group, use btnSelect().
0x100 - This bit marks the selected radio button. Only one button can be selected in each group.
0x200 - This bit marks the first radio button in a group, and hence starts a new group.

btnReset()

Deletes all buttons but does not remove them from screen. Can be used to delete all buttons of a form before creating another form. It is not necessary to call this function before creating the buttons of the first form.

btnPaintAll()

Paints all buttons. This function should be called to paint all buttons after they were created, or to repaint them, e.g., after a dialog was displayed.

btnEvent(int e)

Handles the event e. This should be called whenever a new event arrives. The function returns 1 if it has handled the event and 0 if it has not, e.g., because the user clicked outside of all buttons.

btnPressed()

Returns the number of the button that was pressed during the last btnEvent() or 0 if no button was pressed. A button only was "pressed" if the user clicked and also released the pen inside of the button.

btnSelected(int i)

Returns the number of the currently selected button in a button group. i can be the number of any button in the same group.

btnChecked(int i)

Returns 1 if the check box is checked, and 0 if it is not.

btnSetLabel(int i,string label)

Replaces the label of the button with number i. label must be either a text or a bitmap, depending on the style of button i. The button is repainted but not resized. Therefore, the new label should have the same size as the old one.

btnSelect(int i)

Selects the button i in a button group. The unselected and the selected buttons are repainted.

btnCheck(int i,int state)

If state is 1, check box i is checked. If it is 0, the check box is cleared.

btnHide(int i,int state)

If state is 1, button i is hidden. If it is 0, the button is repainted.

btnSnap()

If this function should be used, BtnSnap must be included. The idea of this function is very simple. The btnCreate functions are very slow because they are quite complex and PocketC is not very fast. However, the results of their calculations are stored in only a few global variables. btnSnap() creates a snapshot of these variables. Thus, it stores the results of all btnCreate calls in the program. The state of the variables is stored as the source code of a function that loads all the variables with their stored values. Therefore, if the button layout is finished in the development process of a program, a call to btnSnap can be inserted after all buttons have been created. After the program has been started, btnSnap() creates a memopad file with the title "// initButtons" that contains a single function initButtons(). Then, the call to btnSnap() can be removed as well as any call to btnCreate...(). Instead, the file initButtons must be included and only a single call to initButtons() must be inserted. This runs a lot faster then the btnCreate calls.

Example

The example in the sequel demonstates the use of BtnLib. It is not trivial, but it does nothing useful. Install it on your Pilot and see what happens.

// BtnDemo
include "BtnLib"

// define some variables
string day[7],mode[3];
int week;

initButtons()
{
// create 3 bitmap buttons as radio button group
// the first button is preselected
  btnCreateBitmap("09000000000000000080000000000000000",1,148, 0x381);
  btnCreateBitmap("09000000000000000550000000000000000",-1,-1,0x81);
  btnCreateBitmap("09000000550000550000550000550000000",-1,-1, 0x81);
// create a button with a rectangular dotted frame
  btnCreate("WWW",36,147,25,2);
// create 2 rounded buttons
  btnCreate("About",67,-1,29,5);
  btnCreate("Quit",-1,-1,24,5);
// create a left arrow bitmap button without a frame
  btnCreateBitmap("0b0000100300700f01f03f01f00f0070030010000",67,0,0);
// create 7 text buttons as radio button group
// the fourth button is preselected
  btnCreate("M",-1,1,-1,0x281);
  btnCreate("T",-1,-1,-1,0x81);
  btnCreate("W",-1,-1,-1,0x81);
  btnCreate("T",-1,-1,-1,0x181);
  btnCreate("F",-1,-1,-1,0x81);
  btnCreate("S",-1,-1,-1,0x81);
  btnCreate("S",-1,-1,-1,0x81);
// create a right arrow bitmap button without a frame
  btnCreateBitmap("0b0001001801c01e01f01f81f01e01c0180100000",-1,0,0);
// create 3 checked check boxes
  btnCreateCheck(37,38,8);
  btnCreateCheck(37,50,8);
  btnCreateCheck(37,62,8);
}

// initialize some other stuff
initStrings()
{
  day[0]="Monday       ";
  day[1]="Tuesday       ";
  day[2]="Wednesday";
  day[3]="Thursday    ";
  day[4]="Friday           ";
  day[5]="Saturday     ";
  day[6]="Sunday         ";
  mode[0]="Day     ";
  mode[1]="Week  ";
  mode[2]="Month";
}

// paint all
paint()
{
  text(50,38,
    "Week "+(week+1)+"  ");
  text(50,50,day[btnSelected(8)-8]);
  text(50,62,
    mode[btnSelected(1)-1]);
  btnPaintAll();
}

// process commands
command(int c)
{
  string s;
  if(c==4) // dotted button pressed
  {
    s=gets("Enter value:");
    if(s)
      btnSetLabel(4,strleft(s,3));
    paint(); // repaint all
  }
  else if(c==5) // About button pressed
  {
    alert("BtnDemo 1.1\n\nThis program was devoloped using\nThomas Röfer's BtnLib.");
    paint(); // repaint all
  }
  else if(c==7) // left arrow pressed
  {
    week=(week+51)%52;
    text(50,38,
      "Week "+(week+1)+"  ");
  }
  else if(c==15) // right arrow pressed
  {
    week=(week+1)%52;
    text(50,38,
      "Week "+(week+1)+"  ");
  }
  else if(c>15&&c<19) // check box pressed
    btnHide(c-12,!btnChecked(c));
  else if(c>7&&c<15) // day selected
    text(50,50,day[c-8]);
  else if(c<4) // mode selected
    text(50,62,mode[c-1]);
}

main()
{
  int b;
  clear();
  puts("Initializing...");
  initButtons();
  initStrings();
  graph_on();
  title("BtnDemo");
  paint();
  while(btnPressed()!=6) // until Quit pressed
  {
    btnEvent(event(1)); // wait for event and handle it
    if(b=btnPressed()) // Has the user pressed a button?
      command(b); // react on the command
  }
  graph_off();
}
By Thomas Röfer Last update Apr 13, 1998