yab


System: BeOS, Haiku, Zeta

Index

1. What is yab? 7. Show graphic
2. Creating a Program window 8. Create Button
3. Inloop - Durable inquiry of functions 9. Testing program in Terminal
4. MenuBar in window 10. Bind program code (Zeta only)
5. Create additional View 11. Help while programming
6. Show text  

 




Was is yab?

The yab Interpreter is a BASIC Dialect, witch is a further development of the Windows, Linux and Playstation 2 available YABASIC. yab was optimized for BeOS, ZETA and Haiku and included many commands for it.

With the help of this programming language it is very easy to create simply small and even complex programs. A good example of it is the burner program JABA contained in ZETA.

You will find out in the process of this tutorial how easy it is to create an application with yab, . This tutorial will not provide a complete application, but simple basic knowledge to learn you to get started in yab.



back to index




Creating a Program window

Creating a Program window is simple, you only need to provide the instruction window open and add a few data concerning size, name and internal designation.

window open 50,50 to 600,500, "View", "WindowName"


A window is opened, which begins 50 pixels of the left edge of screen and 50 pixels of the upper edge of screen. After that to the right and lower edge of window are indicated. Thus we have a window size of 550 pixels in the width and 450 pixels in the height. Like you see the window size is not given, but only the coordinates on the screen.

After the data for the window size the name of the window follows (here: "View") for internal use. Over this name you can address the window for example to close or to insert an entry .

For WindowName you indicate the name, which stands then as window designation in the TAB of the window. Thus the name, which is seen by the user.

back to index


Inloop - Durable inquiry of functions

Next we provide a Inloop, which is helpful  to us in the execution of always recurring requirements in the program. Everything located in this loop in the program runs so long again and again as is required. Everything which is outside of the loop stands either only once or only when it is called for. Here it is to be noted that everything which is before the loop will be executed before the loop is started and everything which stands behind the loop only when called for.

Cinloop = true
while(inloop)
     msg$ = message$
     switch msg$

          Here the entries are inserted into the loop.

     end switch
wend

Closing the window over the TAB is a good example, because this function should be selectable in the program sequence at any time. Insert the following code into the range, that in the loop with " Here the entries are inserted into the loop." is indicated. For this we use the instruction case, which begins with indication of its name and is terminated with break.

case "View:_QuitRequested|"

          window close "View"

     break

When the close range of the TAB is clicked, this with name of the window (View) and the pertinent inquiryis spent (here _ QuitRequested).

All that stands between case "View:_QuitRequested|" and break, will be executed upon calling the sequence. Since we would like to close the window, with window close "View" the window View is closed.

back to index


Window menu bar

In the most cases a menu bar belongs also to a window. In order to add these menu bars,add the following code above inloop and underneath the opening of the program window, in order to have this visible at all times.

menu "Program", "Quit", "Q", "View"


Also with this example we take care of terminating the program. With this code we provides the menu range,Programand under this point lies the sub point Quit (terminate). The indication of the Q is the indication of the keyboard shortcut (Alt + Q) with which one can terminate the program apart from the menu. The last instruction View is the window into which the menu is indicated. In order to bring in further menu ranges, further lines must be inserted, which are build the same way. Changing the first names automatically adds a second menu range. Same applies to the subregions.

For this menu option a further entry must take place in the Inloop. This looks as follows:

case "View:Program:Quit|"

          window close "View"

     break


Since we call a closing of the window over the menu bar, the expenditure of the instruction sits down as together as the order of the selected menu selection. The program window (View) on which the menu lies, the menu range Program and the sub menu range Quit.

back to index

Create additional View

In order not to close the program window always to load a new view, it's recommend to set a further View to the main view yourself. This should begin approx.. 10 pixels below (in case off) a menu bar in the program window the top margin.

view 0,10 to 550,450, "View1", "View"


To set a View is similar to open a window. We provide a View with the name View1 on the program window View. The View begins on the basis of the program window size at the left hand side from 0 pixels and from top margin with 10 pixels (because of the menu bar). The right and lower edge are the data after that to.

The View1 is inserted where it should be indicated, in this case it is directly underneath the program window.

back to index
Show text

On this View1 we will now show some text.

draw text 20, 20, "this is a text edition", "View1"

With draw text we indicate that we would like to add some text. Over the specifications 20.20 we indicate the coordinates of the text on the View. Thus 20 pixels of the left hand side and 20 pixels of the top margin. The text following on it is the text, which is indicated on the View. Here no automatic line-makeup is made, so that this must be provided, by adapting the text to indicate the window (View). At the end the indication of the Views follows, on which the text is to be indicated.

back to index

Show graphic

To show graphics we have to add the next code underneath the Views, on which we would like these announcements (View1).

err = draw image 150,30, "/Path/to/Graphic/graphic.jpg", "View1"

With err = draw image we indicate that we would like to insert a graphic. As is the case for the text, the coordinates follow, at which the diagram is to be indicated. According to the indication of the picture location, the file path and the file are indicated (Path/to/Graphic/graphic.jpg), which you would like to represent. Also at the end of this instruction the indication of the Views follows, on which the diagram is to be indicated.

back to index

Create Button.

What is a program without switching surface for the program-specific functions. Whether forwarding to a further program window or for implementing tasks, a Button is very often used.

button 400, 400 to 450, 420, "internal_Button name", "shown_Button name", "View1"

We provide a Button with 400 pixels of the left Viewborder and 400 pixels of the upper Viewborder. The size of the Buttons results from the data of the following data for the right (450 pixels) and lower (420 pixels) edge of the Buttons. As the example shows the name of the Buttons for the internal use follows and then the name which is to be seen on the Button.

The function of the Buttons is indicated as for terminating the program, in the Inloop as a case instruction.

case "Internal_Button name|"

          window close "View"

     break

Here like before with the other cases the internal name of the Button is indicated. Also in this case we use the window close instruction to terminate the program. The Button could also show for example additional text, button, graphic or open and/or close a further window or View.

back to index

Testing program in Terminal.

If you'd like to test your program in between you can run the source code directly in a Terminal window.

yab /Path/to/source code.yab

Just enter yab in a Terminal window followed by space. Then drag and drop the source file to the Terminal so the path will be shown there, press Enter to execute your program.

In case you are using the yab IDE, you can execute the program over the MenuBar in Program and there with Run in Terminal run the Program.

back to index

Bind program code. (Zeta only)

Is your program ready, then the next step is to bind it. By binding a program you prevent other people from looking into the program code so only you can change and look at the source code.

Open a Terminal window and enter the following:

yab -bind "Name of the program" /Path/to/source code.yab

With yab -bind you declare that you would like to bind the source code. The name of the program is the name of the file that you can find in your home folder. The source code can be added like before with drag and drop.

back to index

Help while programming

- Due to the similarities to YABASIC, it is always recommended to search for solutions in their Documentation.

- yab itself comes with some example codes, which demonstrate different functions, these can be found in your yab folder.

- Here on BeSly there is a  yab ProgramHelp (German), where a lot of functions are described.

back to index

Special thanks to JohnM for sending a PDF file of this Tutorial.
Translation by Luc Schrijvers (Begasus) of the Belgium BeOS Usergroup.
Tutorial written by Christian Albrecht (Lelldorin) March 2006
Made available by BeSly, the BeOS & Zeta knowledge.

yab is based on the yabasic interpreter (http://www.yabasic.de). On the yabasic website you will find additional sources how to enhance the interpreter (titled "Guide into the Guts of Yabasic"). Nevertheless, this documents should give an in-depth introduction too.

You need some basic knowledge about yab, C, C++ and probably the BeAPI for adding new commands to yab. Knowledge about flex and bison are not necessary.

2   Designing a Command

A typical yab command normally is either a procedure (function returning void), a function returning a number (double or int) or a function returning a string (char*).

A command consists of

   -   the command words (lexical entities)

   -   the command rule

   -   the C wrapping function calling the C++ method

   -   the C++ method

This will be descussed in details in the upcomming sections.

2.1   The Command Words

The words needed by a command (tokens) are defined in the file yabasic.flex. Please introduce only new command words, when the existing are not sufficent to describe your new command. Browse through the file to find all yabasic and yab commands.

A command word consists of the word itself (in capital letters) and the token it returns. The token is most often simply the word itself with a t in front of it.

Example:

BUTTON return tBUTTON;

 

There are exceptions for the token name, e.g. tGet represents the comand word GET$ while tGETNUM represents GET.

New tokens have then to be declared in the file yabasic.bison too by simply adding the token name in the token list at the beginning of the file.

2.2   The Command Rule

The actual command rule (grammar) has to be added to the file yabasic.bison. If you scroll through the file you get a good idear how the grammar should look like.

Basically three sections in this file are interesting: the section for procedures, the section for nummerical functions and the section for string functions. We will investigate the different of these functions in next two subsections.

But first we have a look at the similarities. A command rule is written with a leading pipe | followed by the tokens and the arguments. At the very end, a C function identifier follows.

Example:

| tBUTTON coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cBUTTON,NULL);}

Here, coordinates is a subtitution for expression ',' expression and to is a subtitution for the command TO (which is just a ',' anyway).

So basically there are two types of arguments: expression is a number (of type double) and string_expression is a string (of type char*). They can be separated by commas ','. Brackets ('(' and ')') are possible too, but I have not used them often.

Thus, in this example the BUTTON command have 7 arguments, 4 numbers for the coordinates and 3 strings that will contain the own ID, the button text and the view D.

2.3   Procedures

As all procedures, the mentioned example does not return a value (it is a void function in C). It gets a internal identifier named cBUTTON. This identifier has to be declared in the file yabasic.h. Just check the list of other similar indentifiers for the location in the file.

Furthermore, in yabasic.h the name of the C function that is added to the file graphic.c has to be declared. Procedures always get a struct command *, YabInterface * as argument. The command struct contains informations about the yab arguments, line number etc. Thus, in graphic.c the C function will simply forward these information to the main C++ class (YabInterface).

Just before adding the function in grephic.c it has to be added in main.c too. There, add it to the switch that calls the functions according to their identifier. E.g.:

case cBUTTON
    createbutton(current, yab); DONE;

A typical void function in graphic.c looks like the following example:

void createbutton(struct command *cmd, YabInterface* yab)
{
   double x1,y1,x2,y2;
   char *id, *title, *view;

   view = pop(stSTRING)->pointer;
   title = pop(stSTRING)->pointer;
   id = pop(stSTRING)->pointer;
   y2=pop(stNUMBER)->value;
   x2=pop(stNUMBER)->value;
   y1=pop(stNUMBER)->value;
   x1=pop(stNUMBER)->value;

   yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab);
   yi_CreateButton(x1,y1,x2,y2, id, title, view, yab);
}

In our example, first the 7 yab arguments are retrieved from the command struct.

Die Argumente werden auf einem Stack gelagert, also müssen Sie sie im umgekehrten Reihenfolge zurückholen! Hier wird z.B. y1 vor x1 zurückgeholt. Auch Zeichenketten und Zahlen haben unterschiedliche pop calls.

Numbers can be either double or int but for coordinates, always double should be used.

The current line number is passed in to the YabInterface class by calling yi_SetCurrentLineNumber. This line is the samefor all void functions.

Finally, the arguments are passed on to the YabInterface class by calling yi_CreateButton.

2.4   Fuctions

Functions that either return a number or a string are implemented differently. First they get a different identifier starting with an f e.g. fLISTBOXGETNUM. This identifier has to be declared in yabasic.h in the enum functions.

Die Funktionen werden durch die Anzahl ihrer Argumente sortiert!

Additionaly, the name of the C function that is added to the file graphic.c has to be declared in yabasic.h too. Differently to procedures, these functions get their argument set immediatly, e.g.:

int listboxgetnum(const char*, YabInterface *yab, int line, const char* libname);

listboxgetnum returns an int while taking a string as first argument. The further arguments YabInterface *yab, int line, const char* libname have to be added to provide the YabInterface class further informations.

Other than procedures, the stack retrieval of arguments and the function call are all done in the file function.c. These, the yab arguments are retrieved from the stack and forwarded to the wrapper function in graphic.c.

Example:

case fLISTBOXGETNUM:
   str=a1->pointer;
   value = listboxgetnum(str, yab, linenum, current->lib->s);
   result = stNUMBER;
break;

The string argument is retrieved by a1->pointer. Numerical arguments are addressed by e.g. a3->value (not in this example). The arguments are numbered from a1 to a6. More arguments are currently not supported.

Here, the result is stored as a number. For strings, the result should be stored in pointer and result = stSTRING; has to be set. Check the other cimmands in this file for further examples.

Finally, the wrapper function has to be implemented in graphic.c. For our example, this looks like the following code:

int listboxgetnum(const char* id, YabInterface *yab, int line, const char* libname)
{
   yi_SetCurrentLineNumber(line, libname, yab);
   return yi_ListboxGetNum(id, yab);
}

The current line number is passed on to the YabInterface class by calling yi_SetCurrentLineNumber. This line is the same for all functions. The returned number is then simply passed on by yi_ListboxgetNum.

strings have to be copied with my_strdup, e.g. return my_strdup((char*)yi_CheckMessages(yab));. It is up tp you that strings still exist in memory when copied!

3   The C++ Class YabInterface

3.1   Adding a Method

After the above described overhead, we are ready to actually write the new method. The method has a C++ name and a wrapper function with an external name starting with yi_. Both have to be defined in YabInterface.h and implemented in YabInterface.cpp.

The wrapper function takes the pointer to the YabInterface object and calls the main method:

void yi_CreateButton(double x1, double y1, double x2, double y2, const char* id, const char* title, const char* view, YabInterface* yab)
{
   yab->CreateButton(BRect(x1,y1,x2,y2), id, _L(title), view);
}
The _L() macro that is used on all text that should be translated automagically by the ZETA local kit. It will kick in when the LOCALIZE command was used. So please use this macro whenever possilbe, to allow simple localization.

The method itself is part of the YabInterface class which is derived from BApplication. You can always expect BApplication up and running (with the interpreter in an own threat). Thus, all BApplication methods are directly accessable from your method.

void YabInterface::CreateButton(BRect frame, const char* id, const char* title, const char* view)
{
   // code here
}

3.2   Accessing yab Data Structures

yab stores various information in list objects. The probably most waned list is the of available views. These are stored in the YabList object viewList. To initialize a new widget, it is often sufficient to find the parent view. this is done by calling YabList::GetView(const char*):

YabView *myView = cast_as((BView*)viewList->GetView(view), YabView);
if(myView)
{
   YabWindow *w = cast_as(myView->Window(), YabWindow);
   if(w)
   {
    w->Lock();
    // inizialize widget here
    w->unlock();
   }
   else   ErrorGen("Unalbe to lock window"); }
else
  Error(view, "VIEW");

New widgets should allow some usefull layouting. Please refer to the commands for BUTTON and LISTBOX to understand how different kinds of layoutung are used in yab.

If you want to find a specific widget on an unkown view, you have to cycle through that views to look for the view containing your widget. Such a loop looks like this (under the condition that MyWidget is derived from BView):

YabView *myView = NULL;
MyWidget *myWidget = NULL;
for(int i=0; iCountItems(); i++)
{
myView = cast_as((BView*)viewList->ItemAt(i), YabView);
  if(myView)
  {
   YabWindow *w = cast_as(myView->Window(), YabWindow);
   if(w)
   {
    w->Lock();
    myWidget = cast_as(myView->FindView(id), MyWidget);
    if(myWidget)
    {
     // do something with myWidget
     w->Unlock();
     return;
    }
   }
  }
 }
Error(id, "MyWidget");
The return is set after something has been done with the widget and after unlocking the window again. This allows the lazy error checking at the end of the loop..

 


3.3   Some Short Remarks

At the end some short remarks about...

    - BUILD macros: Some commands have BUILD macros that allows to disable whole parts of yab on compiling. This is used for the build factory to produce smaller code size. Unused libraries and code parts are simply left out when they are not needed. Make use of these , macros whenecer you enhance commands that have these macros.

    - Drawing: Drawing commands are a bit tricky. They offer drawing on a view, on a bitmap and canvas. Especially the view drawing has a own storage system. investigate the other drawing commands to understand how they work.

    - Own classes: Adding own classes is nice, but remember to add this new information in the makefiles (R5 and ZETA!) too.

4   Summary

To give you a checklist of what has to be done in short, have a look at the summary:

    - add new command word (token) in yabasic.flex if necessary

    add command rule (grammar) in yabasic.bison

    add command identifer and C method name in yabasic.h

    - add command call in either function.c or main.c

    - add wrapper function in graphic.c

    - add C to C++ wrapper function in YabInterface.h and YabInterface.cpp

    - add C++ method in YabInterface.h and YabInterface.cpp

End

 

Tutorial created by jan_64 at August 11. 2006

carry over from pdf to html by Christian Albrecht (Lelldorin) September 2006
Made available by BeSly, the BeOS, Haiku & Zeta Knowledgebase.