diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e1d824 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bison.c +bison.h +flex.c +bison.output +yab +*.o diff --git a/Documentation/ARTISTIC b/Documentation/ARTISTIC new file mode 100644 index 0000000..be93a35 --- /dev/null +++ b/Documentation/ARTISTIC @@ -0,0 +1,131 @@ + + + + + The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/Documentation/Advanced/HowToMakeABuildFactory.txt b/Documentation/Advanced/HowToMakeABuildFactory.txt new file mode 100644 index 0000000..e7044d3 --- /dev/null +++ b/Documentation/Advanced/HowToMakeABuildFactory.txt @@ -0,0 +1,65 @@ +1. check AutoFooter if all files are there, add new files when necessary + +2. generate flex.c and bison.c by typing: + flex -i -I -L -s -t yabasic.flex >flex.c + perl -i -n -e 'if (!/^\#include\s+\s+$$/) {print if $$i;$$i++}' flex.c + bison -d -l -t -v --output-file bison.c yabasic.bison + +3. edit flex.c as follows: + - add the headers (after #include) and the static declaration + #include + #include "program.h" + static int isparsed = 0; + - replace the default input buffer size + #define YY_BUF_SIZE 16384 + with + #define YY_BUF_SIZE PROGLEN + - search for + #define YY_INPUT(buf,result,max_size) \ + replace the last lines of this define + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); + with + else if ( ((result = zread( buf, 1, max_size, yyin )) == 0) && !ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); + - add to the function + static int yy_get_next_buffer() + after + int ret_val; + the following line + if(isparsed) return EOB_ACT_END_OF_FILE; + - add the function zread at the end of flex.c: + int zread(char* dest, size_t memb_size, size_t num_memb, FILE *file) + { + long destlen = PROGLEN; + if(isparsed==1) + return 0; + isparsed = 1; + uncompress(dest,&destlen,myProg,sizeof(myProg)); + return destlen; + } + - NOTE: you only have to go through this process when new commands have been added to + yabasic.flex. Otherwise you can just take the modified flex.c from the last BuildFactory. + +4. edit main.c as follows: + - search for the function + int isbound(void) + delete the whole function and replace it with: + int isbound(void) + { + FILE *interpreter; + if (!interpreter_path || !interpreter_path[0]) { + error(FATAL,"interpreter_path is not set !"); + return 0; + } + if (!(interpreter=fopen(interpreter_path,"r"))) { + sprintf(string,"Couldn't open '%s' to check, if it is bound: %s",interpreter_path,my_strerror(errno)); + error(WARNING,string); + return 0; + } + + return 1; + } + + diff --git a/Documentation/ChangeLog b/Documentation/ChangeLog new file mode 100644 index 0000000..0ad45bf --- /dev/null +++ b/Documentation/ChangeLog @@ -0,0 +1,44 @@ +yab Version 1.7.4.1 Changes from version 1.7 +-LOCALIZE doesn't work again due to changes in haiku. +-TEXTCONTROL added more options for set options. + yab Version 1.7 Changes from Version 1.6 +- COLUMNBOX updated to Haiku style (thanks Stargater!) +- STATUSBAR didn't follow LAYOUT, fixed now +- RESTORE Label$ allows for dynamic label strings +- various ATTRIBUTE commands +- Localization now works again, see Localizer how it is done +- reorganized localization commands are now: + LOCALIZE mime$, LOCALIZE STOP, LOCALIZE, TRANSLATE$ and MENU TRANSLATE$ +- SUBMENU SET "Remove" now implemented +- yab cleaned up (a bit at least) +- yab IDE cleaned up +- BuildFactory cleaned up +- yab-Commands documentation cleaned up + +yab Version 1.6 Changes from Version 1.5 +- removed all ZETA and BeOS dependencies +- SPINCONTROL look updated to Haiku style +- CALENDAR look updated to Haiku style and code refactored +- TABVIEW look updated to Haiku style +- TABVIEW now supports bottom tabs (like it did on ZETA) +- Haiku native tooltips are now used; they still suck, but this finally + resolves the race condition bug (this should also resolve the hanging + BuildFactory, thx to clasqm for reporting) +- using "copy" for an empty selection in TEXTEDIT does not clear the + clipboard anymore (thx to streakx for reporting) +- Haiku forced a minimum button height, yab does not like force (thx to + Lelldorin for reporting) +- Title in BOXVIEW is now shown correctly (thx to Lelldorin for reporting) +- Window flags don't reset anymore after calling WINDOW SET (thx to clasqm + for reporting) + +Known problems: +- Tooltips cannot be unset, they cannot change color, they steal focus (fixed on + new Haiku builds), they suck (blame the Haiku team ;)) +- Tooltips do not work for all Widgets +- Spincontrol cannot move shift-tab backwards + +Other Fixes (1.6): +- Scrolling in the yab IDE works again with new Haiku builds (the bug in Haiku + got fixed, thx to leszek for reporting, thx for zooey for fixing) + diff --git a/Documentation/Credits b/Documentation/Credits new file mode 100644 index 0000000..89920c8 --- /dev/null +++ b/Documentation/Credits @@ -0,0 +1,30 @@ +Credits + +yab is yabasic for Haiku done by Jan Bungeroth (jan@be-logos.org). + +yab would not be possible without a lot of support. Thanks go to (in no particular order): + +Source Code: +Marc-Oliver Ihm (yabasic) +Alex Sarikov (CalendarControl) +William Kakes (URLView) +YNOP (SplitPane) +DarkWyrm (Spinner) +Brent Miszalski (TexView) +Michael Lloyd Lee (AutoTextView) +Marco Nelissen (BubbleHelper) +Marc Flerackers and Stephan Assmus (Haiku TabView) +Axel Dörfler (Haiku tooltips) + +Alpha and Beta Testing and Feature Nagging: +Michel Clasquin +bbjimmy +Lelldorin +lorglas +Ralf Schuelke +DasJott +Lukas Linemayr +and others + +Translation: +Begasus for the Dutch yab-IDE locale diff --git a/Documentation/License b/Documentation/License new file mode 100644 index 0000000..78c0186 --- /dev/null +++ b/Documentation/License @@ -0,0 +1,22 @@ +Licensing yab or your yab program + +yab is distributed under the Artistic License which is an +approved open source license. Read the file ARTISTIC for +details. + +Basically the Artistic License allows you to: +- bind your program to yab and release it under any license you wish; +especially you are allowed to sell your program commercially, when bound +- compile your program with the BuildFactory and release it under any license you wish; +especially you are allowed to sell your program commercially +- copy and distribute yab freely +- copy or distribute yab as part of a distribution +- modify yab +- distribute a modified yab freely without releasing the source code + +For distributing a modified yab commercially, you should contact me first. +The following parts of yab are not allowed in commercially modified +versions without the permission of the authors: +SplitPane + +Changes to CalanderControl have to be republished under GPL. diff --git a/Documentation/TODO b/Documentation/TODO new file mode 100644 index 0000000..726bda2 --- /dev/null +++ b/Documentation/TODO @@ -0,0 +1,12 @@ +ToDo + +Features: +- LPT and COM signal send/receive, specific request by lorglas +- Layout + +Bugs: +- drop file bug ide +- strings cannot handle chr$(0) +- TEXTEDIT selection somehow buggy, seems to be a Haiku issue +- SOUND commands don't work because of a missing API call in Haiku +- printing seems to be broken (further testing needed) diff --git a/Documentation/yab-Commands b/Documentation/yab-Commands new file mode 100644 index 0000000..d2526c7 --- /dev/null +++ b/Documentation/yab-Commands @@ -0,0 +1,835 @@ +-= A =- + +ALERT Text$, ButtonLabel$, Type$ + Opens an alert window with Text$ and the button Label$ of type Type$ + Type$ = "none/info/idea/warning/stop" +Selected = ALERT Text$, Button1$, Button2$, Button3$, Type$ + A more general Alert window. Specify a text and up to three buttons. + If Button2$ or Button3$ is set to "", the button is not shown. + The selected button is returned, where Selected = 1 is the left, 2 the middle and 3 the right button. + Type$ = "none/info/idea/warning/stop" +ATTRIBUTE SET Type$, Name$, Value$, Filename$ + Set the attribute Name$ of type Type$ for the file Filename$ with the string Value$. + These are valid types Type$: + "String", "Int", "Long", "Double", "Float", "Mime", "Bool" +ues a value$ of "true" or "false" for Bool type attributes +ATTRIBUTE CLEAR Name$, Filename$ + Delete the attribute Name$ from file Filename$. +Value$ = ATTRIBUTE GET$ Name$, Filename$ + Get the string value of the attribute Name$ for file Filename$. + Returns "true" or "false" for "Bool" type attributes. +Value = ATTRIBUTE GET Name$, Filename$ + Get the number value of the attribute Name$ for file Filename$. + + +-= B =- + +BITMAP Width, Height, ID$ + Creates a new bitmap in memory, you can draw on it + A bitmap is always initialized with a white transparent background +color = BITMAP COLOR x,y, ID$, ColorPart$ + ColorPart$ = "red" or "green" or "blue" + Returns the color of the pixel at position (x,y) of the bitmap ID$ +BITMAP GET x1, y1 to x2, y2, Target_bitmap$, Source_bitmap$ + Copies specified area of Source_bitmap$ to Target_bitmap$. +BITMAP GET IconSize, Bitmap$, File$ + Copies the icon, shown in Tracker, of File$ in the specified IconSize onto Bitmap$. +BITMAP GET ID$, Option$, Path$ + copies an icon to a bitmap + An Option can be: + "Path" = Path$ must be the path to a file + "Mime" or "Mime16" = Path$ must be the mimetype of the file which icon is to be swown. + The resulting bitmap is 16 to 16. + "Mime32" = Path$ must be the mimetype of the file which icon is to be swown. + The resulting bitmap is 32 to 32. +BITMAP GET ID$, Option$ + Option$ = "height" or "width" delivers height and width of bitmap ID$ +BITMAP REMOVE Bitmap$ + Removes Bitmap$ from memory +ErrCode = BITMAP IMAGE ImageFile$, Bitmap$ + Load image file ImageFIle$ into a new Bitmap called Bitmap$ +ErrCode = BITMAP SAVE Bitmap$, FileName$, Format$ + Saves a bitmap as FileName$ (overwrites existing ones!) in a Format$ of one of the following: + {"png", "tiff", "ppm", "bmp", "jpeg", "tga"} + ErrCode = 0 everything worked fine + ErrCode = 1 file could not be saved +BOXVIEW x1,y1 TO x2,y2, ID$, Label$, LineType, View$ + Adds a box, note: the actual view of the BOXVIEW (where you can place your widgets) is at + (x1+5,y1+10) to (x2-5,y2-5). This may be a subject of change! + LineType = 0 means no border + LineType = 1 means simple line border + LineType = 2 means fancy line border +BUTTON x1,y1 TO x2,y2, ID$, Label$, View$ + Sets a button at position (x1,y1) to (x2,y2) with label Label$ on the view View$ +BUTTON IMAGE x,y, ID$, EnabledPressed$, EnabledNormal$, Disabled$, View$ + Create an image button at (x,y) on View$ with three files: + EnabledNormal$ The image of the released button + EnabledPressed$ The image of the pressed button + Disabled$ The image of the disabled button (you can put in an empty string "" if you don't need a + disabled button) + + +-= C =- + +CALENDAR x,y, ID$, Format$, Date$, View$ + Open a calendar widget at (x,y), giving the format, the date and put that on the view View$. + Format$ = ("DDMMYYYY" or "MMDDYYYY") + ("." or "/" or "-"); default: "DDMMYYYY." +CALENDAR SET Calendar$, Date$ + Set the date according to the current format (DDMMYYYY or MMDDYYYY). +date$ = CALENDAR GET$ Calendar$ + Get the current date selected in Calendar$. +CANVAS x1,y1 to x2,y2, ID$, View$ + A canvas is a special view for flicker-free drawing. It always shows a bitmap + and thus cannot be resized. However, it does not have a drawing queue, so you + do not need DRAW FLUSH + A canvas is always initialized with a white background +CHECKBOX x1,y1, ID$, Label$, IsActivated, View$ + Display a checkbox at (x1,y1) with Label$ on View$; if IsActivated is set to 0, the checkbox is + off else it is on. +CHECKBOX SET CheckBox$, IsActivated + (De-)Activate the check box CheckBox$. +CHECKBOX IMAGE x,y, ID$, EnabledOn$, EnabledOff$, DisabledOn$, DisabledOff$, IsActivated, View$ + Create an image checkbox at (x,y) on View$ with four files: + EnabledNormal$ The image of the released checkbox + EnabledPressed$ The image of the pressed checkbox + DisabledNormal$ The image of the normal disabled checkbox (you can put in an empty string "" + if you don't need a disabled button) + DisabledPressed$ The image of the pressed disabled checkbox (you can put in an empty string "" + if you don't need a disabled button) + Set isActivated to true/false when the checkbox should be on/off. +CLIPBOARD COPY Text$ + Copy Text$ to the system clipboard. +Text$ = CLIPBOARD PASTE$ + Paste ASCII text from the system clipboard into Text$. +COLORCONTROL x,y, ID$, View$ + Create a color control widget at x,y. Note: it's width is 276 and it's height is 54 pixels. +COLORCONTROL SET ColorControl$, r,g,b + Set the color control ID$ to the color r,g,b. +Value = COLORCONTROL GET ColorControl$, "Red|Blue|Green" + Get the currently selected red/green/blue value of the colorcontrol. +COLUMNBOX x1,y1 TO x2,y2, ID$, HasHScrollbar, Option$, View$ + HasHScrollbar is true, when the columnbox should get a horizontal scrollbar (it always has a vertical). + Option$ affects all columns! The columns can be made movable, resizable, removable + Option$ = "movable, resizable, popup, removable" + Option$ = "no-border" sets up the columnbox without border +COLUMNBOX COLUMN ColumnBox$, Name$, Position, MaxWidth, MinWidth, Width, Option$ + Option$ = "align-left, align-center, align-right" +COLUMNBOX ADD ColumnBox$, Column, Row, Height, Item$ + If Item$ = "__Icon__="+FileName$ then the image file FileName$ will be shown, + if Item$ = "__Path__="+FileName$ then the large Trackericon of the file FileName$ will be shown + if Item$ = "__Mime__="+Signature$ then the small icon of the mime type Signature$ will be shown +COLUMNBOX SELECT ColumnBox$, Row + Selects Row of ColumnBox$. + Row = 0 means deselect. +COLUMNBOX REMOVE ColumnBox$, Row + Removes the entries in Row of ColumnBox$ +COLUMNBOX CLEAR ColumnBox$ + Removes all entries of ColumnBox$. +COLUMNBOX COLOR ColumnBox$, Option$, r,g,b + Option$ = "selection-text, non-focus-selection, selection, text, row-divider, background" +n = COLUMNBOX COUNT ColumnBox$ + Returns the number of entries in ColumnBox$. +Item$ = COLUMNBOX GET$ ColumnBox$, Column, Row + Returns the entry at Row in Column of Columbox$. + + +-= D =- + +DRAW TEXT x1,y1, Text$, View$ + Draws text at position (x1,y1) on View$ +DRAW RECT x1,y1 TO x2,y2, View$ + Draws a rectangle from (x1,y1) to (x2,y2) in the current high color on View$ +DRAW BITMAP x,y, Bitmap$, Mode$, View$ + Draw a bitmap on a view, another bitmap or a canvas. + Possible Mode$: + "Copy" -- copy the bitmap to the target ignoring transparency + "Alpha" -- copy the bitmap to the target supporting transparency +DRAW BITMAP x1,y1 TO x2,y2, Bitmap$, Mode$, View$ + Draws and scales the bitmap Bitmap$. + If x2 is set to -1, the width is scaled according to the height; + if y2 is set to -1, the height is scaled according to the width; + if x2 and y2 are set to -1, the image is not scaled at all (this is like DRAW BITMAP x,y, Bitmap$, Mode$, View$). + Possible Mode$: + "Copy" -- copy the bitmap to the target ignoring transparency + "Alpha" -- copy the bitmap to the target supporting transparency +DRAW DOT x1,y1, View$ +DRAW LINE x1,y1 TO x2,y2, View$ +DRAW CIRCLE x1,y1, Radius, View$ +DRAW CURVE x1,y1, x2,y2, x3,y3, x4,y4, View$ +DRAW ELLIPSE x1,y1, xRadius, yRadius, View$ +DRAW FLUSH View$ + Deletes all former drawing commands from the drawing queue on View$ +LoadError = DRAW IMAGE x,y, ImageFile$, View$ + Draws the image ImageFile$ at position x,y on View$, returns LoadError + LoadError: + 0 = success + 1 = file not found + 2 = translator roster not found + 3 = translation failed + 4 = ditaching bitmap failed +err = DRAW IMAGE x1,y1 TO x2,y2, Image$, View$ + Draws and scales the image file Image$. Transparent images are set correctly now. + If x2 is set to -1, the width is scaled according to the height; + if y2 is set to -1, the height is scaled according to the width; + if x2 and y2 are set to -1, the image is not scaled at all (this is like DRAW IMAGE x1,y1, Image$, View$). +Width = DRAW GET "Text-Width", Text$, View$ + Return the width in pixel of the string Text$ in the current font of View$. +Height = DRAW GET "Max-Text-Height", View$ + Return the maximum height in pixel of the current font of View$. This is the size of the font plus + how far characters can descend below the baseline. +FontFamilies$ = DRAW GET$ "FontFamily" + Returns a list of all installed fonts separated by "|". +FontStyles$ = DRAW GET$ FontFamily$ + Returns a list of all font styles for a font FontFamily$ separated by "|". +DRAW SET FillOrStroke, Pattern$ + FillOrStroke = 0 means fill + FillOrStroke = 1 means stroke + Pattern$ is a 8x8 1 bit map; one line is one character + Pattern$ = "HighSolidFill" means solid fill with the current high color + Pattern$ = "LowSolidFill" means solid fill with the current low color (default) + Pattern$ = "CheckeredFill" means checkered fill +DRAW SET Color$, r,g,b, View$ + Color$ is one of the following: + "BGColor", r,g,b (216,216,216 default) + "HighColor", r,g,b (0,0,0 default) + "LowColor", r,g,b (216,216,216 default) +DRAW SET Color$, Option$, View$ + Option$ is one of the following: + "Panel-Background-Color" + "Panel-Text-Color" + "Panel-Link-Color" + "Menu-Background-Color" + "Menu-Selection-Background-Color" + "Menu-Item-Text-Color" + "Menu-Selected-Item-Text-Color" + "Keyboard-Navigation-Color" + "Jan-Favorite-Color" + + To those options the following can be added: + "Lighten-1-Tint" + "Lighten-2-Tint" + "Lighten-Max-Tint" + "Darken-1-Tint" + "Darken-2-Tint" + "Darken-3-Tint" + "Darken-4-Tint" + "Darken-Max-Tint" + "Disabled-Label-Tint" + "Disabled-Mark-Tint" + "Highlight-Background-Tint" + + Example: + draw set "bgcolor", "Menu-Background-Color, Lighten-1-Tint", View$ + +DRAW SET Font$, View$ + Set the drawing font on View$. + Font$ = FontFamily$ + "," + FontStyle$ + "," + Size + "," + FontOption$ + "," Rotation + "," + Shear + where FontOption$ can contain the following options (only used when supported by the font): + FontOption$ = "bold" or "italic" or "outlined" or "underscore" or "strikeout" or "regular" (regular is default) + where Rotation is between 0.0 (default) and 360.0 + where Shear is between 45.0 (slanted to right) and 135.0 (slanted to left) with 90.0 default + + or Font$ = "system-plain" for the plain system font, + or Font$ = "system-bold" for the bold system font, + or Font$ = "system-fixed" for the fixed system font +DRAW SET "Alpha", Alpha-Value + Sets the Alpha-Channel for the transparency of the drawing colors. Use this before setting the color + with DRAW COLOR. + Alpha-Value is a value between 0 and 255 where 0 is total transparency and 255 is opaque. + Note: When Alpha-Value is below 255, use only HighSolidFill, patterns are ignored! + Note: Transparent drawing (that is Alpha-Value below 255) is not printed (see PRINTER) correctly! +DROPBOX x1,y1 TO x2,y2, ID$, Label$, View$ + Adds an empty dropbox (BMenuField) at (x1,y1) to (x2,y2) known as ID$ and with a label on View$. +DROPBOX ADD DropBox$, Item$ + Add Item$ to the dropbox. Use Item$ = "--" for a separator. +DROPBOX CLEAR DropBox$ + Clear the drop box from all items. +n = DROPBOX COUNT DropBox$ + Count the number of items. +Item$ = DROPBOX GET$ DropBox$, Position + Get the item at Position. +DROPBOX REMOVE DropBox$, Position + Removes item number Position. + Note: If the removed item was marked, the item before it will be marked instead. You will NOT get + a message that the marked item has changed. If the first item will be deleted, the next item in + the drop box will be marked. + Note: Each time an item was removed, the drop box count will change too! +DROPBOX SELECT DropBox$, Position + Select the item at position Position. Counting starts at 0. + + +-= F =- + +File$ = FILEPANEL Mode$, Title$, Directory$ + Mode$ = "Load-File" + Mode$ = "Load-Directory" + Mode$ = "Load-File-and-Directory" + Mode$ = "Save-File" + Opens a filepanel in Directory$. According to the Mode$, you can either select a file, + a directory or both for loading or select/enter a file for saving. The selected file is File$. +File$ = FILEPANEL Mode$, Title$, Directory$, Filename$ + Same as above, except that you can provide preset Filename$ for the mode "Save-File" + + +-= I =- + +State = ISMOUSEIN(View$) + State = 0 the mouse cursor is not in the view View$ + State = 1 the mouse cursor is in the view View$ + + +-= K =- + +Msg$ = KEYBOARD MESSAGE$(View$) + Works like INKEY$ on the command line (well, nearly; it does not wait for input as inkey$ does). + + +-= L =- + +LAUNCH FileName$ + Launch the program FileName$ or the associated executable +LAYOUT Layout$, WindowOfView$ + Set the layout for all views on the window of View$. The layout will affect all following new widgets, + but not the already created. Draw commands are not affected by the layout, put them on an own view. + Layout$ (not case sensitive): + "Standard" = default layout, all widgets follow bottom and right side of the window + except for listboxes and textedit which follow all sides. + "All" = follow all sides (widgets resize) + "None" = follow the top and the left side (equals "top, left") + -OR- Layout$ is a combination of a horizontal and a vertical command (e.g. "Right, Top" etc.). + Horizontal: + "Left" = follow left side (default, when no other horizontal layout is given) + "Right" = follow the right side + "Left, Right" = follow the left and the right side (resize) + "H-Center" = follow the horizontal center + Vertical: + "Top" = follow the top side (default, when no other vertical layout is given) + "Bottom" = follow the bottom side + "Top, Bottom" = follow the top and bottom side (resize) + "V-Center" = follow the vertical center + +LISTBOX x1,y1 TO x2,y2, ID$, ScrollbarType, View$ + Adds an empty listbox at (x1,y1) to (x2,y2) known as ID$ and with a ScrollbarType on View$. + ScrollbarType: + 0 = none + 1 = vertical scrollbars + 2 = horizontal scrollbars + 3 = vertical & horizontal scrollbars +LISTBOX ADD ListBox$, Item$ + Add the item Item$ to the listbox; note: this replaces ITEM ADD, which is obsolete and will be removed. +LISTBOX ADD ListBox$, Position, Item$ + Add the item Item$ at the position Position. +LISTBOX CLEAR ListBox$ + removes all entries in ListBox$. +n = LISTBOX COUNT ListBox$ + Count the number of entries in the list box ListBox$ +Entry$ = LISTBOX GET$ ListBox$, Row + Returns the Entry$ of Row in ListBox$. +LISTBOX REMOVE ListBox$, Item$ + Removes an item Item$ from the Listbox ID$. +LISTBOX REMOVE ListBox$, Position + Remove the item at position Position. +LISTBOX SELECT ListBox$, Position + Select the item at position Position. + Position = 0 means deselect +LISTBOX SORT Listbox$ + Sort the entries of ListBox$ alphabetically. +LOCALIZE Mimetype$ + Initialize automatic translation and use the locale mimetype Mimetype$. See also the Localizer help program. +LOCALIZE STOP + Turn automatic translation off. +LOCALIZE + Turn automatic translation on again. + + +-= M =- + +MENU Head$, Menu$, Shortcut$, View$ + Add a menu to the menubar with the menu head Head$, the menu item Menu$ and the shortcut Shortcut$ + on View$. + Shortcut$ can contain the following modifiers at the beginning and the shortcut character at the end: + Modifiers$+ShortcutCharacter$ + "S" for the shift key + "C" for the control key + "O" for the option key (on most keyboards probably the Windows button) + These modifiers can be combined, but the following combinations do not work: + "SO", "SC" and "SCO" + Note: The command key (ALT) is always part of the shortcut. +MENU SET MenuHead$, SetRadioMode, View$ + Put the menu in radio mode, so up to one item is marked. + Note: you have to set the first marked item yourself. +MENU SET MenuHead$, MenuItem$, Option$, View$ + Enable/Disable or mark/unmark or remove a menu item. + Option$ = "Disable|Enable|Mark|Plain|Remove" +Translation$ = MENU TRANSLATE$(Source$) + Translation$ holds the translation of Source$. Different to TRANSLATE$, the Source$ is splitted at colons : and + and the string parts are translated separatly. This is useful for comparing translated menu messages. + E.g. + if(myMenuMessage$ = menu translate$("File:Open")) ... +msg$ = MESSAGE$ + Collects the messages generated by the GUI elements. +Arrived = MESSAGE SEND Application$, Message$ + Send a string to the yab application with signature Application$ + (default signature is: "application/x-vnd.yab-app", you can change the signature when you add + a comment in the first or second line of your program like this: + // mimetype "application/x-vnd.myapp" + Note: this does not work for bound programs currently!) + The destination yab application will produce a message$ stating: + _Scripting:...| + where the ... are the Message$. + The command returns one of the following error codes: + 0: Message was delivered + 1: The destination program was not found + 2: The target's message queue is full + 3: Time out, the message never made it to the target + 4: An other error occurred +mouse$ = MOUSE MESSAGE$(View$) + Returns the state of the mouse related to View$. + It consists out of X:Y:LMB:MMB:RMB (where MB is the corresponding left, middle, right mousebutton). +mouse$ = MOUSE MESSAGE$ + Returns the state of the mouse related to the application. + It consists out of VIEW:X:Y:LMB:MMB:RMB (where VIEW is the View$ the mouse is over, MB is the + corresponding left, middle, right mousebutton). +MOUSE SET Option$ + Hide or show the mouse cursor for this application. + Option$ = "Hide" -- hide the mouse cursor + Option$ = "Show" -- show the mouse cursor + Option$ = "Obscure" -- hide the mouse cursor until the mouse is moved + + +-= O =- + +OPTION SET View$, "Auto-Resize" + Automatically resize the view View$ to preferred (when this is supported by the view). +OPTION SET View$, "Focus", HasFocus + Set/remove the focus of View$ (when this is supported by the view). +OPTION SET Control$, "Enabled", IsEnabled + Enable/disable the control Control$. +OPTION SET Control$, "Label", NewLabel$ + Give a Control a new label. +OPTION SET Control$, "Visible", IsVisible + Set the control Control$ unvisible or visible + Note: The following widgets are controls: + CHECKBOX, RADIOBUTTON, SLIDER, TEXTCONTROL, BUTTON, COLORCONTROL, SPINCONTROL, CALENDAR +OPTION COLOR View$, "BGColor", r,g,b + Set the background color of any view (note: this is different to DRAW SET!) + + +-= P =- + +x = PEEK("DesktopWidth") + Returns the current X-resolution of the current desktop +y = PEEK("DesktopHeight") + Returns the current Y-resolution of the current desktop +x = PEEK("Deskbar-x") + Returns the position of the left side of the Deskbar +y = PEEK("Deskbar-y") + Returns the position of the top side of the Deskbar +w = PEEK("DeskbarWidth") + Returns the height of the Deskbar +h = PEEK("DeskbarHeight") + Returns the width of the Deskbar +p = PEEK("Deskbarposition") + Returns the position of the Deskbar as follows (clockwise): + 1 = top-left + 2 = top + 3 = top-right + 4 = bottom-right + 5 = bottom + 6 = bottom-left +i = PEEK("Deskbarexpanded") + Returns true if the Deskbar is expanded (only possibe in position 1 and 3) and false if not. +Height = PEEK("menuheight") + Returns the height of the menu (which is related to the user's font settings). + This returns the height only when any window already has a menu, otherwise it returns -1. +Width = PEEK("scrollbarwidth") + Returns the width of the scrollbars. + Different to "menuheight", it returns the correct width even if no scrollbars are used. +Height = PEEK("tabheight") + Returns the height of the tabfield. +Directory$ = PEEK$("directory") + Returns application directory. Use this in the following way: + if (peek("isbound")) then + Directory$ = peek$("directory") + else + Directory$ = system$("pwd") + endif +TrackerItem$ = PEEK$("refsreceived") + Returns TrackerItem which you used 'open with...' your application on. +Selected$ = POPUPMENU x,y, MenuItems$, View$ + Pop up a menu at position (x,y) on View$ with the menu items MenuItems$ which are separated + by "|". Waits until an item is selected and returns it's label as Selected$. +PRINTER SETUP SetupFile$ + Setup the printing enviroment and store it in file named SetupFile$. +PrintingError = PRINTER JobName$, SetupFile$, View$ + Load the settings from SetupFile$ (or ask for them when the file is invalid) and print + the view View$ as the job named JobName$. + Note: Alpha transparency is not printed correctly! + Note: Due to a bug in BeOS and ZETA, there are probably problems printing CHECKBOX IMAGE and + BUTTON IMAGE images, use DRAW IMAGE instead! + Note: currently untested in Haiku + Error codes for PrintingError: + 0 = No Problems + 1 = Page setup failed (probably communication problems with the print server) + 2 = The configuration file was loaded but page setup failed + 3 = The view View$ was not found + 4 = The number of pages is 0 or less + 5 = The printing was canceled or something went wrong with printing + Note: PrintingError = 4 can happen because of a bug in the PDF printing driver; although + a page size is shown, none is selected. If this happens, you may want to call a PRINTER SETUP + for the user and try to print again. + Note: When an error with code 1,2,3 or 4 occurs, you can be shure that nothing was sent to the printer yet. + + +-= R =- + +RADIOBUTTON x1,y1, ID$, Label$, IsActivated, View$ + Add a radio button at (x1,y1) and Label$ on View$. If isActivated is set to 0, the radio button is + off else it is on. Radio buttons should be grouped together in one view. +RADIOBUTTON SET RadioButton$, IsActivated + (De-)Activate the radio button RadioButton$. + + +-= S =- + +SCREENSHOT x1, y1 to x2, y2, Bitmap$ + Takes a screenshot and copies the specified region of the desktop onto Bitmap$, which will be created! +SCROLLBAR ID$, ScrollbarType, View$ + Make View$ scrollable. +SCROLLBAR SET Scrollbar$, Borderoption$ + Borderoption$ = "no-border" or "plain-border" or "fancy-border" (default) +SCROLLBAR SET Scrollbar$, "Vertical Position", Position +SCROLLBAR SET Scrollbar$, "Horizontal Position", Position + Set the scrollbar to the position Position. Default is (0,0). +SCROLLBAR SET Scrollbar$, "Vertical Range", Min, Max +SCROLLBAR SET Scrollbar$, "Horizontal Range", Min, Max + Set the scrollbars to a maximum range, default is (1000,1000). + Note: the Max value will be added to the view's actual width/height. +SCROLLBAR SET Scrollbar$, "Vertical Steps", SmallSteps, BigSteps +SCROLLBAR SET Scrollbar$, "Horizontal Steps", SmallSteps, BigSteps + Set the scrollbar steps. + SmallSteps are the scrolling steps when the user clicks on the arrow buttons (default is 1.0). + BigSteps are the scrolling steps when the user clicks on the empty part of the scrollbar (default is 10.0). +Position = SCROLLBAR GET Scrollbar$, "Horizontal" +Position = SCROLLBAR GET Scrollbar$, "Vertical" + Get the current position of the scrollbars. +SHORTCUT View$, Shortcut$, MyMessage$ + Set a key Shortcut$ on View$, giving back the Message$ when used. + This is comparable to the shortcuts used in menus, but NOTE: + in opposite to a menu, you can't use command -X, -C, -V, -A, -W, -Q ! +SLIDER x1,y1 TO x2,y2, ID$, Label$, Min, Max, View$ + Add a slider with a minimum and and a maximum value (Min, Max). +SLIDER x1,y1 TO x2,y2, ID$, Label$, Min, Max, Option$, View$ + Option$ = "block/triangle, horizontal/vertical" +SLIDER LABEL Slider$, StartLabel$, EndLabel$ + Set start and end limit labels +SLIDER SET Silder$, Location$, Count + Set the hashmarks. + Note: The Zeta sliders do not distinguish between top/bottom/left/right marks, just use "both" + Location$ = "none/bottom/top/both" use hashmarks for horizontal sliders + Location$ = "none/left/rigth/both" use hashmarks for vertical sliders + Count = number of hashmarks +SLIDER COLOR Silder$, Part$, r,g,b + Part$ = "barcolor" + Part$ = "fillcolor" +SLIDER SET Silder$, Value + Set the slider to Value. +Value = SLIDER GET Slider$ + Get the currently selected value of the slider. +ID = SOUND PLAY SoundFile$ + Play the sound file SoundFile$ (can be anything like wav, mp3, etc.). + You are given an ID to handle the playback later in your code. + Note: Currently not supported by Haiku! +SOUND STOP ID + Stop the sound with ID +SOUND WAIT ID + Waits until the sound with ID is finished playing. +SPINCONTROL x,y, ID$, Label$, Min, Max, Step, View$ + Set a spin control for the range (Min,Max), counting by Step. +SPINCONTROL SET SpinControl$, Value + Set the spin control SpinControl$ to Value. +Value = SPINCONTROL GET SpinControl$ + Get the current spin control value. +SPLITVIEW x1,y1 TO x2,y2, ID$, IsVerticalSplit, NormalStyle, View$ + Set up the new view ID$ and split it into two new views ID$+"1" and ID$+"2". + If IsVerticalSplit = true, a vertical splitter is set, + if IsVerticalSplit = false, a horizontal splitter is set. + If NormalStyle = true, the splitter is 10 pixels thick, + If NormalStyle = false, the splitter is 4 pixels thick. +SPLITVIEW SET SplitView$ "Divider", Position + Set the position of the divider, default is the half of the total split view. +SPLITVIEW SET SplitView$ "MinimumSizes", LeftOrTop, RightOrBottom + Set the minimum sizes of the left (or top) view and the right (or bottom) view. +Position = SPLITVIEW GET SplitView$, "Divider" + Get the current position of the divider. +STACKVIEW x1,y1 TO x2,y2, ID$, NumberOfViews, View$ + Set up a stack of views where only one is always visible. +STACKVIEW SET StackView$, ViewNumber + Set the view number ViewNumber as the visible view. +ViewNumber = STACKVIEW GET StackView$ + Get the current number of the visible view. +STATUSBAR x1, y1 to x2, y2, ID$, Label1$, Label2$, View$ + Creates a statusbar with ID$ and label(s) on View$. + Label1$ is on the left side above the actual bar and so is Label2$ on the right. +STATUSBAR SET ID$, Label1$, Label2$, State + Sets Statusbar ID$ to State and changes the Labels to specified ones. +STATUSBAR SET ID$, r, g, b + Set the color of the statusbar +STATUSBAR SET ID$, BarHeight + Set the height of the statusbar +SUBMENU MenuHead$, MenuItem$, SubMenuItem$, Modifier$, View$ + This is the same as MENU, it just adds a submenu instead. Deeper leveling is not possible + in yab, as a deeper menu structure would be bad style anyway. +SUBMENU SET MenuHead$, MenuItem$, SetRadioMode, View$ + Put the submenu in radio mode, so up to one item is marked. + Note: you have to set the first marked item yourself. +SUBMENU SET MenuHead$, MenuItem$, SubMenuItem$, Option$, View$ + Enable/Disable or mark/remove a submenu item. + Option$ = "Disable|Enable|Mark|Plain|Remove" + + +-= T =- + +TABVIEW x1,y1 TO x2,y2, ID$, Option$, View$ + Option$ = "top, bottom" where to place the tabs. +TABVIEW ADD TabView$, TabName$ + For each tab, a new view is created; you can add widgets or draw on these views as ususal. + The ids for the views ist TabView$+"1" for the first, TabView$+"2" for the second view, etc. +TABVIEW SET TabView$, TabNumber + Open the tab number TabNumber. +TabNumber = TABVIEW GET TABVIEW$ + Get the current opened tab. +TEXT x,y, ID$, Text$, View$ + Displays Text$ at position (x,y) on View$. This cannot be flushed like DRAW TEXT and is meant for + permanent labels. +TEXT x1,y1 TO x2,y2, ID$, Text$, View$ + Displays Text$ on View$. This cannot be flushed like DRAW TEXT and is meant for permanent labels. + Furthermore you can set the alignment for this command with the TEXT SET command. +TEXT SET Text$, Alignment$ + Set the alignment of Text$ to either "align-left", "align-center" or "align-right". +TEXTCONTROL x1,y1 TO x2,y2, ID$, Label$, Text$, View$ + Opens a textcontrol from (x1,y1) to (x2,y2) with Label$ and preset Text$ on View$ +TEXTCONTROL SET TextControl$, Text$ + Set the text control's text to Text$. +TEXTCONTROL SET TextControl$, IsPassword + IsPassword = false Normal typing + IsPassword = true Hide typing +TEXTCONTROL SET TextControl$, Option$, Value$ + Option$="align" Value$= "left" / "right" / "center" + *** note *** Haiku has issues aligh right. There are open tickets. + Option$="exclude", Value$=characters to disallow. + Option$="include", Value$=characters to allow. + Option$="length", Value$=str$(number) of characters allowed. + Sets the font used to the system fixed font. + Option$="type" + Value$="number" Only allow to characters 0-9 and ".", full stop. + Value$=""alphanumeric" allow all characters. + Option$="focus" Value$ = "true" / "false" Set the focus of TextControl$. + Option$="Curser", Value$=str$(number) positions the curser, sets the focus to true. +TEXTCONTROL CLEAR TextControl$ + Delete the text of the text control. +Text$ = TEXTCONTROL GET$ TextControl$ + Get the entry of the text control TextControl$. Even works, when Return was not pressed. +TEXTEDIT x1,y1 TO x2,y2, ID$, ScrollbarType, View$ + Opens an editor at (x1,y1) to (x2,y2) with ID$ (not displayed) on View$. For the + scrollbartypes look at the listbox entry. + TEXTEDIT also follows all sides in standard layout. +TEXTEDIT ADD TextEdit$, Text$ + Insert Text$ in the textedit TextEdit$ on View$. +TEXTEDIT CLEAR TextEdit$ + Clears the text from the textedit TextEdit$ on View$. +EnteredText$ = TEXTEDIT GET$ TextEdit$ + EnteredText$ holds the text of the textedit ID$ on View$ +SelectedText$ = TEXTEDIT GET$ TextEdit$, Option$ + Returns the current selected text, can be empty of course. + Option$ = "Selection" +TextLine$ = TEXTEDIT GET$ TextEdit$, LineNumber +Width = TEXTEDIT GET TextEdit$, "Line-Width", LineNumber +Height = TEXTEDIT GET TextEdit$, "Line-Height", LineNumber +LineNumber = TEXTEDIT GET TextEdit$, Option$, Search$ + LineNumber = Option$ = "Find", Search$ + LineNumber = Option$ = "Case-Sensitive-Find", Search$ +LineNumber = TEXTEDIT GET TextEdit$, Option$ + IsChanged = Option$ = "hasChanged" + LineNumber = Option$ = "countlines" + LineNumber = Option$ = "currentline" + YOffset = Option$ = "vertical-scrollbar" + XOffset = Option$ = "horizontal-scrollbar" + Position = Option$ = "cursor-position" + TextLength = Option$ = "textlength" +TEXTEDIT SET TextEdit$, Option$ + Applys an option to the textedit TextEdit$ on View$. + Option$ = "cut, copy, paste, clear, select-all, undo" +TEXTEDIT SET TextEdit$, Option$, Value + Option$ = "autoindent", true/false + Option$ = "wordwrap", true/false + Option$ = "editable", true/false + Option$ = "color-case-sensitive", true/false + Option$ = "changed", true/false + Option$ = "gotoline", LineNumber + Option$ = "select", LineNumber + Option$ = "tabwidth", TabWidth + Option$ = "textwidth", TextWidth + Option$ = "autocomplete-start" + Option$ = "has-autocompletion" + Option$= "align", left/center/right + Default options are: + autoindent = false + wordwrap = true + editable = true + color-case-sensitive = false + changed = false + has-autocompletion = true + autocomplete-start = 4 + align = left +TEXTEDIT SET TextEdit$, Option$, Value$ + Option$ = "autocomplete" + Add a word Value$ to the auto-completion list. + Option$ = "font" + Set the font to Value$ (similar to DRAW SET); default is "system-plain" +TEXTEDIT COLOR TextEdit$, Option$, Command$ + Option$ = "color1, color2, color3, color4, char-color", Command$ + Add the command Command$ to the list of words that are checked for syntax highlighting + The char-color behaves differently and highlights only the first character of Command$ + (this happens after the highlighting of the other colors). +TEXTEDIT COLOR TextEdit$, Option$, r,g,b + Option$ = "bgcolor, textcolor, color1, color2, color3, color4, char-color", r,g,b + Default colors are: + bgcolor = 255,255,255 (white) + textcolor = 0,0,0 (black) + color1 = 0,0,255 (blue) + color2 = 255,0,0 (red) + color3 = 0,250,0 (green) + color4 = 185,185,185 (gray) + char-color = 200,0,255 (magenta) +TEXTURL x,y, ID$, Label$, Address$, View$ + Set the web/email/ftp address at (x,y) with the label Label$ and the url Address$. + This widget is quite nice, it launches the appropriate application when clicked, it supports + a right-click popup-menu and you can drag the url to create either a person file or a bookmark. + Email can be either of the style: "mailto:foo@bar.com" or just "foo@bar.com" + A web url starts either with "http://" or with "file://" + And a ftp address starts with "ftp://" +TEXTURL COLOR TextURL$, Option$, r,g,b + Set the colors for the URL. Valid options are: + "Label" for the color of the label, + "Click" for the color of the label, when clicked and + "Mouse-over" for the color of the label, when the mouse is moved over the label. +Id = THREAD GET Option$, Program$ + Option$ = "TeamID" returns the team ID for the program named Program$ + Specify the whole path with parameters (only the first 64 characters are important) + for the team, the first team with this path and parameters will be returned. + Option$ = "ThreadID" returns the thread ID for the program named Program$ + Specify the program name, the first thread with this name will be returned. + Returns -1 when the program was not found. +Success = THREAD REMOVE Option$, ID + Option$ = "TeamID" kills the team with number ID + Option$ = "ThreadID" kills the thread with number ID + Returns True when successful and False otherwise. + Note: You can crash your system with this command! If you don't know what this command is meant for, + then don't use it! +TOOLTIP View$, Text$ + Set Text$ as the tooltip information for any Widget or View View$. + Set Test$ = "" to remove the tooltip again. +TOOLTIP COLOR "bgcolor/textcolor", r,g,b + Set the background/text color of all tooltips to r,g,b. Note: This is currently not supported. +Translation$ = TRANSLATE$(Source$) + Translation$ holds the translation of Source$ +TREEBOX x1,y1 to x2,y2, ID$, ScrollbarType, View$ + Adds a tree box. This behaves just like a LISTBOX but is able to show nested trees. + Note: ITEM ADD does not work here. Use TREEBOX ADD instead. ITEM ADD will be depricated in + one of the next releases. +TREEBOX ADD TreeBox$, RootItem$ + Add the item RootItem$ to the top level of the tree. +TREEBOX ADD TreeBox$, HeadItem$, ListItem$, IsExpanded + Add the item ListItem$ under the level of HeadItem$ of the tree. +TREEBOX CLEAR TreeBox$ + Clear the tree. +TREEBOX REMOVE TreeBox$, ListItem$ + Removes the first list item ListItem$ from the tree. Note: this also removes all subitems! +n = TREEBOX COUNT TreeBox$ + Returns the number of entries in TreeBox$ +Item$ = TREEBOX GET TreeBox$, Position + Returns the Item$ at position Position in TreeBox$. +TREEBOX EXPAND TreeBox$, Head$ + Expands Head$ in TreeBox$. +TREEBOX COLLAPSE TreeBox$, Head$ + Collapses Head$ in TreeBox$. +TREEBOX REMOVE TreeBox$, Position + Removes the entry at position Position in TreeBox$. +TREEBOX REMOVE TreeBox$, Head$, ListItem$ + Removes ListItem$ under Head$ in TreeBox$. +TREEBOX SELECT TreeBox$, Position + Selects theitem at position Position in TreeBox$. +TREEBOX SORT TreeBox$ + Sorts the entries of TreeBox$ alphabetically. + + +-= V =- + +VIEW x1,y1 TO x2,y2, ID$, View$ + Adds a view +VIEW DROPZONE View$ + Define View$ as a drop zone that accepts dropped files. + DROPZONE now accepts multiple files (and sends them in inversed order as message) +VIEW REMOVE View$ + Remove View$. The window view cannot be removed. Should be much more stable now. + Warning: Currently clears all internal information about menues and drop boxes. It is only safe to + use it, when you don't have any menues or drop boxes on views that will not be removed. + Warning: Never remove menus with shortcuts, otherwise yab will crash when the shortcut key is pressed! +Result = VIEW GET View$, Option$ + Option$ = "Position-X/Position-Y/Width/Height/Exists/Focused" + Returns the requested property or if used with Exists/Focused returns 1 if so and 0 if not. + + +-= W =- + +WINDOW OPEN x1,y1 TO x2,y2, ID$, Title$ + Open window at position x1,y1 to x2,y2 in screen coordinates with title Title$. + Automatically generates a window-sized view called ID$. +WINDOW CLOSE WindowView$ + Closes window containing the view View$. Warning: this might destabilize your program if you try + to reconstruct your old window or further use old views! The yab-taskforce is set on the tracks of + this bug ;) +n = WINDOW COUNT + Returns the number of open windows +Result = WINDOW GET View$, Option$ + Option$ = "Position-X/Position-Y/Width/Height/Minimum-Width/Minimum-Height/Maximum-Width/Maximum-Height/Exists" + Returns the requested property or if used with Exists returns 1 if found and 0 if not. +WINDOW SET Window$, Option$, Value$ + "Look", "Document/Titled(default)/Floating/Modal/Bordered/No-Border" + "Feel", "Normal(default)/Modal-App/Modal-All/Floating-App/Floating-All" + See "BeBook->Interface Kit->BWindow->Constants and Defined Types" for details. + "Title", Title$ + "Flags", "Not-Closable, Not-Zoomable, Not-Minimizable, Not-H-Resizable, Not-V-Resizable, + Not-Resizable, No-Workspace-Activation, Accept-First-Click" + See "BeBook->Interface Kit->BWindow->Constants and Defined Types" for details. + "Flags", "Reset" + Resets the flags back to none. + "Workspace", "All" + Causes the window to appear on all workspaces. + "Workspace", "Current" + Causes the window to appear on only the current workspace. + "Workspace", "n" (where n is a number >= 1) + Causes the window to appear on workspace number n +WINDOW SET Window$, Option$, r,g,b + "BGColor", r,g,b (216,216,216 default) + "HighColor", r,g,b (0,0,0 default) + "LowColor", r,g,b (216,216,216 default) +WINDOW SET Window$, Option$, x,y + "ResizeTo", x,y + "MoveTo", x,y + "MinimumTo", x,y + "MaximumTo", x,y +WINDOW SET WindowView$, Option$ + Option$ = "Activate" + Activate the window, so it is in the foreground. + Option$ = "Deactivate" + Deactivate the window, so it is in the background. + Option$ = "Minimize" + Minimize the window, or restore the window if it is already minimized. + Option$ = "Maximize" + Maximize (zoom) the window. + Option$ = "Enable-Updates" + Updates the window again after a "Disable-Updates". + Option$ = "Disable-Updates" + Disables the automatic window updates. diff --git a/Documentation/yabasic.html b/Documentation/yabasic.html new file mode 100644 index 0000000..41a0e6c --- /dev/null +++ b/Documentation/yabasic.html @@ -0,0 +1,2664 @@ +Yabasic

Yabasic


Chapter 1. Introduction

About this document

+ This document describes yabasic. + You will find information about the yabasic + interpreter (the program yabasic under Unix or + yabasic.exe under Windows) + as well as the language itself.

+

+ This document applies to version 2.750 of yabasic

+ However, this document does not contain the latest news about yabasic or a FAQ. + As such information tends to change rapidly, it is presented online only + at www.yabasic.de.

+ Although basic has its reputation as a language for beginning programmers, + this is not an introduction to programming at large. Rather this text assumes, that + the reader has some (moderate) experience with writing and starting computer programs.

+

About yabasic

yabasic is a traditional basic interpreter. It understands most of the typical basic-constructs, like goto, gosub, line numbers, read, data or string-variables with a trailing '$'. But on the other hand, yabasic implements some more advanced programming-constructs like subroutines or libraries (but not objects). yabasic works much the same under Unix and Windows.

yabasic puts emphasis on giving results quickly and easily; therefore simple commands are provided to open a graphic window, print the graphics or control the console screen and get keyboard or mouse information. The example below opens a window, draws a circle and prints the graphic:

+open window 100,100
+open printer
+circle 50,50,40
+text 10,50,"Press any key to get a printout"
+clear screen
+inkey$
+close printer
+close window
+

This example has fewer lines, than it would have in many other programming languages. In the end however yabasic lacks behind more advanced and modern programming languages like C++ or Java. But as far as it goes it tends to give you results more quickly and easily.

Chapter 2. The yabasic-program under Windows

Starting yabasic

Once, yabasic has been set up correctly, there are three ways to start it:

  1. Rightclick on your desktop: The desktop menu appears with a submenu named new. From this submenu choose yabasic. This will create a new icon on your desktop. If you rightclick on this icon, its context menu will appear; choose Execute to execute the program.

  2. As a variant of the way described above, you may simply create a file with the ending .yab (e.g. with your favorite editor). Everything else then works as described above.

  3. From the start-menu: Choose yabasic from your start-menu. A console-window will open and you will be asked to type in your program. Once you are finished, you need to type return twice, and yabasic will parse and execute your program.

    Note

    This is not the preferred way of starting yabasic ! Simply because the program, that you have typed, can not be saved and will be lost inevitably ! There is no such thing as a save-command and therefore no way to conserve the program, that you have typed. This mode is only intended for quick hacks, and short programs.

Options

Under Windows yabasic will mostly be invoked by double-clicking on an appropriate icon; this way you do not have a chance to specify any of the commandline options below. However, advanced users may add some of those options to the appropriate entries in the registry.

All the options below may be abbreviated, as long as the abbreviation does not become ambigous. For example, you may write -e instead of -execute.

-help or -?

Prints a short help message, which itself describes two further help-options.

-version

Prints the version of yabasic.

-geometry +X-POSITION+Y-POSITION

Sets the position of the graphic window, that is opened by open window (the size of this window, of course, is specified within the open window-command). An example would be -geometry +20+10, which would place the graphic window 10 pixels below the upper border and 20 pixels right of the left border of the screen. This value cannot be changed, once yabasic has been started.

-font NAME-OF-FONT

Name of the font, which will be used for graphic-text; can be any of decorative, dontcare, modern, roman, script, swiss. You may append a fontsize (measured in pixels) to any of those fontnames; for example -font swiss30 chooses a swiss-type font with a size of 30 pixels.

-bind NAME-OF-STANDALONE-PROGRAM

Create a standalone program (whose name is specified by NAME-OF-STANDALONE-PROGRAM) from the yabasic-program, that is specified on the commandline. See the section about creating a standalone-program for details.

-execute A-PROGRAM-AS-A-SINGLE-STRING

With this option you may specify some yabasic-code to be executed rigth away.This is useful for very short programs, which you do not want to save within a file. If this option is given, yabasic will not read any code from a file. Let's say, you have forgotten some of the square numbers between 1 and 10; in this case the command yabasic -e 'for a=1 to 10:print a*a:next a' will give you the answer immediately.

-infolevel INFOLEVEL

Change the infolevel of yabasic, where INFOLEVEL can be one of debug, note, warning, error and fatal (the default is warning). This option changes the amount of debugging-information yabasic produces. However, normally only the author of yabasic (me !) would want to change this.

-doc NAME-OF-A-PROGRAM

Print the embedded documentation of the named program. The embedded documentation of a program consists of all the comments within the program, which start with the special keyword doc. This documentation can also be seen by choosing the corresponding entry from the context-menu of any yabasic-program.

-librarypath DIRECTORY-WITH-LIBRARIES

Change the directory, wherein libraries will be searched and imported (with the import-command). See also this entry for more information about the way, libraries are searched.

The context Menu

Like every other icon under Windows, the icon of every yabasic-program has a context menu offering the most frequent operations, that may be applied to a yabasic-program.

Execute

This will invoke yabasic to execute your program. The same happens, if you doubleclick on the icon.

Edit

notepad will be invoked, allowing you to edit your program.

View docu

This will present the embedded documentation of your program. Embedded documentation is created with the special comment doc.

Chapter 3. The yabasic-program under Unix

Starting yabasic

If your system administrator (vulgo root) has installed yabasic correctly, there are three ways to start it:

  1. You may use your favorite editor (emacs, vi ?) to put your program into a file (e.g. foo). Make sure that the very first line starts with the characters '#!' followed by the full pathname of yabasic (e.g. '#!/usr/local/bin/yabasic'). This she-bang-line ensures, that your Unix will invoke yabasic to execute your program (see also the entry for the hash-character). Moreover, you will need to change the permissions of your yabasic-program foo, e.g. chmod u+x foo. After that you may invoke yabasic to invoke your program by simply typing foo (without even mentioning yabasic). However, if your PATH-variable does not contain a single dot ('.') you will have to type the full pathname of your program: e.g. /home/ihm/foo (or at least ./foo).

  2. Save your program into a file (e.g. foo) and type yabasic foo. This assumes, that the directory, where yabasic resides, is contained within your PATH-variable.

  3. Finally your may simply type yabasic (maybe it will be necessary to include its full pathname). This will make yabasic come up and you will be asked to type in your program. Once you are finished, you need to type return twice, and yabasic will parse and execute your program.

    Note

    This is not the preferred way of starting yabasic ! Simply because the program, that you have typed, can not be saved and will be lost inevitably ! There is no such thing as a save-command and therefore no way to conserve the program, that you have typed. This mode is only intended for quick hacks, and short programs, i.e. for using yabasic as some sort of fancy desktop calculator.

Options

yabasic accepts a number of options on the commandline. All these options below may be abbreviated, as long as the abbreviation does not become ambigous. For example you may write -e instead of -execute.

-help or -?

Prints a short help message, which itself describes two further help-options.

-version

Prints the version of yabasic.

-fg FOREGROUND-COLOR or -foreground FOREGROUND-COLOR

Define the foreground color for the graphics-window (that will be opened with open window). The usual X11 colornames, like red, green, … are accepted. This value cannot be changed, once yabasic has been started.

-bg BACKGROUND-COLOR or -background BACKGROUND-COLOR

Define the background color for the graphics-window. The usual X11 colornames are accepted. This value cannot be changed, once yabasic has been started.

-geometry +X-POSITION+Y-POSITION

Sets the position of the graphic window, that is opened by open window (the size of this window, of course, is specified with the open window-command). An example would be +20+10, which would place the graphic window 10 pixels below the upper border and 20 pixels right of the left border of the screen. Note, that the size of the window may not be specified here (well it may, but it will be ignored anyway). This value cannot be changed, once yabasic has been started.

-display BACKGROUND-COLOR

Specify the display, where the graphics window of yabasic should appear. Normally, however this value will be already present within the environment variable DISPLAY.

-font NAME-OF-FONT

Name of the font, which will be used for text within the graphics window.

-execute A-PROGRAM-AS-A-SINGLE-STRING

With this option you may specify some yabasic-code to be executed rigth away.This is useful for very short programs, which you do not want to save to a file. If this option is given, yabasic will not read any code from a file. E.g.

yabasic -e 'for a=1 to 10:print a*a:next a'
prints the square numbers from 1 to 10. +

-bind NAME-OF-STANDALONE-PROGRAM

Create a standalone program (whose name is specified by NAME-OF-STANDALONE-PROGRAM) from the yabasic-program, that is specified on the commandline. See the section about creating a standalone-program for details.

-infolevel INFOLEVEL

Change the infolevel of yabasic where INFOLEVEL can be one of debug, note, warning, error and fatal (the default is warning). This option changes the amount of debugging-information yabasic produces. However, normally only the author of yabasic (me !) would want to change this.

-doc NAME-OF-A-PROGRAM

Print the embedded documentation of the named program. The embedded documentation of a program consists of all the comments within the program, which start with the special keyword doc.

-librarypath DIRECTORY-WITH-LIBRARIES

Change the directory from which libraries will be imported (with the import-command). See also this entry for more information about the way, libraries will be searched.

Setting defaults

If you want to set some options once for all, you may put them into your X-Windows resource file. This is usually the file .Xresources or some such within your home directory (type man X for details).

Here is a sample section, which may appear within this file:

+yabasic*foreground: blue
+yabasic*background: gold
+yabasic*geometry: +10+10
+yabasic*font: 9x15
+

This will set the foreground color of the graphic-window to blue and the background color to gold. The window will appear at position 10,10 and the text font will be 9x15.

Chapter 4. Some features of yabasic, explained by topic

This chapter has sections for some of the major features of yabasic and names a few commands related with each area. So, depending on your interest, you find the most important commands of this area named; the other commands from this area may then be discovered through the links in the see also-section.

print, input and others

The print-command is used to put text on the text screen. Here, the term text screen stands for your terminal (under Unix) or the console window (under Windows).

At the bottom line, print simply outputs its argument to the text window. However, once you have called clear screen you may use advanced features like printing colors or copying areas of text with getscreen$ or putscreen.

You may ask the user for input with the input-command; use inkey$ to get each key as soon as it is pressed.

Control statements: loops, if and switch

Of course, yabasic has the goto- and gosub-statements; you may go to a label or a line number (which is just a special kind of label). goto, despite its bad reputation ([goto considered harmful]), has still its good uses; however in many cases you are probably better off with loops like repeat-until, while-wend or do-loop; you may leave any of these loops with the break-statement or start the next iteration immediately with continue.

Decisions can be made with the if-statement, which comes either in a short and a long form. The short form has no then-keyword and extends up to the end of the line. The long form extends up to the final endif and may use some of the keywords then (which introduces the long form), else or elsif.

If you want to test the result of an expression against many different values, you should probably use the switch-statement.

Drawing and painting

You need to call open window before you may draw anything with either line, circle or rectangle; all of these statements may be decorated with clear or fill. Note however, that all graphics in yabasic is monochrome ("black on white"). Moreover, there can only be a single window open at any given moment in time.

Evyerything you have drawn can be send to your printer too, if you use the open printer command.

To allow for some (very) limited version of animated graphics, yabasic offers the commands getbit$ and putbit, which retrieve rectangular regions from the graphics-window into a string or vice versa.

If you want to sense mouse-clicks, you may use the inkey$-function.

Reading from and writing to files

Before you may read or write a file, you need to open it; once you are done, you should close it. Each open file is designated by a simple number, which might be stored within a variable and must be supplied if you want to access the file. This is simply done by putting a hash ('#') followd by the number of the file after the keyword input (for reading from) or print (for writing to a file) respectively.

If you need more control, you may consider reading and writing one byte at a time, using the multi-purpose commands peek and poke.

Subroutines and Libraries

The best way to break any yabasic-program into smaller, more manageable chunks are subroutines and libraries. They are yabasic's most advanced means of structuring a program.

Subroutines are created with the command sub. they accept parameters and may return a value. Subroutines can be called much like any builtin function of yabasic; therefore they allow to extend the language itself.

Once you have created a set of related subroutines and you feel that they could be useful in other programs too, you may collect them into a library. Such a library is contained within a separate file and may be included in any of your programs, using the keyword import.

String processing

yabasic has the usual functions to extract parts from a string: left$, mid$ and right$. Note, that all of them can be assigned to, i.e. they may change part of a string.

If you want to split a string into tokens you should use the functions token or split.

There is quite a bunch of other string-processing functions like upper$ (converting to upper case), instr (finding one string within the other), chr$ (converting an ascii-code into a character), glob (testing a string against a pattern) and more. Just follow the links.

Arithmetic

Yabasic handles numbers and arithmetic: You may calculate trigonometric functions like sin or atan, or logarithms (with log). Bitwise operations, like and or or are available as well min or max (calculate the minimum or maximum of its argument) or mod or int (reminder of a division or integer part or a number).

Data and such

You may store data within your program within data-statements; during execution you will probably want to read it into arrays, which must have been dimed before.

Other interesting commands.

  • Yabasic programs may start other programs with the commands system and system$.

  • peek and poke allow to get and set internal information; either for the operating system (i.e. Unix or Windows) or yabasic itself.

  • The current time or date can be retrieved with (guess what !) time$ and date$.

Chapter 5. All commands and functions of yabasic listed by topic

Number processing and conversion

abs()
+ returns the absolute value of its numeric argument +
acos()
+ returns the arcus cosine of its numeric argument +
and()
+ the bitwise arithmetic and
asin()
+ returns the arcus sine of its numeric argument +
atan()
+ returns the arcus tangens of its numeric argument +
bin$()
+ converts a number into a sequence of binary digits +
cos()
+ return the cosine of its single argument +
dec()
+ convert a base 2 or base 16 number into decimal form +
eor()
+ compute the bitwise exclusive or of its two arguments +
euler
+ another name for the constant 2.71828182864
exp()
+ compute the exponential function of its single argument +
frac()
+ return the fractional part of its numeric argument +
int()
+ return the integer part of its single numeric argument +
log()
+ compute the natural logarithm +
max()
+ return the larger of its two arguments +
min()
+ return the smaller of its two arguments +
mod()
+ compute the remainder of a division +
or()
+ arithmetic or, used for bit-operations +
pi
+ a constant with the value 3.14159
ran()
+ return a random number +
sig()
+ return the sign of its argument +
sin()
+ return the sine of its single argument +
sqr()
+ compute the square of its argument +
sqrt()
+ compute the square root of its argument +
tan()
+ return the tangens of its argument +
xor()
+ compute the exclusive or +
** or ^
+ raise its first argument to the power of its second +

Conditions and control structures

and
+ logical and, used in conditions +
break
+ breaks out of a switch statement or a loop +
case
+ mark the different cases within a switch-statement +
continue
+ start the next iteration of a for-, do-, repeat- or while-loop +
default
+ mark the default-branch within a switch-statement +
do
+ start a (conditionless) do-loop
else
+ mark an alternative within an if-statement +
elsif
+ starts an alternate condition within an if-statement +
end
+ terminate your program +
endif
+ ends an if-statement +
false
+ a constant with the value of 0 +
fi
+ another name for endif
for
+ starts a for-loop +
gosub
+ continue execution at another point within your program (and return later) +
goto
+ continue execution at another point within your program (and never come back) +
if
+ evaluate a condition and execute statements or not, depending on the result +
label
+ mark a specific location within your program for goto, gosub or restore
loop
+ marks the end of an infinite loop +
next
+ mark the end of a for loop +
not
+ negate an expression; can be written as !
on gosub
+ jump to one of multiple gosub-targets +
on goto
+ jump to one of many goto-targets +
on interrupt
+ change reaction on keyboard interrupts +
logical or
+ logical or, used in conditions +
pause
+ pause, sleep, wait for the specified number of seconds +
repeat
+ start a repeat-loop +
return
+ return from a subroutine or a gosub +
sleep
+ pause, sleep, wait for the specified number of seconds +
switch
+ select one of many alternatives depending on a value +
then
+ tell the long from the short form of the if-statement +
true
+ a constant with the value of 1 +
until
+ end a repeat-loop +
wait
+ pause, sleep, wait for the specified number of seconds +
wend
+ end a while-loop +
while
+ start a while-loop +
:
+ separate commands from each other +

Data keeping and processing

arraydim()
+ returns the dimension of the array, which is passed as an array reference
arraysize()
+ returns the size of a dimension of an array +
data
+ introduces a list of data-items +
dim
+ create an array prior to its first use +
read
+ read data from data-statements +
redim
+ create an array prior to its first use. A synonym for dim
restore
+ reposition the data-pointer +

String processing

asc()
+ accepts a string and returns the position of its first character within the ascii charset +
chr$()
+ accepts a number and returns the character at this position within the ascii charset +
glob()
+ check if a string matches a simple pattern +
hex$()
+ convert a number into hexadecimal +
instr()
+ searches its second argument within the first; returns its position if found +
left$()
+ return (or change) left end of a string +
len()
+ return the length of a string +
lower$()
+ convert a string to lower case +
ltrim$()
+ trim spaces at the left end of a string +
mid$()
+ return (or change) characters from within a string +
right$()
+ return (or change) the right end of a string +
split()
+ split a string into many strings +
str$()
+ convert a number into a string +
token()
+ split a string into multiple strings +
trim$()
+ remove leading and trailing spaces from its argument +
upper$()
+ convert a string to upper case +
val()
+ converts a string to a number +

File operations and printing

at()
+ can be used in the print-command to place the output at a specified position +
beep
+ ring the bell within your computer; a synonym for bell
bell
+ ring the bell within your computer (just as beep) +
clear screen
+ erases the text window +
close
+ close a file, which has been opened before +
close printer
+ stops printing of graphics +
color
+ print with color +
colour
+ see color
eof
+ check, if an open file contains data +
getscreen$()
+ returns a string representing a rectangular section of the text terminal +
inkey$
+ wait, until a key is pressed +
input
+ read input from the user (or from a file) and assign it to a variable +
line input
+ read in a whole line of text and assign it to a variable +
open
+ open a file +
open printer
+ open printer for printing graphics +
print
+ Write to terminal or file +
putscreen
+ draw a rectangle of characters into the text terminal +
reverse
+ print reverse (background and foreground colors exchanged) +
screen
+ as clear screen clears the text window +
seek()
+ change the position within an open file +
tell
+ get the current position within an open file +
using
+ Specify the format for printing a number +
#
+ either a comment or a marker for a file-number +
@
+ synonymous to at
;
+ suppress the implicit newline after a print-statement +

Subroutines and libraries

end sub
+ ends a subroutine definition +
export
+ mark a function as globally visible +
import
+ import a library +
local
+ mark a variable as local to a subroutine +
numparams
+ return the number of parameters, that have been passed to a subroutine +
return
+ return from a subroutine or a gosub +
static
+ preserves the value of a variable between calls to a subroutine +
step
+ specifies the increment step in a for-loop +
sub
+ declare a user defined subroutine +

Other commands

bind()
+ Binds a yabasic-program and the yabasic-interpreter together into a standalone program. +
compile
+ compile a string with yabasic-code on the fly
date$
+ returns a string with various components of the current date +
doc
+ special comment, which might be retrieved by the program itself +
docu$
+ special array, containing the contents of all docu-statement within the program +
error
+ raise an error and terminate your program +
execute$()
+ execute a user defined subroutine, which must return a string +
execute()
+ execute a user defined subroutine, which must return a number +
exit
+ terminate your program +
pause
+ pause, sleep, wait for the specified number of seconds +
peek
+ retrieve various internal informations +
peek$
+ retrieve various internal string-informations +
poke
+ change selected internals of yabasic
rem
+ start a comment +
sleep
+ pause, sleep, wait for the specified number of seconds +
system$()
+ hand a statement over to your operating system and return its output +
system()
+ hand a statement over to your operating system and return its exitcode +
time$
+ return a string containing the current time +
to
+ this keyword appears as part of other statements +
wait
+ pause, sleep, wait for the specified number of seconds +
//
+ starts a comment +
:
+ separate commands from each other +

Graphics and printing

box
+ draw a rectancle. A synonym for rectangle
circle
+ draws a circle in the graphic-window +
clear
+ Erase circles or rectangles +
clear window
+ clear the graphic window and begin a new page, if prining is under way +
close curve
+ close a curve, that has been drawn by the line-command +
close window
+ close the graphics-window +
dot
+ draw a dot in the graphic-window +
fill
+ draw a filled circles or rectangles +
getbit$()
+ return a string representing the bit pattern of a rectangle within the graphic window +
line
+ draw a line +
mouseb
+ extract the state of the mousebuttons from a string returned by inkey$
mousemod
+ return the state of the modifier keys during a mouseclick +
mousex
+ return the x-position of a mouseclick +
mousey
+ return the y-position of a mouseclick +
new curve
+ start a new curve, that will be drawn with the line-command +
open window
+ open a graphic window +
putbit
+ draw a rectangle of pixels into the graphic window +
rectangle
+ draw a rectangle +
text
+ write text into your graphic-window +
window origin
+ move the origin of a window +

Chapter 6. All commands and functions of yabasic grouped alphabetically

A

Table of Contents

abs() - returns the absolute value of its numeric argument
acos() - returns the arcus cosine of its numeric argument
and - logical and, used in conditions
and() - the bitwise arithmetic and
arraydim() - returns the dimension of the array, which is passed as an array reference
arraysize() - returns the size of a dimension of an array
asc() - accepts a string and returns the position of its first character within the ascii charset
asin() - returns the arcus sine of its numeric argument
at() - can be used in the print-command to place the output at a specified position
atan() - returns the arcus tangens of its numeric argument

abs()

Name

abs() — returns the absolute value of its numeric argument

Synopsis

y=abs(x)

Description

If the argument of the abs-function is positive (e.g. 2) it is returned unchanged, if the argument is negative (e.g. -1) it is returned as a positive value (e.g. 1).

Example

+print abs(-2),abs(2)
+          

This example will print 2 2

See also

sig

acos()

Name

acos() — returns the arcus cosine of its numeric argument

Synopsis

x=acos(angle)

Description

The acos is the arcus cosine-function, i.e. the inverse of the cos-function. Or, more elaborate: It Returns the angle (in radian, not degree !), which, fed to the cosine-function will produce the argument passed to the acos-function.

Example

+print acos(0.5),acos(cos(pi))
+          

This example will print 1.0472 3.14159 which are π/3 and π respectively.

See also

cos, asin

and

Name

and — logical and, used in conditions

Synopsis

+if (a and b) …
+while (a and b) …
+

Description

Used in conditions (e.g within if, while or until) to join two expressions. Returns true, if and only if its left and right argument are both true and false otherwise.

Note, that logical shortcutsmay take place.

Example

+input "Please enter a number" a
+if (a>=1 and a<=9) print "your input is between 1 and 9"
+          

See also

or,not

and()

Name

and() — the bitwise arithmetic and

Synopsis

+x=and(a,b)
+

Description

Used to compute the bitwise and of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if both arguments have a 1 at this position in their binary representation.

Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to and.

Example

+print and(6,3)
+          

This will print 2. This result is clear, if you note, that the binary representation of 6 and 3 are 110 and 011 respectively; this will yield 010 in binary representaion or 2 as decimal.

See also

or, eor and not

arraydim()

Name

arraydim() — returns the dimension of the array, which is passed as an array reference

Synopsis

a=arraydim(b())

Description

If you apply the arraydim()-function on a one-dimensional array (i.e. a vector) it will return 1, on a two-dimensional array (i.e. a matrix) it will return 2, and so on.

This is mostly used within subroutines, which expect an array among their parameters. Such subroutines tend to use the arraydim-funtion to check, if the array which has been passed, has the right dimension. E.g. a subroutine to multiply two matrices may want to check, if it really is invoked with two 2-dimensional arrays.

Example

+dim a(10,10),b(10)
+print arraydim(a()),arraydim(b())
+          

This will print 2 1, which are the dimension of the arrays a() and b(). You may check out the function arraysize for a full-fledged example.

See also

arraysize and dim.

arraysize()

Name

arraysize() — returns the size of a dimension of an array

Synopsis

x=arraysize(a(),b)

Description

The arraysize-function computes the size of a specified dimension of a specified array. Here, size stands for the maximum number, that may be used as an index for this array. The first argument to this function must be an reference to an array, the second one specifies, which of the multiple dimensions of the array should be taken to calculate the size.

An Example involving subroutines: Let's say, an array has been declared as dim a(10,20) (that is a two-dimensional array or a matrix). If this array is passed as an array reference to a subroutine, this sub will not know, what sort of array has been passed. With the arraydim-function the sub will be able to find the dimension of the array, with the arraysize-function it will be able to find out the size of this array in its two dimensions, which will be 10 and 20 respectively.

Our sample array is two dimensional; if you envision it as a matrix this matrix has 10 lines and 20 columns (see the dim-statement above. To state it more formally: The first dimension (lines) has a size of 10, the second dimension (columns) has a size of 20; these mumbers are those returned by arraysize(a(),1) and arraysize(a(),2) respectively. Refer to the example below for a typical usage.

Example

+
+rem
+rem  This program adds two matrices elementwise.
+rem
+
+dim a(10,20),b(10,20),c(10,20)
+
+rem  initialization of the arrays a() and b() 
+for y=1 to 10:for x=1 to 20
+   a(y,x)=int(ran(4)):b(y,x)=int(ran(4))
+next x:next y
+
+matadd(a(),b(),c())
+
+print "Result:"
+for x=1 to 20
+   for y=10 to 1 step -1
+      print c(y,x)," ";
+   next y
+   print
+next x
+
+sub matadd(m1(),m2(),r())
+
+   rem  This sub will add the matrices m1() and m2()
+   rem  elementwise and store the result within r()
+   rem  This is not very useful but easy to implement.
+   rem  However, this sub excels in checking its arguments
+   rem  with arraydim() and arraysize()
+
+   local x:local y
+   
+   if (arraydim(m1())<>2 or arraydim(m2())<>2 or arraydim(r())<>2) then
+      error "Need two dimensional arrays as input"
+   endif
+
+   y=arraysize(m1(),1):x=arraysize(m1(),2)
+   if (arraysize(m2(),1)<>y or arraysize(m2(),2)<>x) then
+      error "The two matrices cannot be added elementwise"
+   endif
+
+   if (arraysize(r(),1)<>y or arraysize(r(),2)<>x) then
+      error "The result cannot be stored in the third argument"
+   endif
+
+   local xx:local yy
+   for xx=1 to x
+      for yy=1 to y
+         r(yy,xx)=m1(yy,xx)+m2(yy,xx)
+      next yy
+   next xx
+
+ end sub
+
+          

See also

arraydim and dim.

asc()

Name

asc() — accepts a string and returns the position of its first character within the ascii charset

Synopsis

a=asc(char$)

Description

The asc-function accepts a string, takes its first character and looks it up within the ascii-charset; this position will be returned. The asc-function is the opposite of the chr$-function. There are valid uses for asc, however, comparing strings (i.e. to bring them into alphabetical sequence) is not among them; in such many cases you might consider to compare strings directly with <, = and > (rather than converting a string to a number and comparing this number).

Example

+input "Please enter a letter between 'a' and 'y': " a$
+if (a$<"a" or a$>"y") print a$," is not in the proper range":end
+print "The letter after ",a$," is ",chr$(asc(a$)+1)
+          

See also

chr$

asin()

Name

asin() — returns the arcus sine of its numeric argument

Synopsis

angle=asin(x)

Description

The acos is the arcus sine-function, i.e. the inverse of the sin-function. Or, more elaborate: It Returns the angle (in radian, not degree !), which, fed to the sine-function will produce the argument passed to the asin-function.

Example

+print asin(0.5),asin(sin(pi))
+          

This will print 0.523599 -2.06823e-13 which is π and almost 0 respectively.

See also

sin, acos

at()

Name

at() — can be used in the print-command to place the output at a specified position

Synopsis

+clear screen
+…
+print at(a,b)
+print @(a,b)
+

Description

The at-clause takes two numeric arguments (e.g. at(2,3)) and can be inserted after the print-keyword. at() can be used only if clear screen has been executed at least once within the program (otherwise you will get an error).

The two numeric arguments of the at-function may range from 0 to the width of your terminal minus 1, and from 0 to the height of your terminal minus 1; if any argument exceeds these values, it will be truncated accordingly. However, yabasic has no influence on the size of your terminal (80x25 is a common, but not mandatory), the size of your terminal and the maximum values acceptable within the at-clause may vary. To get the size of your terminal you may use the peek-function: peek("screenwidth") returns the width of your terminal and peek("screenheight") its height.

Example

+clear screen
+maxx=peek("screenwidth")-1:maxy=peek("screenheight")-1
+for x=0 to maxx
+  print at(x,maxy*(0.5+sin(2*pi*x/maxx)/2)) "*"
+next x
+          

This example plots a full period of the sine-function across the screen.

atan()

Name

atan() — returns the arcus tangens of its numeric argument

Synopsis

+angle=atan(a,b)
+angle=atan(a)
+

Description

The atan is the arcus-tangens-function, i.e. the inverse of the tan-function. Or, more elaborate: It Returns the angle (in radian, not degree !), which, fed to the tan-function will produce the argument passed to the atan-function.

The atan-function has a second form, which accepts two arguments: atan(a,b) which is (mostly) equivilantly to atan(a/b) except for the fact, that the two-argument-form returns an angle in the range -π to π, whereas the one-argument-form returns an angle in the range -π/2 to π/2. To understand this you have to be good at math.

Example

+print atan(1),atan(tan(pi)),atan(-0,-1),atan(-0,1)
+          

This will print 0.463648 2.06823e-13 -3.14159 3.14159 which is π/4, almost 0, -π and π respectively.

See also

tan, sin

B

Table of Contents

beep - ring the bell within your computer; a synonym for bell
bell - ring the bell within your computer (just as beep)
bin$() - converts a number into a sequence of binary digits
bind() - Binds a yabasic-program and the yabasic-interpreter together into a standalone program.
box - draw a rectancle. A synonym for rectangle
break - breaks out of a switch statement or a loop

beep

Name

beep — ring the bell within your computer; a synonym for bell

Synopsis

beep

Description

The bell-command rings the bell within your computer once. This command is not a sound-interface, so you can neither vary the length or the height of the sound (technically, it just prints \a). bell is exactly the same as beep.

Example

+beep:print "This is a problem ..."
+          

See also

beep

bell

Name

bell — ring the bell within your computer (just as beep)

Synopsis

bell

Description

The beep-command rings the bell within your computer once. beep is a synonym for bell.

Example

+print "This is a problem ...":beep
+          

See also

bell

bin$()

Name

bin$() — converts a number into a sequence of binary digits

Synopsis

hexadecimal$=bin$(decimal)

Description

The bin$-function takes a single numeric argument an converts it into a string of binary digits (i.e. zeroes and ones). If you pass a negative number to bin$, the resulting string will be preceeded by a '-'.

If you want to convert the other way around (i.e. from binary to decimal) you may use the dec-function.

Example

+for a=1 to 100
+  print bin$(a)
+next a
+          

This example prints the binary representation of all digits between 1 and 100.

See also

hex$, dec

bind()

Name

bind() — Binds a yabasic-program and the yabasic-interpreter together into a standalone program.

Synopsis

bind("foo.exe")

Description

The bind-command combines your own yabasic-program (plus all the libraries it does import) and the interpreter by copying them into a new file, whose name is passed as an argument. This new program may then be executed on any computer, even if it does not have yabasic installed.

Please see the section about creating a standalone-program for details.

Example

+if (!peek("isbound")) then
+  bind "foo"
+  print "Successfully created the standalone executable 'foo' !"
+  exit
+endif
+
+print "Hello World !"
+          

This example creates a standalone program foo from itself.

See also

The section about creating a standalone-program, the peek-function and the commandline options for Unix and Windows.

box

Name

box — draw a rectancle. A synonym for rectangle

Synopsis

+See the rectangle-command.
+

Description

The box-command does exactly the same as the rectangle-command; it is just a synonym. Therefore you should refer to the entry for the rectangle-command for further information.

break

Name

break — breaks out of a switch statement or a loop

Synopsis

break

Description

break transfers control immediately outside the enclosing loop or switch statement. This is the preferred way of leaving a such a statement (rather than goto, which is still possible in most cases).

Example

+for a=1 to 10
+  break
+  print "Hi"
+next a
+
+while(1)
+  break
+  print "Hi"
+wend
+
+repeat
+  break
+  print "Hi"
+until(0)
+
+switch 1
+case 1:break
+case 2:case 3:print "Hi"
+end switch
+          

This example prints nothing at all, because each of the loops (and the switch-statement) does an immediate break (before it could print any "Hi").

See also

for, while, repeat and switch.

C

Table of Contents

case - mark the different cases within a switch-statement
chr$() - accepts a number and returns the character at this position within the ascii charset
circle - draws a circle in the graphic-window
clear - Erase circles or rectangles
clear screen - erases the text window
clear window - clear the graphic window and begin a new page, if prining is under way
close - close a file, which has been opened before
close curve - close a curve, that has been drawn by the line-command
close printer - stops printing of graphics
close window - close the graphics-window
color - print with color
colour - see color
compile - compile a string with yabasic-code on the fly
continue - start the next iteration of a for-, do-, repeat- or while-loop
cos() - return the cosine of its single argument

case

Name

case — mark the different cases within a switch-statement

Synopsis

+switch a
+  case 1
+  case 2
+  …
+end switch
+
+…
+
+switch a$
+  case "a"
+  case "b"
+  …
+end switch
+

Description

Please see the switch-statement.

Example

+input a
+switch(a)
+  case 1:print "one":break
+  case 2:print "two":break
+  default:print "more"
+end switch
+          

Depending on your input (a number is expected) this code will print one or two or otherwise more.

See also

switch

chr$()

Name

chr$() — accepts a number and returns the character at this position within the ascii charset

Synopsis

character$=chr$(ascii)

Description

The chr$-function is the opposite of the asc-function. It looks up and returns the character at the given position within the ascii-charset. It's typical use is to construct nonprintable characters which do not occur on your keyboard.

Nevertheless you won't use chr$ as often as you might think, because the most important nonprintable characters can be constructed using escape-sequences using the \-character (e.g. you might use \n instead of chr$(10) wherever you want to use the newline-character).

Example

+print "a",chr$(10),"b"
+          

This will print the letters 'a' and 'b' in different lines because of the intervening newline-character, which is returned by chr$(10).

See also

asc

circle

Name

circle — draws a circle in the graphic-window

Synopsis

+circle x,y,r
+clear circle x,y,r
+fill circle x,y,r
+clear fill circle x,y,r
+

Description

The circle-command accepts three parameters: The x- and y-coordinates of the center and the radius of the circle.

Some more observations related with the circle-command:

  • The graphic-window must have been opened already.

  • The circle may well extend over the boundaries of the window.

  • If you have issued open printer before, the circle will finally appear in the printed hardcopy of the window.

  • fill circle will draw a filled (with black ink) circle.

  • clear circle will erase (or clear) the outline of the circle.

  • clear fill circle or fill clear circle will erase the full area of the circle.

Example

+open window 200,200
+
+for n=1 to 2000
+  x=ran(200)
+  y=ran(200)
+  fill circle x,y,10
+  clear fill circle x,y,8
+next n
+          

This code will open a window and draw 2000 overlapping circles within. Each circle is drawn in two steps: First it is filled with black ink (fill circle x,y,10), then most of this circle is erased again (clear fill circle x,y,8). As a result each circle is drawn with an opaque white interior and a 2-pixel outline (2-pixel, because the radii differ by two).

clear

Name

clear — Erase circles or rectangles

Synopsis

+clear rectangle 10,10,90,90
+clear fill circle 50,50,20
+

Description

May be used within the circle or rectangle command and causes these shapes to be erased (i.e. be drawn in the colour of the background).

fill can be used in conjunction with and whereever the fill-clause may appear. Used alone, clear will erase the outline (not the interior) of the shape (circle or rectangle); together with fill the whole shape (including its interior) is erased.

Example

+open window 200,200
+fill circle 100,100,50
+clear fill rectangle 10,10,90,90
+          

This opens a window and draws a pacman-like figure.

clear screen

Name

clear screen — erases the text window

Synopsis

+clear screen
+

Description

clear screen erases the text window (the window where the output of print appears).

It must be issued at least once, before some advanced screen-commands (e.g. print at or inkey$) may be called; this requirement is due to some limititations of the curses-library, which is used by yabasic under Unix for some commands.

Example

+clear screen
+print "Please press a key : ";
+a$=inkey$
+print a$
+          

The clear screen command is essential here; if it would be omitted, yabasic would issue an error ("need to call 'clear screen' first") while trying to execute the inkey$-function.

See also

inkey$

clear window

Name

clear window — clear the graphic window and begin a new page, if prining is under way

Synopsis

clear window

Description

clear window clears the graphic window. If you have started prining the graphic via open printer, the clear window-command starts a new page as well.

Example

+open window 200,200
+open printer "t.ps"
+
+for a=1 to 10
+if (a>1) clear window
+text 100,100,"Hallo "+str$(a)
+next a
+
+close printer
+close window
+          

This example prints 10 pages, with the text "Hello 1", "Hello 2", … and so on. The clear screen-command clears the graphics window and starts a new page.

close

Name

close — close a file, which has been opened before

Synopsis

+close filenum
+close # filenum
+

Description

The close-command closes an open file. You should issue this command as soon as you are done with reading from or writing to a file.

Example

+open "my.data" for reading as 1
+input #1 a
+print a
+close 1
+          

This program opens the file "my.data", reads a number from it, prints this number and closes the file again.

See also

open

close curve

Name

close curve — close a curve, that has been drawn by the line-command

Synopsis

+new curve
+line to x1,y1
+…
+close curve
+

Description

The close curve-command closes a sequence of lines, that has been drawn by repeated line to-commands.

Example

+open window 200,200
+new curve
+line to 100,50
+line to 150,150
+line to 50,150
+close curve
+          

This example draws a triangle: The three line to-commands draw two lines; the final line is however not drawn explicitly, but drawn by the close curve-command.

See also

line, new curve

close printer

Name

close printer — stops printing of graphics

Synopsis

close printer

Description

The close printer-command ends the printing graphics. Between open printer and close printer everything you draw (e.g. circles, lines …) is sent to your printer. close printer puts an end to printing and will make your printer eject the page.

Example

+open window 200,200
+open printer
+circle 100,100,50
+close printer
+close window
+          

As soon as close printer is executed, your printer will eject a page with a circle on it.

See also

open printer

close window

Name

close window — close the graphics-window

Synopsis

close window

Description

The close window-command closes the graphics-window, i.e. it makes it disappear from your screen. It includes an implicit close printer, if a printer has been opened previously.

Example

+open window 200,200
+circle 100,100,50
+close window
+          

This example will open a window, draw a circle and close the window again; all this without any pause or delay, so the window will be closed before you may regard the circle..

See also

open window

color

Name

color — print with color

Synopsis

+print color(fore$) text$
+print color(fore$,back$) text$
+

Description

Not a seperate command, but part of the print-command; may be included just after print and can only be issued after clear screen has been executed.

color() takes one or two string-arguments, specifying the color of the text and (optionally) the background.

The one or two strings passed to color() can be one of these: "black", "white", "red", "blue", "green", "yellow", "cyan" and "magenta" (which can be abbreviated as "bla", "whi", "red", "blu", "gre", "yel", "cya" and "mag" respectively).

color() can only be used, if clear scren has been issued at least once.

Note, that color() can be written as colour() too.

Example

+clear screen
+dim col$(7):for a=0 to 7:read col$(a):next a
+do
+  print color(col$(ran(7)),col$(ran(7))) " Hallo ";
+  pause 0.01
+loop
+data "black","white","red","blue"
+data "green","yellow","cyan","magenta"
+          

This prints the word " Hallo " in all colors accross your screen.

colour

Name

colour — see color

Synopsis

+print colour(fore$) text$
+print colour(fore$,back$) text$
+

See also

color

compile

Name

compile — compile a string with yabasic-code on the fly

Synopsis

compile(code$)

Description

This is an advanced command (closely related with the execute-command). It allows you to compile a string of yabasic-code (which is the only argument). Afterwards the compiled code is a normal part of your program.

Note, that there is no way to remove the compiled code.

Example

+compile("sub mysub(a):print a:end sub")
+mysub(2)
+          

This example creates a function named mysub, which simply prints its single argument.

See also

execute

continue

Name

continue — start the next iteration of a for-, do-, repeat- or while-loop

Synopsis

continue

Description

You may use continue within any loop to start the next iteration immediately. Depending on the type of the loop, the loop-condition will or will not be checked. Especially: for- and while-loops will evaluate their respective conditions, do- and repeat-loops will not.

Remark: Another way to change the flow of execution within a loop, is the break-command.

Example

+for a=1 to 100
+  if mod(a,2)=0 continue
+  print a
+next a
+          

This example will print all odd numbers between 1 and 100.

See also

for, do, repeat, while, break

cos()

Name

cos() — return the cosine of its single argument

Synopsis

+x=cos(angle)
+

Description

The cos-function expects an angle (in radian) and returns its cosine.

Example

+print cos(pi)
+          

This example will print -1.

See also

acos, sin

D

Table of Contents

data - introduces a list of data-items
date$ - returns a string with various components of the current date
dec() - convert a base 2 or base 16 number into decimal form
default - mark the default-branch within a switch-statement
dim - create an array prior to its first use
do - start a (conditionless) do-loop
doc - special comment, which might be retrieved by the program itself
docu$ - special array, containing the contents of all docu-statement within the program
dot - draw a dot in the graphic-window

data

Name

data — introduces a list of data-items

Synopsis

+data 9,"world"
+…
+read b,a$
+

Description

The data-keyword introduces a list of comma-seperated list of strings or numbers, which may be retrieved with the read-command.

The data-command itself does nothing; it just stores data. A single data-command may precede an arbitrarily long list of values, in which strings or numbers may be mixed at will.

yabasic internally uses a data-pointer to keep track of the current location within the data-list; this pointer may be reset with the restore-command.

Example

+do
+  restore
+  for a=1 to 4
+    read num$,num
+    print num$,"=",num
+  next a
+loop
+data "eleven",11,"twelve",12,"thirteen",13,"fourteen",14
+          

This example just prints a series of lines eleven=11 up to fourteen=14 and so on without end.

The restore-command ensures that the list of data-items is read from the start with every iteration.

See also

read, restore

date$

Name

date$ — returns a string with various components of the current date

Synopsis

a$=date$

Description

The date$-function (which must be called without parantheses; i.e. date$() would be an error) returns a string containing various components of a date; an example would be 4-05-27-2004-Thu-May. This string consists of various fields seperated by hyphens ("-"):

  • The day within the week as a number in the range 0 (=sunday) to 6 (=saturday) (in the example above: 4, i.e. thursday).

  • The month as a number in the range 1 (=january) to 12 (=december) (in the example: 5 which stands for may).

  • The day within the month as a number in the range 1 to 31 (in the example: 27).

  • The full, 4-digit year (in the example: 2004, which reminds me that I should adjust the clock within my computer …).

  • The abbreviated name of the day within the week (Mon to Sun).

  • The abbreviated name of the month (Jan to Dec).

Therefore the whole example above (4-05-27-2004-Thu-May) would read: day 4 in the week (counting from 0), May 27 in the year 2004, which is a thursday in May.

Note, that all fields within the string returned by date$ have a fixed with (numbers are padded with zeroes); therefore it is easy to extract the various fields of a date format with mid$.

Example

+rem   Two ways to print the same ...
+
+print mid$(date$,3,10)
+
+dim fields$(6)
+a=split(date$,fields$(),"-")
+print fields$(2),"-",fields$(3),"-",fields$(4)
+          

This example shows two different techniques to extract components from the value returned by date$. The mid$-function is the preferred way, but you could just as well split the return-value of date$ at every "-" and store the result within an array of strings.

See also

time$

dec()

Name

dec() — convert a base 2 or base 16 number into decimal form

Synopsis

+a=dec(number$)
+a=dec(number$,base)
+

Description

The dec-function takes the string-representation of a base-2 or base-16 (which is the default) number and converts it into a decimal number. The optional second argument (base) might be used to specify a base other than 16. However, currently only base 2 or base 16 are supported.

Example

+input "Please enter a binary number: " a$
+print a$," is ",dec(a$)
+          

See also

bin$, hex$

default

Name

default — mark the default-branch within a switch-statement

Synopsis

+switch a+3
+case 1
+  …
+case 2
+  …
+default
+  …
+end switch
+

Description

The default-clause is an optional part of the switch-statement (see there for more information). It introduces a series of statements, that should be executed, if none of the casese matches, that have been specified before (each with its own case-clause).

So default specifies a default to be executed, if none of the explicitly named cases matches; hence its name.

Example

+print "Please enter a number between 0 and 6,"
+print "specifying a day in the week."
+input d
+switch d
+case 0:print "Monday":break
+case 1:print "Tuesday":break
+case 2:print "Wednesday":break
+case 3:print "Thursday":break
+case 4:print "Friday":break
+case 5:print "Saturday":break
+case 6:print "Sunday":break
+default:print "Hey you entered something invalid !"
+end switch
+          

This program translates a number between 0 and 6 into the name of a weekday; the default-case is used to detect (and complain about) invalid input.

See also

sub, case

dim

Name

dim — create an array prior to its first use

Synopsis

+dim array(x,y)
+dim array$(x,y)
+

Description

The dim-command prepares one or more arrays (of either strings or numbers) for later use. This command can also be used to enlarges an existing array.

When an array is created with the dim-statement, memory is allocated and all elements are initialized with either 0 (for numerical arrays) or "" (for string arrays).

If the array already existed, and the dim-statement specifies a larger size than the current size, the array is enlarged and any old content is preserved.

Note, that dim cannot be used to shrink an array: If you specify a size, that is smaller than the current size, the dim-command does nothing.

Finally: To create an array, that is only known within a single subroutine, you should use the command local, which creates local variables as well as local arrays.

Example

+dim a(5,5)
+for x=1 to 5:for y=1 to 5
+  a(x,y)=int(ran(100))
+next y:next x
+printmatrix(a())
+dim a(7,7)
+printmatrix(a())
+
+sub printmatrix(ar())
+  local x,y,p,q
+  x=arraysize(ar(),1)
+  y=arraysize(ar(),2)
+  for q=1 to y
+    for p=1 to y
+      print ar(p,q),"\t";
+    next p
+    print
+  next q
+end sub
+          

This example creates a 2-dimenional array (i.e. a matrix) with the dim-statement and fills it with random numbers. The second dim-statement enlarges the array, all new elements are filled with 0.

The subroutine printmatrix just does, what its name says.

do

Name

do — start a (conditionless) do-loop

Synopsis

+do 
+… 
+loop

Description

Starts a loop, which is terminated by loop; everything between do and loop will be repeated forever. This loop has no condition, so it is an infinite loop; note however, that a break- or goto-statement might be used to leave this loop anytime.

Example

+do
+  a=a+1
+  print a
+  if (a>100) break
+loop
+          

This example prints the numbers between 1 and 101. The break-statement is used to leave the loop.

See also

loop, repeat, while, break

doc

Name

doc — special comment, which might be retrieved by the program itself

Synopsis

+doc   This is a comment
+docu  This is another comment
+

Description

Introduces a comment, which spans up to the end of the line. But other than the rem-comment, any docu-comment is collected within the special docu$-array and might be retrieved later on. Moreover you might invoke yabasic -docu foo.yab on the commandline to retrieve the embedded documentation within the program foo.yab.

Instead of doc you may just as well write docu or even documentation.

Example

+rem   Hi, this has been written by me
+rem
+doc   This program asks for a number and
+doc   prints this number multiplied with 2
+rem
+rem   Print out rhe above message
+for a=1 to arraysize(docu$()):print docu$(a):next a
+
+rem   Read and print the number
+input "Please input a number: " x
+print x*2
+          

This program uses the comments within its code to print out a help message for the user.

The contents of the doc-lines are retrieved from the docu$-array; if you do not want a comment to be collected within this array, use the rem-statement instead.

See also

docu$, rem

docu$

Name

docu$ — special array, containing the contents of all docu-statement within the program

Synopsis

a$=docu$(1)

Description

Before your program is executed, yabasic collects the content of all the doc-statements within your program within this 1-dimensional array (well only those within the main-program, libraries are skipped).

You may use the arraysize function to find out, how many lines it contains.

Example

+docu
+docu  This program reads two numbers 
+docu  and adds them.
+docu
+
+rem retrieve and print the embedded documentation
+for a=1 to arraysize(docu$(),1)
+  print docu$(a)
+next a
+
+input "First number: " b
+input "Second number: " c
+
+print "The sum of ",b," and ",c," is ",b+c
+          

This program uses the embedded documentation to issue a usage-message.

See also

arraydim, rem

dot

Name

dot — draw a dot in the graphic-window

Synopsis

+dot x,y
+clear dot x,y
+

Description

Draws a dot at the specified coordinates within your graphic-window. If printing is in effect, the dot appears on your printout too.

Use the functions peek("winheight") or peek("winwidth") to get the size of your window and hence the boundaries of the coordinates specified for the dot-command.

Example

+open window 200,200
+circle 100,100,100
+do
+  x=ran(200):y=ran(200)
+  dot x,y
+  total=total+1
+  if (sqrt((x-100)^2+(y-100)^2)<100) in=in+1
+  print 4*in/total
+loop
+          

This program uses a well known algorithm to compute π.

See also

line, open window

E

Table of Contents

else - mark an alternative within an if-statement
elsif - starts an alternate condition within an if-statement
end - terminate your program
endif - ends an if-statement
end sub - ends a subroutine definition
eof - check, if an open file contains data
eor() - compute the bitwise exclusive or of its two arguments
error - raise an error and terminate your program
euler - another name for the constant 2.71828182864
execute$() - execute a user defined subroutine, which must return a string
execute() - execute a user defined subroutine, which must return a number
exit - terminate your program
exp() - compute the exponential function of its single argument
export - mark a function as globally visible

else

Name

else — mark an alternative within an if-statement

Synopsis

+if (…) then 
+  … 
+else 
+  … 
+endif
+

Description

The else-statement introduces the alternate branch of an if-statement. I.e. it starts the sequence of statements, which is executed, if the condition of the if-statement is not true.

Example

+input "Please enter a number: " a
+if (mod(a,2)=1) then
+  print a," is odd."
+else
+  print a," is even."
+endif
+          

This program detects, if the number you have entered is even or odd.

See also

if

elsif

Name

elsif — starts an alternate condition within an if-statement

Synopsis

+if (…) then
+  …
+elseif (…) 
+  …
+elsif (…) then
+  …
+else
+  …
+endif
+

Description

The elsif-statement is used to select a single alternative among a series of choices.

With each elsif-statement you may specify a condition, which is tested, if the main condition (specified with the if-statement) has failed. Note that elsif might be just as well written as elseif.

Within the example below, two variables a and b are tested against a range of values. The variable a is tested with the elsif-statement. The very same tests are performed for the variable b too; but here an involved series of if-else-statements is employed, making the tests much more obscure.

Example

+input "Please enter a number: " a
+if (a<0) then
+  print "less than 0"
+elseif (a<=10) then
+  print "between 0 and 10"
+elsif (a<=20)
+  print "between 11 and 20"
+else
+  print "over 20"
+endif
+
+input "Please enter another number: " b
+if (b<0) then
+  print "less than 0"
+else
+  if (b<=10) then
+    print "between 0 and 10"
+  else
+    if (b<=20) then
+      print "between 11 and 20"
+    else
+      print "over 20"
+    endif
+  endif
+endif
+          

Note, that the very same tests are performed for the variables a and b, but can be stated much more clearly with the elsif-statement.

Note, that elsif might be written as elseif too, and that the keyword then is optional.

See also

if, else

end

Name

end — terminate your program

Synopsis

+end
+

Description

Terminate your program. Much (but not exactly) like the exit command.

Note, that end may not end your program immediately; if you have opened a window or called clear screen, yabasic assumes, that your user wants to study the output of your program after it has ended; therfore it issues the line ---Program done, press RETURN--- and waits for a key to be pressed. If you do not like this behaviour, consider using exit.

Example

+print "Do you want to continue ?"
+input "Please answer y(es) or n(o): " a$
+if (lower$(left$(a$,1))="n") then
+  print "bye"
+  end
+fi
+          

See also

exit

endif

Name

endif — ends an if-statement

Synopsis

+if (…) then
+  …
+endif
+

Description

The endif-statement closes (or ends) an if-statement.

Note, that endif may be written in a variety of other ways: end if, end-if or even fi.

The endif-statement must be omitted, if the if-statement does not contain the keyword then (see the example below). Such an if-statement without endif extends only over a single line.

Example

+input "A number please: " a
+if (a<10) then
+  print "Your number is less than 10."
+endif
+
+REM  and now without endif 
+
+input "A number please: " a
+if (a<10) print "Your number is less than 10."
+          

See also

if

end sub

Name

end sub — ends a subroutine definition

Synopsis

+sub foo(…) 
+  …
+end sub
+

Description

Marks the end of a subroutine-definition (which starts with the sub-keyword). + The whole concept of subroutines is explained within the entry for sub. +

Example

+print foo(3)
+
+sub foo(a)
+  return a*2
+end sub
+          

This program prints out 6. The subroutine foo simply returns twice its argument.

See also

sub

eof

Name

eof — check, if an open file contains data

Synopsis

+open 1,"foo.bar"
+if (eof(1)) then 
+   …
+end if
+

Description

The eof-function checks, if there is still data left within an open file. As an argument it expects the file-number as returned by (or used within) the open-function (or statement).

Example

+a=open("foo.bar")
+while(not eof(a)) 
+  input #a,a$
+  print a$
+end while
+          

This example will print the contents of the file "foo.bar". The eof-function will terminate the loop, if there is no more data left within the file.

See also

open

eor()

Name

eor() — compute the bitwise exclusive or of its two arguments

Synopsis

print eor(a,b)

Description

The eor-function takes two arguments and computes their bitwise exclusive or. See your favorite introductory text on informatics for an explanation of this function.

The xor-function is the same as the eor function; both are synonymous; however they have each their own description, so you may check out the entry of xor for a slightly different view.

Example

+for a=0 to 3
+  for b=0 to 3
+    print fill$(bin$(a))," eor ",fill$(bin$(b))," = ",fill$(bin$(eor(a,b)))
+  next b
+next a
+
+sub fill$(a$)
+  return right$("0"+a$,2)
+end sub
+          

This example prints a table, from which you may figure, how the eor-function is computed.

See also

and, or

error

Name

error — raise an error and terminate your program

Synopsis

error "Wrong, wrong, wrong !!"

Description

Produces the same kind or error messages, that yabasic itself produces (e.g. in case of a syntax-error). The single argument is issued along with the current line-number.

Example

+input "Please enter a number between 1 and 10: " a
+if (a<1 or a>10) error "Oh no ..."
+          

This program is very harsh in checking the users input; instead of just asking again, the program terminates with an error, if the user enters something wrong.

The error message would look like this:

+---Error in t.yab, line 2: Oh no ...
+---Error: Program stopped due to an error
+

See also

Well, there should be a corresponding called warning; unfortunately ther is none yet.

euler

Name

euler — another name for the constant 2.71828182864

Synopsis

foo=euler

Description

euler is the well known constant named after Leonard Euler; its value is 2.71828182864. euler is not a function, so parens are not allowed (i.e. euler() will produce an error). Finally, you may not assign to euler; it wouldn't sense anyway, because it is a constant.

Example

+print euler
+          

See also

pi

execute$()

Name

execute$() — execute a user defined subroutine, which must return a string

Synopsis

print execute$("foo$","arg1","arg2")

Description

execute$ can be used to execute a user defined subroutine, whose name may be specified as a string expression.

This feature is the only way to execute a subroutine, whose name is not known by the time you write your program. This might happen, if you want to execute a subroutine, which is compiled (using the compile command) during the course of execution of your program.

Note however, that the execute$-function is not the preferred method to execute a user defined subroutine; almost all cases you should just execute a subroutine by writing down its name within your yabasic program (see the example).

Example

+print execute$("foo$","Hello","world !")
+sub foo$(a$,b$)
+  return a$+" "+b$
+end sub
+          

The example simply prints Hello world !, which is the return value of the user defined subroutine foo$. The same could be achieved by executing:

+print foo$(a$,b$)
+

See also

compile, execute

execute()

Name

execute() — execute a user defined subroutine, which must return a number

Synopsis

print execute("bar","arg1","arg2")

Description

The execute-function is the counterpart of the execute$-function (please see there for some caveats). execute executes subroutines, which returns a number.

Example

+print execute("bar",2,3)
+sub bar(a,b)
+  return a+b
+end sub
+          

See also

compile, execute$

exit

Name

exit — terminate your program

Synopsis

+exit
+exit 1
+

Description

Terminate your program and return any given value to the operating system. exit is similar to end, but it will terminate your program immediately, no matter what.

Example

+print "Do you want to continue ?"
+input "Please answer y(es) or n(o): " a$
+if (lower$(left$(a$,1))="n") exit 1
+          

See also

end

exp()

Name

exp() — compute the exponential function of its single argument

Synopsis

+foo=exp(bar)
+

Description

This function computes e to the power of its argument, where e is the well known euler constant 2.71828182864.

The exp-function is the inverse of the log-function.

Example

+open window 100,100
+for x=0 to 100
+   dot x,100-100*exp(x/100)/euler
+next x
+          

This program plots part of the exp-function, however the range is rather small, so that you may not recognize the function from this plot.

See also

log

export

Name

export — mark a function as globally visible

Synopsis

+export sub foo(bar)
+…
+end sub
+

Description

The export-statement is used within libraries to mark a user defined subroutine as visible outside the library wherein it is defined. Subroutines, which are not exported, must be qualified with the name of the library, e.g. foo.baz (where foo is the name of the library and baz the name of the subroutine); exported subroutines may be used without specifying the name of the library, e.g. bar.

Therefore export may only be useful within libraries.

Example

The library foo.bar (which is listed below) defines two functions bar and baz, however only the function bar is exported and therefore visible even outside the library; baz is not exported and may only be used within the library foo.yab:

+export sub bar()
+  print "Hello"
+end sub
+
+sub baz()
+  print "World"
+end sub
+          

Now within your main program cux.yab (which imports the library foo.yab); note that this program produces an error:

+import foo
+
+print "Calling subroutine foo.bar (okay) ..."
+foo.bar()
+print "done."
+
+print "Calling subroutine bar (okay) ..."
+bar()
+print "done."
+
+print "Calling subroutine foo.baz (okay) ..."
+foo.baz()
+print "done."
+
+print "Calling subroutine baz (NOT okay) ..."
+baz()
+print "done."
+
+

The output when executing yabasic foo.yab is this:

+Calling subroutine foo.bar (okay) ...
+Hello
+done.
+Calling subroutine bar (okay) ...
+Hello
+done.
+Calling subroutine foo.baz (okay) ...
+World
+done.
+Calling subroutine baz (NOT okay) ...
+---Error in main.yab, line 16: can't find subroutine 'baz'
+---Dump: sub baz() called in main.yab,16
+---Error: Program stopped due to an error
+

As the error message above shows, the subroutine baz must be qualified with the name of the library, if used outside the library, wherein it is defined (e.g. foo.baz. I.e. outside the library foo.yab you need to write foo.baz. baz alone would be an error.

The subroutine bar (without adding the name of the library) however may (and probably should) be used in any program, which imports the library foo.yab.

Note

In some sense the set of exported subroutines constitutes the interface of a library.

See also

sub, import

F

Table of Contents

false - a constant with the value of 0
fi - another name for endif
fill - draw a filled circles or rectangles
for - starts a for-loop
frac() - return the fractional part of its numeric argument

false

Name

false — a constant with the value of 0

Synopsis

+okay=false
+

Description

The constant false can be assigned to variables which later appear in conditions (e.g. within an if-statement.

false may also be written as FALSE or even FaLsE.

Example

+input "Please enter a number between 1 and 10: " a
+if (check_input(a)) print "Okay"
+
+sub check_input(x)
+  if (x>10 or x<1) return false
+  return true
+end sub
+          

The subroutine check_input checks its argument and returns true or false according to the outcome of the check..

See also

true

fi

Name

fi — another name for endif

Synopsis

+if (…)
+…
+fi
+

Description

fi marks the end of an if-statement and is exactly equivilent to endif, please see there for further information.

Example

+input "A number please: " a
+if (a<10) then
+  print "Your number is less than 10."
+fi
+          

See also

endif

fill

Name

fill — draw a filled circles or rectangles

Synopsis

+fill rectangle 10,10,90,90
+fill circle 50,50,20
+

Description

The keyword fill may be used within the circle or rectangle command and causes these shapes to be filled.

fill can be used in conjunction with and whereever the clear-clause may appear. Used alone, fill will fill the interior of the shape (circle or rectangle); together with clear the whole shape (including its interior) is erased.

Example

+open window 200,200
+fill circle 100,100,50
+clear fill rectangle 10,10,90,90
+          

This opens a window and draws a pacman-like figure.

for

Name

for — starts a for-loop

Synopsis

+for a=1 to 100 step 2
+  …
+next a
+

Description

The for-loop lets its numerical variable (a in the synopsis) assume all values within the given range. The optional step-clause may specify a value (default: 1) by which the variable will be incremented (or decremented, if step is negative).

Any for-statement can be replaced by a set of ifs and gotos; as you may infer from the example below this is normally not feasable. However if you want to know in detail how the for-statement works, you should study this example, which presents a for-statement and an exactly equivilant series of ifs and gotos.

Example

+for a=1 to 10 step 2:print a:next 
+
+a=1
+label check
+if (a>10) goto done
+  print a
+  a=a+2
+goto check
+label done
+          

This example simply prints the numbers 1, 3, 5, 7 and 9. It does this twice: First with a simple for-statment and then with ifs and gotos.

See also

step, next

frac()

Name

frac() — return the fractional part of its numeric argument

Synopsis

+x=frac(y)
+

Description

The frac-function takes its argument, removes all the digits to the left of the comma and just returns the digits right of the comma, i.e. the fractional part.

Refer to the example to learn how to rewrite frac by employing the int-function.

Example

+for a=1 to 10
+  print frac(sqr(a))
+  print sqr(a)-int(sqr(a))
+next a
+          

The example prints the fractional part of the square root of the numbers between 1 and 10. Each result is computed (and printed) twice: Once by employing the frac-function and once by employing the int-function.

See also

int

G

Table of Contents

getbit$() - return a string representing the bit pattern of a rectangle within the graphic window
getscreen$() - returns a string representing a rectangular section of the text terminal
glob() - check if a string matches a simple pattern
gosub - continue execution at another point within your program (and return later)
goto - continue execution at another point within your program (and never come back)

getbit$()

Name

getbit$() — return a string representing the bit pattern of a rectangle within the graphic window

Synopsis

+a$=getbit$(10,10,20,20)
+a$=getbit$(10,10 to 20,20)
+

Description

The function getbit returns a string, which contains the encoded bit-pattern of a rectangle within graphic window; the four arguments represent the borders of the rectangle. The string returned might later be fed to the putbit-command.

The getbit$-function might be used for simple animations (as in the example below).

Example

+open window 40,40
+fill circle 20,20,18
+circle$=getbit$(0,0,40,40)
+close window
+
+open window 200,200
+for x=1 to 200
+  putbit circle$,x,80
+next x
+          

This example features a circle moving from left to right over the window.

See also

putbit

getscreen$()

Name

getscreen$() — returns a string representing a rectangular section of the text terminal

Synopsis

+a$=getscreen$(2,2,20,20)
+

Description

The getscreen$ function returns a string representing the area of the screen as specified by its four arguments (which specify two corners). I.e. everything you have printed within this rectangle will be encoded in the string returned (including any colour-information).

Like most other commands dealing with advanced text output, getscreen$ requires, that you have called clear screen before.

Example

+clear screen
+
+for a=1 to 1000:
+	print color("red") "1";
+	print color("green") "2";
+	print color("blue") "3";
+next a  
+screen$=getscreen$(10,10,40,10)
+print at(10,10) " Please Press 'y' or 'n' ! "
+a$=inkey$
+putscreen screen$,10,10
+          

This program fills the screen with coloured digits and afterwards asks the user for a choice ( Please press 'y' or 'n' ! ). Afterwards the area of the screen, which has been overwritten by the question will be restored with its previous contents, whhch had been saved via getscreen$.

See also

putscreen$

glob()

Name

glob() — check if a string matches a simple pattern

Synopsis

+if (glob(string$,pattern$)) …
+

Description

The glob-function takes two arguments, a string and a (glob-) pattern, and checks if the string matches the pattern. However glob does not employ the powerful rules of regular expressions; rather it has only two special characters: * (which matches any number (even zero) of characters) and ? (which matches exactly a single character).

Example

+for a=1 to 10
+  read string$,pattern$
+  if (glob(string$,pattern$)) then
+    print string$," matches ",pattern$
+  else
+    print string$," does not match ",pattern$
+  endif
+next a
+
+data "abc","a*"
+data "abc","a?"
+data "abc","a??"
+data "abc","*b*"
+data "abc","*"
+data "abc","???"
+data "abc","?"
+data "abc","*c"
+data "abc","A*"
+data "abc","????"
+          

This program checks the string abc against various patterns and prints the result. The output is:

+abc matches a*
+abc does not match a?
+abc matches a??
+abc matches *b*
+abc matches *
+abc matches ???
+abc does not match ?
+abc matches *c
+abc does not match A*
+abc does not match ????
+

See also

There are no related commands.

gosub

Name

gosub — continue execution at another point within your program (and return later)

Synopsis

+gosub foo
+
+…
+
+label foo
+…
+return
+

Description

gosub remembers the current position within your program and then passes the flow of execution to another point (which is normally marked with a label). Later, when a return-statement is encountered, the execution is resumed at the previous location.

gosub is the traditional command for calling code, which needs to be executed from various places within your program. However, with subroutines yabasic offers a much more flexible way to achieve this (and more). Therefore gosub must to be considered obsolete.

Example

+print "Do you want to exit ? "
+gosub ask
+if (r$="y") exit
+
+label ask
+input "Please answer yes or no, by typing 'y' or 'n': ",r$
+return
+          

goto

Name

goto — continue execution at another point within your program (and never come back)

Synopsis

+goto foo
+
+…
+
+label foo
+

Description

The goto-statement passes the flow of execution to another point within your program (which is normally marked with a label).

goto is normally considered obsolete and harmful, however in yabasic it may be put to the good use of leaving loops (e.g. while or for) prematurely. Note however, that subroutines may not be left with the goto-statement.

Example

+print "Please press any key to continue."
+print "(program will continue by itself within 10 seconds)"
+for a=1 to 10
+  if (inkey$(1)<>"") then goto done
+next a
+label done
+print "Hello World !"
+          

Here the goto-statment is used to leave the for-loop prematurely.

See also

gosub, on goto

H

Table of Contents

hex$() - convert a number into hexadecimal

hex$()

Name

hex$() — convert a number into hexadecimal

Synopsis

+print hex$(foo)
+

Description

The hex$-function converts a number into a string with its hexadecimal representation. hex$ is the inverse of the dec-function.

Example

+open 1,"foo"
+while(!eof(1))
+  print right$("0"+hex$(peek(1)),2)," ";
+  i=i+1
+  if (mod(i,10)=0) print
+end while
+print
+          

This program reads the file foo and prints its output as a hex-dump using the hex-function.

See also

decbin

I

Table of Contents

if - evaluate a condition and execute statements or not, depending on the result
import - import a library
inkey$ - wait, until a key is pressed
input - read input from the user (or from a file) and assign it to a variable
instr() - searches its second argument within the first; returns its position if found
int() - return the integer part of its single numeric argument

if

Name

if — evaluate a condition and execute statements or not, depending on the result

Synopsis

+if (…) then
+  …
+endif
+
+if (…) …
+
+if (…) then
+  …
+else
+  …
+endif
+
+if (…) then
+  …
+elsif (…)
+  …
+elsif (…) then
+  …
+else
+  …
+endif
+

Description

The if-statement is used to evaluate a conditions and take actions accordingly. (As an aside, please note that there is no real difference between conditions and expressions.)

There are two major forms of the if-statement:

  • The one-line-form without the keyword then:

    if (…) …
    This form evaluates the condition and if the result is true executes all commands (seperated by colons) upt to the end of the line. There is neither an endif keyword nor an else-branch.

  • The multi-line-form with the keyword then:

    if (…) then … elsif (…) … else … endif
    (where elsif and else are optional, whereas endif is not.

    According to the requirements of your program, you may specify:

    • elsif(…), which specifies a condition, that will be evaluated only if the condition(s) whithin if or any preceeding elsif did not match.

    • else, which introduces a sequence of commands, that will be executed, if none of the conditions above did match.

    • endif is required and ends the if-statement.

Example

+input "Please enter a number between 1 and 4: " a
+if (a<=1 or a>=4) error "Wrong, wrong !"
+if (a=1) then
+  print "one"
+elsif (a=2)
+  print "two"
+elsif (a=3)
+  print "three"
+else
+  print "four"
+endif
+          

The input-number between 1 and 4 is simply echoed as text (one, two, …). The example demonstrates both forms (short and long) of the if-statement (Note however, that the same thing can be done, probably somewhat more elegant, with the switch-statement).

import

Name

import — import a library

Synopsis

+import foo
+

Description

The import-statment imports a library. It expects a single argument, which must be the name of a library (without the trailing .yab). This library will then be read and parsed and its subroutines (and variables) will be made available within the main program.

Libraries will first be searched within the current directory (i.e. the directory within which you have invoked yabasic), then within a special directory, whose exact location depends on your system. Typical values would be /usr/lib under Unix or C:\yabasic\lib under Windows. However only yabasic -help-usage may tell the truth. The location of this second directory may be changed with the option -library (either under Windows or Unix).

Example

Lets say you have a yabasic-program foo.yab, which imports a library lib.yab. foo.yab reads:

+import lib
+
+rem  This works ...
+lib.x(0)
+
+rem  This works too ..
+x(1)
+
+rem  And this.
+lib.y(2)
+
+rem  But this not !
+y(3)
+          

Now the library lib.yab reads:

+rem  Make the subroutine x easily available outside this library
+export sub x(a)
+  print a
+  return
+end sub
+
+rem  sub y must be referenced by its full name
+rem  outside this library
+sub y(a)
+  print a
+  return
+end sub
+

This program produces an error:

+

+0
+1
+2
+---Error in foo.yab, line 13: can't find subroutine 'y'
+---Dump: sub y() called in foo.yab,13
+---Error: Program stopped due to an error
+
+As you may see from the error message, yabasic is unable to find the subroutine y without specifying the name of the library (i.e. lib.y). The reason for this is, that y, other than x, is not exported from the library lib.yab (using the export-statement). +

See also

export, sub

inkey$

Name

inkey$ — wait, until a key is pressed

Synopsis

+clear screen
+foo$=inkey$
+inkey$
+foo$=inkey$(bar)
+inkey$(bar)
+

Description

The inkeys$-function waits, until the user presses a key on the keyboard or a button of his mouse, and returns this very key. An optional argument specifies the number of seconds to wait; if omitted, inkey$ will wait indefinitely.

inkey$ may only be used, if clear screen has been called at least once.

For normal keys, yabasic simply returns the key, e.g. a, 1 or !. For function keys you will get f1, f2 and so on. Other special keys will return these strings respectively: enter, backspace, del, esc, scrnup (for screen up), scrndown and tab. Modifier keys (e.g. ctrl, alt or shift) by themself can not be detected (however, if you press shift and e.g. a simultaniously, inkey$ will return the letter A instead of a of course).

If a graphical window has been opened (via open window) any mouseclick within this window will be returned by inkey$ too. The string returned (e.g. MB1d+0:0028,0061, MB2u+0:0028,0061 or MB1d+1:0028,0061) is constructed as follows:

  • Every string associated with a mouseclick will start with the fixed string MB

  • The next digit (1, 2 or 3) specifies the mousebutton pressed.

  • A single letter, d or u, specifies, if the mousebutton has been pressed or released: d stands for down, i.e. the mousebutton has been pressed; u means up, i.e. the mousebutton has been released.

  • The plus-sign ('+'), which follows is always fixed.

  • The next digit (in the range 0 to 7) encodes the modifier keys pressed, where 1 stands for shift, 2 stands for alt and 4 stands for ctrl.

  • The next four digits (e.g. 0028) contain the x-position, where the mousebutton has been pressed.

  • The comma to follow is always fixed.

  • The last four digits (e.g. 0061) contain the y-position, where the mousebutton has been pressed.

All those fields are of fixed length, so you may use functions like mid$ to extract certain fields. However, note that with mousex, mousey, mouseb and mousemod there are specialized functions to return detailed information about the mouseclick. Finally it should be noted, that inkey$ will only register mouseclicks within the graphic-window; mouseclicks in the text-window cannot be detected.

inkey$ accepts an optional argument, specifying a timeout in seconds; if no key has been pressed within this span of time, an empty string is returned. If the timeout-argument is omitted, inkey$ will wait for ever.

Example

+clear screen
+open window 100,100
+print "Press any key or press 'q' to stop."
+repeat
+  a$=inkey$
+  print a$
+until(a$="q")
+          

This program simply returns the key pressed. You may use it, to learn, which strings are returned for the special keys on your keyboard (e.g. function-keys).

input

Name

input — read input from the user (or from a file) and assign it to a variable

Synopsis

+input a
+input a,b,c
+input a$
+input "Hello" a
+input #1 a$
+

Description

input reads the new contents of one or many (numeric- or string-) variables, either from the keyboard (i.e. from you) or from a file. An optional first string-argument specifies a prompt, which will be issued before reading any contents.

If you want to read from an open file, you need to specify a hash ('#'), followed by the number, under which the file has been opened.

Note, that the input is split at spaces, i.e. if you enter a whole line consisting of many space-seperated word, the first input-statement will only return the first word; the other words will only be returned on subsequent calls to input; the same applies, if a single input reads multiple variables: The first variable gets only the first word, the second one the second word, and so on. If you don't like this behaviour, you may use line input, which returns a whole line (including embedded spaces) at once.

Example

+input "Please enter the name of a file to read: " a$
+open 1,a$
+while(!eof(1))
+  input #1 b$
+  print b$
+wend
+          

If this program is stored within a file test.yab and you enter this name when prompted for a file to read, you will see this output:

Please enter the name of a file to read: t.yab
+input
+"Please
+enter
+the
+name
+of
+a
+file
+to
+read:
+"
+a$
+open
+1,a$
+while(!eof(1))
+input
+#1
+b$
+print
+b$
+wend
+
+

See also

line input

instr()

Name

instr() — searches its second argument within the first; returns its position if found

Synopsis

+print instr(a$,b$)
+if (instr(a$,b$)) …
+pos=instr(a$,b$,x)
+

Description

The instr-functions requires two string arguments and searches the second argument within the first. If the second argument can be found within the first, the position is returned (counting from one). If it can not be found, the instr-function returns 0; this makes this function usable within the condition of an if-statement (see the example below).

If you supply a third, numeric argument to the instr-function, it will be used as a starting point for the search. Therefore instr("abcdeabcdeabcde","e",8) will return 10, because the search for an "e" starts at position 8 and finds the "e" at position 10 (and not the one at position 5).

Example

+input "Please enter a text containing the string 'bumf': " a$
+if (instr(a$,"bumf")) then
+  print "Well done !"
+else
+  print "not so well ..."
+endif
+          

See also

rinstr

int()

Name

int() — return the integer part of its single numeric argument

Synopsis

+print int(a)
+

Description

The int-function returns only the digits before the comma; int(2.5) returns 2 and int(-2.3) returns -2.

Example

+input "Please enter a whole number between 1 and 10: " a
+if (a=int(a) and a>=1 and a<=10) then
+  print "Thanx !"
+else
+  print "Never mind ..."
+endif
+          

See also

frac

L

Table of Contents

label - mark a specific location within your program for goto, gosub or restore
left$() - return (or change) left end of a string
len() - return the length of a string
line - draw a line
line input - read in a whole line of text and assign it to a variable
local - mark a variable as local to a subroutine
log() - compute the natural logarithm
loop - marks the end of an infinite loop
lower$() - convert a string to lower case
ltrim$() - trim spaces at the left end of a string

label

Name

label — mark a specific location within your program for goto, gosub or restore

Synopsis

+label foo
+
+…
+
+goto foo
+

Description

The label-command can be used to give a name to a specific location within your program. Such a position might be referred from one of three commands: goto, gosub and restore.

You may use labels safely within libraries, because a label (e.g. foo) does not collide with a label with the same name within the main program or within another library; yabasic will not mix them up.

As an aside, please note, that line numbers are a special (however deprecated) case of labels; see the second example below.

Example

+for a=1 to 100
+  if (rand(10)>5) goto done
+next a
+label done
+
+10 for a=1 to 100
+20   if (rand(10)>5) goto 40
+30 next a
+40
+          

Within this example, the for-loop will probably be left prematurely with a goto-statement. This task is done twice: First with labels and then again with line numbers.

See also

gosub, goto.

left$()

Name

left$() — return (or change) left end of a string

Synopsis

+print left$(a$,2)
+left$(b$,3)="foobar"
+

Description

The left$-function accepts two arguments (a string and a number) and returns the part from the left end of the string, whose length is specified by its second argument. Loosely spoken, it simply returns the requested number of chars from the left end of the given string.

Note, that the left$-function can be assigned to, i.e. it may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the left$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below.

Example

+input "Please answer yes or no: " a$
+l=len(a$):a$=lower$(a$):print "Your answer is ";
+if (left$("yes",l)=a$ and l>=1) then
+  print "yes"
+elsif (left$("no",l)=a$ and l>=1) then
+  print "no"
+else
+  print "?"
+endif
+          

This example asks a simple yes/no question and goes some way to accept even incomplete input, while still beeing able to reject invalid input.

This second example demonstrates the capability to assign to the left$-function.

+a$="Heiho World !"
+print a$
+left$(a$,5)="Hello"
+print a$
+

See also

right$, mid$

len()

Name

len() — return the length of a string

Synopsis

+x=len(a$)
+

Description

The len-function returns the length of its single string argument.

Example

+input "Please enter a password: " a$
+if (len(a$)<6) error "Password too short !"
+          

This example checks the length of the password, that the user has entered.

See also

left$, right$ and mid$,

line

Name

line — draw a line

Synopsis

+open window 100,100
+line 0,0,100,100
+line 0,0 to 100,100
+new curve
+line 100,100
+line to 100,100
+
+open window 100,100
+clear line 0,0,100,100
+clear line 0,0 to 100,100
+new curve
+clear line 100,100
+clear line to 100,100
+

Description

The line-command draws a line. Simple as this is, the line-command has a large variety of forms as they are listed in the synopsis above. Lets look at them a little closer:

  • A line has a starting and an end point; therefore the line-command (normally) needs four numbers as arguments, representing these two points. This is the first form appearing within the synopsis.

  • You may seperate the two points with either ',' or to, which accounts for the second form of the line-command.

  • The line-command may be used to draw a connected sequence of lines with a sequence of commands like line x,y; Each command will draw a line from the point where the last line-command left off, to the point specified in the arguments. Note, that you need to use the command new curve before you may issue such a line-command. See the example below.

  • You may insert the word to for beauty: line to x,y, which does exactly the same as line x,y

  • Finally, you may choose not to draw, but to erase the lines; this can be done by prepending the phrase clear. This account for all the other forms of the line-command.

Example

+open window 200,200
+line 10,10 to 10,190
+line 10,190 to 190,190
+new curve
+for a=0 to 360
+  line to 10+a*180/360,100+60*sin(a*pi/180)
+next a
+          

This example draws a sine-curve (with an offset in x- and y-direction). Note, that the first line-command after new curve does not draw anything. Only the coordinates will be stored. The second iteration of the loop then uses these coordinates as a starting point for the first line.

line input

Name

line input — read in a whole line of text and assign it to a variable

Synopsis

+line input a
+line input a$
+line input "Hello" a
+line input #1 a$
+

Description

In most respects line input is like the input-command: It reads the new contents of a variable, either from keyboard or from a file. However, line input always reads a complete line and assigns it to its variable. line input does not stop reading at spaces and is therefore the best way to read in a string which might contain whitespace. Note, that the final newline is stripped of.

Example

+line input "Please enter your name (e.g. Frodo Beutelin): " a$
+print "Hello ",a$
+          

Note that the usage of line input is essential in this example; a simple input-statement would only return the string up to the first space, e.g. Frodo.

See also

input

local

Name

local — mark a variable as local to a subroutine

Synopsis

+sub foo()
+
+  local a,b,c$,d(10),e$(5,5)
+
+  …
+
+end sub 
+

Description

The local-command can (and should be) used to mark a variable (or array) as local to the containing subroutine. This means, that a local variable in your subroutine is totally different from a variable with the same name within your main program. Variables which are known everywhere within your program are called global in contrast.

Declaring variables within the subroutine as local helps to avoid hard to find bugs; therefore local variables should be used whenever possible.

Note, that the parameters of your subroutines are always local.

As you may see from the example, local arrays may be created without using the keyword dim (which is required only for global arrays).

Example

+a=1
+b=1
+print a,b
+foo()
+print a,b
+
+sub foo()
+  local a
+  a=2
+  b=2
+end sub
+          

This example demonstrates the difference between local and global variables; it produces this output:

+

1 1
+1 2
+
+

As you may see, the content of the global variable a is unchanged after the subroutine foo; this is because the assignment a=2 within the subroutine affects the local variable a only and not the global one. However, the variable b is never declared local and therefore the subroutine changes the global variable, which is reflected in the output of the second print-statement.

See also

sub, static, dim

log()

Name

log() — compute the natural logarithm

Synopsis

+a=log(x)
+a=log(x,base)
+

Description

The log-function computes the logarithm of its first argument. The optional second argument gives the base for the logarithm; if this second argument is omitted, the euler-constant 2.71828… will be taken as the base.

Example

+open window 200,200
+for x=10 to 190 step 10:for y=10 to 190 step 10
+  r=3*log(1+x,1+y)
+  if (r>10) r=10
+  if (r<1) r=1
+  fill circle x,y,r
+next y:next x
+          

This draws another nice plot.

See also

exp

loop

Name

loop — marks the end of an infinite loop

Synopsis

+do
+  …
+loop
+

Description

The loop-command marks the ends of a loop (which is started by do), wherein all statements within the loop are repeated forever. In this respect the do loop-loop is infinite, however, you may leave it anytime via break or goto.

Example

+print "Hello, I will throw dice, until I get a 2 ..."
+do
+  r=int(rand(6))+1
+  print r
+  if (r=2) break
+loop
+          

See also

do, for, repeat, while, break

lower$()

Name

lower$() — convert a string to lower case

Synopsis

+l$=lower$(a$)
+

Description

The lower$-function accepts a single string-argument and converts it to all lower case.

Example

+input "Please enter a password: " a$
+if (a$=lower$(a$)) error "Your password is NOT mixed case !"
+          

This example prompts for a password and checks, if it is really lower case.

See also

upper$

ltrim$()

Name

ltrim$() — trim spaces at the left end of a string

Synopsis

+a$=ltrim$(b$)
+

Description

The ltrim$-function removes all whitespace from the left end of a string and returns the result.

Example

+input "Please answer 'yes' or 'no' : " a$
+a$=lower$(ltrim$(rtrim$(a$)))
+if (len(a$)>0 and a$=left$("yes",len(a$))) then
+  print "Yes ..."
+else
+  print "No ..."
+endif
+          

This example prompts for an answer and removes any spaces, which might precede the input; therefore it is even prepared for the (albeit somewhat patological case, that the user first hits space before entering his answer.

See also

rtrim$, trim$

M

Table of Contents

max() - return the larger of its two arguments
mid$() - return (or change) characters from within a string
min() - return the smaller of its two arguments
mod() - compute the remainder of a division
mouseb - extract the state of the mousebuttons from a string returned by inkey$
mousemod - return the state of the modifier keys during a mouseclick
mousex - return the x-position of a mouseclick
mousey - return the y-position of a mouseclick

max()

Name

max() — return the larger of its two arguments

Synopsis

+print max(a,b)
+

Description

Return the maximum of its two arguments.

Example

+dim m(10)
+for a=1 to 1000
+  m=0
+  For b=1 to 10
+    m=max(m,ran(10))
+  next b
+  m(m)=m(m)+1
+next a
+
+for a=1 to 9
+  print a,": ",m(a)
+next a
+          

Within the inner for-loop (the one with the loop-variable b), the example computes the maximum of 10 random numbers. The outer loop (with the loop variable a) now repeats this process 1000 times and counts, how often each maximum appears. The last loop finally reports the result.

Now, the interesting question would be, which will be approached, when we increase the number of iterations from thousend to infinity. Well, maybe someone could just tell me :-)

See also

min

mid$()

Name

mid$() — return (or change) characters from within a string

Synopsis

+print mid$(a$,2,1)
+print mid$(a$,2)
+mid$(a$,5,3)="foo"
+mid$(a$,5)="foo"
+

Description

The mid$-function requires three arguments: a string and two numbers, where the first number specifies a position within the string and the second one gives the number of characters to be returned; if you omit the second argument, the mid$-function returns all characters up to the end of the string.

Note, that you may assign to the mid$-function, i.e. mid$ may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the mid$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below.

Example

+input "Please enter a string: " a$
+for a=1 to len(a$)
+  if (instr("aeiou",lower$(mid$(a$,a,1)))) mid$(a$,a,1)="e"
+next a
+print "When you turn everything to lower case and"
+print "replace every vowel with 'e', your input reads:"
+print
+print a$
+          

This example transforms the input string a bit, using the mid$-function to retrieve a character from within the string as well as to change it.

See also

left$ and right$.

min()

Name

min() — return the smaller of its two arguments

Synopsis

+print min(a,b)
+

Description

Return the minimum of its two argument.

Example

+dim m(10)
+for a=1 to 1000
+  m=min(ran(10),ran(10))
+  m(m)=m(m)+1
+next a
+
+for a=1 to 9
+  print a,": ",m(a)
+next a
+          

For each iteration of the loop, the lower of two random number is recorded. The result is printed at the end.

See also

max

mod()

Name

mod() — compute the remainder of a division

Synopsis

+print mod(a,b)
+

Description

The mod-function divides its two arguments and computes the remainder. Note, that a/b-int(a/b) and mod(a,b) are always equal.

Example

+clear screen
+print at(10,10) "Please wait ";
+p$="-\|/"
+for a=1 to 100
+  rem  ... do something lengthy here, or simply sleep :-)
+  pause(1)
+  print at(22,10) mid$(p$,1+mod(a,4))
+next a
+          

This example executes some time consuming action within a loop (in fact, it simply sleeps) and gives the user some indication of progress by displaying a turning bar (thats where the mod()-function comes into play).

See also

int, frac

mouseb

Name

mouseb — extract the state of the mousebuttons from a string returned by inkey$

Synopsis

+inkey$
+print mouseb()
+print mouseb
+a$=inkey$
+print mouseb(a$)
+

Description

The mouseb-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function. If a mousebutton has been pressed, the mouseb-function returns the number (1,2 or 3) of the mousebutton, when it is pressed and returns its negative (-1,-2 or -3), when it is released.

The mouseb-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mouseb is called without any arguments, it returns the values from the last call to inkey$, which are stored implicitly and internally by yabasic.

Note

Note however, that the value returned by the mouseb-function does not reflect the current state of the mousebuttons. It rather extracts the information from the string passed as an argument (or from the last call to the inkey$-function, if no argument is passed). So the value returned by mouseb reflects the state of the mousebuttons at the time the inkey$-function has been called; as opposed to the time the mouseb-function is called.

Example

+open window 200,200
+clear screen
+print "Please draw lines; press (and keep it pressed)" 
+print "the left mousebutton for the starting point,"
+print "release it for the end-point."
+do
+  if (mouseb(release$)=1) press$=release$
+  release$=inkey$
+  if (mouseb(release$)=-1) then
+    line mousex(press$),mousey(press$) to mousex(release$),mousey(release$)
+  endif
+loop
+          

This is a maybe the most simplistic line-drawing program possible, catching presses as well as releases of the first mousebutton.

mousemod

Name

mousemod — return the state of the modifier keys during a mouseclick

Synopsis

+inkey$
+print mousemod()
+print mousemod
+a$=inkey$
+print mousemod(a$)
+

Description

The mousemod-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function if a mousebutton has been pressed. It returns the state of the keyboard modifiers (shift, ctrl or alt): If the shift-key is pressed, mousemod returns 1, for the alt-key 2 and for the ctrl-key 4. If more than one key is pressed, the sum of these values is returned, e.g. mousemod returns 5, if shift and ctrl are pressed simultanously.

The mousemod-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mousemod is called without any arguments, it returns the values from the last call to inkey$ (which are stored implicitly and internally by yabasic).

Note

Please see also the Note within the mouseb-function.

Example

+open window 200,200
+clear screen
+do
+  a$=inkey$
+  if (left$(a$,2)="MB") then
+    x=mousex(a$)
+    y=mousey(a$)
+    if (mousemod(a$)=0) then
+      circle x,y,20
+    else
+      fill circle x,y,20
+    endif
+  endif
+loop
+          

This program draws a circle, whenever a mousebutton is pressed; the circles are filled, when any modifier is pressed, and empty if not.

See also

inkey$, mousex, mousey and mouseb

mousex

Name

mousex — return the x-position of a mouseclick

Synopsis

+inkey$
+print mousex()
+print mousex
+a$=inkey$
+print mousex(a$)
+

Description

The mousex-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function; It returns the x-position of the mouse as encoded within its argument.

The mousex-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mousex is called without any arguments, it returns the values from the last call to inkey$ (which are stored implicitly and internally by yabasic).

Note

Please see also the Note within the mouseb-function.

Example

+open window 200,200
+clear screen
+do
+  a$=inkey$
+  if (left$(a$,2)="MB") then
+    line mousex,0 to mousex,200
+  endif
+loop
+          

This example draws vertical lines at the position, where the mousebutton has been pressed.

mousey

Name

mousey — return the y-position of a mouseclick

Synopsis

+inkey$
+print mousey()
+print mousey
+a$=inkey$
+print mousey(a$)
+

Description

The mousey-function is a helper function for decoding part of the (rather complicated) strings, which are returned by the inkey$-function. mousey returns the y-position of the mouse as encoded within its argument.

The mousey-function accepts zero or one arguments. A single argument should be a string returned by the inkey$-function; if mousey is called without any arguments, it returns the values from the last call to inkey$ (which are stored implicitly and internally by yabasic).

Note

Please see also the Note within the mouseb-function.

Example

+open window 200,200
+clear screen
+do
+  a$=inkey$
+  if (left$(a$,2)="MB") then
+    line 0,mousey to 200,mousey
+  endif
+loop
+          

This example draws horizontal lines at the position, where the mousebutton has been pressed.

N

Table of Contents

new curve - start a new curve, that will be drawn with the line-command
next - mark the end of a for loop
not - negate an expression; can be written as !
numparams - return the number of parameters, that have been passed to a subroutine

new curve

Name

new curve — start a new curve, that will be drawn with the line-command

Synopsis

+new curve
+line to x,y
+

Description

The new curve-function starts a new sequence of lines, that will be drawn by repeated line to-commands.

Example

+open window 200,200
+ellipse(100,50,30,60)
+ellipse(150,100,60,30)
+sub ellipse(x,y,xr,yr)
+  new curve
+  for a=0 to 2*pi step 0.2
+    line to x+xr*cos(a),y+yr*sin(a)
+  next a
+  close curve
+end sub
+  
+          

This example defines a subroutine ellipse that draws an ellipse. Within this subroutine, the ellipse is drawn as a sequence of lines started with the new curve command and closed with close curve.

See also

line, close curve

next

Name

next — mark the end of a for loop

Synopsis

+for a=1 to 10
+next a
+

Description

The next-keyword marks the end of a for-loop. All statements up to the next-keyword will be repeated as specified with the for-clause. Note, that the name of the variable is optional; so instead of next a you may write next.

Example

+for a=1 to 300000
+  for b=1 to 21+20*sin(pi*a/20)
+    print "*";
+  next b
+  print
+  sleep 0.1
+next a
+          

This example simply plots a sine-curve until you fall asleep.

See also

for

not

Name

not — negate an expression; can be written as !

Synopsis

+if (not a<b) then …
+bad=!okay
+

Description

The keyword not (or ! for short) is mostly used within conditions (e.g. within if- or while-statements). There it is employed to negate the condition or expression (i.e. turn TRUE into FALSE and vice versa)

However not can be used within arithmetic calculations too., simply because there is no difference between arithmetic and logical expressions.

Example

+input "Please enter three ascending numbers: " a,b,c
+if (not (a<b and b<c)) error " the numbers you have entered are not ascending ..."
+          

See also

and,or

numparams

Name

numparams — return the number of parameters, that have been passed to a subroutine

Synopsis

+sub foo(a,b,c)
+  if (numparams=1) …
+  …
+end sub
+

Description

Within a subroutine the local variable numparam or numparams contains the number of parameters, that have been passed to the subroutine. This information can be useful, because the subroutine may have been called with fewer parameters than actually declared. The number of values that actually have been passed while calling the subroutine, can be found in numparams.

Note, that arguments which are used in the definition of a subroutine but are left out during a call to it (thereby reducing the value of numparams) receive a value of 0 or "" (empty string) respectively.

Example

+a$="123456789"
+print part$(a$,4)
+print part$(a$,3,7)
+
+sub part$(a$,f,t)
+  if (numparams=2) then
+    return mid$(a$,f)
+  else 
+    return mid$(a$,f,t-f+1)
+  end if
+end sub
+          

When you run this example, it will print 456789 and 34567. Take a look at the subroutine part$, which returns part of the string which has been passed as an argument. If (besides the string) two numbers are passed, they define the starting and end position of the substring, that will be returned. However, if only one number is passed, the rest of the string, starting from this position will be returned. Each of these cases is recognized with the help of the numparams variable.

See also

sub

O

Table of Contents

on gosub - jump to one of multiple gosub-targets
on goto - jump to one of many goto-targets
on interrupt - change reaction on keyboard interrupts
open - open a file
open printer - open printer for printing graphics
open window - open a graphic window
logical or - logical or, used in conditions
or() - arithmetic or, used for bit-operations

on gosub

Name

on goto — jump to one of multiple gosub-targets

Synopsis

+on a gosub foo,bar,baz
+  …
+label foo
+  …
+return
+
+label bar
+  …
+return
+
+label baz
+  …
+return
+

Description

The on gosub statement uses its numeric argument (the one between on and gosub) to select an element from the list of labels, which follows after the gosub-keyword: If the number is 1, the program does a gosub to the first label; if the number is 2, to the second and, so on. if the number is zero or less, the program continues at the position of the first label; if the number is larger than the total count of labels, the execution continues at the position of the last label; i.e. the first and last label in the list constitute some kind of fallback-slot.

Note, that the on gosub-command can no longer be considered state of the art; people (not me !) may even start to mock you, if you use it.

Example

+do
+  print "Please enter a number between 1 and 3: "
+  print
+  input "Your choice " a
+  on a gosub bad,one,two,three,bad
+loop
+
+label bad
+  print "No. Please between 1 and 3"
+return
+
+label one
+  print "one"
+return
+
+label two
+  print "two"
+return
+
+label three
+  print "three"
+return
+          

Note, how invalid input (a number less than 1, or larger than 3) is automatically detected.

on goto

Name

on goto — jump to one of many goto-targets

Synopsis

+on a goto foo,bar,baz
+  …
+label foo
+  …
+label bar
+  …
+label baz
+  …
+

Description

The on goto statement uses its numeric argument (the one between on and goto to select an element from the list of labels, which follows after the goto-keyword: If the number is 1, the execution continues at the first label; if the number is 2, at the second, and so on. if the number is zero or less, the program continues at the position of the first label; if the number is larger than the total count of labels, the execution continues at the position of the last label; i.e. the first and last label in the list constitute some kind of fallback-slot.

Note, that (unlike the goto-command) the on goto-command can no longer be considered state of the art; people may (not me !) even start to mock you, if you use it.

Example

+label over
+print "Please Select one of these choices: "
+print
+print "  1 -- show time"
+print "  2 -- show date"
+print "  3 -- exit"
+print
+input "Your choice " a
+on a goto over,show_time,show_date,terminate,over
+
+label show_time
+  print time$()
+goto over
+
+label show_date
+  print date$()
+goto over
+
+label terminate
+exit
+          

Note, how invalid input (a number less than 1, or larger than 3) is automatically detected; in such a case the question is simply issued again.

on interrupt

Name

on interrupt — change reaction on keyboard interrupts

Synopsis

+on interrupt break
+…
+on interrupt continue
+

Description

With the on interrupt-command you may change the way, how yabasic reacts on a keyboard interrupt; it comes in two variants: on interrupt break and on interrupt continue. A keyboard interrupt is produced, if you press ctrl-C on your keyboard; normally (and certainly after you have called on interrupt break), yabasic will terminate with an error message. However after the command on interrupt continue yabasic ignores any keyboard interrupt. This may be useful, if you do not want your program beeing interruptible during certain critical operations (e.g. updating of files).

Example

+print "Please stand by while writing a file with random data ..."
+on interrupt continue
+open "random.data" for writing as #1
+for a=1 to 100
+  print #1 ran(100)
+  print a," percent done."
+  sleep 1
+next a
+close #1
+on interrupt continue
+          

This program writes a file with 100 random numbers. The on interrupt continue command insures, that the program will not be terminated on a keyboard interrupt and the file will be written entirely in any case. The sleep-command just stretches the process arificially to give you a chance to try a ctrl-C.

See also

There is no related command.

open

Name

open — open a file

Synopsis

+open a,"file","r"
+open #a,"file","w"
+open #a,printer
+open "file" for reading as a
+open "file" for writing as #a
+a=open("file")
+a=open("file","r")
+if (open(a,"file")) …
+if (open(a,"file","w")) …
+

Description

The open-command opens a file for reading or writing or a printer for printing text. open comes in a wide variety of ways; it requires these arguments:

filenumber

In the synopsis this is a or #a. In yabasic each file is associated with a number between 1 and a maximum value, which depends on the operating system. For historical reasons the filenumber can be preceded by a hash ('#'). Note, that specifying a filenumber is optional; if it is omitted, the open-function will return a filenumber, which should then be stored in a variable for later reference. This filenumber can be a simple number or an arbitrary complex arithmetic expression, in which case braces might be necessary to save yabasic from getting confused.

filename

In the synopsis above this is "file". This string specifies the name of the file to open (note the important caveat on specifying these filenames).

accessmode

In the synopsis this is "r", "w", for reading or for writing. This string or clause specifies the mode in which the file is opened; it may be one of: +

"r"

Open the file for reading (may also be written as for reading). If the file does not exist, the command will fail. This mode is the default, i.e. if no mode is specified with the open-command, the file will be opened with this mode.

"w"

Open the file for writing (may also be written as for writing). If the file does not exist, it will be created.

"a"

Open the file for appending, i.e. what you write to the file will be appended after its initial contents. If the file does not exist, it will be created.

"b"

This letter may not appear alone, but may be combined with the other letters (e.g. "rb") to open a file in binary mode (as opposed to text mode).

+ +

As you may see from the synopsis, the open-command may either be called as a command (without braces) or as a function (with braces). If called as a function, it will return the filenumber or zero if the operation fails. Therefore the open-function may be used within the condition of an if-statement.

If the open-command fails, you may use peek("error") to retrieve the exact nature of the error.

Furthermore note, that there is another, somewhat separate usage of the open-command; if you specify the bareword printer instead of a filename, the command opens a printer for printing text. Every text (and only text) you print to this file will appear on your printer. Note, that this is very different from printing graphics, as can be done with open printer.

Finally you may read the description for peek("error") to learn which errors may have happened during an open-call.

Example

+open "foo.bar" for writing as #1
+print #1 "Hallo !"
+close #1
+if (not open(1,"foo.bar")) error "Could not open 'foo.bar' for reading"
+while(not eof(1)) 
+  line input #1 a$
+  print a$
+wend
+          

This example simply opens the file foo.bar, writes a single line, reopens it and reads its contents again.

open printer

Name

open printer — open printer for printing graphics

Synopsis

+open printer
+open printer "file"
+

Description

The open printer-command opens a printer for printing graphics. The command requires, that a graphic window has been opened before. Everything that is drawn into this window will then be sent to the printer too.

A new piece of paper may be started with the clear window-command; the final (or only) page will appear after the close printer-command.

Note, that you may specify a filename with open printer; in that case the printout will be sent to a filename instead to a printer. Your program or the user will be responsible for sending this file to the printer afterwards.

If you use yabasic under Unix, you will need a postscript printer (because yabasic produces postscript output). Alternatively you may use ghostscript to transfrom the postscript file into a form suitable for your printer; but that is beyond the responsibility of yabasic.

Example

+open window 200,200
+open printer
+line 0,0 to 200,200
+text 100,100,"Hallo"
+close window
+close printer
+          

This example will open a window, draw a line and print some text within; everything will appear on your printer too.

open window

Name

open window — open a graphic window

Synopsis

+open window x,y
+open window x,y,"font"
+

Description

The open window-command opens a window of the specified size. Only one window can be opened at any given moment of time.

An optional third argument specifies a font to be used for any text within the window. Please note, that if you open a window several times with varying font-arguments, only the first one will take effect, all others will be ignored; that means that you may onle use a single font for all windows in your program.

Example

+for a=200 to 400 step 10
+  open window a,a
+  for b=0 to a
+    line 0,b to a,b
+    line b,0 to b,a
+  sleep 0.1
+  close window
+next a
+          

logical or

Name

or — logical or, used in conditions

Synopsis

+if (a or b) …
+while (a or b) …
+

Description

Used in conditions (e.g within if or while) to join two expressions. Returns true, if either its left or its right or both arguments are true; returns false otherwise.

Example

+input "Please enter a number"
+if (a>9 or a<1) print "a is not between 1 and 9"
+          

See also

and,not

or()

Name

or() — arithmetic or, used for bit-operations

Synopsis

+x=or(a,b)
+

Description

Used to compute the bitwise or of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if any of its arguments has 1 at this position in their binary representation.

Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to or.

Example

+print or(14,3)
+          

This will print 15. This result is clear, if you note, that the binary representation of 14 and 3 are 1110 and 0011 respectively; this will yield 1111 in binary representaion or 15 as decimal.

See also

oand, eor and not

P

Table of Contents

pause - pause, sleep, wait for the specified number of seconds
peek - retrieve various internal informations
peek$ - retrieve various internal string-informations
pi - a constant with the value 3.14159
poke - change selected internals of yabasic
print - Write to terminal or file
putbit - draw a rectangle of pixels into the graphic window
putscreen - draw a rectangle of characters into the text terminal

pause

Name

pause — pause, sleep, wait for the specified number of seconds

Synopsis

+pause 5
+

Description

The pause-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yabasic will always do exactly the same.

The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yabasic will not wait at all. The minimal interval that can be waited depends on the system (Unix, Windows) you are using.

The pause-command cannot be interrupted. However, sometimes you may want the wait to be interuptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument).

Example

+deg=0
+do
+  maxx=44+40*sin(deg)
+  for x=1 to maxx
+    print "*";
+  next x
+  pause 0.1+(maxx*maxx/(4*84*84))
+  print
+  deg=deg+0.1
+loop
+          

This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity.

See also

sleep, wait

peek

Name

peek — retrieve various internal informations

Synopsis

+print peek("foo")
+a=peek(#1)
+

Description

The peek-function has many different and mostly unrelated uses. It is a kind of grabbag for retrieving all kinds of numerical information, internal to yabasic. The meaning of the numbers returned be the peek-function depends on the string or number passed as an argument.

peek always returns a number, however the closely related peek$-function exists, which may be used to retrieve string information from among the internals of yabasic. Finally note, that some of the values which are retrieved with peek may even be changed, using the poke-function.

There are two variants of the peek-function: One expects an integer, positive number and is described within the first entry of the list below. The other variant expects one of a well defined set of strings as described in the second and all the following entries of the list below.

peek(a), peek(#a)

Read a single character from the file a (which must be open of course).

peek("winheight")

Return the height of the graphic-window in pixels. If none is open, this peek will return the height of the last window opened or 100, if none has been opened yet.

peek("winwidth")

Return the width of the graphic-window in pixels. If none is open, this peek will return the width of the last window opened or 100, if none has been opened yet.

peek("fontheight")

Return the height of the font used within the graphic window. If none is open, this peek will return the height of the last font used or 10, if no window has been opened yet.

peek("screenheight")

Return the height in characters of the window, wherein yabasic runs. If you have not called clear screen yet, this peekwill return 0, regardless of the size of your terminal.

peek("screenwidth")

Return the width in characters of the window, wherein yabasic runs. If you have not called clear screen yet, this peekwill return 0, regardless of the size of your terminal.

peek("argument")

Return the number of arguments, that have been passed to yabasic at invocation time. E.g. if yabasic has been called like this: yabasic foo.yab bar baz, then peek("argument") will return 2. This is because foo.yab is treated as the name of the program to run, whereas bar and baz are considered arguments to the program, which are passed on the commandline. Note, that for windows-users, who tend to click on the icon (as opposed to starting yabasic on the command line), this peekwill mostly return 0.

The function peek("argument") can be written as peek("arguments") too.

You will want to check out the corresponding function peek$("argument") to actually retrieve the arguments. Note, that each call to peek$("argument") reduces the number returned by peek("argument").

peek("isbound")

Return true, if the executing yabasic-program is part of a standalone program; see the section about creating a standalone-program for details.

peek("version")

Return the version number of yabasic (e.g. 2.72).

peek("error")

Return a number specifying the nature of the last error in an open- or seek-statement. Normally an error within an open-statement immediately terminates your program with an appropriate error-message, so there is no chance and no need to learn more about the nature of the error. However, if you use open as a condition (e.g. if (open(#1,"foo")) …) the outcome (success or failure) of the open-operation will determine, if the condition evaluates to true or false. If now such an operation fails, your program will not be terminated and you might want to learn the reason for failure. This reason will be returned by peek("error") (as a number) or by peek$("error") (as a string)

The table below shows the various error codes; the value returned by peek$("error") explains the nature of the error. Note, that the codes 10,11 and 12 refer to the seek-command.

Table 6.1. Error codes

peek("error")peek$("error")Explanation
2Stream already in useDo not try to open one and the same filenumber twice; rather close it first.
3'x' is not a valid filemodeThe optional filemode argument, which may be passed to the open-function, has an invalid value
4could not open 'foo'The open-call did not work, no further explanation is available.
5reached maximum number of open filesYou have opened more files than your operating system permits.
6cannot open printer: already printing graphicsThe commands open printer and open #1,printer both open a printer (refer to their description for the difference). However, only one can be active at a time; if you try to do both at the same time, you will receive this error.
7could not open line printerWell, it simply did not work.
9invalid stream numberAn attempt to use an invalid (e.g. negative) stream number; example: open(-1,"foo")
10could not position stream x to byte yseek did not work.
11stream x not openYou have tried to seek within a stream, that has not been opened yet.
12seek mode 'x' is none of begin,end,hereThe argument, which has been passed to seek is invalid.

Example

+open "foo" for reading as #1
+open "bar" for writing as #2
+while(not eof(#1))
+  poke #2,chr$(peek(#1));
+wend
+          

This program will copy the file foo byte by byte to bar.

Note, that each peek does something entirely different, and only one has been demonstrated above. Therefore you need to make up examples yourself for all the other peeks.

See also

peek$, poke, open

peek$

Name

peek$ — retrieve various internal string-informations

Synopsis

+print peek$("foo")
+

Description

The peek$-function has many different and unrelated uses. It is a kind of grabbag for retrieving all kinds of string information, internal to yabasic; the exact nature of the strings returned be the peek$-function depends on the string passed as an argument.

peek$ always returns a string, however the closely related peek-function exists, which may be used to retrieve numerical information from among the internals of yabasic. Finally note, that some of the values which are retrieved with peek$ may even be changed, using the poke-function.

The following list shows all possible arguments to peek$:

peek$("infolevel")

Returns either "debug", "note", "warning", "error" or "fatal", depending on the current infolevel. This value can be specified with an option (either under windows or unix) on the commandline or changed during the execution of the program with the corresponding poke; however, normally only the author of yabasic (me !) would want to change this from its default value "warning".

peek$("textalign")

Returns one of nine possible strings, specifying the default alignment of text within the graphics-window. The alignment-string returned by this peek describes, how the text-command aligns its string-argument with respect to the coordinates supplied. However, this value does not apply, if the text-command explicitly specifies an alignment. Each of these strings is two characters long. The first character specifies the horizontal alignment and can be either l, r or c, which stand for left, right or center. The second character specifies the vertical alignment and can be one of t, b or c, which stand for top, bottom or center respectively.

You may change this value with the corresponding command poke "textalign",…; the initial value is lb, which means the top of the left and the top edge if the text will be aligned with the coordinates, that are specified within the text-command.

peek$("windoworigin")

This peek returns a two character string, which specifies the position of the origin of the coordinate system of the window; this string might be changed with the corresponding command poke "windoworigin",x,y or specified as the argument of the origin command; see there for a detailed description of the string, which might be returned by this peek.

peek$("error")

Return a string describing the nature of the last error in an open- or seek-statement. See the corresponding peek("error") for a detailed description.

peek$("library")

Return the name of the library, this statement is contained in. See the import-command for a detailed description or for more about libraries.

peek$("os")

This peek returns the name of the operating system, where your program executes. This can be either windows or unix.

peek$("font")

Return the name of the font, which is used for text within the graphic window; this value can be specified as the third argument to the open window-command.

peek$("env","NAME")

Return the environment variable specified by NAME (which may be any string expression). Which kind of environment variables are available on your system depends, as well as their meaning, on your system; however typing env on the commandline will produce a list (for Windows and Unix alike). Note, that peek$("env",...) can be written as peek$("environment",...) too.

peek$("argument")

Return one of the arguments, that have been passed to yabasic at invocation time (the next call will return the the second argument, and so on). E.g. if yabasic has been called like this: yabasic foo.yab bar baz, then the first call to peek$("argument") will return bar. This is because foo.yab is treated as the name of the program to run, whereas bar and baz are considered arguments to this program, which are passed on the commandline. The second call to peek$("argument") will return baz. Note, that for windows-users, who tend to click on the icon (as opposed to starting yabasic on the command line), this peekwill mostly return the empty string.

Note, that peek$("argument") can be written as peek$("arguments").

Finally you will want to check out the corresponding function peek("argument").

Example

+print "You have supplied these arguments: "
+while(peek("argument"))
+  print peek("argument"),peek$("argument")
+wend
+          

If you save this program in a file foo.yab and execute it via yabasic t.yab a b c (for windows users: please use the commandline for this), your will get this output:

+3a
+2b
+1c
+

See also

peek, poke, open

pi

Name

pi — a constant with the value 3.14159

Synopsis

+print pi
+

Description

pi is 3.14159265359 (well at least for yabasic); do not try to assign to pi (e.g. pi=22/7) this would not only be mathematically dubious, but would also result in a syntax error.

Example

+for a=0 to 180
+  print "The sine of ",a," degrees is ",sin(a*pi/180)
+next a
+          

This program uses pi to transform an angle from degrees into radians.

See also

euler

poke

Name

poke — change selected internals of yabasic

Synopsis

+poke "foo","bar"
+poke "foo",baz
+poke #a,"bar"
+poke #a,baz
+

Description

The poke-command may be used to change details of yabasics behaviour. Like the related function peek, poke does many different things, depending on the arguments supplied.

Here are the different things you can do with poke:

poke "textalign","cc"

This poke changes the default alignment of text with respect to the coordinates supplied within the text-command. However, this value does not apply, if the text-command explicitly specifies an alignment. The second argument ("cc" in the example) must always be two characters long; the first character can be one of l (left), r (right) or c (center); the second character can be either t (top), b (bottom) or c (center); see the corresponding peek$("textalign") for a detailed description of this argument.

poke "windoworigin","lt"

This poke moves the origin of the coordinate system of the window to the specified position. The second argument ("lt" in the example) must always be two characters long; the first character can be one of l (left), r (right) or c (center); the second character can be either t (top), b (bottom) or c (center). Together those two characters specify the new position of the coordinate-origin. See the corresponding peek$("windoworigin") for a more in depth description of this argument.

poke "infolevel","debug"

Change the amount of internal information, that yabasic outputs during execution.

The second argument can be either "debug", "note", "warning", "error" or "fatal". However, normally you will not want to change this from its default value "warning".

See also the related peek$("infolevel").

poke #1,a

Write the given byte (a in the example above) to the specified stream (#a in the example).

See also the related function function peek(#1).

Example

+print "Hello, now you will see, how much work"
+print "a simple for-loop involves ..."
+input "Please press return " a$
+poke "infolevel","debug"
+for a=1 to 10:next a
+          

This example only demonstrates one of the many pokes, which are described above: The program switches the infolevel to debug, which makes yabasic produce a lot of debug-messages during the subsequent for-loop.

See also

peek, peek$

print

Name

print — Write to terminal or file

Synopsis

+print "foo",a$,b
+print "foo","a$,b;
+print #a "foo",a$
+print #a "foo",a$;
+print foo using "##.###"
+print reverse "foo"
+print at(10,10) a$,b
+print @(10,10) a$,b
+print color("red","blue") a$,b
+print color("magenta") a$,b
+print color("green","yellow") at(5,5) a$,b
+

Description

The print-statement outputs strings or characters, either to your terminal (also known as console) or to an open file.

To understand all those uses of the print-statement, let's go throught the various lines in the synopsis above:

print "foo",a$,b

Print the string foo as well as the contents of the variables a$ and b onto the screen, silently adding a newline.

print "foo",a$,b;

(Note the trailing semicolon !) This statement does the same as the one above; only the implicit newline is skipped, which means that the next print-statement will append seamlessly.

print #a "foo",a$

This is the way to write to files. The file with the number a must be open already, an implicit newline is added. Note the file-number #a, which starts with a hash ('#') amd is separated from the rest of the statement by a space only. The file-number (contained in the variable a) must have been returned by a previous open-statement (e.g. a=open("bar")).

print #a "foo",a$;

The same as above, but without the implicit newline.

print foo using "##.###"

Print the number foo with as many digits before and after the decimal dot as given by the number of '#'-signs. See the entries for using and str$ for a detailed description of this format.

print reverse "foo"

As all the print-variants to follow, this form of the print-statement can only be issued after clear screen has been called. The strings and numbers after the reverse-clause are simply printed inverse (compared to the normal print-statement).

print at(10,10) a$,b

Print at the specified (x,y)-position. This is only allowed after clear screen has been called. You may want to query peek$("screenwidth") or peek$("screenheight") to learn the actual size of your screen. You may add a semicolon to suppress the implicit newline.

print @(10,10) a$,b

This is exactly the same as above, however, at may be written as @.

print color("red","blue") at(5,5) a$,b

Print with the specified fore- ("red") and background ("blue") color (or colour). The possible values are "black", "white", "red", "blue", "green", "yellow", "cyan" or "magenta". Again, you need to call clear screen first and add a semicolon if you want to suppress the implicit newline.

print color("magenta") a$,b

You may specify the foreground color only.

print color("green","yellow") a$,b

A color and a position (in this sequence, not the other way around) may be specified at once.

Example

+clear screen
+columns=peek("screenwidth")
+lines=peek("screenheight")
+dim col$(7)
+for a=0 to 7:read col$(a):next a
+data "black","white","red","blue","green","yellow","cyan","magenta"
+
+for a=0 to 2*pi step 0.1
+  print colour(col$(mod(i,8))) at(columns*(0.8*sin(a)+0.9)/2,lines*(0.8*cos(a)+0.9)/2) "*"
+  i=i+1
+next a
+          

This example draws a cloured ellipse within the text window.

putbit

Name

putbit — draw a rectangle of pixels into the graphic window

Synopsis

+open window 200,200
+…
+a$=getbit(20,20,50,50)
+…
+putbit a$,30,30
+putbit a$ to 30,30
+putbit a$,30,30,"or"
+

Description

The putbit-command is the counterpart of the getbit-function. putbit requires a string as returned by the getbit-function. Such a string contains a rectangle from the graphic window; the putbit-function puts such a rectangular region back into the graphic-window.

Note, that the putbit-command currently accepts a third argument. However only the string value "or" is supported here. The effect is, that only those pixel, which are set in the string will be set in the graphic window. Those pixels, which are not set in the string, will not change in the window (as opposed to beeing cleared).

Note, that the format of the string returned by this function is due to change as soon as yabasic will learn, how to deal with colors.

Example

+c$="41,41:0000000000000000000000000400000000cff1000000ffff100000ffff700008fffff30008ffffff0008ffffff3008fffffff000fffffff100fffffff700ffffffff10efffffff30cfffffff70cffffffff18ffffffff30ffffffff70effffffff0cffffffff1cffffffff30ffffffff70effffffff0cffffffff18ffffffff30ffffffff70cfffffff708ffffffff00ffffffff10cfffffff100fffffff100effffff3008ffffff3000efffff30008fffff30000cffff100000ffff1000000ff700000000000000000000000000000000000"
+
+open window 200,200
+do
+  x=ran(200)
+  y=ran(200)
+  putbit c$,x,y,"or"
+loop
+          

This program uses a precanned string (containing the image of a circle) and draws it repeatedly into the graphic-window. The mode "or" ensures, that no pixels will be cleared.

putscreen

Name

putscreen — draw a rectangle of characters into the text terminal

Synopsis

+clear screen
+…
+a$=getscreen$(5,5,10,10)
+…
+putscreen a$,7,7
+

Description

The putscreen-command is the counterpart of the getscreen$-function. putscreen requires a string as returned by the getscreen-function. Such a string contains a rectangular detail from the terminal; the putscreen-function puts such a region back into the terminal-window.

Note, that clear screen must have been called before.

Example

+clear screen
+for a=1 to 200
+  print color("red") "Hallo !"; 
+  print color("blue") "Welt !";
+next a
+r$=getscreen$(0,0,20,20)
+for x=0 to 60
+  putscreen r$,x,0
+  sleep 0.1
+next x
+          

This example prints the string "Hallo !Welt !" all over the screen and then moves a rectangle from one side to the other.

R

Table of Contents

ran() - return a random number
read - read data from data-statements
rectangle - draw a rectangle
redim - create an array prior to its first use. A synonym for dim
rem - start a comment
repeat - start a repeat-loop
restore - reposition the data-pointer
return - return from a subroutine or a gosub
reverse - print reverse (background and foreground colors exchanged)
right$() - return (or change) the right end of a string
rinstr() - find the rightmost occurence of one string within the other
rtrim$() - trim spaces at the right end of a string

ran()

Name

ran() — return a random number

Synopsis

+print ran()
+x=ran(y)
+

Description

The ran-function returns a random number. If no argument is given, the number returned is in the range from 0 to 1; where only 0 is a possible value; 1 will never be returned. If an argument is supplied, the number returned will be in the range from 0 up to this argument, whereas this argument itself is not a possible return value.

Example

+clear screen
+c=peek("screenwidth")-1
+l=peek("screenheight")
+
+dim col$(8)
+for a=0 to 7:read col$(a):next a
+data "black","white","red","blue","green","yellow","cyan","magenta"
+
+do
+  x=ran(c)
+  y=l-ran(l*exp(-32*((x/c-1/2)**2)))
+  i=i+1
+  print color(col$(mod(i,8))) at(x,y) "*";
+loop
+          

This example will print a cloured bell-curve.

See also

int

read

Name

read — read data from data-statements

Synopsis

+read a$,a
+…
+data "Hello !",7
+

Description

The read-statement retrieves literal data, which is stored within data-statements elsewhere in your program.

Example

+read num
+dim col$(num)
+for a=1 to num:read col$(a):next a
+clear screen
+print "These are the colours known to yabasic:\n"
+for a=1 to num
+  print colour(col$(a)) col$(a)
+next a
+
+data 8,"black","white","red","blue"
+data "green","yellow","cyan","magenta"
+          

This program prints the names of the colors known to yabasic in those very colors.

See also

data, restore

rectangle

Name

rectangle — draw a rectangle

Synopsis

+open window 100,100
+rectangle 10,10 to 90,90
+rectangle 20,20,80,80
+rect 20,20,80,80
+box 30,30,70,70
+clear rectangle 30,30,70,70
+fill rectangle 40,40,60,60
+clear fill rectangle 60,60,40,40
+

Description

The rectangle-command (also known as box or rect, for short) draws a recatangle; it accepts four parameters: The x- and y-coordinates of two facing cornerpoints of the rectangle. With the optional clauses clear and fill (which may appear both and in any sequence) the rectangle can be cleared and filled respectively.

Example

+open window 200,200
+c=1
+do 
+  for phi=0 to pi step 0.1
+    if (c) then 
+      rectangle 100+100*sin(phi),100+100*cos(phi) to 100-100*sin(phi),100-100*cos(phi)
+    else 
+      clear rectangle 100+100*sin(phi),100+100*cos(phi) to 100-100*sin(phi),100-100*cos(phi)
+    endif
+    sleep 0.1
+  next phi
+  c=not c
+loop
+          

This example draws a nice animated pattern; watch it for a couple of hours, to see how it develops.

redim

Name

redim — create an array prior to its first use. A synonym for dim

Synopsis

+See the dim-command.
+

Description

The redim-command does exactly the same as the dim-command; it is just a synonym. redim has been around in older versions of basic (not even yabasic) for many years; therefore it is supported in yabasic for compatibility reasons.

Please refer to the entry for the dim-command for further information.

rem

Name

rem — start a comment

Synopsis

+rem  Hey, this is a comment
+#    this is a comment too
+// even this
+print "Not a comment" #    This is an error !!
+print "Not a comment"://   But this is again a valid comment
+print "Not a comment" //   even this.
+print "Not a comment" rem  and this !
+

Description

rem introduces a comment (like # or //), that extends up to the end of the line.

Those comments do not even need a colon (':' infront of them); they (rem, # and //) all behave alike except for #, which may only appear at the very beginning of a line; therefore the fourth example in the synopsis above (print "Not a comment" # This is an error !!) is indeed an error.

Note, that rem is an abbreviation for remark. remark however is not a valid command in yabasic.

Finally note, that a comment intoduced with '#' may have a special meaning under unix; see the entry for # for details.

Example

+#
+rem   comments on data structures
+#     are more useful than
+//    comments on algorithms.
+rem
+          

This program does nothing, but in a splendid and well commented way.

See also

#, //

repeat

Name

repeat — start a repeat-loop

Synopsis

+repeat 
+  …
+until (…)
+

Description

The repeat-loop executes all the statements up to the final until-keyword over and over. The loop is executed as long as the condition, which is specified with the until-clause, becomes true. By construction, the statements within the loop are executed at least once.

Example

+x=0
+clear screen
+print "This program will print the numbers from 1 to 10"
+repeat
+  x=x+1
+  print x
+  print "Press any key for the next number, or 'q' to quit"
+  if (inkey$="q") break
+until(x=10)
+          

This program is pretty much useless, but self-explanatory.

See also

until, break, while, do

restore

Name

restore — reposition the data-pointer

Synopsis

+read a,b,c,d,e,f
+restore
+read g,h,i
+restore foo
+data 1,2,3
+label foo
+data 4,5,6
+

Description

The restore-command may be used to reset the reading of data-statements, so that the next read-statement will read data from the first data-statement.

You may specify a label with the restore-command; in that case, the next read-statement will read data starting at the given label. If the label is omitted, reading data will begin with the first data-statement within your program.

Example

+input "Which language (german/english) ? " l$
+if (instr("german",l$)>0) then
+  restore german
+else
+  restore english
+endif
+
+for a=1 to 3
+  read x,x$
+  print x,"=",x$
+next a
+
+label english
+data 1,"one",2,"two",3,"three"
+label german
+data 1,"eins",2,"zwei",3,"drei"
+          

This program asks to select one of those languages known to me (i.e. english or german) and then prints the numbers 1,2 and 3 and their textual equivalents in the chosen language.

See also

read, data, label

return

Name

return — return from a subroutine or a gosub

Synopsis

+gosub foo
+…
+label foo
+…
+return
+
+sub bar(baz)
+  …
+  return quertz
+end sub
+

Description

The return-statement serves two different (albeit somewhat related) purposes. The probably more important use of return is to return control from within a subroutine to the place in your program, where the subroutine has been called. If the subroutine is declared to return a value, the return-statement might be accompanied by a string or number, which constitutes the return value of the subroutine.

However, even if the subroutine should return a value, the return-statement need not carry a value; in that case the subroutine will return 0 or the empty string (depending on the type of the subroutine). Moreover, feel free to place multiple return-statements within your subroutine; it's a nice way of controlling the flow of execution.

The second (but historcially first) use of return is to return to the position, where a prior gosub has left off. In that case return may not carry a value.

Example

+do
+  read a$
+  if (a$="") then
+    print
+    end
+  endif
+  print mark$(a$)," ";
+loop
+
+data "The","quick","brown","fox","jumped"
+data "over","the","lazy","dog",""
+
+sub mark$(a$)
+  if (instr(lower$(a$),"q")) return upper$(a$)
+  return a$
+end sub
+          

This example features a subroutine mark$, that returns its argument in upper case, if it contains the letter "q", or unchanged otherwise. In the test-text the word quick will end up beeing marked as QUICK.

The example above demonstrates return within subroutines; please see gosub for an example of how to use return in this context.

See also

sub, gosub

reverse

Name

reverse — print reverse (background and foreground colors exchanged)

Synopsis

+clear screen
+…
+print reverse "foo"
+

Description

reverse may be used to print text in reverse. reverse is not a seperate command, but part of the print-command; it may be included just after the print and can only be issued once that clear screen has been issued.

Example

+clear screen
+
+print "1 ";
+c=3
+do
+  prim=true
+  for a=2 to sqrt(c)
+    if (frac(c/a)=0) then
+      prim=false
+      break
+    endif
+  next a
+  if (prim) then
+    print
+    print reverse c;
+  else
+    print c;
+  endif
+  print " ";
+  c=c+1
+loop
+          

This program prints numbers from 1 on and marks each prime number in reverse.

right$()

Name

right$() — return (or change) the right end of a string

Synopsis

+print right$(a$,2)
+right$(b$,2)="baz"
+

Description

The right$-function requires two arguments (a string and a number) and returns the part from the right end of the string, whose length is specified by its second argument. So, right$ simply returns the requested number of chars from the right end of the given string.

Note, that the right$-function can be assigned to, i.e. it may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the right$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below.

Example

+print "Please enter a length either in inch or centimeter"
+print "please add 'in' or 'cm' to mark the unit."
+input "Length: " a$
+if (right$(a$,2)="in") then
+   length=val(a$)*2.56
+elsif (right$(a$,2)="cm") then
+   length=val(a$)
+else
+   error "Invalid input: "+a$
+endif
+          

This program allows the user to enter a length qulified with a unit (either inch or centimeter).

This second example demonstrates the capability to assign to the right$-function.

+a$="Heiho World !"
+print a$
+right$(a$,7)="dwarfs."
+print a$
+

See also

right$ and mid$

rinstr()

Name

rinstr() — find the rightmost occurence of one string within the other

Synopsis

+pos=rinstr("Thequickbrownfox","equi")
+pos=rinstr(a$,b$,x)
+

Description

The rinstr-function accepts two string-arguments and tries to find the second within the first. However, unlike the instr, the rinstr-function finds the rightmost (or last) occurence of the string; whereas the instr-function finds the leftmost (or first) occurence. In any case however, the position is counted from the left.

If you supply a third, numeric argument to the rinstr-function, it will be used as a starting point for the search. Therefore rinstr("abcdeabcdeabcde","e",8) will return 5, because the search for an "e" starts at position 8 and finds the first one at position 5.

Example

+print rinstr("foofoofoobar","foo")
+          

This simple example will print 7, because it finds the rightmost among the three occurences of foo within the string. Note, that

+print instr("foofoofoobar","foo")
+

would have printed 1.

See also

instr

rtrim$()

Name

rtrim$() — trim spaces at the right end of a string

Synopsis

+a$=rtrim$(b$)
+

Description

The rtrim$-function removes all wthitespace from the right end of a string and returns the result.

Example

+open 1,"foo"
+dim lines$(100)
+l=1
+while(not eof(1))
+  input #1 a$
+  a$=rtrim$(a$)
+  if (right$(line$,1)="\\") then
+    line$=line$+" "+a$
+  else
+    lines$(l)=line$
+    l=l+1
+    line$=a$
+  endif
+end while
+print "Read ",l," lines"
+          

This example reads the file foo allowing for continuation lines, which are marked by a \, which appears as the last character on a line. For convenience whitespace at the right end of a line is trimmed with rtrim.

See also

ltrim$, trim$

S

Table of Contents

screen - as clear screen clears the text window
seek() - change the position within an open file
sig() - return the sign of its argument
sin() - return the sine of its single argument
sleep - pause, sleep, wait for the specified number of seconds
split() - split a string into many strings
sqr() - compute the square of its argument
sqrt() - compute the square root of its argument
static - preserves the value of a variable between calls to a subroutine
step - specifies the increment step in a for-loop
str$() - convert a number into a string
sub - declare a user defined subroutine
switch - select one of many alternatives depending on a value
system$() - hand a statement over to your operating system and return its output
system() - hand a statement over to your operating system and return its exitcode

screen

Name

screen — as clear screen clears the text window

Synopsis

+clear screen
+

Description

The keyword screen appears only within the sequence clear screen; please see there for a description.

See also

clear screen

seek()

Name

seek() — change the position within an open file

Synopsis

+open 1,"foo"
+seek #1,q
+seek #1,x,"begin"
+seek #1,y,"end"
+seek #1,z,"here"
+

Description

The seek-command changes the position, where the next input (or peek) statement will read from an open file. Usually files are read from the beginning to the end sequentially; however sometimes you may want to depart from this simple scheme. This can be done with the seek-command, allowing you to change the position, where the next piece of data will be read from the file.

seek accepts two or three arguments: The first one is the number of an already open file. The second one is the position where the next read from the file will start. The third argument is optional and specifies the the point from where the position (the second argument) will count. It can be one of:

begin

Count from the beginning of the file.

end

Count from the end of the file.

here

Count from the current position within the file.

Example

+open #1,"count.dat","w"
+for a=1 to 10
+  print #1,"00000000";
+  if (a<10) print #1,";";
+next a
+
+dim count(10)
+do
+  x=int(ran(10))
+  i=i+1
+  if (mod(i,1000)=0) print ".";
+  count(x)=count(x)+1
+  curr$=right$("00000000"+str$(count(x)),8)
+  seek #1,9*x,"begin"
+  print #1,curr$;
+loop
+          

This example increments randomly one of ten counters (in the array count()); however, the result is always kept and updated within the file count.dat, so even in case of an unexpected interrupt, the result will not be lost.

See also

tell, open, print, peek

sig()

Name

sig() — return the sign of its argument

Synopsis

+a=sig(b)
+

Description

Return +1, -1 or 0, if the single argument is positive, negative or zero.

Example

+clear screen
+dim c$(3):c$(1)="red":c$(2)="white":c$(3)="green"
+do
+  num=ran(100)-50
+  print color(c$(2+sig(num))) num
+loop
+          

This program prints an infinite sequence of random number; positive numbers are printed in green, negative numbers are printed red (an exact zero would be printed white). (With a little extra work, this program could be easily extended into a brogerage system)

See also

abs, int, frac

sin()

Name

sin() — return the sine of its single argument

Synopsis

+y=sin(angle)
+

Description

The sin-function expects an angle (in radian, not degree) and returns its sine.

Example

+open window 200,200
+new curve
+for phi=0 to 2*pi step 0.1
+  line to 100+90*sin(phi),100+90*cos(phi)
+next phi
+close curve
+          

This program draws a circle (ignoring the existence of the circle-command).

See also

asin, cos

sleep

Name

sleep — pause, sleep, wait for the specified number of seconds

Synopsis

+sleep 4
+

Description

The sleep-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yabasic will always do exactly the same.

Therefore you should refer to the entry for the pause-function for further information.

split()

Name

split() — split a string into many strings

Synopsis

+dim w$(10)
+…
+num=split(a$,w$())
+num=split(a$,w$(),s$)
+

Description

The split-function requires a string (containing the text to be split), a reference to a string-array (which will receive the resulting strings, i.e. the tokens) and an optional string (with a set of characters, at which to split, i.e. the delimiters).

The split-function regards its first argument (a string) as a list of tokens separated by delimiters and it will store the list of tokens within the array-reference you have supplied. Note, that the array, which is passed as a reference (w$() in the synopsis), will be resized accordingly, so that you don't have to figure out the number of tokens in advance. The element at position zero (i.e. w$(0)) will not be used.

normally (i.e. if you omit the third, which is the delimiter-argument) the function will regard space or tab as delimiters for tokens; however by supplying a third argument, you may split at any single of the characters within this string. E.g. if you supply ":;" as the third argument, then colon (:) or semicolon (;) will delimit tokens.

Note, that a sequence of separator-characters will produce a sequence of empty tokens; that way, the number of tokens returned will always be one plus the number of separator characters contained within the string. Refer to the closely related token-function, if you do not like this behaviour. In some way, the split-function focuses on the separators (other than the token-function, which focuses on the tokens), hence its name.

The second argument is a reference on a string-array, where the tokens will be stored; this array will be expanded (or shrinked) to have room for all tokens, if necessary.

The first argument finally contains the text, that will be split into tokens. The split-function returns the number of tokens that have been found.

Please see the examples below for some hints on the exact behaviour of the split-function and how it differs from the token-function:

Example

+print "This program will help you to understand, how the"
+print "split()-function exactly works and how it behaves"
+print "in certain special cases."
+print
+print "Please enter a line containing tokens separated"
+print "by either '=' or '-'"
+dim t$(10)
+do
+  print 
+  input "Please enter a line: " l$
+  num=split(l$,t$(),"=-")
+  print num," Tokens: ";
+  for a=1 to num
+    if (t$(a)="") then
+      print "(EMPTY)";
+    else 
+      print t$(a);
+    endif
+    if (a<num) print ","; 
+  next a
+  print
+loop
+          

This program prints the following output:

+

+Please enter a line: a
+1 Tokens: a
+
+Please enter a line:
+0 Tokens:
+
+Please enter a line: ab
+1 Tokens: ab
+
+Please enter a line: a=b
+2 Tokens: a,b
+
+Please enter a line: a-
+2 Tokens: a,(EMPTY)
+
+Please enter a line: a-=
+3 Tokens: a,(EMPTY),(EMPTY)
+
+Please enter a line: =a-
+3 Tokens: (EMPTY),a,(EMPTY)
+
+Please enter a line: a=-b
+3 Tokens: a,(EMPTY),b
+
+Please enter a line: a--b-
+4 Tokens: a,(EMPTY),b,(EMPTY)
+
+Please enter a line: -a==b-c==
+7 Tokens: (EMPTY),a,(EMPTY),b,c,(EMPTY),(EMPTY)
+
+

See also

token

sqr()

Name

sqr() — compute the square of its argument

Synopsis

+a=sqr(b)
+

Description

The sqr-function computes the square of its numerical argument (i.e. it multiplies its argument with itself).

Example

+for a=1 to 10
+  print a,sqr(a),a**2
+next a
+          

As you may see from the output, sqr can be written as **2 (or ^2) too.

See also

sqrt, **, ^

sqrt()

Name

sqrt() — compute the square root of its argument

Synopsis

to be written

Description

The sqrt-function computes the square root of its numerical argument.

Example

+for a=1 to 5
+  print a,sqrt(a),a**(1/2)
+next a
+          

As you may see from the output, sqrt can be written as **(1/2) (or ^(1/2)) too.

See also

sqr, **, ^

static

Name

static — preserves the value of a variable between calls to a subroutine

Synopsis

+sub foo()
+
+  static a
+
+  …
+
+end sub 
+

Description

The static keyword can be used within subroutines to mark variables as static. This has two effects: First, the variable is local to the subroutine, i.e. its value is not know outside the subroutine (this is the effect of the local keyword). Second, the static-keyword arranges things, so that the variable keeps its value between invocations of the subroutine (this is different from the local-keyword).

Example

+foo()
+foo()
+foo()
+
+sub foo()
+  static a
+  local b
+  a=a+1
+  b=b+1
+  print a,b
+end sub
+          

This program shows the difference between static and local variables within a subroutine; it produces this output:

+

1 1
+2 1
+3 1
+
+

The output shows, that the static variable a keeps its value between subroutine calls, whereas b is initialized with the value 0 at every call to the subroutine foo.

See also

sub, local

step

Name

step — specifies the increment step in a for-loop

Synopsis

+for a=1 to 10 step 3
+  …
+next a
+

Description

Specify, by which amount the loop-variable of a for-loop will be incremented at each step.

The step (as well as the lower and upper bound) are computed anew in each step; this is not common, but possible, as the example below demonstrates.

Example

+for x=1 to 1000 step y
+  y=x+y
+  print x," ",y," ";
+next x
+print
+          

This program computes the fibonacci numbers between 1 and 1000.

See also

for

str$()

Name

str$() — convert a number into a string

Synopsis

+a$=str$(a)
+b$=str$(x,"##.###")
+b$=str$(x,"###,###.##")
+b$=str$(x,"###,###.##","_.")
+

Description

The str$-function accepts a numeric argument and returns it as a string. This conversion between number and string can be controlled with the optional third argument (the format argument). See the following table of examples to learn about valid values of this argument. Note, that those examples fall in one of two categories: C-style and basic-style; the first 4 examples in the table below are C-style, the rest of the examples are basic-style. For more information on the C-style formats, you may refer to your favorite documentation on the C programming language. The basic-style formats are much simpler, they just depict the desired output, marking digits with '#'; groups of (usually three) digits may be separated with colons (','), the decimal dot must be marked by a literal dot ('.'). Moreover these characters (colons and dot) may be replaced by other characters to satisfy the needs of non-english (e.g. german) languages; see the examples below.

Note, that for clarity, each space in the result has been replaced by the letter 'x', because it would be hard to figure out, how many spaces are produced exactly otherwise.

Table 6.2. Examples for the format argument

Example stringResult for converting 1000*piDescription
%2.5f3141.59265The '2' determines the minimum length of the output; but if needed (as in the example) the output can be longer. The '5' is the number of digits after the decimal point.
%12.5fxx3141.59265Two spaces (which appear as 'x') are added to pad the output to the requested length of 12 characters.
%012.5g0000003141.6The 'g' requests, that the precision ('5') specifies the overall number of digits (before and after the decimal point).
%-12.5f3141.59265xxThe '-' requests the output to be left-centered (therefor the filling space appears at thi right).
#####.##x3141.59Each '#' specifies a digit (either before or after the dot), the '.' specifies the position of the dot. As 1000*pi does not have enough digits, the 5 requested digits before the dot are filled up with a space (which shows up as an 'x').
##,###.##x3,141.59Nearly the same as above, but the colon from the format shows up within the result.
##,###.## and an addtional argument of ".,"x3.141,59Similar to the example above, but colon and dot are replaced with dot and colon respectivly.
##,###.## and an addtional argument of "_,"x3_141,59Similar to the example above, but colon and dot are replaced with underscore and colon respectivly.
#####x3142The format string does not contain a dot, and therefore the result does not have any fractional digits.
##.#####.###As 1000*pi has 4 digits infront of the decimal dot and the format only specifies 2, yabasic does not know what to do; therefore it chooses just to reproduce the format string.

Example

+do
+  input "Please enter a format string: " f$
+  a$=str$(1000*pi,f$)
+  for a=1 to len(a$)
+    if (mid$(a$,a,1)=" ") mid$(a$,a,1)="x"
+  next a
+  print a$
+loop
+          

This is the program, that has been used to get the results shown in the table above.

See also

print, using

sub

Name

sub — declare a user defined subroutine

Synopsis

+foo(2,"hello")
+
+…
+
+sub foo(bar,baz$)
+  …
+  return qux
+  …
+end sub
+

Description

The sub-keyword starts the definition of a user defined subroutine. With user defined subroutines you are able to somewhat extend yabasic with your own commands or functions. A subroutine accepts arguments (numbers or strings) and returns a number or a string (however, you are not required to assign the value returned to a variable).

The name of the subroutine follows after the keyword sub. If the name (in the synopsis: foo) ends on a '$', the subroutine should return a string (with the return-statement), otherwise a number.

After the name of the subroutine yabasic requires a pair of braces; within those braces you may specify a list of parameters, for which values can (but need not) be included when calling the subroutine. If you omit one of those parameters when calling such a subroutine, it assumes the value zero (for numeric parameters) or the empty string (for string-parameters). However with peek("argument") you may find out, how many arguments have really been passed while calling the subroutine.

Parameters of a subroutine are always local variables (see the keyword local for more explanation).

From within the subroutine you may return any time with the keyword return; along with the return-keyword you may specify the return value. Note that more than one return is allowed within a single subroutine.

Finally, the keyword end sub ends the subroutine definition. Note, that the definition of a subroutine need not appear within the program before the first call to this sub.

Note

As braces have two uses in yabasic (i.e. for supplying arguments to a subroutine as well as to list the indices of an array). yabasic can not tell apart an array from a subroutine with the same name. Therefore you cannot define a subroutine with the same name as an array !

Example

+p=2
+do 
+  if (is_prime(p)) print p
+  p=p+1
+loop
+
+sub is_prime(a)
+  local b
+  for b=2 to sqrt(a)
+    if (frac(a/b)=0) return false
+  next b
+  return true
+end sub
+          

This example is not the recommended way to compute prime numbers. However it gives a nice demonstration of using a subroutine.

See also

local, static, peek

switch

Name

switch — select one of many alternatives depending on a value

Synopsis

+switch a
+  case 1
+  case 2
+  …
+end switch
+
+…
+
+switch a$
+  case "a"
+  case "b"
+end switch
+

Description

The switch-statment selects one of many codepaths depending on a numerical or string expression. I.e. it takes an expression (either numeric or string) and compares it with a series of values, each wrapped within a case-clause. If the expression equals the value given in a case-clause, the subsequent statements are executed.

The default-clause allows to specify commands, which should be executed, if none of case-clauses matches.

Note, that many case-clauses might be clustered (e.g. case "a":case "b":case "c"). Or put another way: You need a break-statement at the end of a case-branch, if you do not want to run into the next case.

Example

+input "Please enter a single digit: " n
+switch n
+  case 0:print "zero":break
+  case 1:print "one":break
+  case 2:print "two":break
+  case 3:print "three":break
+  case 4:print "four":break
+  case 5:case 6: case 7:case 8:case 9
+    print "Much !":break
+  default:print "Hey ! That was more than a single digit !"
+end switch 
+          

This example translates a single digit into a string; note, how the cases 5 to 7 are clustered.

See also

switch, case, break

system$()

Name

system$() — hand a statement over to your operating system and return its output

Synopsis

+print system$("dir")
+

Description

The system$-command accepts a single string argument, specifying a command, that can be found and executed by your operating system. It returns the output of this command as one big string.

Example

+input "Please enter the name of a directory: " d$
+print
+print "This is the contents of the '"+d$+"':"
+print system$("dir "+d$)
+          

This example lists the contents of a directory, employing the dir-command (which is about the only program, that is known under Unix as well as Windows).

See also

system

system()

Name

system() — hand a statement over to your operating system and return its exitcode

Synopsis

+ret=system("foo")
+system("bar")
+

Description

The system-command accepts a single string argument, which specifies a command to be executed. The function will return the exitcode of the command; its output (if any) will be lost.

Example

+print "Please enter the name of the file, that should be deleted."
+input f$
+if (system("rm "+f$+" >/dev/null 2>&1")) then
+  print "Error !"
+else
+  print "okay."
+endif
+          

This program is Unix-specific: It uses the Unix-command rm to remove a file.

See also

system$

T

Table of Contents

tan() - return the tangens of its argument
tell - get the current position within an open file
text - write text into your graphic-window
then - tell the long from the short form of the if-statement
time$ - return a string containing the current time
to - this keyword appears as part of other statements
token() - split a string into multiple strings
trim$() - remove leading and trailing spaces from its argument
true - a constant with the value of 1

tan()

Name

tan() — return the tangens of its argument

Synopsis

+foo=tan(bar)
+

Description

The tan-function computes the tangens of its arguments (which should be specified in radian).

Example

+for a=0 to 45
+  print tan(a*pi/180)
+next a
+          

This example simply prints the tangens of all angles between 0 and 45 degree.

See also

atan, sin

tell

Name

tell — get the current position within an open file

Synopsis

+open #1,"foo"
+  …
+position=tell(#1)
+

Description

The tell-function requires the number of an open file as an argument. It returns the position (counted in bytes, starting from the beginning of the file) where the next read will start.

Example

+open #1,"foo","w"
+print #1 "Hello World !"
+close #1
+
+open #1,"foo"
+seek #1,0,"end"
+print tell(#1)
+close 1
+          

This example (mis)uses tell to get the size of the file. The seek positions the file pointer at the end of the file, therefor the call to tell returns the total length of the file.

See also

tell, open

text

Name

text — write text into your graphic-window

Synopsis

+text x,y,"foo"
+text x,y,"foo","l"
+

Description

The text-function displays a text-string (the third argument) at the given position (the first two arguments) within an already opened window. There is no way to specify a font for the text, that will be written (this font can only be specified once, as an argument to the open window-statement).

The fourth, optional argument can be used to specify the alignment of the text with respect to the specified position. This argument is always two characters long: The first character specifies the horizontal alignment and can be either l, r or c, which stand for left, right or center. The second character specifies the vertical alignment and can be one of t, b or c, which stand for top, bottom or center respectively. If you omit this alignment argument, the default "lb" applies; however this default may be changed with poke "textalign","xx"

Example

+open window 500,200
+clear screen
+data "lt","lc","lb","ct","cc","cb","rt","rc","rb"
+for a=1 to 9
+  read align$	
+  print "Alignment: ",align$
+  line 50*a-15,100,50*a+15,100
+  line 50*a,85,50*a,115
+  text 50*a,100,"Test",align$
+  inkey$ 
+next a
+          

This program draws nine crosses and writes the same text at each; however it goes through all possible nine alignment strings, showing their effect.

then

Name

then — tell the long from the short form of the if-statement

Synopsis

+if (a<b) then
+  …
+endif
+

Description

The keyword then is part of the if-statement; please see there for further explanations. However, not every if-statement requires the keyword then: If the keyword then is present, the if-clause may extend over more than one line, and the keyword endif is required to end it. If the keyword then is not present, the if-statement extends up to the end of the line, and any endif would be an error.

Example

+if (1<2) then 
+  print "Hello ";
+endif
+
+if (2<3) print "world"
+if (2<1)
+  print "!"
+          

This example prints Hello world. Note, that no exclamation mark (!) is printed, which might come as a surprise and may be changed in future versions of yabasic.

See also

if

time$

Name

time$ — return a string containing the current time

Synopsis

+print time$
+print time$()
+

Description

The time$ function returns the current time in four fields separated by hyphens '-'. The fields are:

+

  • The current hour in the range from 0 to 23, padded with zeroes (e.g. 00 or 04) to a length of two characters.

  • The number of minutes, padded with zeroes.

  • The number of seconds, padded with zeroes.

  • The number of seconds, that have elapsed since the program has been started. This value encreases as long as your program runs and is therefore unbound and not padded with zeroes.

+

At the time of writing this documentation, time$ returns 22-58-53-0. Note, that the first three of the four fields returned by time$ have a fixed width; therefore it is easy to extract some fields with the usual string-functions mid$ (and others).

Example

+print "Hello it is ",time$
+print "An empty for-loop with ten million iterations takes ";
+s=val(mid$(time$,10))
+for a=1 to 10000000:next a
+e=val(mid$(time$,10))
+print e-s," seconds"
+          

This program benchmarks the for-loop and uses the fourth field of the string returned by time$.

See also

date

to

Name

to — this keyword appears as part of other statements

Synopsis

+for a=1 to 100 step 2
+  …
+next a
+
+line x,y to a,b
+

Description

The to-keyword serves two purposes (which are not related at all):

  • within for-statements, to specify the upper bound of the loop.

  • Within any graphical command (e.g. line), that requires two points (i.e. four numbers) as arguments, a comma ',' might be replaced with the keyword to. I.e. instead of 100,100,200,200 you may write 100,100 to 200,200 in such commands.

Example

Pleas see the command listed under "See also" for examples.

See also

for, line, rectangle

token()

Name

token() — split a string into multiple strings

Synopsis

+dim w$(10)
+…
+num=token(a$,w$())
+num=token(a$,w$(),s$)
+

Description

The token-function accepts a string (containing the text to be split), a reference to a string-array (which will receive the resulting strings, i.e. the tokens) and an optional string (with a set of characters, at which to split, i.e. the delimiters).

The token-function regards its first argument as a list of tokens separated by delimiters and it will store the list of tokens within the array-reference that has been supplied. Note, that the array, which is passed as a reference (w$() in the synopsis), will be resized accordingly, so that you don't have to figure out the number of tokens in advance. The element at position zero (i.e. w$(0)) will not be used.

Normally (i.e. if you omit the third, the delimiter-argument) the function will regard space or tab as delimiters for tokens; however by supplying a third argument, you may split at any single of the characters within this string. E.g. if you supply ":;" as the third argument, then colon (:) or semicolon (;) will delimit tokens.

Note, that token will never produce empty tokens, even if two or more separators follow in sequence. Refer to the closely related split-function, if you do not like this behaviour. In some way, the token-function focuses on the tokens and not on the separators (other than the split-function, which focuses on the separators).

The second argument is a reference on a string-array, where the tokens will be stored; this array will be expanded (or shrinked) as necessary to have room for all tokens.

The first argument finally contains the text, that will be split into tokens. The token-function returns the number of tokens, that have been found.

Please see the examples below for some hints on the exact behaviour of the token-function and how it differs from the split-function:

Example

+print "This program will help you to understand, how the"
+print "token()-function exactly works and how it behaves"
+print "in certain special cases."
+print
+print "Please enter a line containing tokens separated"
+print "by either '=' or '-'"
+dim t$(10)
+do
+  print 
+  input "Please enter a line: " l$
+  num=token(l$,t$(),"=-")
+  print num," Tokens: ";
+  for a=1 to num
+    if (t$(a)="") then
+      print "(EMPTY)";
+    else 
+      print t$(a);
+    endif
+    if (a<num) print ","; 
+  next a
+  print
+loop
+          
+ This program prints the following output: +

+

+Please enter a line: a
+1 Tokens: a
+
+Please enter a line:
+0 Tokens:
+
+Please enter a line: ab
+1 Tokens: ab
+
+Please enter a line: a=b
+2 Tokens: a,b
+
+Please enter a line: a-
+1 Tokens: a
+
+Please enter a line: a-=
+1 Tokens: a
+
+Please enter a line: =a-
+1 Tokens: a
+
+Please enter a line: a=-b
+2 Tokens: a,b
+
+Please enter a line: a--b-
+2 Tokens: a,b
+
+Please enter a line: -a==b-c==
+3 Tokens: a,b,c
+
+

See also

split

trim$()

Name

trim$() — remove leading and trailing spaces from its argument

Synopsis

+a$=trim$(b$)
+

Description

The trim$-function removes all whitespaces from the left and from the right end of a string and returns the result. Calling trim$ is equivalent to calling rtrim$(ltrim$()).

Example

+do
+  input "Continue ? Please answer yes or no: " a$
+  a$=lower$(trim$(a$))
+  if (len(a$)>0 and a$=left$("no",len(a$)) exit
+loop
+          

This example asks for an answer (yes or no) and removes spaces with trim$ to make the comparison with the string "no" more bulletproof.

See also

ltrim$, rtrim$

true

Name

true — a constant with the value of 1

Synopsis

+okay=true
+

Description

The constant true can be assigned to variables which will later appear in conditions (e.g. an if-statement.

true may also be written as TRUE or even TrUe.

Example

+input "Please enter a string of all upper letters: " a$
+if (is_upper(a$)) print "Okay"
+
+sub is_upper(a$)
+  if (a$=upper$(a$)) return true
+  return false
+end sub
+          

See also

false

U

Table of Contents

until - end a repeat-loop
upper$() - convert a string to upper case
using - Specify the format for printing a number

until

Name

until — end a repeat-loop

Synopsis

+repeat 
+  …
+until (…)
+

Description

The until-keyword ends a loop, which has been introduced by the repeat-keyword. until requires a condition in braces (or an expression, see here for details) as an argument; the loop will continue until this condition evaluates to true.

Example

+c=1
+s=1
+repeat
+  l=c
+  s=-(s+sig(s))
+  c=c+1/s
+  print c
+until(abs(l-c)<0.000001)
+          

This program calculates the sequence 1/1-1/2+1/3-1/4+1/5-1/6+1/7-1/8+ … ; please let me know, if you know against which value this converges.

See also

repeat

upper$()

Name

upper$() — convert a string to upper case

Synopsis

+u$=upper$(a$)
+

Description

The upper$-function accepts a single string argument and converts it to all upper case.

Example

+line input "Please enter a sentence without the letter 'e': " l$
+p=instr(upper$(l$),"E")
+if (p) then
+  l$=lower$(l$)
+  mid$(l$,p,1)="E"
+  print "Hey, you are wrong, see here!"
+  print l$
+else
+  print "Thanks."
+endif
+          

This program asks for a sentence and marks the first (if any) occurence of the letter 'e' by coverting it to upper case (in contrast to the rest of the sentence, which is converted to lower case).

See also

lower$

using

Name

using — Specify the format for printing a number

Synopsis

+print a using "##.###"
+print a using("##.###",",.")
+

Description

The using-keyword may appear as part of the print-statement and specifies the format (e.g. the number of digits before and after the decimal dot), which should be used to print the number.

The possible values for the format argument ("##.###" in the synopsis above) are described within the entry for the str$-function; especially the second line in the synopsis (print a using("##.###",",.")) will become clear after referring to str$. In fact the using clause is closely related to the str$-function; the former can always be rewritten using the latter; i.e. print foo using bar$ is always equivalent to print str$(foo,bar$). Therefore you should check out str$ to learn more.

Example

+for a=1 to 10
+  print sqrt(ran(10000*a)) using "#########.#####"
+next a
+          

This example prints a column of square roots of random number, nicely aligned at the decimal dot.

See also

print, str$

V

Table of Contents

val() - converts a string to a number

val()

Name

val() — converts a string to a number

Synopsis

+x=val(x$)
+

Description

The val-function checks, if the start of its string argument forms a floating point number and then returns this number. The string therefore has to start with digits (only whitespace infront is allowed), otherwise the val-function returns zero.

Example

+input "Please enter a length, either in inches (in) or centimeters (cm) " l$
+if (right$(l$,2)="in") then
+  l=val(l$)*2.51
+else
+  l=val(l$)
+print "You have entered ",l,"cm."
+          

This example queries for a length and checks, if it has been specified in inches or centimeters. The length is then converted to centimeters.

See also

str$

W

Table of Contents

wait - pause, sleep, wait for the specified number of seconds
wend - end a while-loop
while - start a while-loop
window origin - move the origin of a window

wait

Name

wait — pause, sleep, wait for the specified number of seconds

Synopsis

+wait 4
+

Description

The wait-command has many different names: You may write pause, sleep or wait interchangeable; whatever you write, yabasic will always do exactly the same.

Therefore you should refer to the entry for the pause-function for further information.

wend

Name

wend — end a while-loop

Synopsis

+while(a<b)
+  …
+wend
+

Description

The wend-keyword marks the end of a while-loop. Please see the while-keyword for more details.

wend can be written as end while or even end-while.

Example

+line input "Please enter a sentence: " a$
+p=instr(a$,"e")
+while(p)
+  mid$(a$,p,1)="E"
+  p=instr(a$,"e")
+wend
+print a$
+          

This example reads a sentence and converts every occurence of the letter e into uppercase (E).

See also

while (which is just the following entry).

while

Name

while — start a while-loop

Synopsis

+while(…)
+  …
+wend
+

Description

The while-keyword starts a while-loop, i.e. a loop that is excuted as long as the condition (which is specified in braces after the keyword while) evaluates to true.

Note, that the body of such a while-loop will not be executed at all, if the condition following the while-keyword is not true initially.

If you want to leave the loop prematurely, you may use the break-statement.

Example

+open #1,"foo"
+while(!eof(1))
+  line input #1 a$
+  print a$
+wend
+          

This program reads the file foo and prints it line by line.

See also

until, break, wend, do

window origin

Name

origin — move the origin of a window

Synopsis

+open window 200,200
+origin "cc"
+

Description

The origin-command applies to graphic windows and moves the origin of the coordinate system to one of nine point within the window. The normal position of the origin is in the upper left corner of the window; however in some cases this is inconvenient and moving the origin may save you from substracting a constant offset from all of your coordinates.

However, you may not move the origin to an arbitrary position; in horizontal possition there are only three positions: left, center and right, which are decoded by the letters l, c and r. In vertical position the allowed positions are top, center and bottom; encoded by the letters t, c and b. Taking the letters together, you arrive at a string, which might be passed as an argument to the command; e.g. "cc" or "rt".

Example

100,100 +
+open window 200,200
+window origin "cc"
+circle 0,0,60
+          

This example draws a circle, centered at the center of the window.

See also

open window

X

Table of Contents

xor() - compute the exclusive or

xor()

Name

xor() — compute the exclusive or

Synopsis

+x=xor(a,b)
+

Description

The xor computes the bitwise exclusive or of its two numeric arguments. To understand the result, both arguments should be viewed as binary numbers (i.e. a series of 0 and 1); a bit of the result will then be 1, if exactly one argument has a 1 and the other has a 0 at this position in their binary representation.

Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to and.

Example

+print xor(7,4)
+          

This will print 3. This result is obvious, if you note, that the binary representation of 7 and 4 are 111 and 100 respectively; this will yield 011 in binary representaion or 2 as decimal.

The eor-function is the same as the xor function; both are synonymous; however they have each their own description, so you may check out the entry of eor for a slightly different view.

See also

and, or, eor, not

Special characters

Table of Contents

# - either a comment or a marker for a file-number
// - starts a comment
@ - synonymous to at
: - separate commands from each other
; - suppress the implicit newline after a print-statement
** or ^ - raise its first argument to the power of its second

#

Name

# — either a comment or a marker for a file-number

Synopsis

+# This is a comment, but the line below not !
+open #1,"foo"
+

Description

The hash ('#') has two totally unrelated uses:

  • A hash might appear in commands related with file-io. yabasic uses simple numbers to refer to open files (within input, print, peek or eof). In those commands the hash may precede the number, which species the file. Please see those commands for further information and examples; the rest of this entry is about the second use (as a comment).

  • As the very first character within a line, a hash introduces comments (similar to rem).

'#' as a comment is common in most scripting languages and has a special use under Unix: If the very first line of any Unix-program begins with the character sequence '#!' ("she-bang", no spaces allowed), the rest of the line is taken as the program that should be used to execute the script. I.e. if your yabasic-program starts with '#!/usr/local/bin/yabasic', the program /usr/local/bin/yabasic will be invoked to execute the rest of the program. As a remark for windows-users: This mechanism ensures, that yabasic will be invoked to execute your program; the ending of the file (e.g. .yab) will be ignored by Unix.

Example

+# This line is a valid comment
+print "Hello " : # But this is a syntax error, because
+print "World!" : # the hash is not the first character !
+          

Note, that this example will produce a syntax error and is not a valid program !

See also

input, print, peek or eof, //, rem

//

Name

// — starts a comment

Synopsis

+//  This is a comment !
+

Description

The double-slash ('//') is (besides REM and '#') the third way to start a comment. '//' is the latest and greatest in the field of commenting and allows yabasic to catch up with such cool languages like C++ and Java.

Example

+// Another comment.
+print "Hello world !" // Another comment
+          

Unlike the example given for '#' this example is syntactically correct and will not produce an error.

See also

#, rem

@

Name

@ — synonymous to at

Synopsis

+clear screen
+…
+print @(a,b)
+

Description

As '@' is simply a synonym for at, please see at for further information.

See also

at

:

Name

: — separate commands from each other

Synopsis

+print "Hello ":print "World"
+

Description

The colon (':') separates multiple commands on a single line.

The colon and the newline-character have mostly the same effect, only that the latter, well, starts a new line too. The only other difference is their effect within the (so-called) short if, which is an if-statement without the keyword then. Please see the entry for if for more details.

Example

+if (a<10) print "Hello ":print "World !"
+          

This example demonstrates the difference between colon and newline as described above.

See also

if

;

Name

; — suppress the implicit newline after a print-statement

Synopsis

+print "foo",bar;
+

Description

The semicolon (';') may only appear at the last position within a print-statement. It supresses the implicit newline, which yabasic normally adds after each print-statement.

Put another way: Normally the output of each print-statement appears on a line by itself. If you rather want the output of many print-statements to appear on a single line, you should end the print-statement with a semicolon.

Example

+print "Hello ";:print "World !"
+          

This example prints Hello World ! in a single line.

See also

print

** or ^

Name

** or ^ — raise its first argument to the power of its second

Synopsis

+print 2**b
+print 3^4
+

Description

** (or ^, which is an exact synonym), is the arithmetic operator of exponentiation; it requires one number to its left and a second one to its right; ** then raises the first argument to the power of the second and returns the result. The result will only be computed if it yields a real number (as opposed to a complex number); this means, that the power can not be computed, if the first argument is negative and the second one is fractional. On the other hand, the second argument can be fractional, if the first one ist positive; this means, that ** may be used to compute arbitrary roots: e.g. x**0.5 computes the square root of x.

Example

+print 2**0.5
+          

See also

sqrt

Chapter 7. A grab-bag of some general concepts and terms

This chapter presents some general concepts and terms, which deserve a description on their own, but are not associated with a single command or function in yabasic. Most of these topics do not lend themselves to be read alone, rather they might be read (or skimmed) as background material if an entry from the alphabetical list of commands refers to them.

Logical shortcuts

Logical shortcuts are no special language construct and there is no keyword for them; they are just a way to evaluate logical expressions. Logical expressions (i.e. a series of conditions or comparisons joined by and or or) are only evaluated until the final result of the expression can be determined. An example:

+if (a<>0 and b/a>2) print "b is at least twice as big as a"
+

+ The logical expression a<>0 and b/a>2 consists of two comparisons, both of which must be true, if the print statement should be executed. Now, if the first comparison (a<>0) is false, the whole logical expression can never be true and the second comparison (b/a>2) need not be evaluated. +

This is exactly, how yabasic behaves: The evaluation of a composed logical expressions is terminated immediately, as soon as the final result can be deduced from the already evaluated parts.

In practice, this has the following consequences:

  • If two or more comparisons are joined with and and one comparison results in false, the logical expression is evaluated no further and the overall result is false.

  • If two or more comparisons are joined with or and one comparison results in true, the logical expression is evaluated no further and the result is true.

“Nice, but whats this good for ?”, I hear you say. Well, just have another look at the example, especially the second comparison (b/a>2); deviding b by a is potentially hazardous: If a equals zero, the expression will cause an error and your program will terminate. To avoid this, the first part of the comparison (a<>0) checks, if the second one can be evaluated without risk. This pre-checking is the most common usage and primary motivation for logical shortcuts (and the reason why most programming languages implement them).

Conditions and expressions

Well, bottomline there is no difference or distinction between conditions and expressions, at least as yabasic is concerned. So you may assign the result of comparisons to variables or use an arithmetic expression or a simple variable within a condition (e.g. within an if-statement). So the constructs shown in the example below are all totally valid:

+input "Please enter a number between 1 and 10: " a
+
+rem   Assigning the result of a comparison to a variable
+okay=a>=1 and a<=10
+
+rem   Use a variable within an if-statement
+if (not okay) error "Wrong, wrong !"
+

So conditions and expressions are really the same thing (at least as long as yabasic is concerned). Therefore the terms conditions and expression can really be used interchangeably, at least in theory. In reality the term condition is used in connection with if or while whereas the term expression tends to be used more often within arithmetic context.

References on arrays

References on arrays are the only way to refer to an array as a whole and to pass it to subroutines or functions like arraydim or arraysize. Whereas (for example) a(2) designates the second element of the array a, a() (with empty braces) refers to the array a itself. a() is called an array reference.

If you pass an array reference to one of your own subroutines, you need to be aware, that the subroutine will be able to modify the array you have passed in. So passing an array reference does not create a copy of the array; this has some interesting consequences:

  • Speed and space: Creating a copy of an array would be a time- and resourceconsuming operation; passing just a reference is cheap and fast.

  • Returning many values: A subroutine, that wants to give back more than one value, may require an array reference among its arguments and then store its many return values within this array. This is the only way to return more than one value from a subroutine.

Specifying Filenames under Windows

As you probably know, windows uses the character '\' to separate the directories within a pathname; an example would be C:\yabasic\yabasic.exe (the usual location of the yabasic executable). However, the very same character '\' is used to contstruct escape sequences, not only in yabasic but in most other programming languages.

Therefore the string "C:\t.dat" does not specify the file t.dat within the directory C:; this is because the sequence '\t' is translated into the tab-character. To specify this filename, you need to use the string "C:\\t.dat" (note the double slash '\\').

Escape-sequences

Escape-sequences are the preferred way of specifying 'special' characters. They ar intoduced by the '\'-character and followed by one of a few regular letters, e.g. '\n' or '\r' (see the table below).

Escape-sequences may occur within any string at any position; they are replaced at parsetime (opposed to runtime), i.e. as soon as yabasic discovers the string, with their corresponding special character. As a consequence of this len("\a") returns 1, because yabasic replaces "\a" with the matching special character just before the program executes.

Table 7.1. Escape sequences

Escape SeqenceMatching special character
\nnewline
\ttabulator
\vvertical tabulator
\bbackspace
\rcarriage return
\fformfeed
\aalert (i.e. a beeping sound)
\\backslash
\'single quote
\"double quote
\xHEXchr$(HEX) (see below)

Note, that an escape sequences of the form \xHEX allows to encode arbitrary + characters as long as you know their position (as a hex-number) within the + ascii-charset: + For example \x012 is transformed into the character chr$(18) (or chr$(dec("12",16)). Note that \x requires a + hexa-decimal number (and the hexa-decimal string "12" corresponds to the decimal number 18).

Creating a standalone program from your yabasic-program

Note

The bind-feature, which is described below, is at an experimental stage right now. It works (at least for me !) under Windows and Linux, but I cannot even promise it for other variants of Unix. However, if it does not work for your Unix, I will at least try to make it work, if you give me sufficient information of your system.

Sometimes you may want to give one of your yabasic-programs to other people. However, what if those other people do not have yabasic installed ? In that case you may create a standalone-program from your yabasic-program, i.e. an executable, that may be executed on its own, standalone, even (and especially !) on computers, that do not have yabasic installed. Having created a standalone program, you may pass it around like any other program (e.g. one written in C) and you can be sure that your program will execute right away.

Such a standalone-program is simply created by copying the full yabasic-interpreter and your yabasic-program (plus all the libraries it does import) together into a single, new program, whose name might be chosen at will (under windows of course it should have the ending .exe). If you decide to create a standalone-program, there are three bits in yabasic, that you may use:

  • The bind-command, which does the actual job of creating the standalone program from the yabasic-interpreter and your program.

  • The command-line Option -bind (available under windows and Unix), which does the same from the command-line.

  • The special peek("isbound"), which may be used to check, if the yabasic-program containing this peek is bound to the interpreter as part of a standalone program.

With these bits you know enough to create a standalone-program. Actually there are two ways to do this: on the commandline and from within your program.

Creating a standalone-program from the commandline

Let's say you have the following very simple program within the file foo.yab:

+print "Hello World !"
+

Normally you would start this yabasic-program by typing yabasic foo.yab and as a result the string Hello World ! would appear on your screen. However, to create a standalone-program from foo.yab you would type:

yabasic -bind foo.exe foo.yab

This command does not execute your program foo.yab but rather create a standalone-program foo.exe. Note: under Unix you would probably name the standalone program foo or such, omitting the windows-specific ending .exe.

Yabasic will confirm by printing something like: ---Info: Successfully bound 'yabasic' and 'foo.yab' into 'foo.exe'.

After that you will find a program foo.exe (which must be made executable with the chmod-command under Unix first). Now, executing this program foo.exe (or foo under Unix) will produce the output Hello World !.

This newly created program foo.exe might be passed around to anyone, even if he does not have yabasic installed.

Creating a standalone-program from within your program

It is possible to write a yabasic-program, that binds itself to the yabasic-interpreter. Here is an example:

+if (!peek("isbound")) then
+  bind "foo"
+  print "Successfully created the standalone executable 'foo' !"
+  exit
+endif
+
+print "Hello World !"
+

If you run this program (which may be saved in the file foo.yab) via yabasic foo.yab, the peek("isbound") in the first line will check, if the program is already part of a standalone-program. If not (i.e. if the yabasic-interpreter and the yabasic-program are seperate files) the bind-command will create a standalone program foo containing both. As a result you would see the output Successfully created the standalone executable 'foo' !. Note: Under Windows you would probably choose the filename foo.exe.

Now, if you run this standalone executable foo (or foo.exe), the very same yabasic-program that is shown above will be executed again. However, this time the peek("isbound") will return TRUE and therefore the condition of the if-statement is false and the three lines after then are not executed. Rather the last print-statement will run, and you will see the output Hello World !.

That way a yabasic-program may turn itself into a standalone-program.

Downsides of creating a standalone program

Now, before you go out and turn all your yabasic-programs into standalone programs, please take a second to consider the downsides of doing so:

  • The new standalone program will be at least as big as the interpreter itself, so you need to pass a few hundred kilobytes around, just to save people from having to install yabasic themselves.

  • There is no easy way to extract your yabasic-program from within the standalone program: If you ever want to change it, you need to have it around seperately.

  • If a new version of yabasic becomes available, again you need to recreate all of your standalone programs to take advantage of bugfixes and improvements.

So, beeing able to create a standalone program is certainly a good thin, but certainly not a silver bullet.

See also

The bind-command, the peek-function and the commandline options for Unix and Windows.

Chapter 8. A few example programs

A very simple program

The program below is a very simple program:

+repeat
+  input "Please enter the first number, to add " a
+  input "Please enter the second number, to add " b
+  print a+b
+until(a=0 and b=0)
+

This program requests two numbers, which it than adds. The process is repeated until you enter zero (or nothing) twice.

A part of the demo of yabasic

The listing below is an abbreviated and slightly refreshed version of the demo of yabasic. However this demo has been written before some of the more advanced features of yabasic have been implemented. For example subroutines have only been retrofitted on the original version of this demo. So please do not take this as a particular good example of yabasic-code. On the other hand: This is no beauty contest. However you could make it one, if you send me some better code (which should do nice and simple things with less than 200 lines).

+
+//
+//	This program demoes yabasic
+//
+
+
+// 	Check, if screen is large enough
+clear screen
+sw=peek("screenwidth"):sh=peek("screenheight")
+if (sw<78 or sh<24) then
+  print
+  print "  Sorry, but your screen is to small to run this demo !"
+  print
+  end
+endif
+sw=78:sh=24
+
+//  Initialize everything
+restore mmdata
+read mmnum:dim mmtext$(mmnum)
+for a=1 to mmnum:read mmtext$(a):next a
+
+//  Main loop selection of demo
+ysel=1
+label mainloop
+clear screen
+print colour("cyan","magenta") at(7,2) "################################"
+print colour("cyan","magenta") at(7,3) "################################"
+print colour("cyan","magenta") at(7,4) "################################"
+print colour("yellow","blue") at(8,3) " This is the demo for yabasic "
+yoff=7
+for a=1 to mmnum
+  if (a=mmnum) then ydisp=1:else ydisp=0:fi
+  if (a=ysel) then
+    print colour("blue","green") at(5,yoff+ydisp+a) mmtext$(a);
+  else
+    print at(5,yoff+ydisp+a) mmtext$(a);
+  endif
+next a
+print at(3,sh-3) "Move selection with CURSOR KEYS (or u and d),"
+print at(3,sh-2) "Press RETURN or SPACE to choose, ESC to quit."
+
+
+do    // loop for keys pressed
+  rev=1
+  do    // loop for blinking
+    k$=inkey$(0.4)
+    if (k$="") then
+      if (ysel=mmnum) then
+        if (rev=1) then 
+          print colour("blue","green") at(5,yoff+mmnum+1) mmtext$(mmnum);
+          rev=0
+        else
+          print colour("yellow","red") at(5,yoff+mmnum+1) mmtext$(mmnum);
+          rev=1
+        endif
+      endif
+    else    // key has been pressed, leave loop
+      break
+    endif
+  loop    // loop for blinking
+
+  yalt=ysel
+  if (k$="up" or k$="u") then 
+    if (ysel=1) then ysel=mmnum else ysel=ysel-1 fi
+    redraw():heal():continue
+  fi
+  if (k$="down" or k$="d") then 
+    if (ysel=mmnum) then ysel=1 else ysel=ysel+1 fi
+    redraw():heal():continue
+  fi
+  if (k$=" " or k$="enter" or k$="right") then 
+    on ysel gosub overview,bitmap,endit,notyet
+    goto mainloop
+  fi
+  if (k$="esc") then
+    endit()
+  fi
+  beep
+  print at(3,sh-5) "Invalid key: ",k$,"         "
+loop    // loop for keys pressed
+
+
+//  redraw line
+sub redraw()
+  if (yalt=mmnum) then ydisp=1:else ydisp=0:fi
+  print at(5,yoff+yalt+ydisp) mmtext$(yalt);
+  if (ysel=mmnum) then ydisp=1:else ydisp=0:fi
+  print colour("blue","green") at(5,yoff+ysel+ydisp) mmtext$(ysel);
+  return
+end sub
+
+
+//  erase a line
+sub heal()
+  print at(3,sh-5) "                                                       "
+  return
+end sub
+
+
+//  Go here to exit
+label endit
+  print at(3,sh-8) "Hope you liked it ...\n   ";
+  exit
+return
+
+
+//  Present a short overview
+label overview
+  clear screen
+  print "\n  Yabasic is a quite traditional basic: It comes with"
+  print "  print, input, for-next-loops, goto, gosub, while and"
+  print "  repeat and even user defined procedures and libraries."
+  print "\n  Yabasic has the usual functions, from sin(), int() to mid$();"
+  print "  more advanced functions are date$ (is ",date$,"),"
+  print "  or token$(), system$(), ran() and glob$()."
+  print "\n  Yabasic makes it easy to open a window, draw lines"
+  print "  and print the resulting picture."
+  print "\n  Yabasic programs are interpreted and run under Unix"
+  print "  and Windows. Yabasic is small (around 200k) and"
+  print "  free, i.e. subject to the GNU copyleft."
+  print "\n  Finally, this demo itself is written in yabasic and"
+  print "  gives an idea of what can be done with the language."
+  print "\n\n\n  While you read this, I am calculating prime numbers,"
+  print "  Press any key to return to main menu ..."
+  can=1
+  print at(6,19) "This is a prime number: "
+  label nextcan
+  can=can+2
+  for i=2 to sqrt(can):if (frac(can/i)=0) then goto notprime:fi:next i
+  print at(32,19) can;
+  label notprime
+  if (lower$(inkey$(0))<>"") then return:fi
+goto nextcan
+
+
+//  Show some animated bitmaps
+label bitmap
+  clear screen
+  print at(5,5) "Yabasic offers limited support for bitmapped graphics."
+  print at(5,6) "You can retrieve and alter rectangular regions of"
+  print at(5,7) "the graphics window with a single command."
+  print reverse at(5,12) " Press any key to return to main menu ... "
+  n=20
+  open window 400,400
+  if (picsinitialized=0) then
+    picsinitialized=1
+    dim pics(n,4)
+    dim pics$(5)
+    restore pics
+    for a=1 to 5:read pics$(a):next a
+  endif
+  tick=1
+  for a=1 to n:pics(a,4)=0:next a
+  cx=ran(370):cy=ran(370):vx=10-ran(20):vy=10-ran(20)
+  label picloop
+    for a=1 to n
+      if (pics(a,4)<=tick) then
+        if (pics(a,4)=tick) then
+          bitblit pics$(pics(a,3)) to pics(a,1),pics(a,2),"xor"
+        endif
+        x=cx+50-ran(100):y=cy+50-ran(100)
+        if (ran(10)>3) then
+          pics(a,1)=x:pics(a,2)=y:pics(a,3)=ran(5)+1
+          pics(a,4)=tick+4+int(ran(4))
+    bitblit pics$(pics(a,3)) to pics(a,1),pics(a,2),"xor"          
+        endif
+      endif
+    next a
+    tick=tick+1
+    cx=cx+vx:cy=cy+vy
+    if (cx<-30 or cx>400) then cx=cx-vx:vx=-vx fi
+    if (cy<-30 or cy>400) then cy=cy-vy:vy=-vy fi
+  if (inkey$(0.1)="") then goto picloop fi
+  close window
+return
+
+
+//  data for bitmaps
+label pics
+data "24,24:00000000000000000000000008f1000eff000fff308f9f30cf0c70e30870e30070e00070e07070e07870e0fc70e1ff30e1ff3ec1cf1ec3000fc700cf8f3cf78ffff30efff000ff00"
+data "24,24:00c10000e10000f10000f10008f30008f30008f700fff700ffff30ffffffefffffefffff0ffff70eff700eff000cff100eff300fff70cfff70ef7ef1ef1cf3e700e3e100c3000000"
+data "24,24:0000000000700e00700e00700e00700e10700e38700c38700c7c30087c3000fe1000ff1000ef0000e70000c70000c30000c30000e10000f10000f0000c70000c70000c3000000000"
+data "24,24:000000000000008700008f30008f7000cf7000c37000e97000f97000f83008f8300878300cf8300ef8300efb300eef700fcf700f0f708700f0c700f1c300e1c100e1000000000000"
+data "24,24:0000000000000cf1000cff000cff300cbf300c3c700838700c30700cff700cff700cff700c9f700c1c700e10700e10700f38708fff708fff7083ff10000000000000000000000000"
+
+
+//  Go here for a feature not yet implemented
+label notyet
+  clear screen
+  print "\n\n  Sorry this section is not yet implemented !"
+  print "  Press any key to return to main menu ..."
+  inkey$
+return
+
+
+//  Data section ...
+label mmdata
+//  Data for main menu: Number and text of entries in main menu
+data 3
+data " Yabasic in a nutshell "
+data " Animated Bitmaps "
+data " Exit this demo "
+
+   

Chapter 9. The Copyright of yabasic

yabasic may be copied only under the terms of the Artistic License or the GNU General Public License (GPL), both of which are distributed with yabasic.

[Can't you make up your mind ?!], I hear you say. Umm, well yes. In fact I do not want to read or try to understand them both, so I have put the burden on you (grin). However, I think that the Artistic License is more liberal and gives you more rights and you should choose it; on the other hand the GPL is more widely known and a lot of software is distributed under its terms.

Here is a list of things that are possible under the terms of the Artistic License:

  • Put yabasic on your own homepage or CD and even charge for the service of distributing yabasic.

  • Write your own yabasic-programs, pack your program and yabasic into a package and sell the whole thing.

  • Modify yabasic and add or remove features, sell the modified version.

diff --git a/Localizer/Language/de.catalog b/Localizer/Language/de.catalog new file mode 100644 index 0000000..35853f0 --- /dev/null +++ b/Localizer/Language/de.catalog @@ -0,0 +1,66 @@ +1 de x-vnd.Localizer 1483942934 +File Datei +Help Hilfe +New... Neu... +Import ZETA... Importiere aus ZETA... +Mime Type Mime-Typ +English Source Englischer Quelltext +Target Language Code Zielsprachencode +Add Phrase Zeile hinzufügen +Cancel Abbrechen +Commit Ändern +Open... Öffnen... +Save... Speichern... +Save and Install... Speichern und Installieren... +Quit Beenden +Help... Hilfe... +About... Über... +Localizer for Haiku\n\n2011 by Jan Bungeroth Localizer für Haiku\n\n2011 von Jan Bungeroth +Ok Ok +Saving catalog completed.\n\nSaved to Katalog erfolgreich gespeichert.\n\nGespeichert in +All existing data will be lost!\n\nAre you sure? Alle Daten werden gelöscht!\n\nSind Sie sicher? +Yes Ja +No Nein +Error reading file\n Fehler beim Einlesen\n +Duplicate source lines were skipped. Doppelte Zeilen wurden ignoriert. +Mime type invalid.\n\nA valid mime type has the form:\nx-vnd.ApplicationName Mime-Typ ungültig.\n\nEin gültiger Mime-Typ hat die Form:\nx-vnd.ApplicationName +Error writing file\n Fehler beim Schreiben\n +Error reading or writing file\n Fehler beim Lesen oder Schreiben\n +No target language specified.\nOnly the English catalog was generated. Keine Zielsprache angegeben.\nNur der englische Katalog wurde erstellt. +Catalogs saved and installed. Kataloge gespeichert und installiert. +Open Catalog Öffne Katalog +Import ZETA Locale Importiere ZETA Lokalisierung +Select Save Directory Wähle Zielverzeichnis +Delete Löschen +Close Schließen +Localizer helps you to bring localization to your Haiku applications.\n\n Localizer hilft bei der Lokalisierung deiner Haiku Programme.\n\n +Localization is done using special catalog files. These catalog files are then compiled into BMessages and stored in a specific directory. The directory and the catalog files are signed by an application mimetype.\n\n Die Lokalisierung wird mit speziellen Katalogdateien umgesetzt. Diese Dateien werden zu BMessages umgewandelt und in einem speziellen Verzeichnis abgelegt. Das Verzeichnis und die Kataloge werden über den Mime-Typ signiert.\n\n +How to use Localizer:\n\n So funktioniert Localizer:\n\n +1. Add the English strings of your program to the left list and their translations into the right list.\n\n 1. Füge die englischen Strings aus deinem Programm in die linke Liste ein, die übersetzten Strings in die rechte Liste.\n\n +2. Enter the translation short code for the target language and the mimetype of your program.\n\n 2. Trage das Sprachkürzel und den Mime-Typ deines Programmes ein.\n\n +3. 'Save and Install' will save your translations locally and install their compiled version to /boot/common/data/locale/catalogs\n\n 3. 'Speichern und Installieren' speichert deine Übersetzungen und installiert die kompilierten Kataloge nach /boot/common/data/locale/catalogs\n\n +Make sure, both lists are also in sync!\n\n Achte darauf, daß beide Listen synchron sind!\n\n +The language code consists of a two letter country code (e.g. de for Germany or nl for Netherlands) or a combined code if the language code differs from the country code (e.g. nl_be for Dutch in Belgium).\n\n Das Sprachkürzel besteht aus einem Code für das Land (z.B. de für Deutschland) und einem Sprachcode, wenn dieser vom Ländercode abweicht (z.B. nl_be für Niederländisch in Belgien).\n\n +The mimetype identifies the application. An application mimetype usually has the format: x-vnd.ApplicationName Der Mime-Typ identifiziert die Applikation. Ein Applikations-Mime-Typ hat das Format: x-vnd.ApplikationsName +Importing ZETA locale files:\n\n Import von ZETA-Lokalisierungen:\n\n +Localizer allows you to import old ZETA locale files.\n\n Localizer erlaubt den Import von alten ZETA-Lokalisierungsdateien.\n\n +Currently Localizer does feature context support, so all source strings are allowed only once. If there are several equal English strings in the ZETA file, only the first one is imported. The others are ignored.\n\n Zur Zeit unterstützt Localizer noch keinen Context, deshalb dürfen Quelltexte nur einmal vorkommen. Sollte ein englischer String mehrfach in einer ZETA-Datei vorkommen, wird nur der erste verwendet.\n\n +Localizer supports ZETA files using the format:\n Localizer unterstützt das folgende ZETA-Format:\n + \"English string\" \"Target string\"\n\n \"Englischer String\" \"Übersetzung\"\n\n +And also this format:\n Und außerdem noch folgendes Format:\n + \"_key\" = \"English string\"\n \"_key\" = \"Englischer String\"\n + \"_value\" = \"Target string\"\n \"_value\" = \"Übersetzung\"\n +(Note: _key and _value need to be on separate lines.) (Achtung: _key und _value müssen jeweils in einer eigenen Zeile stehen.) +How to use localization in yab programs:\n\n Lokalisierung in yab-Programmen:\n\n +First you have to load the locale catalog with the mimetype name:\n localize \"x-vnd.MyApplication\"\n\n Zuerst wird der Lokalisierungskatalog mit einem Mime-Typ geladen:\n localize \"x-vnd.MeineApplikation\"\n\n +All widgets will now automatically translate all their strings.\n\n Alle Strings in Widgets werden jetzt automatisch übersetzt.\n\n +To translate a specific string use:\n translate$(myString$)\n\n Um gezielt einen String zu übersetzen, verwende:\n translate$(meinString$)\n\n +A new feature allows you to turn the automatic translation of widget strings off and on again.\n Eine neue Erweiterung läßt dich die Lokalisierung aus- und einschalten.\n +To turn the automatic translation off, use:\n localize stop\n\n Um die Übersetzung auszuschalten, verwende:\n localize stop\n\n +To turn it on again, use:\n localize Um sie wieder einzuschalten, verwende:\n localize +How to use localization in C++ programs:\n\n Lokalisierung in C++-Programmen:\n\n +First, include Catalog.h and Locale.h:\n #include \n #include \n\n Zunächst müssen Catalog.h und Locale.h eingebunden werden:\n #include \n #include \n\n +Within your code, now you can simply translate a string with:\n B_TRANSLATE(myString);\n\n Im Code kann man dann einfach einen String folgendermaßen übersetzen:\n B_TRANSLATE(meinString);\n\n +The locale kit will search for the catalog files associated with your application's signature mimetype.\n\n Das Locale Kit wird die passenden Katalogdateien zum Mime-Typ deiner Applikationssignatur suchen.\n\n +To link your program, add the locale and localestub libraries:\n -l locale -l localestub Um dein Programm zu linken, verwenden die Libraries locale und localestub:\n -l locale -l localestub +To translate a string separated with colons : use:\n menu translate$(myString$)\nThis is useful for translating menu entries because menu messages are separated with :\n\n Um Strings zu übersetzen, die mit einem Doppelpunkt : getrennt sind, verwende:\n menu translate$(meinString$)\nDas ist besonders bei den Menü-Messages sinnvoll, weil diese mit einem : getrennt werden.\n\n diff --git a/Localizer/Language/en.catalog b/Localizer/Language/en.catalog new file mode 100644 index 0000000..40c045d --- /dev/null +++ b/Localizer/Language/en.catalog @@ -0,0 +1,66 @@ +1 english x-vnd.Localizer 1483942934 +File File +Help Help +New... New... +Import ZETA... Import ZETA... +Mime Type Mime Type +English Source English Source +Target Language Code Target Language Code +Add Phrase Add Phrase +Cancel Cancel +Commit Commit +Open... Open... +Save... Save... +Save and Install... Save and Install... +Quit Quit +Help... Help... +About... About... +Localizer for Haiku\n\n2011 by Jan Bungeroth Localizer for Haiku\n\n2011 by Jan Bungeroth +Ok Ok +Saving catalog completed.\n\nSaved to Saving catalog completed.\n\nSaved to +All existing data will be lost!\n\nAre you sure? All existing data will be lost!\n\nAre you sure? +Yes Yes +No No +Error reading file\n Error reading file\n +Duplicate source lines were skipped. Duplicate source lines were skipped. +Mime type invalid.\n\nA valid mime type has the form:\nx-vnd.ApplicationName Mime type invalid.\n\nA valid mime type has the form:\nx-vnd.ApplicationName +Error writing file\n Error writing file\n +Error reading or writing file\n Error reading or writing file\n +No target language specified.\nOnly the English catalog was generated. No target language specified.\nOnly the English catalog was generated. +Catalogs saved and installed. Catalogs saved and installed. +Open Catalog Open Catalog +Import ZETA Locale Import ZETA Locale +Select Save Directory Select Save Directory +Delete Delete +Close Close +Localizer helps you to bring localization to your Haiku applications.\n\n Localizer helps you to bring localization to your Haiku applications.\n\n +Localization is done using special catalog files. These catalog files are then compiled into BMessages and stored in a specific directory. The directory and the catalog files are signed by an application mimetype.\n\n Localization is done using special catalog files. These catalog files are then compiled into BMessages and stored in a specific directory. The directory and the catalog files are signed by an application mimetype.\n\n +How to use Localizer:\n\n How to use Localizer:\n\n +1. Add the English strings of your program to the left list and their translations into the right list.\n\n 1. Add the English strings of your program to the left list and their translations into the right list.\n\n +2. Enter the translation short code for the target language and the mimetype of your program.\n\n 2. Enter the translation short code for the target language and the mimetype of your program.\n\n +3. 'Save and Install' will save your translations locally and install their compiled version to /boot/common/data/locale/catalogs\n\n 3. 'Save and Install' will save your translations locally and install their compiled version to /boot/common/data/locale/catalogs\n\n +Make sure, both lists are also in sync!\n\n Make sure, both lists are also in sync!\n\n +The language code consists of a two letter country code (e.g. de for Germany or nl for Netherlands) or a combined code if the language code differs from the country code (e.g. nl_be for Dutch in Belgium).\n\n The language code consists of a two letter country code (e.g. de for Germany or nl for Netherlands) or a combined code if the language code differs from the country code (e.g. nl_be for Dutch in Belgium).\n\n +The mimetype identifies the application. An application mimetype usually has the format: x-vnd.ApplicationName The mimetype identifies the application. An application mimetype usually has the format: x-vnd.ApplicationName +Importing ZETA locale files:\n\n Importing ZETA locale files:\n\n +Localizer allows you to import old ZETA locale files.\n\n Localizer allows you to import old ZETA locale files.\n\n +Currently Localizer does feature context support, so all source strings are allowed only once. If there are several equal English strings in the ZETA file, only the first one is imported. The others are ignored.\n\n Currently Localizer does feature context support, so all source strings are allowed only once. If there are several equal English strings in the ZETA file, only the first one is imported. The others are ignored.\n\n +Localizer supports ZETA files using the format:\n Localizer supports ZETA files using the format:\n + \"English string\" \"Target string\"\n\n \"English string\" \"Target string\"\n\n +And also this format:\n And also this format:\n + \"_key\" = \"English string\"\n \"_key\" = \"English string\"\n + \"_value\" = \"Target string\"\n \"_value\" = \"Target string\"\n +(Note: _key and _value need to be on separate lines.) (Note: _key and _value need to be on separate lines.) +How to use localization in yab programs:\n\n How to use localization in yab programs:\n\n +First you have to load the locale catalog with the mimetype name:\n localize \"x-vnd.MyApplication\"\n\n First you have to load the locale catalog with the mimetype name:\n localize \"x-vnd.MyApplication\"\n\n +All widgets will now automatically translate all their strings.\n\n All widgets will now automatically translate all their strings.\n\n +To translate a specific string use:\n translate$(myString$)\n\n To translate a specific string use:\n translate$(myString$)\n\n +A new feature allows you to turn the automatic translation of widget strings off and on again.\n A new feature allows you to turn the automatic translation of widget strings off and on again.\n +To turn the automatic translation off, use:\n localize stop\n\n To turn the automatic translation off, use:\n localize stop\n\n +To turn it on again, use:\n localize To turn it on again, use:\n localize +How to use localization in C++ programs:\n\n How to use localization in C++ programs:\n\n +First, include Catalog.h and Locale.h:\n #include \n #include \n\n First, include Catalog.h and Locale.h:\n #include \n #include \n\n +Within your code, now you can simply translate a string with:\n B_TRANSLATE(myString);\n\n Within your code, now you can simply translate a string with:\n B_TRANSLATE(myString);\n\n +The locale kit will search for the catalog files associated with your application's signature mimetype.\n\n The locale kit will search for the catalog files associated with your application's signature mimetype.\n\n +To link your program, add the locale and localestub libraries:\n -l locale -l localestub To link your program, add the locale and localestub libraries:\n -l locale -l localestub +To translate a string separated with colons : use:\n menu translate$(myString$)\nThis is useful for translating menu entries because menu messages are separated with :\n\n To translate a string separated with colons : use:\n menu translate$(myString$)\nThis is useful for translating menu entries because menu messages are separated with :\n\n diff --git a/Localizer/Localizer.yab b/Localizer/Localizer.yab new file mode 100755 index 0000000..9b6b450 --- /dev/null +++ b/Localizer/Localizer.yab @@ -0,0 +1,645 @@ +#!yab + +doc Author: Jan Bungeroth +doc (c) 2011 in terms of the Artistic License +doc +doc The Localizer helps you to localize your yab applications +doc and import old Zeta localizations. + +localize "x-vnd.Localizer" + +INSTALLPATH$ = "/boot/common/data/locale/catalogs" +mime$ = "x-vnd." +lastdir$ = "/boot/home" +targetLang$ = "" + +OpenMainWindow() +MainMessageLoop() +CloseWindows() + +sub MainMessageLoop() + local finished, i, j, n, selected, tmp + local tmp$, t$ + + dim msg$(1) + while(not finished) + n = split(message$, msg$(), "|") + + for i = 1 to n + // if(msg$(i) <> "") print msg$(i) + + // menu + switch(msg$(i)) + case menu translate$("MainWindow:File:New...") + NewLocale() + break + case menu translate$("MainWindow:File:Open...") + OpenLocale() + break + case menu translate$("MainWindow:File:Import ZETA...") + ImportZETA() + break + case menu translate$("MainWindow:File:Save...") + if(SaveLocale()) then + alert translate$("Saving catalog completed.\n\nSaved to ") + lastdir$, "Ok", "info" + endif + break + case menu translate$("MainWindow:File:Save and Install...") + if(SaveLocale()) then + InstallLocale() + endif + break + case menu translate$("MainWindow:File:Quit") + case "MainWindow:_QuitRequested" + case "_QuitRequested" + finished = true + break + case menu translate$("MainWindow:Help:Help...") + Help() + break + case menu translate$("MainWindow:Help:About...") + About() + break + end switch + + // textcontrols + if(left$(msg$(i), 6) = "AddSrc") then + tmp$ = right$(msg$(i), len(msg$(i)) - 7) + selected = 0 + for j = 1 to listbox count "SrcList" + t$ = listbox get$ "SrcList", j + if(t$ = tmp$) then + selected = j + break + endif + next j + if(selected = 0) then + localize stop + listbox add "SrcList", tmp$ + localize + selected = listbox count "SrcList" + endif + listbox select "SrcList", selected + if(listbox count "TgtList" >= selected) then + listbox select "TgtList", selected + else + listbox select "TgtList", 0 + endif + end if + if(left$(msg$(i), 6) = "AddTgt") then + listbox add "TgtList", right$(msg$(i), len(msg$(i)) - 7) + selected = listbox count "TgtList" + listbox select "TgtList", selected + if(listbox count "SrcList" >= selected) then + listbox select "SrcList", selected + else + listbox select "SrcList", 0 + endif + end if + if(left$(msg$(i), 4) = "Mime") then + mime$ = right$(msg$(i), len(msg$(i)) - 5) + end if + + // listboxes + if(left$(msg$(i), 7) = "SrcList") then + selected = val(right$(msg$(i), len(msg$(i)) - 16)) + if(listbox count "TgtList" >= selected) then + listbox select "TgtList", selected + else + listbox select "TgtList", 0 + end if + end if + if(left$(msg$(i), 7) = "TgtList") then + selected = val(right$(msg$(i), len(msg$(i)) - 16)) + if(listbox count "SrcList" >= selected) then + listbox select "SrcList", selected + else + listbox select "SrcList", 0 + end if + end if + if(mid$(msg$(i), 9, 7) = "_Invoke") then + OpenEditor(msg$(i)) + end if + next i + wend +end sub + +sub OpenMainWindow() + local h, w + + h = peek("desktopheight") - 200 + w = peek("desktopwidth") - 400 + window open 200, 100 to w + 200, h + 100, "MainWindow", "Localizer" + window set "MainWindow", "minimumto", 100,100 + + menu "File", "New...", "N", "MainWindow" + menu "File", "Open...", "O", "MainWindow" + menu "File", "Import ZETA...", "Z", "MainWindow" + menu "File", "--", "", "MainWindow" + menu "File", "Save...", "S", "MainWindow" + menu "File", "Save and Install...", "I", "MainWindow" + menu "File", "--", "", "MainWindow" + menu "File", "Quit", "Q", "MainWindow" + + menu "Help", "Help...", "H", "MainWindow" + menu "Help", "--", "", "MainWindow" + menu "Help", "About...", "", "MainWindow" + + layout "top, left, right", "MainWindow" + textcontrol 10,30 to w-20,55, "Mime", "Mime Type", mime$, "MainWindow" + + layout "top, bottom, left, right", "MainWindow" + splitview 0,65 to w,h, "Split", true, true, "MainWindow" + layout "top, left", "Split1" + text 10,10, "EngText", "English Source", "Split1" + layout "top, bottom, left, right", "Split1" + listbox 10,30 to w/2 - 10,h-125, "SrcList", 3, "Split1" + layout "bottom, left", "Split1" + text 10,h-115, "AddEngText", "Add Phrase", "Split1" + + layout "top, left, right", "Split2" + textcontrol 10, 4 to w/2-20, 25, "TgtLang", "Target Language Code", targetLang$, "Split2" + layout "top, bottom, left, right", "Split2" + listbox 10,30 to w/2 - 20,h-125, "TgtList", 3, "Split2" + layout "bottom, left", "MainWindow" + text 10,h-115, "AddTgtText", "Add Phrase", "Split2" + + layout "bottom, left, right", "Split1" + textcontrol 10,h-100 to w/2 - 20, h-80, "AddSrc", "", "", "Split1" + layout "bottom, left, right", "MainWindow" + textcontrol 10,h-100 to w/2-20, h-80, "AddTgt", "", "", "Split2" +end sub + +sub CloseWindows() + window close "MainWindow" +end sub + +sub OpenEditor(msg$) + local h, w, pos + local entry$, list$, t$ + local editorFinished, i, n + + h = peek("desktopheight") / 2 + w = peek("desktopwidth") / 2 + window open w-300,h - 40 to w+300,h+40, "EditorWindow", "" + window set "EditorWindow", "look", "bordered" + window set "EditorWindow", "feel", "modal-app" + + pos = val(right$(msg$, len(msg$)-16)) + list$ = left$(msg$, 7) + entry$ = listbox get$ list$, pos + + localize stop + textcontrol 10,10 to 580,35, "Editor", "", entry$, "EditorWindow" + localize + button 300,40 to 390,70, "Cancel", "Cancel", "EditorWindow" + button 400,40 to 490,70, "Delete", "Delete", "EditorWindow" + button 500,40 to 590,70, "Commit", "Commit", "EditorWindow" + option set "Editor", "Focus", true + + dim editorMsg$(1) + editorFinished = false + while(not editorFinished) + n = split(message$, editorMsg$(), "|") + for i = 1 to n + if(editorMsg$(i) = "_QuitRequested") exit(1) + if(editorMsg$(i) = "Cancel") editorFinished = true + if(editorMsg$(i) = "Commit") then + listbox remove list$, pos + t$ = textcontrol get$ "Editor" + localize stop + listbox add list$, pos, t$ + localize + listbox select list$, pos + editorFinished = true + endif + if(editorMsg$(i) = "Delete") then + listbox remove list$, pos + listbox select list$, 0 + editorFinished = true + endif + next i + wend + + window close "EditorWindow" +end sub + +sub NewLocale() + local selected + selected = alert "All existing data will be lost!\n\nAre you sure?", "Yes", "No", "", "warning" + if(selected = 1) then + ClearAll() + endif +end sub + +sub OpenLocale() + local readno, n + local line$ + + file$ = filepanel "load-file", "Open Catalog", lastdir$ + if(file$ = "") return + + ClearAll() + lastdir$ = left$(file$, rinstr(file$, "/")) + + readno = open(file$, "r") + if(readno = 0) then + alert translate$("Error reading file\n") + peek$("error"), "Ok", "stop" + return + endif + + line input #readno line$ + dim tabs$(1) + n = split(line$, tabs$(), "\t") + if(n <> 4) then + alert "Error reading file\n", "Ok", "stop" + close(readno) + return + endif + + if(tabs$(2) <> "english") then + targetLang$ = tabs$(2) + else + targetLang$ = "" + endif + mime$ = tabs$(3) + + textcontrol set "TgtLang", targetLang$ + textcontrol set "Mime", mime$ + + while(not eof(readno)) + line input #readno line$ + n = split(line$, tabs$(), "\t") + if(n <> 4) then + alert "Error reading file\n", "Ok", "stop" + close(readno) + return + endif + localize stop + listbox add "SrcList", tabs$(1) + localize + if(targetLang$ <> "") then + listbox add "TgtList", tabs$(4) + endif + wend + close(readno) +end sub + +sub ClearAll() + listbox clear "SrcList" + listbox clear "TgtList" + textcontrol clear "AddSrc" + textcontrol clear "AddTgt" + mime$ = "x-vnd." + textcontrol set "Mime", mime$ +end sub + +sub ImportZETA() + local file$, line$ + file$ = filepanel "load-file", "Import ZETA Locale", lastdir$ + if(file$ <> "") then + ClearAll() + lastdir$ = left$(file$, rinstr(file$, "/")) + open file$ for reading as #1 + while(not eof(#1)) + line input #1 line$ + ParseZETA(line$) + wend + close #1 + file$ = right$(file$, len(file$) - rinstr(file$, "/")) + if(lower$(right$(file$,2)) = mid$(file$,len(file$)-3,2)) then + targetLang$ = lower$(right$(file$,2)) + else + targetLang$ = mid$(file$,len(file$)-3,2) + "_" + lower$(right$(file$,2)) + endif + textcontrol set "TgtLang", targetLang$ + mime$ = "x-vnd." + left$(file$, instr(file$, ".") - 1) + textcontrol set "Mime", mime$ + if(warnDuplicates) then + warnDulicates = false + alert "Duplicate source lines were skipped.", "Ok", "warning" + endif + endif +end sub + +sub ParseZETA(line$) + local i, counter + local a$, b$, m$ + + line$ = trim$(line$) + if(left$(line$,1) <> "#") then + counter = 0 + for i = 1 to len(line$) + m$ = mid$(line$, i, 1) + if(m$ = chr$(34) and (mid$(line$, i-1, 1) <> chr$(92))) then + counter = counter + 1 + endif + if(counter = 1) a$ = a$ + m$ + if(counter = 3) b$ = b$ + m$ + next i + if(trim$(a$) <> "") then + a$ = right$(a$, len(a$) - 1) + b$ = right$(b$, len(b$) - 1) + if(a$ = "_key") then + if(IsUnique(b$)) then + localize stop + listbox add "SrcList", b$ + localize + else + warnDuplicates = true + endif + elsif(a$ = "_value") then + listbox add "TgtList", b$ + else + if(IsUnique(a$)) then + localize stop + listbox add "SrcList", a$ + localize + listbox add "TgtList", b$ + else + warnDuplicates = true + endif + endif + endif + endif +end sub + +sub IsUnique(entry$) + local i + local t$ + + for i = 1 to listbox count "SrcList" + t$ = listbox get$ "SrcList", i + if(t$ = entry$) return false + next i + return true +end sub + +sub SaveLocale() + local fileno, i, writerno, n + local entry$, file$, saveFile$ + + targetLang$ = textcontrol get$ "TgtLang" + + if(targetLang$ <> "") then + saveFile$ = targetLang$ + ".catalog" + else + saveFile$ = "en.catalog" + endif + dir$ = filepanel "Save-File", "Save Catalog", lastdir$, saveFile$ + if(dir$ = "") return false + + lastdir$ = left$(dir$, rinstr(dir$, "/") - 1) + + mime$ = textcontrol get$ "Mime" + + if(mime$ = "" or mime$ = "x-vnd.") then + alert "Mime type invalid.\n\nA valid mime type has the form:\nx-vnd.ApplicationName", "Ok", "warning" + return false + endif + file$ = right$(mime$, len(mime$) - instr(mime$, ".")) + + fileno = open(file$ + ".tmp", "w") + if(fileno = 0) then + alert translate$("Error writing file\n") + peek$("error"), "Ok", "stop" + return false + endif + + for i = 1 to listbox count "SrcList" + entry$ = listbox get$ "SrcList", i + entry$ = "B_CATKEY\"" + entry$ + "\"" + print #fileno entry$ + next i + close fileno + + system("collectcatkeys -l english -s " + mime$ + " " + file$ + ".tmp") + + fileno = open(file$ + ".catkeys", "r") + if(targetLang$ <> "") then + writerno = open(lastdir$ + "/en.catalog", "w") + else + writerno = open(dir$, "w") + endif + if(fileno = 0 or writerno = 0) then + alert translate$("Error reading or writing file\n") + peek$("error"), "Ok", "stop" + return false + endif + + line input #fileno entry$ + dim tabs$(1) + n = split(entry$, tabs$(), "\t") + if(n <> 4) then + alert "Error reading file\n", "Ok", "stop" + close(writerno) + close(fileno) + return false + endif + print #writerno tabs$(1) + "\tenglish\t" + tabs$(3) + "\t" + tabs$(4) + for i = 1 to listbox count "SrcList" + entry$ = listbox get$ "SrcList", i + print #writerno entry$ + "\t\t\t" + entry$ + next i + close(writerno) + close(fileno) + + system("rm " + file$ + ".catkeys") + if(targetLang$ <> "") then + fileno = open(lastdir$ + "/en.catalog", "r") + writerno = open(dir$, "w") + if(fileno = 0 or writerno = 0) then + alert translate$("Error reading or writing file\n") + peek$("error"), "Ok", "stop" + return false + endif + + line input #fileno entry$ + dim tabs$(1) + n = split(entry$, tabs$(), "\t") + if(n <> 4) then + alert "Error reading file\n", "Ok", "stop" + close(writerno) + close(fileno) + return false + endif + print #writerno tabs$(1) + "\t" + targetLang$ + "\t" + tabs$(3) + "\t" + tabs$(4) + i = 1 + while(not eof(fileno)) + line input #fileno entry$ + n = split(entry$, tabs$(), "\t") + if(n <> 4) then + alert "Error reading file\n", "Ok", "stop" + close(writerno) + close(fileno) + return false + endif + print #writerno tabs$(1) + "\t\t\t" + GetTarget$(tabs$(1)) + i = i + 1 + wend + + close(writerno) + close(fileno) + else + alert "No target language specified.\nOnly the English catalog was generated.", "Ok", "warning" + endif + system("rm " + file$ + ".tmp") + return true +end sub + +sub InstallLocale() + local inst$ + + inst$ = INSTALLPATH$ + "/" + mime$ + system("mkdir -p " + inst$) + if(targetLang$ <> "") then + system("linkcatkeys -l english -s "+mime$+" -o "+inst$+"/en.catalog "+lastdir$+"/en.catalog") + system("linkcatkeys -l "+targetLang$+" -s "+mime$+" -o "+inst$+"/"+targetLang$+".catalog "+dir$) + else + system("linkcatkeys -l english -s "+mime$+" -o "+inst$+"/en.catalog "+dir$) + endif + alert "Catalogs saved and installed.", "Ok", "info" +end sub + +sub GetTarget$(source$) + local t$ + local i + + for i = 1 to listbox count "SrcList" + t$ = listbox get$ "SrcList", i + if(t$ = source$) then + if(i <= listbox count "TgtList") then + return listbox get$ "TgtList", i + else + return "" + endif + endif + next i + return "" +end sub + +sub About() + alert "Localizer for Haiku\n\n2011 by Jan Bungeroth", "Ok", "idea" +end sub + +sub Help() + local w,h, helpFinished, i, n, currentPage, maxPages + + h = peek("desktopheight") + w = peek("desktopwidth") + + window open w/2-200,150 to w/2+200,h-150, "HelpWindow", "Help" + window set "HelpWindow", "Flags", "not-zoomable, not-resizable" + view 0,0 to 400,h-350, "HelpText", "HelpWindow" + draw set "bgcolor", 255,255,255, "HelpText" + draw set "highcolor", "Panel-Background-Color, Lighten-1-Tint", "HelpWindow" + draw line 0,h-347 to 400,h-347, "HelpWindow" + draw set "highcolor", "Panel-Background-Color, Darken-1-Tint", "HelpWindow" + draw line 0,h-348 to 400,h-348, "HelpWindow" + + button 10,h-340 to 40,h-310, "HelpBack", "\xe2\x86\xa9", "HelpWindow" + option set "HelpBack", "enabled", false + button 360,h-340 to 390,h-310, "HelpForward", "\xe2\x86\xaa", "HelpWindow" + button 120,h-340 to 280,h-310, "HelpClose", "Close", "HelpWindow" + + textedit 0,0 to 400,h-350, "Help", 1, "HelpText" + textedit set "Help", "editable", false + + restore Pages + read maxPages + + currentPage = 1 + ShowHelpPage(currentPage) + + dim helpMsg$(1) + helpFinished = false + while(not helpFinished) + n = split(message$, helpMsg$(), "|") + for i = 1 to n + switch(helpMsg$(i)) + case "_QuitRequested" + exit(0) + break + case "HelpWindow:_QuitRequested" + case "HelpClose" + helpFinished = true + break + case "HelpForward" + if(currentPage < maxPages) then + currentPage = currentPage + 1 + ShowHelpPage(currentPage) + if(currentPage = maxPages) option set "HelpForward", "enabled", false + if(currentPage = 2) option set "HelpBack", "enabled", true + endif + break + case "HelpBack" + if(currentPage > 1) then + currentPage = currentPage - 1 + ShowHelpPage(currentPage) + if(currentPage = 1) option set "HelpBack", "enabled", false + if(currentPage = maxPages - 1) option set "HelpForward", "enabled", true + endif + break + end switch + next i + wend + + window close "HelpWindow" +end sub + +sub ShowHelpPage(num) + local lines, i + local line$ + + textedit clear "Help" + restore "Page" + str$(num) + read lines + for i = 1 to lines + read line$ + textedit add "Help", translate$(line$) + next i +end sub + +// Help pages +label Pages +data 4 + +label Page1 +data 9 // data lines for this page +data "Localizer helps you to bring localization to your Haiku applications.\n\n" +data "Localization is done using special catalog files. These catalog files are then compiled into BMessages and stored in a specific directory. The directory and the catalog files are signed by an application mimetype.\n\n" +data "How to use Localizer:\n\n" +data "1. Add the English strings of your program to the left list and their translations into the right list.\n\n" +data "2. Enter the translation short code for the target language and the mimetype of your program.\n\n" +data "3. 'Save and Install' will save your translations locally and install their compiled version to /boot/common/data/locale/catalogs\n\n" +data "Make sure, both lists are also in sync!\n\n" +data "The language code consists of a two letter country code (e.g. de for Germany or nl for Netherlands) or a combined code if the language code differs from the country code (e.g. nl_be for Dutch in Belgium).\n\n" +data "The mimetype identifies the application. An application mimetype usually has the format: x-vnd.ApplicationName" + +label Page2 +data 9 +data "Importing ZETA locale files:\n\n" +data "Localizer allows you to import old ZETA locale files.\n\n" +data "Currently Localizer does feature context support, so all source strings are allowed only once. If there are several equal English strings in the ZETA file, only the first one is imported. The others are ignored.\n\n" +data "Localizer supports ZETA files using the format:\n" +data " \"English string\" \"Target string\"\n\n" +data "And also this format:\n" +data " \"_key\" = \"English string\"\n" +data " \"_value\" = \"Target string\"\n" +data "(Note: _key and _value need to be on separate lines.)" + +label Page3 +data 7 +data "How to use localization in yab programs:\n\n" +data "First you have to load the locale catalog with the mimetype name:\n localize \"x-vnd.MyApplication\"\n\n" +data "All widgets will now automatically translate all their strings.\n\n" +data "To translate a specific string use:\n translate$(myString$)\n\n" +data "To translate a string separated with colons : use:\n menu translate$(myString$)\nThis is useful for translating menu entries because menu messages are separated with :\n\n" +data "A new feature allows you to turn the automatic translation of widget strings off and on again.\n" +data "To turn the automatic translation off, use:\n localize stop\n\n" +data "To turn it on again, use:\n localize" + +label Page4 +data 5 +data "How to use localization in C++ programs:\n\n" +data "First, include Catalog.h and Locale.h:\n #include \n #include \n\n" +data "Within your code, now you can simply translate a string with:\n B_TRANSLATE(myString);\n\n" +data "The locale kit will search for the catalog files associated with your application's signature mimetype.\n\n" +data "To link your program, add the locale and localestub libraries:\n -l locale -l localestub" diff --git a/README.md b/README.md index 13c940a..96ed09b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,19 @@ -# YAB1 +# YAB yab | yet another Basic for HAIKU +=== +Yab is a complete BASIC programming language for Haiku. + + +Yab allows fast prototyping with simple and clean code. yab contains a large number of BeAPI specific commands for GUI creation and much, much more. This package includes only the yab binary and documentation. + + +Compiling +--------------------- +run `make` in `src`. + +run `fixattributes.sh` in `src`. + +type `gcc -o yab-compress yab-compress.c -lz` in `/yab-IDE/BuildFactory`. + +LICENSE: Artistic License -- Create your own stand-alone binaries with yab under any license you want. +AUTHOR: jan__64 diff --git a/src/CalendarControl.cpp b/src/CalendarControl.cpp new file mode 100644 index 0000000..6c7e5a7 --- /dev/null +++ b/src/CalendarControl.cpp @@ -0,0 +1,252 @@ +// Calendar Control version 2.5 +// by Al.V. Sarikov. +// Kherson, Ukraine, 2006. +// E-mail: avix@ukrpost.net. +// Home page: http://avix.pp.ru. + +// Updated for Haiku and removed all stuff that is not needed and refactored by jan__64 2009 + +// Control which allows to work with dates: +// enter date to text field and choose it from calendar. + +// Distributed under BSD license (see LICENSE file). + +#define __LANG_ENGLISH // to compile english version + +#include "CalendarControl.h" + +#define myButtonMessage 'DCBP' + +#include "DateTextView.cpp" +#include "MonthWindow.cpp" + +#include +#include +#include +#include +#include +#include + + +CalendarControl::CalendarControl(BPoint p, const char* name, int day, int month, int year, uint32 flags, uint32 look) + :BControl(BRect(100,100,200,200),name, NULL, NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW) +{ + + uint32 divider=look & CC_ALL_DIVIDERS; + + myDateTextView = new DateTextView(day,month,year,flags,divider); + myButton = new CalendarButton(BRect(70,0,85,15), "CalendarButton", "", new BMessage(myButtonMessage), B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW); + myOrigin = p; + + AddChild(myDateTextView); + myDateTextView->MoveTo(3,3); + ResizeTo(myDateTextView->Bounds().Width()+6,myDateTextView->Bounds().Height()+7); + + AddChild(myButton); + + myButton->ResizeTo(Bounds().Height()*0.7,Bounds().Height()-1); + myButton->MoveTo(Bounds().right+1, Bounds().top); + ResizeBy(myButton->Bounds().Width()+1, 0); +} + + +CalendarControl::~CalendarControl() +{ + RemoveChild(myDateTextView); + delete myDateTextView; + RemoveChild(myButton); + delete myButton; +} + + +void CalendarControl::AttachedToWindow(void) +{ + BControl::AttachedToWindow(); + + myButton->SetTarget(this); + + if(Parent()!=NULL) + view_color=Parent()->ViewColor(); + else + view_color.red=view_color.green=view_color.blue=view_color.alpha=255; + + SetViewColor(view_color); // function of CalendarControl class + + // MakeButton(); // for BeOS interface is called only from here, + MoveTo(myOrigin); +} + + +void CalendarControl::Draw(BRect r) +{ + BRect bounds(Bounds()); + bounds.bottom--; + bounds.right = myButton->Frame().left - 1; + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + + bool active = myDateTextView->IsFocus() && Window()->IsActive(); + uint32 flags = 0; + if (!IsEnabled()) + flags |= BControlLook::B_DISABLED; + if (active) + flags |= BControlLook::B_FOCUSED; + be_control_look->DrawTextControlBorder((BView*)this, bounds, r, base, flags, 15); +} + + +void CalendarControl::KeyDown(const char *bytes, int32 numBytes) +{ + BControl::KeyDown(bytes, numBytes); + if(bytes[0]==B_TAB) Draw(Bounds()); +} + + +void CalendarControl::MakeFocus(bool focused) +{ + myDateTextView->MakeFocus(focused); +} + + +void CalendarControl::MessageReceived(BMessage *msg) +{ + switch(msg->what) + { + case myButtonMessage: + { + if(IsEnabled()) + { + MakeFocus(true); + int day, month, year; + int first_year, last_year; + GetDate(&day, &month, &year); + GetYearRange(&first_year, &last_year); + new MonthWindow(ConvertToScreen(BPoint(Bounds().left+1,Bounds().bottom+1)), + new BMessenger(this), day, month, year, first_year, last_year); + } + break; + } + case 'MVME': // message has come from window with calendar + { + int32 day, month, year; + msg->FindInt32("day",&day); + msg->FindInt32("month",&month); + msg->FindInt32("year",&year); + SetDate((int)day, (int)month, (int)year); + break; + } + default: + BControl::MessageReceived(msg); + } +} + + +void CalendarControl::SetEnabled(bool enabled) +{ + if(enabled==IsEnabled()) return; + BControl::SetEnabled(enabled); + myButton->SetEnabled(enabled); + myDateTextView->SetEnabled(enabled); + Invalidate(); +} + + +void CalendarControl::SetViewColor(rgb_color color) +{ + view_color=color; + BControl::SetViewColor(view_color); + Draw(Bounds()); + Invalidate(); +} + + +void CalendarControl::SetViewColor(uchar red, uchar green, + uchar blue, uchar alpha) +{ + rgb_color color={red, green, blue, alpha}; + SetViewColor(color); +} + + +void CalendarControl::WindowActivated(bool active) +{ + myWindowActive = active; // true if window where control is placed is active + Draw(Bounds()); +} + + +const char* CalendarControl::Text() const +{ + return myDateTextView->Text(); +} + + +void CalendarControl::GetDate(int *day, int *month, int *year) +{ + myDateTextView->GetDate(day,month,year); +} + + +void CalendarControl::SetDate(int day, int month, int year) +{ + myDateTextView->SetDate(day,month,year); +} + + +void CalendarControl::SetDate(const char *tdate) +{ + myDateTextView->SetDate(tdate); +} + + +void CalendarControl::GetYearRange(int *first_year, int *last_year) +{ + myDateTextView->GetYearRange(first_year, last_year); +} + + +uint32 CalendarControl::GetLook() +{ + return (myDateTextView->GetDivider()); +} + + +void CalendarControl::SetLook(uint32 look) +{ + myDateTextView->SetDivider(look & CC_ALL_DIVIDERS); +} + + +uint32 CalendarControl::GetFlags() +{ + return myDateTextView->GetDateFlags(); +} + + +void CalendarControl::SetFlags(uint32 flags) +{ + myDateTextView->SetDateFlags(flags); +} + + +BTextView *CalendarControl::TextView(void) const +{ + return (BTextView *)myDateTextView; +} + + +void CalendarButton::Draw(BRect update) +{ + BButton::Draw(update); + BRect rect = Bounds(); + rect.InsetBy(2.0,4.0); + uint32 flags = 0; + rgb_color base = ui_color(B_PANEL_TEXT_COLOR); + float tint = B_NO_TINT; + if(!IsEnabled()) + { + tint = B_LIGHTEN_MAX_TINT; + flags |= BControlLook::B_DISABLED; + } + be_control_look->DrawArrowShape(this, rect, update, base, 3, flags, tint); +} diff --git a/src/CalendarControl.h b/src/CalendarControl.h new file mode 100644 index 0000000..005b132 --- /dev/null +++ b/src/CalendarControl.h @@ -0,0 +1,97 @@ +// Calendar Control version 2.5 +// by Al.V. Sarikov. +// Kherson, Ukraine, 2006. +// E-mail: avix@ukrpost.net. +// Home page: http://avix.pp.ru. + +// Control which allows to work with dates: +// enter date to text field and choose it from calendar. + +// Distributed under BSD license (see LICENSE file). + +#include +#include +#include +#include + +class DateTextView; + +class CalendarButton : public BButton +{ + public: + CalendarButton(BRect frame, const char* name, const char* label, + BMessage* message, uint32 resizingMode, uint32 flags) + : BButton(frame, name, label, message, resizingMode, flags) + {}; + ~CalendarButton() {}; + void Draw(BRect update); +}; + +// Formats of date + +enum date_format { + CC_DD_MM_YYYY_FORMAT = 0, + CC_MM_DD_YYYY_FORMAT +}; + +enum full_short_year { + CC_FULL_YEAR = 0, // DD.MM.YYYY + CC_SHORT_YEAR = 8 // DD.MM.YY +}; + +enum century_begin { + CC_FULL_CENTURY = 0, // first year is first year of century (01-00) + CC_HALF_CENTURY = 16 // first year is 51th year of century (51-50) +}; + +enum divider_format { + CC_DOT_DIVIDER = 0, // . + CC_SLASH_DIVIDER, // / + CC_MINUS_DIVIDER, // - + CC_ALL_DIVIDERS // 2 bits, and some one bit is reserved +}; + + +class CalendarControl: public BControl +{ + public: + CalendarControl(BPoint p, + const char* name, + int day=0, + int month=0, + int year=0, + uint32 flags=CC_DD_MM_YYYY_FORMAT | CC_FULL_YEAR, + uint32 look=CC_DOT_DIVIDER); + ~CalendarControl(); + virtual void AttachedToWindow(void); + virtual void Draw(BRect r); + virtual void KeyDown(const char *bytes, int32 numBytes); + virtual void MakeFocus(bool focused=true); + virtual void MessageReceived(BMessage *msg); + virtual void SetEnabled(bool enabled); + virtual void SetViewColor(rgb_color color); + void SetViewColor(uchar red, uchar green, uchar blue, uchar alpha=255); + virtual void WindowActivated(bool active); + + void GetDate(int *day, int *month, int *year); + void SetDate(int day=0, int month=0, int year=0); + void SetDate(const char *tdate); + void GetYearRange(int *first_year, int *last_year); + uint32 GetLook(); + void SetLook(uint32 look); + uint32 GetFlags(); + void SetFlags(uint32 flags); + const char* Text() const; + BTextView *TextView(void) const; + const char* Version(); + + private: + void MakeButton(); + + DateTextView *myDateTextView; + CalendarButton *myButton; + bool myWindowActive; + BPoint myOrigin; + rgb_color view_color; +}; + diff --git a/src/ControlLook.cpp b/src/ControlLook.cpp new file mode 100644 index 0000000..984502e --- /dev/null +++ b/src/ControlLook.cpp @@ -0,0 +1,2293 @@ +/* + * Copyright 2009, Stephan Aßmus + * Distributed under the terms of the MIT License. + */ +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace BPrivate { + +static const float kEdgeBevelLightTint = 0.59; +static const float kEdgeBevelShadowTint = 1.0735; + + +BControlLook::BControlLook() +{ +} + + +BControlLook::~BControlLook() +{ +} + + +BAlignment +BControlLook::DefaultLabelAlignment() const +{ + return BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER); +} + + +float +BControlLook::DefaultLabelSpacing() const +{ + return 4.0;//ceilf(be_plain_font->Size() / 4.0); +} + + +uint32 +BControlLook::Flags(BControl* control) const +{ + uint32 flags = 0; + + if (!control->IsEnabled()) + flags |= B_DISABLED; + + if (control->IsFocus()) + flags |= B_FOCUSED; + + if (control->Value() == B_CONTROL_ON) + flags |= B_ACTIVATED; + + return flags; +} + + +// #pragma mark - + + +void +BControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, const rgb_color& background, uint32 flags, + uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, base, background, 1.0, 1.0, flags, + borders); +} + + +void +BControlLook::DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders, enum orientation orientation) +{ + if (!rect.IsValid() || !updateRect.Intersects(rect)) + return; + + // the surface edges + + // colors + rgb_color buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT); + rgb_color maxLightColor; + + rgb_color bevelColor1; + rgb_color bevelColor2; + + if ((flags & B_DISABLED) == 0) { + maxLightColor = tint_color(base, 0.2); + bevelColor1 = tint_color(base, 1.08); + bevelColor2 = base; + } else { + maxLightColor = tint_color(base, 0.7); + bevelColor1 = base; + bevelColor2 = buttonBgColor; + buttonBgColor = maxLightColor; + } + + if (flags & B_ACTIVATED) { + view->BeginLineArray(4); + + bevelColor1 = tint_color(bevelColor1, B_DARKEN_1_TINT); + bevelColor2 = tint_color(bevelColor2, B_DARKEN_1_TINT); + + // shadow along left/top borders + if (borders & B_LEFT_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.left, rect.bottom), bevelColor1); + rect.left++; + } + if (borders & B_TOP_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.right, rect.top), bevelColor1); + rect.top++; + } + + // softer shadow along left/top borders + if (borders & B_LEFT_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.left, rect.bottom), bevelColor2); + rect.left++; + } + if (borders & B_TOP_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.right, rect.top), bevelColor2); + rect.top++; + } + + view->EndLineArray(); + } else { + _DrawFrame(view, rect, + maxLightColor, maxLightColor, + bevelColor1, bevelColor1, + buttonBgColor, buttonBgColor, borders); + } + + // the actual surface top + + float topTint = 0.49; + float middleTint1 = 0.62; + float middleTint2 = 0.76; + float bottomTint = 0.90; + + if (flags & B_ACTIVATED) { + topTint = 1.11; + bottomTint = 1.08; + } + + if (flags & B_DISABLED) { + topTint = (topTint + B_NO_TINT) / 2; + middleTint1 = (middleTint1 + B_NO_TINT) / 2; + middleTint2 = (middleTint2 + B_NO_TINT) / 2; + bottomTint = (bottomTint + B_NO_TINT) / 2; + } else if (flags & B_HOVER) { + static const float kHoverTintFactor = 0.85; + topTint *= kHoverTintFactor; + middleTint1 *= kHoverTintFactor; + middleTint2 *= kHoverTintFactor; + bottomTint *= kHoverTintFactor; + } + + if (flags & B_ACTIVATED) { + _FillGradient(view, rect, base, topTint, bottomTint, orientation); + } else { + _FillGlossyGradient(view, rect, base, topTint, middleTint1, + middleTint2, bottomTint, orientation); + } +} + + +void +BControlLook::DrawMenuBarBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !updateRect.Intersects(rect)) + return; + + // the surface edges + + // colors + float topTint; + float bottomTint; + + if (flags & B_ACTIVATED) { + rgb_color bevelColor1 = tint_color(base, 1.40); + rgb_color bevelColor2 = tint_color(base, 1.25); + + topTint = 1.25; + bottomTint = 1.20; + + _DrawFrame(view, rect, + bevelColor1, bevelColor1, + bevelColor2, bevelColor2, + borders & B_TOP_BORDER); + } else { + rgb_color cornerColor = tint_color(base, 0.9); + rgb_color bevelColorTop = tint_color(base, 0.5); + rgb_color bevelColorLeft = tint_color(base, 0.7); + rgb_color bevelColorRightBottom = tint_color(base, 1.08); + + topTint = 0.69; + bottomTint = 1.03; + + _DrawFrame(view, rect, + bevelColorLeft, bevelColorTop, + bevelColorRightBottom, bevelColorRightBottom, + cornerColor, cornerColor, + borders); + } + + // the actual surface top + + _FillGradient(view, rect, base, topTint, bottomTint); +} + + +void +BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, + const rgb_color& background, uint32 flags, uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, base, background, 0.6, 1.0, flags, + borders); +} + + +void +BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, bool popupIndicator, + uint32 flags) +{ + if (popupIndicator) { + BRect leftRect(rect); + leftRect.right -= 10; + + BRect rightRect(rect); + rightRect.left = rightRect.right - 9; + + DrawMenuFieldBackground(view, leftRect, updateRect, base, flags, + B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER); + + rgb_color indicatorBase; + rgb_color markColor; + if (flags & B_DISABLED) { + indicatorBase = tint_color(base, 1.05); + markColor = tint_color(base, 1.35); + } else { + indicatorBase = tint_color(base, 1.12); + markColor = tint_color(base, 1.65); + } + + DrawMenuFieldBackground(view, rightRect, updateRect, indicatorBase, + flags, B_RIGHT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER); + + // popup marker + BPoint center(roundf((rightRect.left + rightRect.right) / 2.0), + roundf((rightRect.top + rightRect.bottom) / 2.0)); + BPoint triangle[3]; + triangle[0] = center + BPoint(-2.5, -0.5); + triangle[1] = center + BPoint(2.5, -0.5); + triangle[2] = center + BPoint(0.0, 2.0); + + uint32 viewFlags = view->Flags(); + view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); + + view->SetHighColor(markColor); + view->FillTriangle(triangle[0], triangle[1], triangle[2]); + + view->SetFlags(viewFlags); + + rect = leftRect; + } else { + DrawMenuFieldBackground(view, rect, updateRect, base, flags); + } +} + +void +BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !updateRect.Intersects(rect)) + return; + + // the surface edges + + // colors + rgb_color cornerColor = tint_color(base, 0.85); + rgb_color bevelColor1 = tint_color(base, 0.3); + rgb_color bevelColor2 = tint_color(base, 0.5); + rgb_color bevelColor3 = tint_color(base, 1.03); + + if (flags & B_DISABLED) { + cornerColor = tint_color(base, 0.8); + bevelColor1 = tint_color(base, 0.7); + bevelColor2 = tint_color(base, 0.8); + bevelColor3 = tint_color(base, 1.01); + } else { + cornerColor = tint_color(base, 0.85); + bevelColor1 = tint_color(base, 0.3); + bevelColor2 = tint_color(base, 0.5); + bevelColor3 = tint_color(base, 1.03); + } + + _DrawFrame(view, rect, + bevelColor2, bevelColor1, + bevelColor3, bevelColor3, + cornerColor, cornerColor, + borders); + + // the actual surface top + + float topTint = 0.49; + float middleTint1 = 0.62; + float middleTint2 = 0.76; + float bottomTint = 0.90; + + if (flags & B_DISABLED) { + topTint = (topTint + B_NO_TINT) / 2; + middleTint1 = (middleTint1 + B_NO_TINT) / 2; + middleTint2 = (middleTint2 + B_NO_TINT) / 2; + bottomTint = (bottomTint + B_NO_TINT) / 2; + } else if (flags & B_HOVER) { + static const float kHoverTintFactor = 0.85; + topTint *= kHoverTintFactor; + middleTint1 *= kHoverTintFactor; + middleTint2 *= kHoverTintFactor; + bottomTint *= kHoverTintFactor; + } + + _FillGlossyGradient(view, rect, base, topTint, middleTint1, + middleTint2, bottomTint); +} + +void +BControlLook::DrawMenuBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !updateRect.Intersects(rect)) + return; + + // the surface edges + + rgb_color bevelLightColor; + rgb_color bevelShadowColor; + rgb_color background = tint_color(base, 0.75); + + if (flags & B_DISABLED) { + bevelLightColor = tint_color(background, 0.80); + bevelShadowColor = tint_color(background, 1.07); + } else { + bevelLightColor = tint_color(background, 0.6); + bevelShadowColor = tint_color(background, 1.12); + } + + _DrawFrame(view, rect, + bevelLightColor, bevelLightColor, + bevelShadowColor, bevelShadowColor, + borders); + + // the actual surface top + + view->SetHighColor(background); + view->FillRect(rect); +} + + +void +BControlLook::DrawMenuItemBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !updateRect.Intersects(rect)) + return; + + // the surface edges + + float topTint; + float bottomTint; + rgb_color selectedColor = base; + + if (flags & B_ACTIVATED) { + topTint = 0.9; + bottomTint = 1.05; + selectedColor = tint_color(base, 1.26); + } else if (flags & B_DISABLED) { + topTint = 0.80; + bottomTint = 1.07; + } else { + topTint = 0.6; + bottomTint = 1.12; + } + + rgb_color bevelLightColor = tint_color(selectedColor, topTint); + rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint); + + _DrawFrame(view, rect, + bevelLightColor, bevelLightColor, + bevelShadowColor, bevelShadowColor, + borders); + + // the actual surface top + + view->SetLowColor(selectedColor); +// _FillGradient(view, rect, selectedColor, topTint, bottomTint); + _FillGradient(view, rect, selectedColor, bottomTint, topTint); +} + + +void +BControlLook::DrawStatusBar(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, const rgb_color& barColor, float progressPosition) +{ + if (!rect.Intersects(updateRect)) + return; + + _DrawOuterResessedFrame(view, rect, base, 0.6); + + // colors + rgb_color dark1BorderColor = tint_color(base, 1.3); + rgb_color dark2BorderColor = tint_color(base, 1.2); + rgb_color dark1FilledBorderColor = tint_color(barColor, 1.20); + rgb_color dark2FilledBorderColor = tint_color(barColor, 1.45); + + BRect filledRect(rect); + filledRect.right = progressPosition - 1; + + BRect nonfilledRect(rect); + nonfilledRect.left = progressPosition; + + bool filledSurface = filledRect.Width() > 0; + bool nonfilledSurface = nonfilledRect.Width() > 0; + + if (filledSurface) { + _DrawFrame(view, filledRect, + dark1FilledBorderColor, dark1FilledBorderColor, + dark2FilledBorderColor, dark2FilledBorderColor); + + _FillGlossyGradient(view, filledRect, barColor, 0.55, 0.68, 0.76, 0.90); + } + + if (nonfilledSurface) { + _DrawFrame(view, nonfilledRect, dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor, + B_TOP_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER); + + if (nonfilledRect.left < nonfilledRect.right) { + // shadow from fill bar, or left border + rgb_color leftBorder = dark1BorderColor; + if (filledSurface) + leftBorder = tint_color(base, 0.50); + view->SetHighColor(leftBorder); + view->StrokeLine(nonfilledRect.LeftTop(), + nonfilledRect.LeftBottom()); + nonfilledRect.left++; + } + + _FillGradient(view, nonfilledRect, base, 0.25, 0.06); + } +} + + +void +BControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 flags) +{ + if (!rect.Intersects(updateRect)) + return; + + rgb_color dark1BorderColor; + rgb_color dark2BorderColor; + rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + + if (flags & B_DISABLED) { + _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags); + + dark1BorderColor = tint_color(base, 1.15); + dark2BorderColor = tint_color(base, 1.15); + } else if (flags & B_CLICKED) { + dark1BorderColor = tint_color(base, 1.50); + dark2BorderColor = tint_color(base, 1.48); + + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor); + + dark2BorderColor = dark1BorderColor; + } else { + _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags); + + dark1BorderColor = tint_color(base, 1.40); + dark2BorderColor = tint_color(base, 1.38); + } + + if (flags & B_FOCUSED) { + dark1BorderColor = navigationColor; + dark2BorderColor = navigationColor; + } + + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor); + + if (flags & B_DISABLED) { + _FillGradient(view, rect, base, 0.4, 0.2); + } else { + _FillGradient(view, rect, base, 0.15, 0.0); + } + + rgb_color markColor; + if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) { + view->SetHighColor(markColor); + + rect.InsetBy(2, 2); + view->SetPenSize(max_c(1.0, ceilf(rect.Width() / 3.5))); + view->SetDrawingMode(B_OP_OVER); + + view->StrokeLine(rect.LeftTop(), rect.RightBottom()); + view->StrokeLine(rect.LeftBottom(), rect.RightTop()); + } +} + + +void +BControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 flags) +{ + if (!rect.Intersects(updateRect)) + return; + + rgb_color borderColor; + rgb_color bevelLight; + rgb_color bevelShadow; + rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + + if (flags & B_DISABLED) { + borderColor = tint_color(base, 1.15); + bevelLight = base; + bevelShadow = base; + } else if (flags & B_CLICKED) { + borderColor = tint_color(base, 1.50); + bevelLight = borderColor; + bevelShadow = borderColor; + } else { + borderColor = tint_color(base, 1.45); + bevelLight = tint_color(base, 0.55); + bevelShadow = tint_color(base, 1.11); + } + + if (flags & B_FOCUSED) { + borderColor = navigationColor; + } + + BGradientLinear bevelGradient; + bevelGradient.AddColor(bevelShadow, 0); + bevelGradient.AddColor(bevelLight, 255); + bevelGradient.SetStart(rect.LeftTop()); + bevelGradient.SetEnd(rect.RightBottom()); + + view->FillEllipse(rect, bevelGradient); + rect.InsetBy(1, 1); + + bevelGradient.MakeEmpty(); + bevelGradient.AddColor(borderColor, 0); + bevelGradient.AddColor(tint_color(borderColor, 0.8), 255); + view->FillEllipse(rect, bevelGradient); + rect.InsetBy(1, 1); + + float topTint; + float bottomTint; + if (flags & B_DISABLED) { + topTint = 0.4; + bottomTint = 0.2; + } else { + topTint = 0.15; + bottomTint = 0.0; + } + + BGradientLinear gradient; + _MakeGradient(gradient, rect, base, topTint, bottomTint); + view->FillEllipse(rect, gradient); + + rgb_color markColor; + if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) { + view->SetHighColor(markColor); + rect.InsetBy(3, 3); + view->FillEllipse(rect); + } +} + + +void +BControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2, + const BRect& updateRect, const rgb_color& base, uint32 flags, + enum orientation orientation) +{ + DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation); + DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation); +} + +void +BControlLook::DrawScrollBarBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + enum orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + float gradient1Tint; + float gradient2Tint; + float darkEdge1Tint; + float darkEdge2Tint; + float shadowTint; + + if (flags & B_DISABLED) { + gradient1Tint = 0.9; + gradient2Tint = 0.8; + darkEdge1Tint = B_DARKEN_2_TINT; + darkEdge2Tint = B_DARKEN_2_TINT; + shadowTint = gradient1Tint; + } else { + gradient1Tint = 1.10; + gradient2Tint = 1.05; + darkEdge1Tint = B_DARKEN_3_TINT; + darkEdge2Tint = B_DARKEN_2_TINT; + shadowTint = gradient1Tint; + } + + rgb_color darkEdge1 = tint_color(base, darkEdge1Tint); + rgb_color darkEdge2 = tint_color(base, darkEdge2Tint); + rgb_color shadow = tint_color(base, shadowTint); + + if (orientation == B_HORIZONTAL) { + // dark vertical line on left edge + if (rect.Width() > 0) { + view->SetHighColor(darkEdge1); + view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); + rect.left++; + } + // dark vertical line on right edge + if (rect.Width() >= 0) { + view->SetHighColor(darkEdge2); + view->StrokeLine(rect.RightTop(), rect.RightBottom()); + rect.right--; + } + // vertical shadow line after left edge + if (rect.Width() >= 0) { + view->SetHighColor(shadow); + view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); + rect.left++; + } + // fill + if (rect.Width() >= 0) { + _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, + orientation); + } + } else { + // dark vertical line on top edge + if (rect.Height() > 0) { + view->SetHighColor(darkEdge1); + view->StrokeLine(rect.LeftTop(), rect.RightTop()); + rect.top++; + } + // dark vertical line on bottom edge + if (rect.Height() >= 0) { + view->SetHighColor(darkEdge2); + view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); + rect.bottom--; + } + // horizontal shadow line after top edge + if (rect.Height() >= 0) { + view->SetHighColor(shadow); + view->StrokeLine(rect.LeftTop(), rect.RightTop()); + rect.top++; + } + // fill + if (rect.Height() >= 0) { + _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, + orientation); + } + } +} + + +void +BControlLook::DrawScrollViewFrame(BView* view, BRect& rect, + const BRect& updateRect, BRect verticalScrollBarFrame, + BRect horizontalScrollBarFrame, const rgb_color& base, + border_style border, uint32 flags, uint32 _borders) +{ + // calculate scroll corner rect before messing with the "rect" + BRect scrollCornerFillRect(rect.right, rect.bottom, + rect.right, rect.bottom); + if (horizontalScrollBarFrame.IsValid()) + scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1; + if (verticalScrollBarFrame.IsValid()) + scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1; + + if (border == B_NO_BORDER) { + if (scrollCornerFillRect.IsValid()) { + view->SetHighColor(base); + view->FillRect(scrollCornerFillRect); + } + return; + } + + bool excludeScrollCorner = border == B_FANCY_BORDER + && horizontalScrollBarFrame.IsValid() + && verticalScrollBarFrame.IsValid(); + + uint32 borders = _borders; + if (excludeScrollCorner) { + rect.bottom = horizontalScrollBarFrame.top; + rect.right = verticalScrollBarFrame.left; + borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER); + } + + rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT); + + if (border == B_FANCY_BORDER) + _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); + + if (flags & B_FOCUSED) { + rgb_color focusColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + _DrawFrame(view, rect, focusColor, focusColor, focusColor, focusColor, + borders); + } else { + _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, borders); + } + + if (excludeScrollCorner) { + horizontalScrollBarFrame.InsetBy(-1, -1); + // do not overdraw the top edge + horizontalScrollBarFrame.top += 2; + borders = _borders; + borders &= ~B_TOP_BORDER; + _DrawOuterResessedFrame(view, horizontalScrollBarFrame, base, + 1.0, 1.0, flags, borders); + _DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, + borders); + + + verticalScrollBarFrame.InsetBy(-1, -1); + // do not overdraw the left edge + verticalScrollBarFrame.left += 2; + borders = _borders; + borders &= ~B_LEFT_BORDER; + _DrawOuterResessedFrame(view, verticalScrollBarFrame, base, + 1.0, 1.0, flags, borders); + _DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, + borders); + + // exclude recessed frame + scrollCornerFillRect.top++; + scrollCornerFillRect.left++; + } + + if (scrollCornerFillRect.IsValid()) { + view->SetHighColor(base); + view->FillRect(scrollCornerFillRect); + } +} + + +void +BControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 direction, uint32 flags, float tint) +{ + BPoint tri1, tri2, tri3; + float hInset = rect.Width() / 3; + float vInset = rect.Height() / 3; + rect.InsetBy(hInset, vInset); + + switch (direction) { + case B_LEFT_ARROW: + tri1.Set(rect.right, rect.top); + tri2.Set(rect.right - rect.Width() / 1.33, + (rect.top + rect.bottom + 1) /2 ); + tri3.Set(rect.right, rect.bottom + 1); + break; + case B_RIGHT_ARROW: + tri1.Set(rect.left, rect.bottom + 1); + tri2.Set(rect.left + rect.Width() / 1.33, + (rect.top + rect.bottom + 1) / 2); + tri3.Set(rect.left, rect.top); + break; + case B_UP_ARROW: + tri1.Set(rect.left, rect.bottom); + tri2.Set((rect.left + rect.right + 1) / 2, + rect.bottom - rect.Height() / 1.33); + tri3.Set(rect.right + 1, rect.bottom); + break; + case B_DOWN_ARROW: + default: + tri1.Set(rect.left, rect.top); + tri2.Set((rect.left + rect.right + 1) / 2, + rect.top + rect.Height() / 1.33); + tri3.Set(rect.right + 1, rect.top); + break; + } + // offset triangle if down + if (flags & B_ACTIVATED) + view->MovePenTo(BPoint(1, 1)); + else + view->MovePenTo(BPoint(0, 0)); + + BShape arrowShape; + arrowShape.MoveTo(tri1); + arrowShape.LineTo(tri2); + arrowShape.LineTo(tri3); + + if (flags & B_DISABLED) + tint = (tint + B_NO_TINT + B_NO_TINT) / 3; + + view->SetHighColor(tint_color(base, tint)); + + float penSize = view->PenSize(); + drawing_mode mode = view->DrawingMode(); + + view->SetPenSize(ceilf(hInset / 2.0)); + view->SetDrawingMode(B_OP_OVER); + view->StrokeShape(&arrowShape); + + view->SetPenSize(penSize); + view->SetDrawingMode(mode); +} + + +rgb_color +BControlLook::SliderBarColor(const rgb_color& base) +{ + return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT); +} + + +void +BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, + const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor, + float sliderScale, uint32 flags, enum orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // separate the bar in two sides + float sliderPosition; + BRect leftBarSide = rect; + BRect rightBarSide = rect; + + if (orientation == B_HORIZONTAL) { + sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2) + * sliderScale); + leftBarSide.right = sliderPosition - 1; + rightBarSide.left = sliderPosition; + } else { + sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2) + * sliderScale); + leftBarSide.bottom = sliderPosition - 1; + rightBarSide.top = sliderPosition; + } + + // fill the background for the corners, exclude the middle bar for now + BRegion region(rect); + region.Exclude(rightBarSide); + view->ConstrainClippingRegion(®ion); + + view->PushState(); + + DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags, + orientation); + + view->PopState(); + + region.Set(rect); + region.Exclude(leftBarSide); + view->ConstrainClippingRegion(®ion); + + view->PushState(); + + DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags, + orientation); + + view->PopState(); + + view->ConstrainClippingRegion(NULL); +} + + +void +BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, + const rgb_color& base, rgb_color fillColor, uint32 flags, + enum orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // separate the rect into corners + BRect leftCorner(rect); + BRect rightCorner(rect); + BRect barRect(rect); + + if (orientation == B_HORIZONTAL) { + leftCorner.right = leftCorner.left + leftCorner.Height(); + rightCorner.left = rightCorner.right - rightCorner.Height(); + barRect.left += ceilf(barRect.Height() / 2); + barRect.right -= ceilf(barRect.Height() / 2); + } else { + leftCorner.bottom = leftCorner.top + leftCorner.Width(); + rightCorner.top = rightCorner.bottom - rightCorner.Width(); + barRect.top += ceilf(barRect.Width() / 2); + barRect.bottom -= ceilf(barRect.Width() / 2); + } + + // fill the background for the corners, exclude the middle bar for now + BRegion region(rect); + region.Exclude(barRect); + view->ConstrainClippingRegion(®ion); + + view->SetHighColor(base); + view->FillRect(rect); + + // figure out the tints to be used + float edgeLightTint; + float edgeShadowTint; + float frameLightTint; + float frameShadowTint; + float fillLightTint; + float fillShadowTint; + + if (flags & B_DISABLED) { + edgeLightTint = 1.0; + edgeShadowTint = 1.0; + frameLightTint = 1.20; + frameShadowTint = 1.25; + fillLightTint = 0.9; + fillShadowTint = 1.05; + + fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6); + fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6); + fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6); + } else { + edgeLightTint = 0.65; + edgeShadowTint = 1.07; + frameLightTint = 1.40; + frameShadowTint = 1.50; + fillLightTint = 0.8; + fillShadowTint = 1.1; + } + + rgb_color edgeLightColor = tint_color(base, edgeLightTint); + rgb_color edgeShadowColor = tint_color(base, edgeShadowTint); + rgb_color frameLightColor = tint_color(fillColor, frameLightTint); + rgb_color frameShadowColor = tint_color(fillColor, frameShadowTint); + rgb_color fillLightColor = tint_color(fillColor, fillLightTint); + rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint); + + if (orientation == B_HORIZONTAL) { + _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation); + + _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation); + } else { + _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation); + + _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation); + } + + view->ConstrainClippingRegion(NULL); + + view->BeginLineArray(4); + if (orientation == B_HORIZONTAL) { + view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor); + view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), + edgeLightColor); + barRect.InsetBy(0, 1); + view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor); + view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), + frameLightColor); + barRect.InsetBy(0, 1); + } else { + view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor); + view->AddLine(barRect.RightTop(), barRect.RightBottom(), + edgeLightColor); + barRect.InsetBy(1, 0); + view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor); + view->AddLine(barRect.RightTop(), barRect.RightBottom(), + frameLightColor); + barRect.InsetBy(1, 0); + } + view->EndLineArray(); + + _FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint, + orientation); +} + + +void +BControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 flags, enum orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // figure out frame color + rgb_color frameLightColor; + rgb_color frameShadowColor; + rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 }; + + if (flags & B_FOCUSED) { + // focused + frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + frameShadowColor = frameLightColor; + } else { + // figure out the tints to be used + float frameLightTint; + float frameShadowTint; + + if (flags & B_DISABLED) { + frameLightTint = 1.30; + frameShadowTint = 1.35; + shadowColor.alpha = 30; + } else { + frameLightTint = 1.6; + frameShadowTint = 1.65; + } + + frameLightColor = tint_color(base, frameLightTint); + frameShadowColor = tint_color(base, frameShadowTint); + } + + BRect originalRect(rect); + rect.right--; + rect.bottom--; + + _DrawFrame(view, rect, frameLightColor, frameLightColor, + frameShadowColor, frameShadowColor); + + flags &= ~B_ACTIVATED; + DrawButtonBackground(view, rect, updateRect, base, flags); + + // thumb shadow + view->SetDrawingMode(B_OP_ALPHA); + view->SetHighColor(shadowColor); + originalRect.left++; + originalRect.top++; + view->StrokeLine(originalRect.LeftBottom(), originalRect.RightBottom()); + originalRect.bottom--; + view->StrokeLine(originalRect.RightTop(), originalRect.RightBottom()); + + // thumb edge + if (orientation == B_HORIZONTAL) { + rect.InsetBy(0, floorf(rect.Height() / 4)); + rect.left = floorf((rect.left + rect.right) / 2); + rect.right = rect.left + 1; + shadowColor = tint_color(base, B_DARKEN_2_TINT); + shadowColor.alpha = 128; + view->SetHighColor(shadowColor); + view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); + rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT); + lightColor.alpha = 128; + view->SetHighColor(lightColor); + view->StrokeLine(rect.RightTop(), rect.RightBottom()); + } else { + rect.InsetBy(floorf(rect.Width() / 4), 0); + rect.top = floorf((rect.top + rect.bottom) / 2); + rect.bottom = rect.top + 1; + shadowColor = tint_color(base, B_DARKEN_2_TINT); + shadowColor.alpha = 128; + view->SetHighColor(shadowColor); + view->StrokeLine(rect.LeftTop(), rect.RightTop()); + rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT); + lightColor.alpha = 128; + view->SetHighColor(lightColor); + view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); + } + + view->SetDrawingMode(B_OP_COPY); +} + + +void +BControlLook::DrawSliderTriangle(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + enum orientation orientation) +{ + DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation); +} + + +void +BControlLook::DrawSliderTriangle(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, const rgb_color& fill, + uint32 flags, enum orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // figure out frame color + rgb_color frameLightColor; + rgb_color frameShadowColor; + rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 }; + + float topTint = 0.49; + float middleTint1 = 0.62; + float middleTint2 = 0.76; + float bottomTint = 0.90; + + if (flags & B_DISABLED) { + topTint = (topTint + B_NO_TINT) / 2; + middleTint1 = (middleTint1 + B_NO_TINT) / 2; + middleTint2 = (middleTint2 + B_NO_TINT) / 2; + bottomTint = (bottomTint + B_NO_TINT) / 2; + } else if (flags & B_HOVER) { + static const float kHoverTintFactor = 0.85; + topTint *= kHoverTintFactor; + middleTint1 *= kHoverTintFactor; + middleTint2 *= kHoverTintFactor; + bottomTint *= kHoverTintFactor; + } + + if (flags & B_FOCUSED) { + // focused + frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + frameShadowColor = frameLightColor; + } else { + // figure out the tints to be used + float frameLightTint; + float frameShadowTint; + + if (flags & B_DISABLED) { + frameLightTint = 1.30; + frameShadowTint = 1.35; + shadowColor.alpha = 30; + } else { + frameLightTint = 1.6; + frameShadowTint = 1.65; + } + + frameLightColor = tint_color(base, frameLightTint); + frameShadowColor = tint_color(base, frameShadowTint); + } + + // make room for the shadow + rect.right--; + rect.bottom--; + + uint32 viewFlags = view->Flags(); + view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); + view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN); + + float center = (rect.left + rect.right) / 2; + + BShape shape; + shape.MoveTo(BPoint(rect.left + 0.5, rect.bottom + 0.5)); + shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5)); + shape.LineTo(BPoint(rect.right + 0.5, rect.bottom - 1 + 0.5)); + shape.LineTo(BPoint(center + 0.5, rect.top + 0.5)); + shape.LineTo(BPoint(rect.left + 0.5, rect.bottom - 1 + 0.5)); + shape.Close(); + + view->MovePenTo(BPoint(1, 1)); + + view->SetDrawingMode(B_OP_ALPHA); + view->SetHighColor(shadowColor); + view->StrokeShape(&shape); + + view->MovePenTo(B_ORIGIN); + + view->SetDrawingMode(B_OP_COPY); + view->SetHighColor(frameLightColor); + view->StrokeShape(&shape); + + rect.InsetBy(1, 1); + shape.Clear(); + shape.MoveTo(BPoint(rect.left, rect.bottom + 1)); + shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1)); + shape.LineTo(BPoint(center + 0.5, rect.top)); + shape.Close(); + + BGradientLinear gradient; + if (flags & B_DISABLED) { + _MakeGradient(gradient, rect, fill, topTint, bottomTint); + } else { + _MakeGlossyGradient(gradient, rect, fill, topTint, middleTint1, + middleTint2, bottomTint); + } + + view->FillShape(&shape, gradient); + + view->SetFlags(viewFlags); +} + + +void +BControlLook::DrawSliderHashMarks(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, int32 count, + hash_mark_location location, uint32 flags, enum orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color lightColor; + rgb_color darkColor; + + if (flags & B_DISABLED) { + lightColor = tint_color(base, 0.9); + darkColor = tint_color(base, 1.07); + } else { + lightColor = tint_color(base, 0.8); + darkColor = tint_color(base, 1.14); + } + + int32 hashMarkCount = max_c(count, 2); + // draw at least two hashmarks at min/max if + // fHashMarks != B_HASH_MARKS_NONE + float factor; + float startPos; + if (orientation == B_HORIZONTAL) { + factor = (rect.Width() - 2) / (hashMarkCount - 1); + startPos = rect.left + 1; + } else { + factor = (rect.Height() - 2) / (hashMarkCount - 1); + startPos = rect.top + 1; + } + + if (location & B_HASH_MARKS_TOP) { + view->BeginLineArray(hashMarkCount * 2); + + if (orientation == B_HORIZONTAL) { + float pos = startPos; + for (int32 i = 0; i < hashMarkCount; i++) { + view->AddLine(BPoint(pos, rect.top), + BPoint(pos, rect.top + 4), darkColor); + view->AddLine(BPoint(pos + 1, rect.top), + BPoint(pos + 1, rect.top + 4), lightColor); + + pos += factor; + } + } else { + float pos = startPos; + for (int32 i = 0; i < hashMarkCount; i++) { + view->AddLine(BPoint(rect.left, pos), + BPoint(rect.left + 4, pos), darkColor); + view->AddLine(BPoint(rect.left, pos + 1), + BPoint(rect.left + 4, pos + 1), lightColor); + + pos += factor; + } + } + + view->EndLineArray(); + } + + if (location & B_HASH_MARKS_BOTTOM) { + + view->BeginLineArray(hashMarkCount * 2); + + if (orientation == B_HORIZONTAL) { + float pos = startPos; + for (int32 i = 0; i < hashMarkCount; i++) { + view->AddLine(BPoint(pos, rect.bottom - 4), + BPoint(pos, rect.bottom), darkColor); + view->AddLine(BPoint(pos + 1, rect.bottom - 4), + BPoint(pos + 1, rect.bottom), lightColor); + + pos += factor; + } + } else { + float pos = startPos; + for (int32 i = 0; i < hashMarkCount; i++) { + view->AddLine(BPoint(rect.right - 4, pos), + BPoint(rect.right, pos), darkColor); + view->AddLine(BPoint(rect.right - 4, pos + 1), + BPoint(rect.right, pos + 1), lightColor); + + pos += factor; + } + } + + view->EndLineArray(); + } +} + + +void +BControlLook::DrawActiveTab(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 flags, uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color edgeShadowColor; + rgb_color edgeLightColor; + rgb_color frameShadowColor; + rgb_color frameLightColor; + rgb_color bevelShadowColor; + rgb_color bevelLightColor; + BGradientLinear fillGradient; + fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3)); + fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3)); + + if (flags & B_DISABLED) { + edgeShadowColor = base; + edgeLightColor = base; + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.25); + bevelShadowColor = tint_color(base, 1.07); + bevelLightColor = tint_color(base, 0.8); + fillGradient.AddColor(tint_color(base, 0.85), 0); + fillGradient.AddColor(base, 255); + } else { + edgeShadowColor = tint_color(base, 1.03); + edgeLightColor = tint_color(base, 0.80); + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.30); + bevelShadowColor = tint_color(base, 1.07); + bevelLightColor = tint_color(base, 0.6); + fillGradient.AddColor(tint_color(base, 0.75), 0); + fillGradient.AddColor(tint_color(base, 1.03), 255); + } + + static const float kRoundCornerRadius = 4; + + // left/top corner + BRect cornerRect(rect); + cornerRect.right = cornerRect.left + kRoundCornerRadius; + cornerRect.bottom = cornerRect.top + kRoundCornerRadius; + + BRegion clipping(rect); + clipping.Exclude(cornerRect); + + _DrawRoundCornerLeftTop(view, cornerRect, updateRect, base, edgeShadowColor, + frameLightColor, bevelLightColor, fillGradient); + + // left/top corner + cornerRect.right = rect.right; + cornerRect.left = cornerRect.right - kRoundCornerRadius; + + clipping.Exclude(cornerRect); + + _DrawRoundCornerRightTop(view, cornerRect, updateRect, base, edgeShadowColor, + edgeLightColor, frameLightColor, frameShadowColor, bevelLightColor, + bevelShadowColor, fillGradient); + + // rest of frame and fill + view->ConstrainClippingRegion(&clipping); + + _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, + edgeLightColor, + borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER)); + if ((borders & B_LEFT_BORDER) == 0) + rect.left++; + if ((borders & B_RIGHT_BORDER) == 0) + rect.right--; + + _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, + frameShadowColor, B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER); + + _DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor, + bevelShadowColor); + + view->FillRect(rect, fillGradient); + + view->ConstrainClippingRegion(NULL); +} + + +void +BControlLook::DrawInactiveTab(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 flags, uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color edgeShadowColor; + rgb_color edgeLightColor; + rgb_color frameShadowColor; + rgb_color frameLightColor; + rgb_color bevelShadowColor; + rgb_color bevelLightColor; + BGradientLinear fillGradient; + fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3)); + fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3)); + + if (flags & B_DISABLED) { + edgeShadowColor = base; + edgeLightColor = base; + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.25); + bevelShadowColor = tint_color(base, 1.07); + bevelLightColor = tint_color(base, 0.8); + fillGradient.AddColor(tint_color(base, 0.85), 0); + fillGradient.AddColor(base, 255); + } else { + edgeShadowColor = tint_color(base, 1.03); + edgeLightColor = tint_color(base, 0.80); + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.30); + bevelShadowColor = tint_color(base, 1.17); + bevelLightColor = tint_color(base, 1.10); + fillGradient.AddColor(tint_color(base, 1.12), 0); + fillGradient.AddColor(tint_color(base, 1.08), 255); + } + + // active tabs stand out at the top, but this is an inactive tab + view->SetHighColor(base); + view->FillRect(BRect(rect.left, rect.top, rect.right, rect.top + 4)); + rect.top += 4; + + // frame and fill + _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, + edgeLightColor, + borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER)); + + _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, + frameShadowColor, + borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER)); + + if (rect.IsValid()) { + _DrawFrame(view, rect, bevelShadowColor, bevelShadowColor, + bevelLightColor, bevelLightColor, B_LEFT_BORDER & ~borders); + } else { + if ((B_LEFT_BORDER & ~borders) != 0) + rect.left++; + } + + view->FillRect(rect, fillGradient); +} + + +void +BControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, enum orientation orientation, uint32 flags, + uint32 borders) +{ + rgb_color background; + if ((flags & (B_CLICKED | B_ACTIVATED)) != 0) + background = tint_color(base, B_DARKEN_1_TINT); + else + background = base; + + rgb_color light = tint_color(background, 0.6); + rgb_color shadow = tint_color(background, 1.21); + + // frame + if (borders != 0 && rect.Width() > 3 && rect.Height() > 3) + DrawRaisedBorder(view, rect, updateRect, background, flags, borders); + + // dots and rest of background + if (orientation == B_HORIZONTAL) { + if (rect.Width() > 2) { + // background on left/right + BRegion region(rect); + rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5); + rect.right = rect.left + 1; + region.Exclude(rect); + view->SetHighColor(background); + view->FillRegion(®ion); + } + + BPoint dot = rect.LeftTop(); + BPoint stop = rect.LeftBottom(); + int32 num = 1; + while (dot.y <= stop.y) { + rgb_color col1; + rgb_color col2; + switch (num) { + case 1: + col1 = background; + col2 = background; + break; + case 2: + col1 = shadow; + col2 = background; + break; + case 3: + default: + col1 = background; + col2 = light; + num = 0; + break; + } + view->SetHighColor(col1); + view->StrokeLine(dot, dot, B_SOLID_HIGH); + view->SetHighColor(col2); + dot.x++; + view->StrokeLine(dot, dot, B_SOLID_HIGH); + dot.x -= 1.0; + // next pixel + num++; + dot.y++; + } + } else { + if (rect.Height() > 2) { + // background on left/right + BRegion region(rect); + rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5); + rect.bottom = rect.top + 1; + region.Exclude(rect); + view->SetHighColor(background); + view->FillRegion(®ion); + } + + BPoint dot = rect.LeftTop(); + BPoint stop = rect.RightTop(); + int32 num = 1; + while (dot.x <= stop.x) { + rgb_color col1; + rgb_color col2; + switch (num) { + case 1: + col1 = background; + col2 = background; + break; + case 2: + col1 = shadow; + col2 = background; + break; + case 3: + default: + col1 = background; + col2 = light; + num = 0; + break; + } + view->SetHighColor(col1); + view->StrokeLine(dot, dot, B_SOLID_HIGH); + view->SetHighColor(col2); + dot.y++; + view->StrokeLine(dot, dot, B_SOLID_HIGH); + dot.y -= 1.0; + // next pixel + num++; + dot.x++; + } + } +} + + +// #pragma mark - + + +void +BControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, border_style border, uint32 flags, uint32 borders) +{ + if (border == B_NO_BORDER) + return; + + rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT); + if (flags & B_FOCUSED) + scrollbarFrameColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + + if (border == B_FANCY_BORDER) + _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); + + _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, borders); +} + + +void +BControlLook::DrawRaisedBorder(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + rgb_color lightColor; + rgb_color shadowColor; + + if (flags & B_DISABLED) { + lightColor = base; + shadowColor = base; + } else { + lightColor = tint_color(base, 0.85); + shadowColor = tint_color(base, 1.07); + } + + _DrawFrame(view, rect, lightColor, lightColor, shadowColor, shadowColor, + borders); +} + + +void +BControlLook::DrawTextControlBorder(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.Intersects(updateRect)) + return; + + rgb_color dark1BorderColor; + rgb_color dark2BorderColor; + rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + + if (flags & B_DISABLED) { + _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders); + + if (flags & B_BLEND_FRAME) + dark1BorderColor = (rgb_color){ 0, 0, 0, 40 }; + else + dark1BorderColor = tint_color(base, 1.15); + dark2BorderColor = dark1BorderColor; + } else if (flags & B_CLICKED) { + dark1BorderColor = tint_color(base, 1.50); + dark2BorderColor = tint_color(base, 1.49); + + // BCheckBox uses this to indicate the clicked state... + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor); + + dark2BorderColor = dark1BorderColor; + } else { + _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags, borders); + + if (flags & B_BLEND_FRAME) { + dark1BorderColor = (rgb_color){ 0, 0, 0, 102 }; + dark2BorderColor = (rgb_color){ 0, 0, 0, 97 }; + } else { + dark1BorderColor = tint_color(base, 1.40); + dark2BorderColor = tint_color(base, 1.38); + } + } + + if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED)) { + dark1BorderColor = navigationColor; + dark2BorderColor = navigationColor; + } + + if (flags & B_BLEND_FRAME) { + drawing_mode oldMode = view->DrawingMode(); + view->SetDrawingMode(B_OP_ALPHA); + + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor, borders); + + view->SetDrawingMode(oldMode); + } else { + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor, borders); + } +} + + +void +BControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 borders) +{ + rgb_color frameColor = tint_color(base, 1.30); + rgb_color bevelLight = tint_color(base, 0.8); + rgb_color bevelShadow = tint_color(base, 1.03); + + _DrawFrame(view, rect, bevelShadow, bevelShadow, bevelLight, bevelLight, + borders); + + _DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor, + borders); + + _DrawFrame(view, rect, bevelLight, bevelLight, bevelShadow, bevelShadow, + borders); +} + + +void +BControlLook::DrawLabel(BView* view, const char* label, BRect rect, + const BRect& updateRect, const rgb_color& base, uint32 flags) +{ + DrawLabel(view, label, rect, updateRect, base, flags, + DefaultLabelAlignment()); +} + + +void +BControlLook::DrawLabel(BView* view, const char* label, BRect rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + const BAlignment& alignment) +{ + if (!rect.Intersects(updateRect)) + return; + + // setup the text color + rgb_color color; + if (base.red + base.green + base.blue > 128 * 3) + color = tint_color(base, B_DARKEN_MAX_TINT); + else + color = tint_color(base, B_LIGHTEN_MAX_TINT); + + if (flags & B_DISABLED) { + color.red = (uint8)(((int32)base.red + color.red + 1) / 2); + color.green = (uint8)(((int32)base.green + color.green + 1) / 2); + color.blue = (uint8)(((int32)base.blue + color.blue + 1) / 2); + } + + view->SetHighColor(color); + view->SetDrawingMode(B_OP_OVER); + + // truncate the label if necessary and get the width and height + BString truncatedLabel(label); + + BFont font; + view->GetFont(&font); + + float width = rect.Width(); + font.TruncateString(&truncatedLabel, B_TRUNCATE_END, width); + width = font.StringWidth(truncatedLabel.String()); + + font_height fontHeight; + font.GetHeight(&fontHeight); + float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); + + // handle alignment + BPoint location; + + switch (alignment.horizontal) { + default: + case B_ALIGN_LEFT: + location.x = rect.left; + break; + case B_ALIGN_RIGHT: + location.x = rect.right - width; + break; + case B_ALIGN_CENTER: + location.x = (rect.left + rect.right - width) / 2.0f; + break; + } + + switch (alignment.vertical) { + case B_ALIGN_TOP: + location.y = rect.top + ceilf(fontHeight.ascent); + break; + default: + case B_ALIGN_MIDDLE: + location.y = floorf((rect.top + rect.bottom - height) / 2.0f + 0.5f) + + ceilf(fontHeight.ascent); + break; + case B_ALIGN_BOTTOM: + location.y = rect.bottom - ceilf(fontHeight.descent); + break; + } + + view->DrawString(truncatedLabel.String(), location); +} + + +// #pragma mark - + + +void +BControlLook::_DrawButtonFrame(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, const rgb_color& background, + float contrast, float brightness, uint32 flags, uint32 borders) +{ + // colors + rgb_color dark1BorderColor; + rgb_color dark2BorderColor; + + if ((flags & B_DISABLED) == 0) { + if (flags & B_BLEND_FRAME) { + dark1BorderColor = (rgb_color){ 0, 0, 0, 75 }; + dark2BorderColor = (rgb_color){ 0, 0, 0, 95 }; + } else { + dark1BorderColor = tint_color(base, 1.33); + dark2BorderColor = tint_color(base, 1.45); + } + + if (flags & B_DEFAULT_BUTTON) { + // TODO: B_BLEND_FRAME + dark2BorderColor = tint_color(dark1BorderColor, 1.5); + dark1BorderColor = tint_color(dark1BorderColor, 1.35); + } + } else { + // TODO: B_BLEND_FRAME + dark1BorderColor = tint_color(base, 1.147); + dark2BorderColor = tint_color(base, 1.24); + + if (flags & B_DEFAULT_BUTTON) { + dark1BorderColor = tint_color(dark1BorderColor, 1.14); + dark2BorderColor = tint_color(dark1BorderColor, 1.12); + } + } + + if (flags & B_ACTIVATED) { + rgb_color temp = dark2BorderColor; + dark2BorderColor = dark1BorderColor; + dark1BorderColor = temp; + } + + // indicate focus by changing main button border + if (flags & B_FOCUSED) { + dark1BorderColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + dark2BorderColor = dark1BorderColor; + } + + if (flags & B_DEFAULT_BUTTON) { + // TODO: B_BLEND_FRAME + float focusTint = 1.2; + if (flags & B_DISABLED) + focusTint = (B_NO_TINT + focusTint) / 2; + + rgb_color focusColor = tint_color(base, focusTint); + view->SetHighColor(base); + + view->StrokeRect(rect); + rect.InsetBy(1.0, 1.0); + + view->SetHighColor(focusColor); + view->StrokeRect(rect); + rect.InsetBy(1.0, 1.0); + view->StrokeRect(rect); + rect.InsetBy(1.0, 1.0); + + // bevel around external border + _DrawOuterResessedFrame(view, rect, focusColor, + contrast * (((flags & B_DISABLED) ? 0.3 : 0.8)), + brightness * (((flags & B_DISABLED) ? 1.0 : 0.9)), + flags, borders); + } else { + // bevel around external border + _DrawOuterResessedFrame(view, rect, background, + contrast * ((flags & B_DISABLED) ? 0.0 : 1.0), brightness * 1.0, + flags, borders); + } + + if (flags & B_BLEND_FRAME) { + drawing_mode oldDrawingMode = view->DrawingMode(); + view->SetDrawingMode(B_OP_ALPHA); + + _DrawFrame(view, rect, dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor, borders); + + view->SetDrawingMode(oldDrawingMode); + } else { + _DrawFrame(view, rect, dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor, borders); + } +} + + +void +BControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect, + const rgb_color& base, float contrast, float brightness, uint32 flags, + uint32 borders) +{ + if (flags & B_BLEND_FRAME) { + // assumes the background has already been painted + drawing_mode oldDrawingMode = view->DrawingMode(); + view->SetDrawingMode(B_OP_ALPHA); + + uint8 alpha = uint8(20 * contrast); + uint32 white = uint8(255 * brightness); + + rgb_color borderBevelShadow = (rgb_color){ 0, 0, 0, alpha }; + rgb_color borderBevelLight = (rgb_color){ white, white, white, alpha }; + + _DrawFrame(view, rect, borderBevelShadow, borderBevelShadow, + borderBevelLight, borderBevelLight, borders); + + view->SetDrawingMode(oldDrawingMode); + } else { + // colors + float tintLight = kEdgeBevelLightTint; + float tintShadow = kEdgeBevelShadowTint; + + if (contrast == 0.0) { + tintLight = B_NO_TINT; + tintShadow = B_NO_TINT; + } else if (contrast != 1.0) { + tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast; + tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast; + } + + rgb_color borderBevelShadow = tint_color(base, tintShadow); + rgb_color borderBevelLight = tint_color(base, tintLight); + + if (brightness < 1.0) { + borderBevelShadow.red = uint8(borderBevelShadow.red * brightness); + borderBevelShadow.green = uint8(borderBevelShadow.green * brightness); + borderBevelShadow.blue = uint8(borderBevelShadow.blue * brightness); + borderBevelLight.red = uint8(borderBevelLight.red * brightness); + borderBevelLight.green = uint8(borderBevelLight.green * brightness); + borderBevelLight.blue = uint8(borderBevelLight.blue * brightness); + } + + _DrawFrame(view, rect, borderBevelShadow, borderBevelShadow, + borderBevelLight, borderBevelLight, borders); + } +} + + +void +BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left, + const rgb_color& top, const rgb_color& right, const rgb_color& bottom, + uint32 borders) +{ + view->BeginLineArray(4); + + if (borders & B_LEFT_BORDER) { + view->AddLine( + BPoint(rect.left, rect.bottom), + BPoint(rect.left, rect.top), left); + rect.left++; + } + if (borders & B_TOP_BORDER) { + view->AddLine( + BPoint(rect.left, rect.top), + BPoint(rect.right, rect.top), top); + rect.top++; + } + if (borders & B_RIGHT_BORDER) { + view->AddLine( + BPoint(rect.right, rect.top), + BPoint(rect.right, rect.bottom), right); + rect.right--; + } + if (borders & B_BOTTOM_BORDER) { + view->AddLine( + BPoint(rect.left, rect.bottom), + BPoint(rect.right, rect.bottom), bottom); + rect.bottom--; + } + + view->EndLineArray(); +} + + +void +BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left, + const rgb_color& top, const rgb_color& right, const rgb_color& bottom, + const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders) +{ + view->BeginLineArray(6); + + if (borders & B_TOP_BORDER) { + if (borders & B_RIGHT_BORDER) { + view->AddLine( + BPoint(rect.left, rect.top), + BPoint(rect.right - 1, rect.top), top); + view->AddLine( + BPoint(rect.right, rect.top), + BPoint(rect.right, rect.top), rightTop); + } else { + view->AddLine( + BPoint(rect.left, rect.top), + BPoint(rect.right, rect.top), top); + } + rect.top++; + } + + if (borders & B_LEFT_BORDER) { + view->AddLine( + BPoint(rect.left, rect.top), + BPoint(rect.left, rect.bottom - 1), left); + view->AddLine( + BPoint(rect.left, rect.bottom), + BPoint(rect.left, rect.bottom), leftBottom); + rect.left++; + } + + if (borders & B_BOTTOM_BORDER) { + view->AddLine( + BPoint(rect.left, rect.bottom), + BPoint(rect.right, rect.bottom), bottom); + rect.bottom--; + } + + if (borders & B_RIGHT_BORDER) { + view->AddLine( + BPoint(rect.right, rect.bottom), + BPoint(rect.right, rect.top), right); + rect.right--; + } + + view->EndLineArray(); +} + + +//void +//BControlLook::_DrawShadowFrame(BView* view, BRect& rect, const rgb_color& base, +// uint32 borders) +//{ +// view->BeginLineArray(4); +// +// bevelColor1 = tint_color(base, 1.2); +// bevelColor2 = tint_color(base, 1.1); +// +// // shadow along left/top borders +// if (rect.Height() > 0 && borders & B_LEFT_BORDER) { +// view->AddLine(BPoint(rect.left, rect.top), +// BPoint(rect.left, rect.bottom), bevelColor1); +// rect.left++; +// } +// if (rect.Width() > 0 && borders & B_TOP_BORDER) { +// view->AddLine(BPoint(rect.left, rect.top), +// BPoint(rect.right, rect.top), bevelColor1); +// rect.top++; +// } +// +// // softer shadow along left/top borders +// if (rect.Height() > 0 && borders & B_LEFT_BORDER) { +// view->AddLine(BPoint(rect.left, rect.top), +// BPoint(rect.left, rect.bottom), bevelColor2); +// rect.left++; +// } +// if (rect.Width() > 0 && borders & B_TOP_BORDER) { +// view->AddLine(BPoint(rect.left, rect.top), +// BPoint(rect.right, rect.top), bevelColor2); +// rect.top++; +// } +// +// view->EndLineArray(); +//} + + +void +BControlLook::_FillGradient(BView* view, const BRect& rect, + const rgb_color& base, float topTint, float bottomTint, + enum orientation orientation) +{ + BGradientLinear gradient; + _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation); + view->FillRect(rect, gradient); +} + + +void +BControlLook::_FillGlossyGradient(BView* view, const BRect& rect, + const rgb_color& base, float topTint, float middle1Tint, + float middle2Tint, float bottomTint, enum orientation orientation) +{ + BGradientLinear gradient; + _MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint, + middle2Tint, bottomTint, orientation); + view->FillRect(rect, gradient); +} + + +void +BControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect, + const rgb_color& base, float topTint, float bottomTint, + enum orientation orientation) const +{ + gradient.AddColor(tint_color(base, topTint), 0); + gradient.AddColor(tint_color(base, bottomTint), 255); + gradient.SetStart(rect.LeftTop()); + if (orientation == B_HORIZONTAL) + gradient.SetEnd(rect.LeftBottom()); + else + gradient.SetEnd(rect.RightTop()); +} + + +void +BControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect, + const rgb_color& base, float topTint, float middle1Tint, + float middle2Tint, float bottomTint, + enum orientation orientation) const +{ + gradient.AddColor(tint_color(base, topTint), 0); + gradient.AddColor(tint_color(base, middle1Tint), 132); + gradient.AddColor(tint_color(base, middle2Tint), 136); + gradient.AddColor(tint_color(base, bottomTint), 255); + gradient.SetStart(rect.LeftTop()); + if (orientation == B_HORIZONTAL) + gradient.SetEnd(rect.LeftBottom()); + else + gradient.SetEnd(rect.RightTop()); +} + + +bool +BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base, + rgb_color& color, uint32 flags) const +{ + if ((flags & (B_ACTIVATED | B_CLICKED)) == 0) { + // no mark to be drawn at all + return false; + } + + // TODO: Get from UI settings + color.red = 27; + color.green = 82; + color.blue = 140; + + float mix = 1.0; + + if (flags & B_DISABLED) { + // activated, but disabled + mix = 0.4; + } else if (flags & B_CLICKED) { + if (flags & B_ACTIVATED) { + // loosing activation + mix = 0.7; + } else { + // becoming activated + mix = 0.3; + } + } else { + // simply activated + } + + color.red = uint8(color.red * mix + base.red * (1.0 - mix)); + color.green = uint8(color.green * mix + base.green * (1.0 - mix)); + color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix)); + + return true; +} + + +void +BControlLook::_DrawRoundBarCorner(BView* view, BRect& rect, + const BRect& updateRect, + const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor, + const rgb_color& frameLightColor, const rgb_color& frameShadowColor, + const rgb_color& fillLightColor, const rgb_color& fillShadowColor, + float leftInset, float topInset, float rightInset, float bottomInset, + enum orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BGradientLinear gradient; + gradient.AddColor(edgeShadowColor, 0); + gradient.AddColor(edgeLightColor, 255); + gradient.SetStart(rect.LeftTop()); + if (orientation == B_HORIZONTAL) + gradient.SetEnd(rect.LeftBottom()); + else + gradient.SetEnd(rect.RightTop()); + + view->FillEllipse(rect, gradient); + + rect.left += leftInset; + rect.top += topInset; + rect.right += rightInset; + rect.bottom += bottomInset; + + gradient.MakeEmpty(); + gradient.AddColor(frameShadowColor, 0); + gradient.AddColor(frameLightColor, 255); + gradient.SetStart(rect.LeftTop()); + if (orientation == B_HORIZONTAL) + gradient.SetEnd(rect.LeftBottom()); + else + gradient.SetEnd(rect.RightTop()); + + view->FillEllipse(rect, gradient); + + rect.left += leftInset; + rect.top += topInset; + rect.right += rightInset; + rect.bottom += bottomInset; + + gradient.MakeEmpty(); + gradient.AddColor(fillShadowColor, 0); + gradient.AddColor(fillLightColor, 255); + gradient.SetStart(rect.LeftTop()); + if (orientation == B_HORIZONTAL) + gradient.SetEnd(rect.LeftBottom()); + else + gradient.SetEnd(rect.RightTop()); + + view->FillEllipse(rect, gradient); +} + + +void +BControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, const rgb_color& edgeColor, + const rgb_color& frameColor, const rgb_color& bevelColor, + const BGradientLinear& fillGradient) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BRegion clipping(rect); + view->ConstrainClippingRegion(&clipping); + + // background + view->SetHighColor(base); + view->FillRect(rect); + + // outer edge + BRect ellipseRect(rect); + ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; + ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; + + view->SetHighColor(edgeColor); + view->FillEllipse(ellipseRect); + + // frame + ellipseRect.InsetBy(1, 1); + view->SetHighColor(frameColor); + view->FillEllipse(ellipseRect); + + // bevel + ellipseRect.InsetBy(1, 1); + view->SetHighColor(bevelColor); + view->FillEllipse(ellipseRect); + + // fill + ellipseRect.InsetBy(1, 1); + view->FillEllipse(ellipseRect, fillGradient); + + view->ConstrainClippingRegion(NULL); +} + +void +BControlLook::_DrawRoundCornerRightTop(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, + const rgb_color& edgeTopColor, const rgb_color& edgeRightColor, + const rgb_color& frameTopColor, const rgb_color& frameRightColor, + const rgb_color& bevelTopColor, const rgb_color& bevelRightColor, + const BGradientLinear& fillGradient) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BRegion clipping(rect); + view->ConstrainClippingRegion(&clipping); + + // background + view->SetHighColor(base); + view->FillRect(rect); + + // outer edge + BRect ellipseRect(rect); + ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; + ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; + + BGradientLinear gradient; + gradient.AddColor(edgeTopColor, 0); + gradient.AddColor(edgeRightColor, 255); + gradient.SetStart(rect.LeftTop()); + gradient.SetEnd(rect.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + + // frame + ellipseRect.InsetBy(1, 1); + rect.right--; + rect.top++; + if (frameTopColor == frameRightColor) { + view->SetHighColor(frameTopColor); + view->FillEllipse(ellipseRect); + } else { + gradient.SetColor(0, frameTopColor); + gradient.SetColor(1, frameRightColor); + gradient.SetStart(rect.LeftTop()); + gradient.SetEnd(rect.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + } + + // bevel + ellipseRect.InsetBy(1, 1); + rect.right--; + rect.top++; + gradient.SetColor(0, bevelTopColor); + gradient.SetColor(1, bevelRightColor); + gradient.SetStart(rect.LeftTop()); + gradient.SetEnd(rect.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + + // fill + ellipseRect.InsetBy(1, 1); + view->FillEllipse(ellipseRect, fillGradient); + + view->ConstrainClippingRegion(NULL); +} + + +// NOTE: May come from a add-on in the future. Initialized in +// InterfaceDefs.cpp +BControlLook* be_control_look = NULL; + +} // namespace BPrivate diff --git a/src/DateTextView.cpp b/src/DateTextView.cpp new file mode 100644 index 0000000..510aa50 --- /dev/null +++ b/src/DateTextView.cpp @@ -0,0 +1,620 @@ +// Calendar Control version 2.5 +// by Al.V. Sarikov. +// Kherson, Ukraine, 2006. +// E-mail: avix@ukrpost.net. +// Home page: http://avix.pp.ru. + +// Control which allows to work with dates: +// enter date to text field and choose it from calendar. + +// Distributed under BSD license (see LICENSE file). + +#include +#include +#include +#include +#include +#include +#include + + +#define LAST_FORMAT 1 // quantity of formats - 1 +#define LAST_DIVIDER 2 // quantity of dividers - 1 + + +class DateTextView: public BTextView +{ + public: + DateTextView(int day, int month, int year, uint32 flags, uint32 look); + virtual void Cut(BClipboard *clip); + virtual void KeyDown(const char *bytes, int32 numBytes); + virtual void MakeFocus(bool focused); + virtual void Paste(BClipboard *clip); + virtual void SetEnabled(bool enabled); + + void GetDate(int *day, int *month, int *year); + void SetDate(int day, int month, int year); + void SetDate(const char *tdate); + void GetYearRange(int *first_year, int *last_year); + uint32 GetDivider(); + void SetDivider(uint32 dvder); + uint32 GetDateFlags(); + void SetDateFlags(uint32 flags); + + protected: + virtual void DeleteText(int32 start, int32 finish); + private: + virtual bool AcceptsDrop(const BMessage *message); + virtual bool AcceptsPaste(BClipboard *clip); + + void DrawDate(int day, int month, int year); + bool VerifyDate(int *day, int *month, int *year); + + bool is_ins; // is it necessar to insert symbol + uint32 flags; + char *div[LAST_DIVIDER+1]; // Ñstrings of dividers + uint32 divider; + + bool enabled; + + int first_year; + int last_year; // first and last year which control accepts + + int textlen; // length of text string (10 or 8 symbols) + + uint32 interface; // the same as control variable +}; + + +////////////////////////////////////////////////////////////////////////// +DateTextView::DateTextView(int day, int month, int year, + uint32 flags, uint32 look) + :BTextView(BRect(0,0,110,15),"DateTextViewAViX", + BRect(0,0,110,15),B_FOLLOW_LEFT | B_FOLLOW_TOP, + B_WILL_DRAW | B_NAVIGABLE) +{ + enabled=true; + + is_ins=false; + + interface=look; + + div[0]=(char*)"."; + div[1]=(char*)"/"; + div[2]=(char*)"-"; + + divider=look & CC_ALL_DIVIDERS; + if(divider>LAST_DIVIDER || divider<0) divider=0; // index of divider + + this->flags=(flags & (LAST_FORMAT | CC_SHORT_YEAR | CC_HALF_CENTURY)); + if((this->flags & (CC_SHORT_YEAR | CC_HALF_CENTURY))==CC_HALF_CENTURY) + this->flags=this->flags^CC_HALF_CENTURY; // XOR; CC_FULL_YEAR and CC_HALF_CENTURY + // at the same time may not be used + + first_year=1; + last_year=9999; + + if((this->flags & CC_SHORT_YEAR)==CC_SHORT_YEAR) + { + textlen=8; + + // Changing first and last acceptable years + // Working in range of century defined by year variable + + if(yearlast_year) + { + // Range is set relative to today's year + struct tm *dat; + time_t tmp; + time(&tmp); + dat=localtime(&tmp); + + year=dat->tm_year+1900; // today's year + } + + first_year=(year/100)*100+1; // dividing with loosing rest + last_year=first_year+99; + if(last_year==10000) last_year--; // full century + + if((this->flags & CC_HALF_CENTURY)==CC_HALF_CENTURY) + { + if(year<51 || year>9950) + this->flags=this->flags^CC_HALF_CENTURY; // HALF_CENTURY may nor be set + else + { + if((year%100)>50) + { + first_year+=50; + last_year+=50; + } + else + { + first_year-=50; + last_year-=50; + } + } + } + } + else textlen=10; // length of text string + + SetDate(day,month,year); + + float width=0; + BString s(""); + for(char i='0'; i<='9'; i++) + { + s<width) width=StringWidth(s.String()); + s.SetTo(""); + } + + ResizeTo(width*(textlen-2)+StringWidth("/")*2.5, LineHeight()-1); + + SetWordWrap(false); + SetMaxBytes(textlen); + SetTextRect(Bounds()); + SetDoesUndo(false); + for(int32 i=0;i<256;i++) DisallowChar(i); + for(int32 i='0';i<='9';i++) AllowChar(i); +} + + +/////////////////////////////////////////////////////// +bool DateTextView::AcceptsDrop(const BMessage *message) +{ + return false; +} + + +///////////////////////////////////////////////// +bool DateTextView::AcceptsPaste(BClipboard *clip) +{ + return false; +} + + +//////////////////////////////////////// +void DateTextView::Cut(BClipboard *clip) +{ + Copy(clip); +} + + +//////////////////////////////////////////////////////// +void DateTextView::DeleteText(int32 start, int32 finish) +{ + BTextView::DeleteText(start,finish); + if(is_ins) + { + if(start==2 || start==5) InsertText(div[divider],1,start,NULL); + else InsertText("0",1,start,NULL); + } +} + + +///////////////////////////////////////////////////////////// +void DateTextView::KeyDown(const char *bytes, int32 numBytes) +{ + if(!enabled) if(bytes[0]!=B_TAB) return; + + int32 i1,i2; + GetSelection(&i1,&i2); + + if(bytes[0]>='0' && bytes[0]<='9') + { + if(i1>(textlen-1)) return; // not to insert after end of string + Select(i1,i1); + if(i1==2 || i1==5) + { + i1++; + Select(i1,i1); + } + DeleteText(i1,i1+1); + BTextView::KeyDown(bytes, numBytes); + } + else if(bytes[0]==B_DELETE) + { + if(i1>(textlen-1)) return; // not to insert after end of string + Select(i1,i1); + is_ins=true; // symbol "0" or divider will be inserted + BTextView::KeyDown(bytes, numBytes); + is_ins=false; + } + else if(bytes[0]==B_BACKSPACE) + { + Select(i1,i1); + is_ins=true; + BTextView::KeyDown(bytes, numBytes); + is_ins=false; + } + else if(bytes[0]==B_TAB) + { + Parent()->KeyDown(bytes, numBytes); + } + else if(bytes[0]==B_DOWN_ARROW) + { + // Is Ctrl+DownArrow pressed? + if(modifiers() & B_CONTROL_KEY) + { + // yes + BMessage msg(myButtonMessage); + Parent()->MessageReceived(&msg); + } + else + BTextView::KeyDown(bytes, numBytes); + } + else + BTextView::KeyDown(bytes, numBytes); +} + + +/////////////////////////////////////////////// +void DateTextView::MakeFocus(bool focused=true) +{ + BTextView::MakeFocus(focused); + + int day, month, year; + GetDate(&day, &month, &year); + Parent()->Draw(Parent()->Bounds()); +} + + +////////////////////////////////////////// +void DateTextView::Paste(BClipboard *clip) +{ + return; +} + + +/////////////////////////////////////////// +void DateTextView::SetEnabled(bool enabled) +{ + this->enabled=enabled; + SetFlags(Flags()^B_NAVIGABLE); + MakeEditable(enabled); + + BFont font; + rgb_color color; + GetFontAndColor((int32) 0, &font, &color); + color.alpha=0; + if(enabled) + { + SetViewColor(255,255,255,255); + color.red=color.green=color.blue=0; + } + else + { + SetViewColor(239,239,239,255); + color.red=color.green=color.blue=128; + } + + SetFontAndColor(&font,B_FONT_ALL,&color); + Invalidate(); +} + + +///////////////////////////////////////////////////////// +void DateTextView::DrawDate(int day, int month, int year) +{ + // It is assumed that date is correct + BString s; + s.SetTo(""); + + if(!((flags & CC_MM_DD_YYYY_FORMAT)==CC_MM_DD_YYYY_FORMAT)) + { + if(day<10) s.Append("0"); + s<last_year) + { + int year1=*year%100; + if((flags & CC_HALF_CENTURY)==CC_HALF_CENTURY) + { + if(year1<51) year1+=50; else year1-=50; + } + else if(year1==0) year1=100; + + *year=year1+first_year-1; + flag=false; + } + } + else // FULL_YEAR + { + if(*year<1 || *year>9999) + { + *year=dat->tm_year+1900; + flag=false; + } + } + + if(*month<1 || *month>12) + { + *month=dat->tm_mon+1; + flag=false; + } + + if(*day<1 || *day>31) + { + *day=dat->tm_mday; + flag=false; + } + + if((*month==4 || *month==6 || *month==9 || *month==11) && *day>30) + { + if((*day=dat->tm_mday)>30) *day=30; + flag=false; + } + else if (*month==2) + { + int tmpday; + + if((*year)%4==0) // leap year? + { + if((*year)%100==0 && (*year)%400!=0) tmpday=28; // no + else tmpday=29; // yes + } + else tmpday=28; + + if(*day>tmpday) + { + if((*day=dat->tm_mday)>tmpday) *day=tmpday; + flag=false; + } + } + + return flag; +} + + +//////////////////////////////////////////////////////////////// +void DateTextView::GetYearRange(int *first_year, int *last_year) +{ + *first_year=this->first_year; + *last_year=this->last_year; +} + + +///////////////////////////////// +uint32 DateTextView::GetDivider() +{ + return divider; +} + + +/////////////////////////////////////////// +void DateTextView::SetDivider(uint32 dvder) +{ + if(dvder<0 || dvder>LAST_DIVIDER) dvder=0; + + BString s(Text()); + SetText((s.ReplaceAll(div[divider],div[dvder])).String()); + this->divider=dvder; +} + + +/////////////////////////////////// +uint32 DateTextView::GetDateFlags() +{ + return flags; +} + + +/////////////////////////////////////////// +void DateTextView::SetDateFlags(uint32 fmt) +{ + int mday, mmonth, myear; + GetDate(&mday, &mmonth, &myear); + + // Blocking changing of parameters of year + // (full/short year, full/half century) + fmt=fmt & 0xFFE7; + + if(fmt<0 || fmt>LAST_FORMAT) fmt=0; + + flags=fmt | (flags & 0xFFFE); // LAST_FORMAT==1, 1 bit + + SetDate(mday, mmonth, myear); +} diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..f14c361 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,129 @@ +## +## yab Haiku Makefile +## +## (c) Jan Bungeroth 2009 - 2012 +## Artistic License. +## +## Use +## make +## to compile yab for Haiku. +## +## Needs a valid installation of at least: gcc, flex, bison, perl, ncurses +## + +## +## Haiku stuff +## +HAIKUTAB = YabTabView.o +HAIKUOPT = -DHAIKU -DLIBRARY_PATH=\"`finddir B_USER_SETTINGS_DIRECTORY`/yab\" + + +## +## Use our own column list view +## +COLUMN = column/ColumnListView.o + +## +## enable debug +## +# DBG = -g +# + +## +## enable optimization +## +OPT = -O +# + +## +## GCC Options +## +GCC = gcc +GCC_OPT = $(DBG) $(OPT) -I. -I/boot/home/config/include/ -I/boot/home/config/include/ncurses/ -DHAVE_CONFIG -DUNIX $(HAIKUOPT) +GPP = g++ +GPP_OPT = $(DBG) $(OPT) -I. -DHAVE_CONFIG -DUNIX $(HAIKUOPT) + +## +## Libraries +## +##LIBPATH = -L/boot/home/config/lib +LIBPATHS = $(shell findpaths B_FIND_PATH_LIB_DIRECTORY) +LIBPATH=$(addprefix -L,$(LIBPATHS)) +##LIBPATH = -L`finddir B_SYSTEM_LIB_DIRECTORY` ##/boot/system/lib +LIB = -lbe -lroot -ltranslation -ltracker -lmedia + +## flags for flex (-d for debugging) +FLEXFLAGS = -i -I -L -s + +## flags for bison (-t -v for debugging) +BISONFLAGS = -d -l -t -v + +## +## Compile and link +## +yab: YabMain.o YabInterface.o YabWindow.o YabView.o YabBitmapView.o YabFilePanel.o YabFilePanelLooper.o YabList.o \ + YabText.o flex.o bison.o symbol.o function.o graphic.o io.o main.o $(COLUMN) column/YabColumnType.o column/ColorTools.o YabStackView.o SplitPane.o URLView.o YabControlLook.o \ + $(HAIKUTAB) Spinner.o column/ColumnListView.o CalendarControl.o + $(GPP) $(GPP_OPT) -o yab YabMain.o YabInterface.o YabWindow.o YabView.o YabBitmapView.o YabText.o YabFilePanel.o \ + YabFilePanelLooper.o YabList.o main.o function.o io.o graphic.o symbol.o bison.o flex.o $(COLUMN) column/YabColumnType.o column/ColorTools.o \ + YabStackView.o SplitPane.o URLView.o YabControlLook.o $(HAIKUTAB) Spinner.o $(TABLIB) CalendarControl.o \ + $(LIBPATH) $(LIB) +YabMain.o: YabMain.cpp + $(GPP) $(GPP_OPT) -c YabMain.cpp -o YabMain.o +YabInterface.o: YabInterface.cpp YabInterface.h YabMenu.h + $(GPP) $(GPP_OPT) -c YabInterface.cpp -o YabInterface.o +YabWindow.o: YabWindow.cpp YabWindow.h + $(GPP) $(GPP_OPT) -c YabWindow.cpp -o YabWindow.o +YabView.o: YabView.cpp YabView.h + $(GPP) $(GPP_OPT) -c YabView.cpp -o YabView.o +YabBitmapView.o: YabBitmapView.cpp YabBitmapView.h + $(GPP) $(GPP_OPT) -c YabBitmapView.cpp -o YabBitmapView.o +YabFilePanel.o: YabFilePanel.cpp YabFilePanel.h + $(GPP) $(GPP_OPT) -c YabFilePanel.cpp -o YabFilePanel.o +YabFilePanelLooper.o: YabFilePanelLooper.cpp YabFilePanelLooper.h + $(GPP) $(GPP_OPT) -c YabFilePanelLooper.cpp -o YabFilePanelLooper.o +YabList.o: YabList.cpp YabList.h + $(GPP) $(GPP_OPT) -c YabList.cpp -o YabList.o +YabText.o: YabText.cpp YabText.h + $(GPP) $(GPP_OPT) -c YabText.cpp -o YabText.o +bison.o: bison.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c bison.c -o bison.o +flex.o: flex.c bison.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c flex.c -o flex.o +function.o: function.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c function.c -o function.o +io.o: io.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c io.c -o io.o +graphic.o: graphic.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c graphic.c -o graphic.o +symbol.o: symbol.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c symbol.c -o symbol.o +main.o: main.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c main.c -o main.o +flex.c: yabasic.flex + flex $(FLEXFLAGS) -t yabasic.flex >flex.c +bison.c: yabasic.bison + bison $(BISONFLAGS) --output-file bison.c yabasic.bison +YabStackView.o: YabStackView.cpp YabStackView.h + $(GPP) $(GPP_OPT) -c YabStackView.cpp -o YabStackView.o +SplitPane.o: SplitPane.cpp SplitPane.h + $(GPP) $(GPP_OPT) -c SplitPane.cpp -o SplitPane.o +URLView.o: URLView.cpp URLView.h + $(GPP) $(GPP_OPT) -c URLView.cpp -o URLView.o +Spinner.o: Spinner.cpp Spinner.h + $(GPP) $(GPP_OPT) -c Spinner.cpp -o Spinner.o +column/ColumnListView.o: column/ColumnListView.cpp column/ColumnListView.h column/ObjectList.h + $(GPP) $(GPP_OPT) -c column/ColumnListView.cpp -o column/ColumnListView.o +column/ColorTools.o: column/ColorTools.cpp column/ColorTools.h + $(GPP) $(GPP_OPT) -c column/ColorTools.cpp -o column/ColorTools.o +column/YabColumnType.o: column/YabColumnType.cpp column/YabColumnType.h + $(GPP) $(GPP_OPT) -c column/YabColumnType.cpp -o column/YabColumnType.o +$(HAIKUTAB): YabTabView.cpp YabTabView.h + $(GPP) $(GPP_OPT) -c YabTabView.cpp -o YabTabView.o +CalendarControl.o: CalendarControl.cpp CalendarControl.h DateTextView.cpp MonthWindow.cpp MonthView.cpp MouseSenseStringView.cpp + $(GPP) $(GPP_OPT) -c CalendarControl.cpp -o CalendarControl.o +YabControlLook.o: YabControlLook.h YabControlLook.cpp + $(GPP) $(GPP_OPT) -c YabControlLook.cpp -o YabControlLook.o + +clean: + rm -f core *.o column/*.o flex.* bison.* yab yabasic.output diff --git a/src/MonthView.cpp b/src/MonthView.cpp new file mode 100644 index 0000000..5d6847d --- /dev/null +++ b/src/MonthView.cpp @@ -0,0 +1,960 @@ +// Calendar Control version 2.5 +// by Al.V. Sarikov. +// Kherson, Ukraine, 2006. +// E-mail: avix@ukrpost.net. +// Home page: http://avix.pp.ru. + +// Control which allows to work with dates: +// enter date to text field and choose it from calendar. + +// Distributed under BSD license (see LICENSE file). + +#include +#include +#include +#include +#include "MouseSenseStringView.cpp" + + +class MonthView : public BView +{ + public: + MonthView(int day, int month, int year, int first_year, int last_year); + ~MonthView(); + virtual void AttachedToWindow(void); + virtual void Draw(BRect r); + virtual void KeyDown(const char *bytes, int32 numBytes); + virtual void MessageReceived(BMessage *msg); + virtual void MouseDown(BPoint p); + virtual void MouseUp(BPoint p); + void MouseMoved(BPoint pt, uint32 transit, const BMessage *msg); + + private: + void DrawMonth(); + + BMessenger *msng; + MouseSenseStringView *yearMStringView[2]; + MouseSenseStringView *monthMStringView[2]; + + MouseSenseStringView *todayStringView; + BStringView *monthStringView; + BStringView *yearStringView; + char *weekdayNames[7]; + char *monthNames[12]; + int monthDays[12]; + + BBitmap *Bmp; + BView *BmpView; + + int cday, cmonth, cyear; // current date in window + int cwday1; // day of week of 1st of month in window + int cwday; // day of week of current day of month in window + + int first_year, last_year; + + int tday, tmonth, tyear; // today + int twday; // is needed to calculate days of week + + float h_cell, w_cell; // height and width of cell for one number of day of nonth + + BRect cursor; // rectangle arounding chosen date + + BRect cursorPressed; // rectangle arounding date where mouse was pressed + bool MousePressed; // is mouse pressed on date + int dayPressed; // date where mouse is pressed + + bool NewMonth; // if true field must be cleared + + int which_focused; // 0 - if month, 1 - if year, + // 2 - if days of month, 3 - if today +}; + + +MonthView::MonthView(int day, int month, int year, int first_year, int last_year) + :BView(BRect(0,0,100,100), "MonthViewAViX", B_FOLLOW_LEFT, B_WILL_DRAW) +{ + this->cday=day; + this->cmonth=month; + this->cyear=year; + + this->first_year=first_year; + this->last_year=last_year; + + struct tm *dat; + time_t tmp; + time(&tmp); + dat=localtime(&tmp); + + tday=dat->tm_mday; + tmonth=dat->tm_mon+1; + tyear=dat->tm_year+1900; // new day coming when window is opened is not handled + // because it is very rear case + twday=dat->tm_wday; + + weekdayNames[0]=(char*)"Mo"; + weekdayNames[1]=(char*)"Tu"; + weekdayNames[2]=(char*)"We"; + weekdayNames[3]=(char*)"Th"; + weekdayNames[4]=(char*)"Fr"; + weekdayNames[5]=(char*)"Sa"; + weekdayNames[6]=(char*)"Su"; + + monthNames[0]=(char*)"January"; + monthNames[1]=(char*)"February"; + monthNames[2]=(char*)"March"; + monthNames[3]=(char*)"April"; + monthNames[4]=(char*)"May"; + monthNames[5]=(char*)"June"; + monthNames[6]=(char*)"July"; + monthNames[7]=(char*)"August"; + monthNames[8]=(char*)"September"; + monthNames[9]=(char*)"October"; + monthNames[10]=(char*)"November"; + monthNames[11]=(char*)"December"; + + monthDays[0]=31; + monthDays[1]=28; + monthDays[2]=31; + monthDays[3]=30; + monthDays[4]=31; + monthDays[5]=30; + monthDays[6]=31; + monthDays[7]=31; + monthDays[8]=30; + monthDays[9]=31; + monthDays[10]=30; + monthDays[11]=31; + + NewMonth=false; // first field is cleared and clearing is not needed + + MousePressed=false; +} + + +MonthView::~MonthView() +{ + delete todayStringView; + delete monthStringView; + delete monthMStringView[0]; + delete monthMStringView[1]; + delete yearStringView; + delete yearMStringView[0]; + delete yearMStringView[1]; + delete msng; + Bmp->RemoveChild(BmpView); + delete BmpView; + delete Bmp; +} + + +void MonthView::AttachedToWindow(void) +{ + SetFont(be_plain_font); + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // Calculate size of cell needed for number of day of month + font_height h; + be_plain_font->GetHeight(&h); + h_cell = (int)(h.ascent+h.descent+h.leading+6); + w_cell = StringWidth("4")*4; + + // add today's date + BString s(""); + s << tday << " " << monthNames[tmonth-1] << " " << tyear; + + msng=new BMessenger(this); + todayStringView=new MouseSenseStringView(new BMessage('TODA'), msng, + BRect(10,10,100,100),"todayMStringViewAViX", s.String()); + todayStringView->ResizeToPreferred(); + todayStringView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(todayStringView); + + // add month selection + monthStringView=new BStringView(BRect(10,10,100,100),"monthStringViewAViX", monthNames[8]); + monthStringView->SetAlignment(B_ALIGN_CENTER); + monthStringView->ResizeToPreferred(); + monthStringView->SetText(monthNames[cmonth-1]); + monthStringView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(monthStringView); + + // add year selection + s.SetTo(""); + if(cyear<10) s.Append("000"); + else if(cyear<100) s.Append("00"); + else if(cyear<1000) s.Append("0"); + s << cyear; + yearStringView=new BStringView(BRect(10,10,100,100),"yearStringViewAViX", + "0000"); + yearStringView->ResizeToPreferred(); + yearStringView->SetText(s.String()); + yearStringView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(yearStringView); + + ResizeTo(w_cell*7+1,h_cell*7+3+16+yearStringView->Bounds().bottom+todayStringView->Bounds().bottom); + Window()->ResizeTo(Bounds().right, Bounds().bottom); + + // year to the left button + yearMStringView[0]=new MouseSenseStringView(new BMessage('YEA0'),msng, + BRect(10,10,100,100), + "yearMStringViewAViX0", + "<<"); + AddChild(yearMStringView[0]); + yearMStringView[0]->ResizeToPreferred(); + yearMStringView[0]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // year to the right button + yearMStringView[1]=new MouseSenseStringView(new BMessage('YEA1'),msng, + BRect(10,10,100,100), + "yearMStringViewAViX1", + ">>"); + AddChild(yearMStringView[1]); + yearMStringView[1]->ResizeToPreferred(); + yearMStringView[1]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // month to the left button + monthMStringView[0]=new MouseSenseStringView(new BMessage('MON0'),msng, + BRect(10,10,100,100), + "monthMStringViewAViX0", + "<<"); + AddChild(monthMStringView[0]); + monthMStringView[0]->ResizeToPreferred(); + monthMStringView[0]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // month to the right button + monthMStringView[1]=new MouseSenseStringView(new BMessage('MON1'),msng, + BRect(10,10,100,100), + "monthMStringViewAViX1", + ">>"); + AddChild(monthMStringView[1]); + monthMStringView[1]->ResizeToPreferred(); + monthMStringView[1]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // move all in correct position + todayStringView->MoveTo((Bounds().right-todayStringView->Bounds().right)/2, + Bounds().bottom-todayStringView->Bounds().bottom-2); + + if(tyearlast_year) todayStringView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_3_TINT)); + + yearMStringView[1]->MoveTo(Bounds().right-yearMStringView[1]->Bounds().right,5); + yearStringView->MoveTo(yearMStringView[1]->Frame().left-yearStringView->Bounds().right,5); + yearMStringView[0]->MoveTo(yearStringView->Frame().left-yearMStringView[0]->Bounds().right,5); + + monthStringView->MoveTo((yearMStringView[0]->Frame().left-monthStringView->Bounds().right)/2,5); + monthMStringView[0]->MoveTo(monthStringView->Frame().left-monthMStringView[0]->Bounds().right,5); + monthMStringView[1]->MoveTo(monthStringView->Frame().right,5); + + which_focused=2; // days of month + + // Bitmap for the dates + Bmp=new BBitmap(Bounds(),B_RGB32,true); + BmpView=new BView(Bmp->Bounds(),"BV",0,B_WILL_DRAW); + Bmp->AddChild(BmpView); + + Bmp->Lock(); + BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BmpView->FillRect(BmpView->Frame()); + BmpView->SetHighColor(255,255,255); + BRect bmpRect(Bounds()); + bmpRect.top = yearStringView->Frame().bottom + 2; + bmpRect.bottom = todayStringView->Frame().top - 5; + BmpView->FillRect(bmpRect); + + BmpView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT)); + BmpView->StrokeLine(BPoint(0,bmpRect.top), BPoint(BmpView->Bounds().right,bmpRect.top)); + BmpView->StrokeLine(BPoint(0,bmpRect.bottom), BPoint(BmpView->Bounds().right,bmpRect.bottom)); + BmpView->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + float y=yearStringView->Frame().bottom+h_cell; + float x=0; + for(int i=0;i<7;i++) + { + BmpView->DrawString(weekdayNames[i],BPoint(x+(w_cell-StringWidth(weekdayNames[i]))/2,y)); + x+=w_cell; + } + + BmpView->Sync(); + Bmp->Unlock(); + + DrawMonth(); +} + + +void MonthView::Draw(BRect r) +{ + Window()->Lock(); + DrawBitmap(Bmp, BPoint(0,0)); + Window()->Unlock(); +} + + +void MonthView::DrawMonth() +{ + Bmp->Lock(); + + float y=yearStringView->Frame().bottom+h_cell; + float x=0; + + if(NewMonth) + { + BmpView->SetHighColor(255,255,255); + BmpView->FillRect(BRect(0,y+1, BmpView->Bounds().right,todayStringView->Frame().top - 6)); + BmpView->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + BmpView->SetLowColor(255,255,255); + NewMonth=false; + } + + int byear=cyear; // base year + if(tyearSetHighColor(236,0,0,0); + BmpView->DrawString(s.String(),BPoint(x+(w_cell-StringWidth(s.String()))/2,y)); + if(cyear==tyear) if(cmonth==tmonth) if(t==tday) BmpView->SetHighColor(0,0,0,0); + + if(t==cday) + { + cwday=k; + if(which_focused==2) BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + else + // BmpView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_3_TINT)); + BmpView->SetHighColor(255,255,255); + cursor.Set(x,y-h_cell+5,x+w_cell-1,y+4); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(0,0,0,0); + } + + x+=w_cell; + k++; + s.SetTo(""); + + if(k==7) + { + k=0; + y+=h_cell; + x=1; + } + } + + BmpView->Sync(); + Bmp->Unlock(); + Draw(Bounds()); +} + + +//////////////////////////////////////////////////////////////// +void MonthView::KeyDown(const char *bytes, int32 numBytes) +{ + switch(bytes[0]) + { + case B_TAB: + { + Bmp->Lock(); + switch(which_focused) + { + case 0: // months + { + BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BmpView->StrokeLine(BPoint(monthMStringView[0]->Frame().left, + monthMStringView[0]->Frame().bottom+1), + BPoint(monthMStringView[1]->Frame().right, + monthMStringView[1]->Frame().bottom+1)); + BmpView->SetHighColor(0,0,0); + break; + } + case 1: // years + { + BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BmpView->StrokeLine(BPoint(yearMStringView[0]->Frame().left, + yearMStringView[0]->Frame().bottom+1), + BPoint(yearMStringView[1]->Frame().right, + yearMStringView[1]->Frame().bottom+1)); + BmpView->SetHighColor(0,0,0); + break; + } + case 2: // days of month + { + BmpView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_3_TINT)); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(0,0,0); + break; + } + case 3: // today + { + BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BmpView->StrokeLine(BPoint(todayStringView->Frame().left, + todayStringView->Frame().bottom+1), + BPoint(todayStringView->Frame().right, + todayStringView->Frame().bottom+1)); + BmpView->SetHighColor(0,0,0); + break; + } + } + + // changing which_focused + if(modifiers() & B_SHIFT_KEY) + { + if(which_focused==0) + which_focused=3; + else which_focused--; + } + else // simply Tab + { + if(which_focused==3) + which_focused=0; + else which_focused++; + } + + // drawing with new which_focused + switch(which_focused) + { + case 0: // months + { + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeLine(BPoint(monthMStringView[0]->Frame().left, + monthMStringView[0]->Frame().bottom+1), + BPoint(monthMStringView[1]->Frame().right, + monthMStringView[1]->Frame().bottom+1)); + BmpView->SetHighColor(0,0,0); + break; + } + case 1: // years + { + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeLine(BPoint(yearMStringView[0]->Frame().left, + yearMStringView[0]->Frame().bottom+1), + BPoint(yearMStringView[1]->Frame().right, + yearMStringView[1]->Frame().bottom+1)); + BmpView->SetHighColor(0,0,0); + break; + } + case 2: // days of month + { + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(0,0,0); + break; + } + case 3: // today + { + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeLine(BPoint(todayStringView->Frame().left, + todayStringView->Frame().bottom+1), + BPoint(todayStringView->Frame().right, + todayStringView->Frame().bottom+1)); + BmpView->SetHighColor(0,0,0); + break; + } + } + BmpView->Sync(); + Bmp->Unlock(); + Draw(Bounds()); + break; + } // B_TAB + + case B_DOWN_ARROW: + { + if(which_focused==0) // month + { + BMessage msg('MON0'); + MessageReceived(&msg); + } + else if(which_focused==1) // year + { + BMessage msg('YEA0'); + MessageReceived(&msg); + } + else if(which_focused==2) // days of month + { + int qu_days=monthDays[cmonth-1]; + if(cmonth==2) if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) qu_days=29; + if((cday+7)<=qu_days) + { + Bmp->Lock(); + BmpView->SetHighColor(255,255,255); + BmpView->StrokeRect(cursor); + cursor.OffsetBySelf(0, h_cell); + cday+=7; + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(0,0,0); + BmpView->Sync(); + Bmp->Unlock(); + Draw(Bounds()); + } + } + break; + } + + case B_UP_ARROW: + { + // Test whether Ctrl+UpArrow is pressed + if(modifiers() & B_CONTROL_KEY) + Window()->PostMessage(B_QUIT_REQUESTED); + else + { + if(which_focused==0) // month + { + BMessage msg('MON1'); + MessageReceived(&msg); + } + else if(which_focused==1) // year + { + BMessage msg('YEA1'); + MessageReceived(&msg); + } + else if(which_focused==2) // days of month + { + if((cday-7)>=1) + { + Bmp->Lock(); + BmpView->SetHighColor(255,255,255); + BmpView->StrokeRect(cursor); + cursor.OffsetBySelf(0, -h_cell); + cday-=7; + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(0,0,0); + BmpView->Sync(); + Bmp->Unlock(); + Draw(Bounds()); + } + } + } + break; + } + + case B_LEFT_ARROW: + { + if(which_focused==0) // month + { + BMessage msg('MON0'); + MessageReceived(&msg); + } + else if(which_focused==1) // year + { + BMessage msg('YEA0'); + MessageReceived(&msg); + } + else if(which_focused==2) // days of month + { + if(cday>1) + { + Bmp->Lock(); + BmpView->SetHighColor(255,255,255); + BmpView->StrokeRect(cursor); + if(cwday>0) // by dates no matter of day of week + { + cursor.OffsetBySelf(-w_cell,0); + cwday--; + } + else // cwday==0 + { + cursor.OffsetBySelf(w_cell*6,-h_cell); + cwday=6; + } + cday--; + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(0,0,0); + BmpView->Sync(); + Bmp->Unlock(); + Draw(Bounds()); + } + else // 1st of month, go month before + { + if(cyear>first_year || cmonth>1) // one can go + { + int cm=(cmonth==1) ? 12 : cmonth-1; + int qu_days=monthDays[cm-1]; + if(cm==2) if(cyear%4==0) + if((cyear%100!=0) || (cyear%400==0)) qu_days=29; + // it is correct not to pay attention to year changing + // because if we moved to february then year was not changed + // but if month is other then february + // then it has the same number of days every year. + cday=qu_days; + + BMessage msg('MON0'); + MessageReceived(&msg); // here month, cwday and year (if needed) will be changed + } + } + } + break; + } + + case B_RIGHT_ARROW: + { + if(which_focused==0) // month + { + BMessage msg('MON1'); + MessageReceived(&msg); + } + else if(which_focused==1) // year + { + BMessage msg('YEA1'); + MessageReceived(&msg); + } + else if(which_focused==2) // days of month + { + int qu_days=monthDays[cmonth-1]; + if(cmonth==2) if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) qu_days=29; + if(cdayLock(); + BmpView->SetHighColor(255,255,255); + BmpView->StrokeRect(cursor); + if(cwday<6) // by dates no matter of day of week + { + cursor.OffsetBySelf(w_cell,0); + cwday++; + } + else // cwday==6 + { + cursor.OffsetBySelf(-w_cell*6,h_cell); + cwday=0; + } + cday++; + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(0,0,0); + BmpView->Sync(); + Bmp->Unlock(); + Draw(Bounds()); + } + else // last of month, go next month + { + if(cyearPostMessage(B_QUIT_REQUESTED); + break; + } + + case B_ENTER: + case B_SPACE: + { + if(which_focused==2) + { + // here it is needed to send dayPressed (==cwday), cyear, cmonth + // to window and leave + BMessage *msg=new BMessage('MVME'); + msg->AddInt32("day",cday); + msg->AddInt32("month",cmonth); + msg->AddInt32("year",cyear); + Window()->PostMessage(msg); + } + else if(which_focused==3) + { + BMessage msg('TODA'); + MessageReceived(&msg); + } + break; + } + + default: + BView::KeyDown(bytes, numBytes); + } +} + + +//////////////////////////////////////////////////// +void MonthView::MessageReceived(BMessage *msg) +{ + switch(msg->what) + { + case 'YEA0': // year before + { + if(cyear<=first_year) break; + cyear--; + NewMonth=true; + BString s(""); + if(cyear<10) s.Append("000"); + else if(cyear<100) s.Append("00"); + else if(cyear<1000) s.Append("0"); + s<SetText(s.String()); + + if(cmonth==2) if(cday==29) // one can do simplier: if cday==29, then make + // cday=28, because two leap years one after other can't be + { + if(cyear%4!=0) cday=28; + else if(cyear%100==0 && cyear%400!=0) cday=28; + } + + DrawMonth(); + break; + } + case 'YEA1': // year after + { + if(cyear>=last_year) break; + cyear++; + NewMonth=true; + BString s(""); + if(cyear<10) s.Append("000"); + else if(cyear<100) s.Append("00"); + else if(cyear<1000) s.Append("0"); + s<SetText(s.String()); + + if(cmonth==2) if(cday==29) + { + if(cyear%4!=0) cday=28; + else if(cyear%100==0 && cyear%400!=0) cday=28; + } + + DrawMonth(); + break; + } + case 'MON0': // month before + { + if(cmonth>1) cmonth--; + else if(cyear>first_year) + { + cmonth=12; + cyear--; + + BString s(""); + if(cyear<10) s.Append("000"); + else if(cyear<100) s.Append("00"); + else if(cyear<1000) s.Append("0"); + s<SetText(s.String()); + } + else break; // nothing is changed + + NewMonth=true; + monthStringView->SetText(monthNames[cmonth-1]); + + if(cmonth==2) + { + int tmpday=28; + if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) tmpday=29; + if(cday>tmpday) cday=tmpday; + } + else if(cday>monthDays[cmonth-1]) cday=monthDays[cmonth-1]; + + DrawMonth(); + break; + } + case 'MON1': // month after + { + if(cmonth<12) cmonth++; + else if(cyearSetText(s.String()); + } + else break; // nothing is changed + + NewMonth=true; + monthStringView->SetText(monthNames[cmonth-1]); + + if(cmonth==2) + { + int tmpday=28; + if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) tmpday=29; + if(cday>tmpday) cday=tmpday; + } + else if(cday>monthDays[cmonth-1]) cday=monthDays[cmonth-1]; + + DrawMonth(); + break; + } + case 'TODA': // to place to today's date + { + if(tyearlast_year) break; + + NewMonth=true; + + cyear=tyear; + cmonth=tmonth; + cday=tday; + + BString s(""); + if(cyear<10) s.Append("000"); + else if(cyear<100) s.Append("00"); + else if(cyear<1000) s.Append("0"); + s<SetText(s.String()); + monthStringView->SetText(monthNames[cmonth-1]); + + DrawMonth(); + break; + } + default: + BView::MessageReceived(msg); + } +} + + +///////////////////////////////////////// +void MonthView::MouseDown(BPoint p) +{ + // It's necessary to define whether mouse cursor is on one of dates + BRect r; + + int k=cwday1; + float x=w_cell*k+1; + float y=yearStringView->Frame().bottom+h_cell+h_cell; + + int qu_days=monthDays[cmonth-1]; // quantity of days in month + + if(cmonth==2) if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) qu_days=29; + + bool flag=false; // whether mouse is pressed just on date + int t=0; + while(tLock(); + BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BmpView->StrokeRect(cursor); + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeRect(cursorPressed); + Bmp->Unlock(); + Invalidate(); + break; // exit while + } + + x+=w_cell; + k++; + + if(k==7) + { + k=0; + y+=h_cell; + x=1; + } + } +} + + +void MonthView::MouseUp(BPoint p) +{ + if(!MousePressed) return; + + if(cursorPressed.Contains(p)) + { + // here it is needed to send dayPressed, cyear, cmonth + // to window and leave + BMessage *msg=new BMessage('MVME'); + msg->AddInt32("day",dayPressed); + msg->AddInt32("month",cmonth); + msg->AddInt32("year",cyear); + Window()->PostMessage(msg); + } + else + { + Bmp->Lock(); + BmpView->SetHighColor(255,255,255); + BmpView->StrokeRect(cursorPressed); + BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + BmpView->StrokeRect(cursor); + Bmp->Unlock(); + Invalidate(); + MousePressed=false; + } +} + + +void MonthView::MouseMoved(BPoint pt, uint32 transit, const BMessage *msg) +{ + BPoint point; + uint32 buttons; + GetMouse(&point,&buttons); + + if(transit==B_ENTERED_VIEW) + { + if( (buttons & B_PRIMARY_MOUSE_BUTTON)==0 && + (buttons & B_SECONDARY_MOUSE_BUTTON)==0 && + (buttons & B_PRIMARY_MOUSE_BUTTON)==0 ) + MousePressed = false; + else + MousePressed = true; + } + + if(transit==B_EXITED_VIEW || transit==B_OUTSIDE_VIEW) + MouseUp(Bounds().LeftTop()); +} diff --git a/src/MonthWindow.cpp b/src/MonthWindow.cpp new file mode 100644 index 0000000..9517460 --- /dev/null +++ b/src/MonthWindow.cpp @@ -0,0 +1,112 @@ +// Calendar Control version 2.5 +// by Al.V. Sarikov. +// Kherson, Ukraine, 2006. +// E-mail: avix@ukrpost.net. +// Home page: http://avix.pp.ru. + +// Control which allows to work with dates: +// enter date to text field and choose it from calendar. + +// Distributed under BSD license (see LICENSE file). + +#include +#include +#include +#include +#include + +#include "MonthView.cpp" + +class MonthWindow: public BWindow +{ + public: + MonthWindow(BPoint LT, BMessenger *msng, int day, int month, int year, + int first_year, int last_year); + virtual void MessageReceived(BMessage *msg); + virtual bool QuitRequested(void); + virtual void WindowActivated(bool active); + private: + MonthView *myMonthView; + BMessenger *messenger; + + int first_year; + int last_year; +}; + + +MonthWindow::MonthWindow(BPoint LT, BMessenger *msng, int day, int month, int year, int first_year, int last_year) + :BWindow(BRect(LT,BPoint(LT.x+200,LT.y+200)),"MonthWindowAViX", + B_BORDERED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_MOVABLE|B_AVOID_FOCUS) +{ + this->first_year=first_year; + this->last_year=last_year; + + myMonthView = new MonthView(day, month, year, first_year, last_year); + + AddChild(myMonthView); + myMonthView->MakeFocus(true); + + messenger = msng; + + BRect screenFrame = BScreen(this).Frame(); + if(LT.x < 0) + LT.x = 0; + if(LT.x > screenFrame.right - Bounds().Width()) + LT.x = screenFrame.right - Bounds().Width(); + if(LT.y > screenFrame.bottom - Bounds().Height()) + LT.y = screenFrame.bottom - Bounds().Height(); + MoveTo(LT); + + Show(); +} + + +void MonthWindow::MessageReceived(BMessage *msg) +{ + if(msg->what=='MVME') + { + // Is date correct? + int32 day, month, year; + if(msg->FindInt32("day",&day)!=B_OK) return; + if(msg->FindInt32("month",&month)!=B_OK) return; + if(msg->FindInt32("year",&year)!=B_OK) return; + + if(yearlast_year) return; + if(month<1 || month>12) return; + int32 tmp; + + tmp=31; + if(month==4 || month==6 || month==9 || month==11) + tmp=30; + else if(month==2) + { + if(year%4==0) + { + if(year%100==0 && year%400!=0) + tmp=28; + else + tmp=29; + } + else + tmp=28; + } + if(day<1 || day>tmp) return; + messenger->SendMessage(msg); + Quit(); + } + else + BWindow::MessageReceived(msg); +} + + +bool MonthWindow::QuitRequested(void) +{ + return true; +} + + +void MonthWindow::WindowActivated(bool active) +{ + // exit if unfocused + if(!active) Quit(); +} diff --git a/src/MouseSenseStringView.cpp b/src/MouseSenseStringView.cpp new file mode 100644 index 0000000..abc9e35 --- /dev/null +++ b/src/MouseSenseStringView.cpp @@ -0,0 +1,95 @@ +// Calendar Control version 2.5 +// by Al.V. Sarikov. +// Kherson, Ukraine, 2006. +// E-mail: avix@ukrpost.net. +// Home page: http://avix.pp.ru. + +// Control which allows to work with dates: +// enter date to text field and choose it from calendar. + +// Distributed under BSD license (see LICENSE file). + +#include +#include +#include +#include +#include +#include + +class MouseSenseStringView:public BStringView +{ + public: + MouseSenseStringView(BMessage *msg, + BMessenger *msng, + BRect frame, + const char *name, + const char *text, + uint32 resizingMode=B_FOLLOW_LEFT|B_FOLLOW_TOP, + uint32 flags=B_WILL_DRAW); + virtual void MouseDown(BPoint p); + virtual void MouseUp(BPoint p); + void Draw(BRect(update)); + + private: + BMessage *msg; + BMessenger *msng; + bool isMouseDown; +}; + +MouseSenseStringView::MouseSenseStringView(BMessage *msg, + BMessenger *msng, + BRect frame, + const char *name, + const char *text, + uint32 resizingMode, + uint32 flags) + :BStringView(frame,name,text,resizingMode,flags) +{ + this->msg=msg; + this->msng=msng; + isMouseDown = false; +} + + +void MouseSenseStringView::MouseDown(BPoint p) +{ + isMouseDown = true; + // if(msg!=NULL) if(msng!=NULL) + // msng->SendMessage(msg); +} + +void MouseSenseStringView::MouseUp(BPoint p) +{ + BPoint mouse; + uint32 buttons; + GetMouse(&mouse, &buttons); + if(Bounds().Contains(mouse)) + if(msg!=NULL) if(msng!=NULL) + msng->SendMessage(msg); + isMouseDown = false; +} + +void MouseSenseStringView::Draw(BRect update) +{ + BString t(Text()); + BRect r1(Bounds()); + r1.right = r1.right/2; + BRect r2(Bounds()); + r2.left= r2.right/4; + r2.right= r2.right*3/4; + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 flags = 0; + + if(t == "<<") + { + be_control_look->DrawArrowShape(this, r1, update, base, 0); + be_control_look->DrawArrowShape(this, r2, update, base, 0); + } + else if(t == ">>") + { + be_control_look->DrawArrowShape(this, r1, update, base, 1); + be_control_look->DrawArrowShape(this, r2, update, base, 1); + } + else + BStringView::Draw(update); +} diff --git a/src/RdefApply b/src/RdefApply new file mode 100755 index 0000000..fe19566 --- /dev/null +++ b/src/RdefApply @@ -0,0 +1,34 @@ +#!yab + +doc RdefApply +doc adds icon, application signature and version info attributes from an rdef file. +doc +doc Copyright © 2015 Jim Saxton, Fat Elk Software + +if (peek("argument") >= 2) then + filename$=peek$("argument") + Outfilename$=peek$("argument") + make$=peek$("argument") + make=0 + if (make$="M") make=1 + readicon() +else + print"RdefApply" + print "Adds icon, application signature and version info attributes from an rdef file. + " + print "usage:" + print "RdefApply " + print "if M is used, OutoutFilename is created if it does not exist +or the creation date is set if it does exist." +endif + +sub readicon() + + if (not open(1,filename$)) print "Could not open file'"+filename$+"' for reading":exit + +if (make=1) system("touch "+Outfilename$) +close #1 +system("rc -o "+filename$+".rsrc "+filename$) +system("resattr -O -o "+Outfilename$+" "+filename$+".rsrc") +end sub + diff --git a/src/Spinner.cpp b/src/Spinner.cpp new file mode 100644 index 0000000..6d828a4 --- /dev/null +++ b/src/Spinner.cpp @@ -0,0 +1,624 @@ +/* + Spinner.cpp: A number spinner control. + Written by DarkWyrm , Copyright 2004 + Released under the MIT license. + + Original BScrollBarButton class courtesy Haiku project +*/ +#include "Spinner.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "global.h" + +enum +{ + M_UP='mmup', + M_DOWN, + M_TEXT_CHANGED='mtch' +}; + +typedef enum +{ + ARROW_LEFT=0, + ARROW_RIGHT, + ARROW_UP, + ARROW_DOWN, + ARROW_NONE +} arrow_direction; + +class SpinnerMsgFilter : public BMessageFilter +{ +public: + SpinnerMsgFilter(void); + ~SpinnerMsgFilter(void); + virtual filter_result Filter(BMessage *msg, BHandler **target); +}; + +class SpinnerArrowButton : public BView +{ +public: + SpinnerArrowButton(BPoint location, const char *name, + arrow_direction dir); + ~SpinnerArrowButton(void); + void AttachedToWindow(void); + void DetachedToWindow(void); + void MouseDown(BPoint pt); + void MouseUp(BPoint pt); + void MouseMoved(BPoint pt, uint32 code, const BMessage *msg); + void Draw(BRect update); + void SetEnabled(bool value); + bool IsEnabled(void) const { return enabled; } + void SetViewColor(rgb_color color); + +private: + arrow_direction fDirection; + BPoint tri1,tri2,tri3; + Spinner *parent; + bool mousedown; + bool enabled; + rgb_color myColor; +}; + +class SpinnerPrivateData +{ +public: + SpinnerPrivateData(void) + { + thumbframe.Set(0,0,0,0); + enabled=true; + tracking=false; + mousept.Set(0,0); + thumbinc=1.0; + repeaterid=-1; + exit_repeater=false; + arrowdown=ARROW_NONE; + + #ifdef TEST_MODE + sbinfo.proportional=true; + sbinfo.double_arrows=false; + sbinfo.knob=0; + sbinfo.min_knob_size=14; + #else + get_scroll_bar_info(&sbinfo); + #endif + } + + ~SpinnerPrivateData(void) + { + if(repeaterid!=-1) + { + exit_repeater=false; + kill_thread(repeaterid); + } + } + thread_id repeaterid; + scroll_bar_info sbinfo; + BRect thumbframe; + bool enabled; + bool tracking; + BPoint mousept; + float thumbinc; + bool exit_repeater; + arrow_direction arrowdown; +}; + +Spinner::Spinner(BRect frame, const char *name, const char *label, int32 min, int32 max, int32 step, BMessage *msg, + uint32 resize,uint32 flags) + : BControl(frame, name,NULL,msg,resize,flags) +{ + + BRect r(Bounds()); + if(r.Height()<14*2) + r.bottom=r.top+14*2; + ResizeTo(r.Width(),r.Height()); + + r.right-=14; + + font_height fh; + BFont font; + font.GetHeight(&fh); + float textheight=fh.ascent+fh.descent+fh.leading; + + BString t(""); + t << max; + BFont f(be_plain_font); + float width1 = f.StringWidth(t.String())+2; + float width2 = f.StringWidth(label); + ResizeTo(width1+width2+18+14, 14*2-2); + r = Bounds(); + r.right-=14+3; + + r.bottom=r.top+textheight+8; + r.OffsetTo(0, ( (Bounds().Height()-r.Height())/2) ); + + fTextControl=new BTextControl(r,"textcontrol",label,"0",new BMessage(M_TEXT_CHANGED), + B_FOLLOW_ALL,B_WILL_DRAW|B_NAVIGABLE); + AddChild(fTextControl); + BTextView *tview=fTextControl->TextView(); + tview->SetAlignment(B_ALIGN_LEFT); + tview->SetWordWrap(false); + + fTextControl->SetDivider(width2+5); + + BString string("QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,/qwertyuiop{}| " + "asdfghjkl:\"zxcvbnm<>?!@#$%^&*()-_=+`~\r"); + + for(int32 i=0; iDisallowChar(c); + } + r=Bounds(); + r.left=r.right-15; + r.bottom/=2; + + fUpButton=new SpinnerArrowButton(BPoint(r.left, r.top),"up",ARROW_UP); + AddChild(fUpButton); + + r=Bounds(); + r.left=r.right-15; + r.top=r.bottom/2+1; + + fDownButton=new SpinnerArrowButton(BPoint(r.left, r.top-1),"down",ARROW_DOWN); + AddChild(fDownButton); + + fStep=step; + fMin=min; + fMax=max; + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + privatedata=new SpinnerPrivateData; + fFilter=new SpinnerMsgFilter; + + SetValue(min); +} + +Spinner::~Spinner(void) +{ + delete privatedata; + delete fFilter; +} + +void Spinner::AttachedToWindow(void) +{ + Window()->AddCommonFilter(fFilter); + fTextControl->SetTarget(this); +} + +void Spinner::DetachedFromWindow(void) +{ + Window()->RemoveCommonFilter(fFilter); +} + +void Spinner::SetValue(int32 value) +{ + if(value>GetMax() || valueSetText(string); +} + +void Spinner::SetViewColor(rgb_color color) +{ + BControl::SetViewColor(color); + fTextControl->SetViewColor(color); + fTextControl->SetLowColor(color); + fUpButton->SetViewColor(color); + fDownButton->SetViewColor(color); +} + +void Spinner::SetLabel(const char *text) +{ + fTextControl->SetLabel(text); +} + +void Spinner::ValueChanged(int32 value) +{ +} + +void Spinner::MessageReceived(BMessage *msg) +{ + if(msg->what==M_TEXT_CHANGED) + { + BString string(fTextControl->Text()); + int32 newvalue=0; + + sscanf(string.String(),"%ld",&newvalue); + if(newvalue>=GetMin() && newvalue<=GetMax()) + { + // new value is in range, so set it and go + SetValue(newvalue); + Invoke(); + Draw(Bounds()); + ValueChanged(Value()); + } + else + { + // new value is out of bounds. Clip to range if current value is not + // at the end of its range + if(newvalueGetMax() && Value()!=GetMax()) + { + SetValue(GetMax()); + Invoke(); + Draw(Bounds()); + ValueChanged(Value()); + } + else + { + char string[100]; + sprintf(string,"%ld",Value()); + fTextControl->SetText(string); + } + } + } + else + BControl::MessageReceived(msg); +} + +void Spinner::SetSteps(int32 stepsize) +{ + fStep=stepsize; +} + +void Spinner::SetRange(int32 min, int32 max) +{ + SetMin(min); + SetMax(max); +} + +void Spinner::GetRange(int32 *min, int32 *max) +{ + *min=fMin; + *max=fMax; +} + +void Spinner::SetMax(int32 max) +{ + fMax=max; + if(Value()>fMax) + SetValue(fMax); +} + +void Spinner::SetMin(int32 min) +{ + fMin=min; + if(Value()SetEnabled(value); + fTextControl->TextView()->MakeSelectable(value); + fUpButton->SetEnabled(value); + fDownButton->SetEnabled(value); +} + +void Spinner::MakeFocus(bool value) +{ + fTextControl->MakeFocus(value); +} + + +SpinnerArrowButton::SpinnerArrowButton(BPoint location, + const char *name, arrow_direction dir) + :BView(BRect(0,0,16,12).OffsetToCopy(location), + name, B_FOLLOW_ALL, B_WILL_DRAW) +{ + fDirection=dir; + enabled=true; + myColor = ui_color(B_PANEL_BACKGROUND_COLOR); + mousedown=false; +} + +SpinnerArrowButton::~SpinnerArrowButton(void) +{ +} + +void SpinnerArrowButton::MouseDown(BPoint pt) +{ + if(enabled==false) + return; + + if (!IsEnabled()) + return; + + mousedown=true; + int redcost = 1000; + Draw(Bounds()); + + BRect bounds = Bounds(); + uint32 buttons; + BPoint point; + + int32 step=parent->GetSteps(); + int32 newvalue=parent->Value(); + int32 waitvalue=150000; + + do + { + if(fDirection==ARROW_UP) + { + parent->privatedata->arrowdown=ARROW_UP; + newvalue+=step; + } + else + { + parent->privatedata->arrowdown=ARROW_DOWN; + newvalue-=step; + } + + if( newvalue>=parent->GetMin() && newvalue<=parent->GetMax()) + { + // new value is in range, so set it and go + parent->SetValue(newvalue); + parent->Invoke(); +// parent->Draw(parent->Bounds()); + parent->ValueChanged(parent->Value()); + } + else + { + // new value is out of bounds. Clip to range if current value is not + // at the end of its range + if(newvalueGetMin() && parent->Value()!=parent->GetMin()) + { + parent->SetValue(parent->GetMin()); + parent->Invoke(); +// parent->Draw(parent->Bounds()); + parent->ValueChanged(parent->Value()); + } + else + if(newvalue>parent->GetMax() && parent->Value()!=parent->GetMax()) + { + parent->SetValue(parent->GetMax()); + parent->Invoke(); +// parent->Draw(parent->Bounds()); + parent->ValueChanged(parent->Value()); + } + else + { + // cases which go here are if new value is maximum and value already at maximum + return; + } + } + + Window()->UpdateIfNeeded(); + + snooze(waitvalue); + + GetMouse(&point, &buttons, false); + + bool inside = bounds.Contains(point); + + // if ((parent->Value() == B_CONTROL_ON) != inside) + // parent->SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF); + + if(waitvalue<=50000) + waitvalue=50000; + else + { + waitvalue -= redcost; + redcost = redcost*10; + } + + } while (buttons != 0); + +} + +void SpinnerArrowButton::MouseUp(BPoint pt) +{ + if(enabled) + { + mousedown=false; + + if(parent) + { + parent->privatedata->arrowdown=ARROW_NONE; + parent->privatedata->exit_repeater=true; + } + Draw(Bounds()); + } +} + +void SpinnerArrowButton::MouseMoved(BPoint pt, uint32 transit, const BMessage *msg) +{ + if(enabled==false) + return; + + if(transit==B_ENTERED_VIEW) + { + BPoint point; + uint32 buttons; + GetMouse(&point,&buttons); + if( (buttons & B_PRIMARY_MOUSE_BUTTON)==0 && + (buttons & B_SECONDARY_MOUSE_BUTTON)==0 && + (buttons & B_PRIMARY_MOUSE_BUTTON)==0 ) + mousedown=false; + else + mousedown=true; + Draw(Bounds()); + } + + if(transit==B_EXITED_VIEW || transit==B_OUTSIDE_VIEW) + MouseUp(Bounds().LeftTop()); +} + +void SpinnerArrowButton::Draw(BRect update) +{ + BRect rect(Bounds()); + rgb_color background = B_TRANSPARENT_COLOR; + if (Parent()) + background = Parent()->ViewColor(); + if (background == B_TRANSPARENT_COLOR) + background = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + + uint32 flags = 0; + if(!parent->IsEnabled()) + flags |= BControlLook::B_DISABLED; + if(mousedown) + flags = 1 << 2; + BRect r(Bounds()); + if(fDirection == ARROW_UP) + r.bottom = r.bottom*2; + else + r.top = - r.bottom; + be_control_look->DrawButtonFrame(this, r, update, base, background, flags); + be_control_look->DrawButtonBackground(this, r, update, base, flags); + + rect.InsetBy(2.0,2.0); + base = ui_color(B_PANEL_TEXT_COLOR); + float tint = B_NO_TINT; + if(!parent->IsEnabled()) + tint = B_LIGHTEN_MAX_TINT; + be_control_look->DrawArrowShape(this, rect, update, base, fDirection, flags, tint); +} + +void SpinnerArrowButton::AttachedToWindow(void) +{ + parent=(Spinner*)Parent(); +} + +void SpinnerArrowButton::DetachedToWindow(void) +{ + parent=NULL; +} + +void SpinnerArrowButton::SetEnabled(bool value) +{ + enabled=value; + Invalidate(); +} + +void SpinnerArrowButton::SetViewColor(rgb_color color) +{ + myColor = color; + Invalidate(); +} + +SpinnerMsgFilter::SpinnerMsgFilter(void) + : BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE,B_KEY_DOWN) +{ +} + +SpinnerMsgFilter::~SpinnerMsgFilter(void) +{ +} + +filter_result SpinnerMsgFilter::Filter(BMessage *msg, BHandler **target) +{ + int32 c; + msg->FindInt32("raw_char",&c); + switch(c) + { + case B_ENTER: + { + BTextView *text=dynamic_cast(*target); + if(text && text->IsFocus()) + { + BView *view=text->Parent(); + while(view) + { + Spinner *spin=dynamic_cast(view); + if(spin) + { + BString string(text->Text()); + int32 newvalue=0; + + sscanf(string.String(),"%ld",&newvalue); + if(newvalue!=spin->Value()) + { + spin->SetValue(newvalue); + spin->Invoke(); + } + return B_SKIP_MESSAGE; + } + view=view->Parent(); + } + } + return B_DISPATCH_MESSAGE; + }/* + case B_TAB: + { + // Cause Tab characters to perform keybaord navigation + BHandler *h=*target; + BView *v=NULL; + + h=h->NextHandler(); + while(h) + { + v=dynamic_cast(h); + if(v) + { + *target=v->Window(); + return B_DISPATCH_MESSAGE; + } + h=h->NextHandler(); + } + return B_SKIP_MESSAGE; + // return B_DISPATCH_MESSAGE; + }*/ + case B_UP_ARROW: + case B_DOWN_ARROW: + { + BTextView *text=dynamic_cast(*target); + if(text && text->IsFocus()) + { + // We have a text view. See if it currently has the focus and belongs + // to a Spinner control. If so, change the value of the spinner + + // TextViews are complicated beasts which are actually multiple views. + // Travel up the hierarchy to see if any of the target's ancestors are + // a Spinner. + + BView *view=text->Parent(); + while(view) + { + Spinner *spin=dynamic_cast(view); + if(spin) + { + int32 step=spin->GetSteps(); + if(c==B_DOWN_ARROW) + step=0-step; + + spin->SetValue(spin->Value()+step); + spin->Invoke(); + return B_SKIP_MESSAGE; + } + view=view->Parent(); + } + } + + return B_DISPATCH_MESSAGE; + } + default: + return B_DISPATCH_MESSAGE; + } + + // shut the stupid compiler up + return B_SKIP_MESSAGE; +} diff --git a/src/Spinner.h b/src/Spinner.h new file mode 100644 index 0000000..4cdffcd --- /dev/null +++ b/src/Spinner.h @@ -0,0 +1,59 @@ +#ifndef SPINNER_H_ +#define SPINNER_H_ + +#include +#include +#include +#include +#include + +class SpinnerPrivateData; +class SpinnerArrowButton; +class SpinnerMsgFilter; + +class Spinner : public BControl +{ +public: + Spinner(BRect frame, const char *name, const char *label, int32 min, int32 max, int32 step, BMessage *msg, + uint32 resize=B_FOLLOW_LEFT|B_FOLLOW_TOP,uint32 flags=B_WILL_DRAW|B_NAVIGABLE); + virtual ~Spinner(void); + virtual void AttachedToWindow(void); + virtual void DetachedFromWindow(void); + virtual void ValueChanged(int32 value); + virtual void MessageReceived(BMessage *msg); + virtual void SetViewColor(rgb_color color); + + virtual void SetSteps(int32 stepsize); + int32 GetSteps(void) const { return fStep; } + + virtual void SetRange(int32 min, int32 max); + void GetRange(int32 *min, int32 *max); + + virtual void SetMax(int32 max); + int32 GetMax(void) const { return fMax; } + virtual void SetMin(int32 min); + int32 GetMin(void) const { return fMin; } + + virtual void MakeFocus(bool value=true); + + virtual void SetValue(int32 value); + // int32 Value(); + virtual void SetLabel(const char *text); + BTextControl *TextControl(void) const { return fTextControl; } + + virtual void SetEnabled(bool value); + +private: + friend class SpinnerArrowButton; + friend class SpinnerPrivateData; + + BTextControl *fTextControl; + SpinnerArrowButton *fUpButton, *fDownButton; + SpinnerPrivateData *privatedata; + + int32 fStep; + int32 fMin, fMax; + SpinnerMsgFilter *fFilter; +}; + +#endif diff --git a/src/SplitPane.cpp b/src/SplitPane.cpp new file mode 100644 index 0000000..68e85f4 --- /dev/null +++ b/src/SplitPane.cpp @@ -0,0 +1,726 @@ +/******************************************************* +* SplitPane© +* +* SplitPane is a usefull UI component. It alows the +* use to ajust two view Horizontaly or Vertacly so +* that they are a desired size. This type of Pane +* shows up most comonly in Mail/News Readers. +* +* @author YNOP (ynop@acm.org) +* @version beta +* @date Dec. 10 1999 +*******************************************************/ +#include +#include +#include +#include +#include +#include +#include + +//#include + +#include "SplitPane.h" +//#include "SplitPaneConfig.h" + +/******************************************************* +* Setup the main view. Add in all the niffty components +* we have made and get things rolling +*******************************************************/ +SplitPane::SplitPane(BRect frame, const char* name, BView *one, BView *two,uint32 Mode):BView(frame, name, Mode,B_WILL_DRAW|B_FRAME_EVENTS){ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); // This is default get from parent if exist + //SetViewColor(B_TRANSPARENT_32_BIT); // go tran so we have control over drawing + BRect b; + b = Bounds(); + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + PaneOne = one; + PaneTwo = two; + + align = B_VERTICAL; // Most people use it this way + pos = (int)b.Width()/2; // Center is a good start place + thickness = 10; + jump = 1; // 1 makes a smother slide + VOneDetachable = false; + VTwoDetachable = false; + pad = 1; + MinSizeOne = 0; // full left + MinSizeTwo = 0; // full right + poslocked = false; // free movement + alignlocked = false; // free alignment + Draggin = false; + attached = false; + + WinOne = NULL; + WinTwo = NULL; + ConfigWindow = NULL; + + AddChild(one); + AddChild(two); +} + +/******************************************************* +* When ready grap the parents color and refreash. +*******************************************************/ +void SplitPane::AttachedToWindow(){ + //SetViewColor(Parent()->ViewColor()); + attached = true; + Update(); +} + +/******************************************************* +* If we are being resized. Fix the stuff we need to fix +*******************************************************/ +void SplitPane::FrameResized(float,float){ +// if bar is on the left side follow left +// else if it is on the right side follow the right +// Need to implements smart follow still + Update(); + Invalidate(); +} + +/******************************************************* +* The main draw stuff here. basicly just the slider +*******************************************************/ +void SplitPane::Draw(BRect f){ + SetHighColor(160,160,160); + + if(align == B_VERTICAL){ + SetHighColor(185,185,185); + // SetHighColor(145,145,145); + //FillRect(BRect(pos,Bounds().top+pad+1,pos,Bounds().bottom-pad-1)); // 145 + FillRect(BRect(pos,Bounds().top+pad+1,pos,Bounds().bottom-pad-1)); // 145 + + SetHighColor(255,255,255); + FillRect(BRect(pos+1,Bounds().top+pad+1,pos+2,Bounds().bottom-pad-1)); // 255 + + //SetHighColor(216,216,216); + SetHighColor(Parent()->ViewColor()); + FillRect(BRect(pos+2,Bounds().top+pad+1,pos+thickness-2,Bounds().bottom-pad-1));// 216 + + if(thickness>9) + { + float y = (Bounds().bottom - Bounds().top)/2; + float x = pos + (thickness/2); + SetPenSize(2); + SetHighColor(255,255,255); + StrokeLine(BPoint(x-3,y-11),BPoint(x+3,y-5)); + StrokeLine(BPoint(x-3,y-7),BPoint(x+3,y-1)); + StrokeLine(BPoint(x-3,y-3),BPoint(x+3,y+3)); + StrokeLine(BPoint(x-3,y+1),BPoint(x+3,y+7)); + StrokeLine(BPoint(x-3,y+5),BPoint(x+3,y+11)); + SetPenSize(1); + SetHighColor(145,145,145); + StrokeLine(BPoint(x-3,y-10),BPoint(x+3,y-4)); + StrokeLine(BPoint(x-3,y-6),BPoint(x+3,y+0)); + StrokeLine(BPoint(x-3,y-2),BPoint(x+3,y+4)); + StrokeLine(BPoint(x-3,y+2),BPoint(x+3,y+8)); + StrokeLine(BPoint(x-3,y+6),BPoint(x+3,y+12)); + } + + SetHighColor(185,185,185); + // SetHighColor(145,145,145); + FillRect(BRect(pos+thickness-2,Bounds().top+pad+1,pos+thickness-2,Bounds().bottom-pad-1)) ;// 145 + + SetHighColor(145,145,145); + FillRect(BRect(pos+thickness-1,Bounds().top+pad+1,pos+thickness-1,Bounds().bottom-pad-1)); // 96 + //FillRect(BRect(pos+thickness,Bounds().top+pad+1,pos+thickness,Bounds().bottom-pad-1)); + }else{ + SetHighColor(185,185,185); + // SetHighColor(145,145,145); + //FillRect(BRect(Bounds().left+pad+1,pos,Bounds().right-pad-1,pos)); // 145 + FillRect(BRect(Bounds().left+pad+1,pos,Bounds().right-pad-1,pos)); // 145 + + SetHighColor(255,255,255); + FillRect(BRect(Bounds().left+pad+1,pos+1,Bounds().right-pad-1,pos+2)); // 255 + + //SetHighColor(216,216,216); + SetHighColor(Parent()->ViewColor()); + FillRect(BRect(Bounds().left+pad+1,pos+2,Bounds().right-pad-1,pos+thickness-2));// 216 + + if(thickness>9) + { + SetHighColor(255,255,255); + float x = (Bounds().right - Bounds().left)/2; + float y = pos + (thickness/2); + SetPenSize(2); + StrokeLine(BPoint(x-11,y-3),BPoint(x-5,y+3)); + StrokeLine(BPoint(x-7,y-3),BPoint(x-1,y+3)); + StrokeLine(BPoint(x-3,y-3),BPoint(x+3,y+3)); + StrokeLine(BPoint(x+1,y-3),BPoint(x+7,y+3)); + StrokeLine(BPoint(x+5,y-3),BPoint(x+11,y+3)); + SetPenSize(1); + SetHighColor(145,145,145); + StrokeLine(BPoint(x-10,y-3),BPoint(x-4,y+3)); + StrokeLine(BPoint(x-6,y-3),BPoint(x+0,y+3)); + StrokeLine(BPoint(x-2,y-3),BPoint(x+4,y+3)); + StrokeLine(BPoint(x+2,y-3),BPoint(x+8,y+3)); + StrokeLine(BPoint(x+6,y-3),BPoint(x+12,y+3)); + } + + SetHighColor(185,185,185); + // SetHighColor(145,145,145); + FillRect(BRect(Bounds().left+pad+1,pos+thickness-2,Bounds().right-pad-1,pos+thickness-2)) ;// 145 + + SetHighColor(145,145,145); + // SetHighColor(96,96,96); + FillRect(BRect(Bounds().left+pad+1,pos+thickness-1,Bounds().right-pad-1,pos+thickness-1)); // 96 + //FillRect(BRect(Bounds().left+pad+1,pos+thickness,Bounds().right-pad-1,pos+thickness)); + } +} + +/******************************************************* +* Keeps Modes for both panles uptodate and acctually +* is the func that sets the location of the slider +*******************************************************/ +void SplitPane::Update(){ + Window()->Lock(); + if(align == B_VERTICAL){ + PaneOne->SetResizingMode(B_FOLLOW_LEFT|B_FOLLOW_TOP_BOTTOM); + PaneTwo->SetResizingMode(B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP_BOTTOM); + if(pos > (Bounds().Width()-thickness-MinSizeTwo)){ + if(!poslocked){ + pos = (int)Bounds().Width()-thickness-MinSizeTwo; + } + } + if(pos < MinSizeOne){ + if(!poslocked){ + pos = MinSizeOne; + } + } + }else{ + PaneOne->SetResizingMode(B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); + PaneTwo->SetResizingMode(B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP_BOTTOM); + if(pos > (Bounds().Height()-thickness-MinSizeTwo)){ + if(!poslocked){ + pos = (int)Bounds().Height()-thickness-MinSizeTwo; + } + } + if(pos < MinSizeOne){ + if(!poslocked){ + pos = MinSizeOne; + } + } + } + + // this block should go in FrameResized .. think about it + if(align == B_VERTICAL){ + if(pos >= (Bounds().IntegerWidth()/2)){ + //pos should follow the right side + // staying the same distans from it that + // it is right now + } + }else{ + if(pos >= (Bounds().IntegerHeight()/2)){ + //should follow bottom and stay the + // same distance that we are way from + // it now + } + } + + + if(PaneOne){ + if(!WinOne){ + if(align == B_VERTICAL){ + PaneOne->MoveTo(pad,Bounds().top+pad); + PaneOne->ResizeTo(pos-pad, Bounds().Height()-pad-pad); // widht x height + }else{ + PaneOne->MoveTo(pad,Bounds().top+pad); + PaneOne->ResizeTo(Bounds().Width()-pad-pad, pos-pad-pad); // widht x height + } + } + } + if(PaneTwo){ + if(!WinTwo){ + if(align == B_VERTICAL){ + PaneTwo->MoveTo(pos+thickness,Bounds().top+pad); + PaneTwo->ResizeTo(Bounds().Width()-(pos+thickness)-pad, Bounds().Height()-pad-pad); + }else{ + PaneTwo->MoveTo(Bounds().left+pad,pos+thickness); + PaneTwo->ResizeTo(Bounds().Width()-pad-pad, Bounds().Height()-pos-pad-thickness); + } + } + } + + Window()->Unlock(); +} + +/******************************************************* +* Hook for when we click. This takes care of all the +* little stuff - Like where is the mouse and what is +* going on. +*******************************************************/ +void SplitPane::MouseDown(BPoint where){ + Window()->Lock(); + BMessage *currentMsg = Window()->CurrentMessage(); + if (currentMsg->what == B_MOUSE_DOWN) { + uint32 buttons = 0; + currentMsg->FindInt32("buttons", (int32 *)&buttons); + uint32 modifiers = 0; + currentMsg->FindInt32("modifiers", (int32 *)&modifiers); + uint32 clicks = 0; + currentMsg->FindInt32("clicks",(int32*)&clicks); + + if (buttons & B_SECONDARY_MOUSE_BUTTON){ + if(!alignlocked){ + switch(align){ + case B_VERTICAL: + align = B_HORIZONTAL; + break; + case B_HORIZONTAL: + align = B_VERTICAL; + break; + } + Update(); + Invalidate(); + } + + /*if(VOneDetachable){ + WinOne = new BWindow(ConvertToScreen(PaneOne->Bounds()),"PanelOne",B_TITLED_WINDOW,B_ASYNCHRONOUS_CONTROLS); + RemoveChild(PaneOne); + WinOne->AddChild(PaneOne); + PaneOne->SetResizingMode(B_FOLLOW_ALL_SIDES); + // PaneOne->SetTarget(this); + WinOne->Show(); + }*/ + } + // if((buttons & B_PRIMARY_MOUSE_BUTTON) && (clicks >= 2)){ + //Config window for split pane + // (new BAlert(NULL,"This is - or will be - a configuration panel for SplitPane.","Ok"))->Go(); + //ConfigWindow = new SplitPaneConfig(this); + //ConfigWindow->Show(); + //}else + if((buttons & B_PRIMARY_MOUSE_BUTTON) && !Draggin){ + if(!poslocked){ + Draggin= true; // this is so we can drag + here = where; + } + SetMouseEventMask(B_POINTER_EVENTS,B_LOCK_WINDOW_FOCUS); + } + } + Window()->Unlock(); +} + +/******************************************************* +* If we unclick then stop dragging or whatever it is +* we are doing +*******************************************************/ +void SplitPane::MouseUp(BPoint where){ + Draggin = false; // stop following mouse +} + +/******************************************************* +* If the mouse moves while we dragg. Then follow it +* Also Invalidate so we update the views +*******************************************************/ +void SplitPane::MouseMoved(BPoint where,uint32 info,const BMessage *m){ + if(Draggin){ + switch(align){ + case B_HORIZONTAL: + pos = (int)(where.y)-(thickness/2);//- here.x + break; + case B_VERTICAL: + pos = (int)(where.x)-(thickness/2); + break; + } + + /* + // This code figures out which jump we are closest + // to and if needed we "snap" to that. + int c = Bounds().IntegerWidth() / pos + Jump * c ... hmmm this is not right at all + */ + + if(pos < MinSizeOne){ + pos = MinSizeOne; + } + + if(align == B_VERTICAL){ + if(pos > (Bounds().Width() - thickness - MinSizeTwo)){ + pos = (int)(Bounds().Width() - thickness - MinSizeTwo + 1); + } + }else{ + if(pos > (Bounds().Height() - thickness - MinSizeTwo)){ + pos = (int)(Bounds().Height() - thickness - MinSizeTwo + 1); + } + } + + Update(); + + Invalidate(); + } +} + +/******************************************************* +* If you already have a view One, but want to change +* if for some odd reason. This should work. +*******************************************************/ +void SplitPane::AddChildOne(BView *v){ + RemoveChild(PaneOne); + PaneOne = v; + AddChild(PaneOne); +} +/*void SplitPane::MakePaneTwoFocus() +{ + if(PaneTwo) + PaneTwo->MakeFocus(); + +} +*/ +/******************************************************* +* If you already have a view Two, and want to put +* another view there, this is what to use. +*******************************************************/ +void SplitPane::AddChildTwo(BView* v,bool IsAdded,bool ShowAfterHide) +{ + if(!v->IsHidden()) + v->Hide(); + + PaneTwo = v; + //WinTwo = NULL; + + + PaneTwo = v; + if(IsAdded) + { + Update(); + if(ShowAfterHide) + { + if(v->IsHidden()) + v->Show(); + } + + } + if(!IsAdded) + { + AddChild(PaneTwo); + } + PaneTwo = v; + +} + +/******************************************************* +* Sets is we are horizontal or Vertical. We use the +* standard B_HORIZONTAL and B_VERTICAL flags for this +*******************************************************/ +void SplitPane::SetAlignment(uint a){ + align = a; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Returns wheather the slider is horizontal or vertical +*******************************************************/ +uint SplitPane::GetAlignment(){ + return align; +} + +/******************************************************* +* Sets the location of the bar. (we do no bounds +* checking for you so if its off the window thats +* your problem) +*******************************************************/ +void SplitPane::SetBarPosition(int i){ + pos = i; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Returns about where the bar is ... +*******************************************************/ +int SplitPane::GetBarPosition(){ + return pos; +} + +/******************************************************* +* Sets how thick the bar should be. +*******************************************************/ +void SplitPane::SetBarThickness(int i){ + thickness = i; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Retuns to us the thickness of the slider bar +*******************************************************/ +int SplitPane::GetBarThickness(){ + return thickness; +} + +/******************************************************* +* Sets the amount of jump the bar has when it is +* moved. This can also be though of as snap. The bar +* will start at 0 and jump(snap) to everry J pixels. +*******************************************************/ +void SplitPane::SetJump(int i){ + jump = i; + if(attached){ + Update(); + } +} + +/******************************************************* +* Lets you know what the jump is .. see SetJump +*******************************************************/ +int SplitPane::GetJump(){ + return jump; +} + +/******************************************************* +* Do we have a View One or is it NULL +*******************************************************/ +bool SplitPane::HasViewOne(){ + if(PaneOne) return true; + return false; +} + +/******************************************************* +* Do we have a View Two .. or is it NULL too +*******************************************************/ +bool SplitPane::HasViewTwo(){ + if(PaneTwo) return true; + return false; +} + +/******************************************************* +* Sets wheather View one is detachable from the +* slider view and from the app. This will creat a +* window that is detached (floating) from the app. +*******************************************************/ +void SplitPane::SetViewOneDetachable(bool b){ + VOneDetachable = b; +} + +/******************************************************* +* Sets view tow detachable or not +*******************************************************/ +void SplitPane::SetViewTwoDetachable(bool b){ + VTwoDetachable = b; +} + +/******************************************************* +* Returns whether the view is detachable +*******************************************************/ +bool SplitPane::IsViewOneDetachable(){ + return VOneDetachable; +} + +/******************************************************* +* Returns if this view is detachable +*******************************************************/ +bool SplitPane::IsViewTwoDetachable(){ + return VTwoDetachable; +} + +/******************************************************* +* Tells the view if the user is alowed to open the +* configuration window for the slider. +*******************************************************/ +void SplitPane::SetEditable(bool b){ + //ADD CODE HERE YNOP +} + +/******************************************************* +* Tells use if the split pane is user editable +*******************************************************/ +bool SplitPane::IsEditable(){ + return true; //ADD SOME MORE CODE HERE +} + +/******************************************************* +* Sets the inset that the view has. +*******************************************************/ +void SplitPane::SetViewInsetBy(int i){ + pad = i; + if(attached){ + Update(); + } Invalidate(); +} + +/******************************************************* +* Returns to use the padding around the views +*******************************************************/ +int SplitPane::GetViewInsetBy(){ + return pad; +} + +/******************************************************* +* This sets the minimum size that View one can be. +* if the user trys to go past this .. we just stop +* By default the minimum size is set to 0 (zero) so +* the user can put the slider anywhere. +*******************************************************/ +void SplitPane::SetMinSizeOne(int i){ + MinSizeOne = i; +} + +/******************************************************* +* Gives us the minimum size that one can be. +*******************************************************/ +int SplitPane::GetMinSizeOne(){ + return MinSizeOne; +} + +/******************************************************* +* This sets the Minimum size that the second view +* can be. +*******************************************************/ +void SplitPane::SetMinSizeTwo(int i){ + MinSizeTwo = i; +} + +/******************************************************* +* Lets us know what that minimum size is. +*******************************************************/ +int SplitPane::GetMinSizeTwo(){ + return MinSizeTwo; +} + +/******************************************************* +* Locks the bar from being moved by the User. The +* system can still move the bar (via SetBarPosition) +*******************************************************/ +void SplitPane::SetBarLocked(bool b){ + poslocked = b; +} + +/******************************************************* +* Returns to use if the bar is in a locked state or +* not. +*******************************************************/ +bool SplitPane::IsBarLocked(){ + return poslocked; +} + +/******************************************************* +* Locks the alignment of the bar. The user can no +* longer toggle between Horizontal and Vertical +* Slider bar. Again you can still progomaticly set +* the position how ever you want. +*******************************************************/ +void SplitPane::SetBarAlignmentLocked(bool b){ + alignlocked = b; +} + +/******************************************************* +* Lets us know about the lock state of the bar +*******************************************************/ +bool SplitPane::IsBarAlignmentLocked(){ + return alignlocked; +} + +/******************************************************* +* Gets the Total state of the bar, alignment, size, +* position and many other things that are required +* to fully capture the state of the SplitPane. +* We pack all of this into a cute little BMessage +* so that it is esally expandable and can be saved +* off easyaly too. The SplitPane System does not +* however save the state for you. Your program must +* grab the state and save it in its config file. +*******************************************************/ +BMessage* SplitPane::GetState(){ + BMessage *state; + + state = new BMessage(SPLITPANE_STATE); + + state->AddBool("onedetachable",VOneDetachable); + state->AddBool("twodetachable",VTwoDetachable); + state->AddInt32("align",align); + state->AddInt32("pos",pos); + state->AddInt32("thick",thickness); + state->AddInt32("jump",jump); + state->AddInt32("pad",pad); + state->AddInt32("minsizeone",MinSizeOne); + state->AddInt32("minsizetwo",MinSizeTwo); + state->AddBool("poslock",poslocked); + state->AddBool("alignlock",alignlocked); + return state; + // delete state; +} + +/******************************************************* +* Sets the state of the SplitPane from a BMessage +* like the one recived from GetState(). +* This is one of three ways the user can rebuild the +* state of the SplitPane. The second is to simply +* send the SplitPane the state message, it is the +* same as calling SetState but it ashyncronouse. +* The third way is to use all the Get/Set methouds +* for each element of the SplitPane, this way is +* long and boarding. I suggest you just send the +* View a message :) +*******************************************************/ +void SplitPane::SetState(BMessage *state){ + int32 Npos,Nthickness,Njump,Npad,NMSO,NMST; + int32 Nalign;//uint + + if(state->FindBool("onedetachable",&VOneDetachable) != B_OK){ + VOneDetachable = false; + } + if(state->FindBool("towdetachable",&VTwoDetachable) != B_OK){ + VTwoDetachable = false; + } + if(state->FindInt32("align",&Nalign) == B_OK){ + align = Nalign; + } + if(state->FindInt32("pos",&Npos) == B_OK){ + pos = Npos; + } + if(state->FindInt32("thick",&Nthickness) == B_OK){ + thickness = Nthickness; + } + if(state->FindInt32("jump",&Njump) == B_OK){ + jump = Njump; + } + if(state->FindInt32("pad",&Npad) == B_OK){ + pad = Npad; + } + if(state->FindInt32("minsizeonw",&NMSO) == B_OK){ + MinSizeOne = NMSO; + } + if(state->FindInt32("minsizetwo",&NMST) == B_OK){ + MinSizeTwo = NMST; + } + if(state->FindBool("poslock",&poslocked) != B_OK){ + poslocked = false; + } + if(state->FindBool("alignlock",&alignlocked) != B_OK){ + alignlocked = false; + } + + Update(); + Invalidate(); +} + +/******************************************************* +* Ok, hmm what does this do. NOT MUCH. if we get a +* STATE message then lets set the state. This is here +* to provide a asyncronuse way of seting the state and +* also to make life easyer. +*******************************************************/ +void SplitPane::MessageReceived(BMessage *msg){ + switch(msg->what){ + case SPLITPANE_STATE: + SetState(msg); + break; + default: + BView::MessageReceived(msg); + break; + } +} + + + + + + + diff --git a/src/SplitPane.h b/src/SplitPane.h new file mode 100644 index 0000000..7098041 --- /dev/null +++ b/src/SplitPane.h @@ -0,0 +1,93 @@ +/******************************************************* +* SplitPane© +* +* SplitPane is a usefull UI component. It alows the +* use to ajust two view Horizontaly or Vertacly so +* that they are a desired size. This type of Pane +* shows up most comonly in Mail/News Readers. +* +* @author YNOP (ynop@acm.org) +* @version beta +* @date Dec. 10 1999 +*******************************************************/ +#ifndef _SPLIT_PANE_VIEW_H +#define _SPLIT_PANE_VIEW_H + +#include +#include +// #include +#include +#include +#define SPLITPANE_STATE 'spst' + +class SplitPane : public BView { + public: + SplitPane(BRect,const char*,BView*,BView*,uint32); + void AddChildOne(BView*); + void AddChildTwo(BView* v,bool IsAdded,bool ShowAfterHide); + void SetAlignment(uint); + uint GetAlignment(); + void SetBarPosition(int); + int GetBarPosition(); + void SetBarThickness(int); + int GetBarThickness(); + void SetJump(int); + int GetJump(); + bool HasViewOne(); + bool HasViewTwo(); + void SetViewOneDetachable(bool); + void SetViewTwoDetachable(bool); + bool IsViewOneDetachable(); + bool IsViewTwoDetachable(); + void SetEditable(bool); + bool IsEditable(); + void SetViewInsetBy(int); + int GetViewInsetBy(); + void SetMinSizeOne(int); + int GetMinSizeOne(); + void SetMinSizeTwo(int); + int GetMinSizeTwo(); + BMessage* GetState(); + void SetBarLocked(bool); + bool IsBarLocked(); + void SetBarAlignmentLocked(bool); + bool IsBarAlignmentLocked(); + void SetState(BMessage*); + virtual void Draw(BRect); + virtual void AttachedToWindow(); + virtual void FrameResized(float,float); + virtual void MouseDown(BPoint); + virtual void MouseUp(BPoint); + virtual void MouseMoved(BPoint,uint32,const BMessage*); + virtual void MessageReceived(BMessage*); + //void MakePaneTwoFocus(); + private: + void Update(); + BView *PaneOne; + BView *PaneTwo; + + //State info + bool VOneDetachable; + bool VTwoDetachable; + uint align; + int pos; + int thickness; + int jump; + int pad; + int MinSizeOne; + int MinSizeTwo; + bool poslocked; + bool alignlocked; + //end State info + + bool Draggin; + BPoint here; + bool attached; + + BWindow *WinOne; + BWindow *WinTwo; + + BWindow *ConfigWindow; +}; +#endif + diff --git a/src/URLView.cpp b/src/URLView.cpp new file mode 100644 index 0000000..fd6f7e7 --- /dev/null +++ b/src/URLView.cpp @@ -0,0 +1,1126 @@ +/* URLView 2.11 + written by William Kakes of Tall Hill Software. + + This class provides an underlined and clickable BStringView + that will launch the web browser, e-mail program, or FTP client + when clicked on. Other features include hover-highlighting, + right-click menus, and drag-and-drop support. + + You are free to use URLView in your own programs (both open-source + and closed-source) free of charge, but a mention in your read me + file or your program's about box would be appreciated. See + http://www.tallhill.com for current contact information. + + URLView is provided as-is, with no warranties of any kind. If + you use it, you are on your own. +*/ + + + +#include "URLView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// #include +#include "global.h" + +#ifndef ZETA + #define _T(str) str +#else + #include +#endif + +URLView::URLView( BRect frame, const char *name, const char *label, + const char *url, uint32 resizingMode, uint32 flags ) + : BStringView( frame, name, label, resizingMode, flags ) { + + // Set the default values for the other definable instance variables. + this->color = blue; + this->clickColor = red; + this->hoverColor = dark_blue; + this->disabledColor = gray; + this->hoverEnabled = true; + this->draggable = true; + this->iconSize = 16; + this->underlineThickness = 1; + + // The link should be enabled by default (unless the URL is invalid, which + // is handled by the SetURL() function). + enabled = true; + + // Set the instance variables. + this->url = 0; + SetURL( url ); + + // Create the cursor to use when over the link. + this->linkCursor = new BCursor( url_cursor ); + + // The link is not currently selected. + selected = false; + + // The URL is currently not hover-colored. + hovering = false; + + // The user has not dragged out of the view. + draggedOut = false; + + // The user has not yet opened the popup menu. + inPopup = false; + + // Initialize the attributes list (there are 14 standard + // Person attributes). + attributes = new BList( 14 ); + +} + + +URLView::~URLView() { + delete url; + delete linkCursor; + + // Delete all the attributes. + KeyPair *item; + for( int i = 0; (item = (KeyPair *) attributes->ItemAt(i)); i++ ) { + delete item->key; + delete item->value; + delete item; + } + delete attributes; +} + + + + + +void URLView::AttachedToWindow() { + // When the view is first attached, we want to draw the link + // in the normal color. Also, we want to set our background color + // to meet that of our parent. + if( IsEnabled() ) + SetHighColor( color ); + else + SetHighColor( disabledColor ); + + if( Parent() != NULL ) { + SetLowColor( Parent()->ViewColor() ); + SetViewColor( Parent()->ViewColor() ); + } +} + + + +void URLView::Draw( BRect updateRect ) { + BRect rect = Frame(); + rect.OffsetTo( B_ORIGIN ); + + // We want 'g's, etc. to go below the underline. When the BeOS can + // do underlining of any font, this code can be removed. + font_height height; + GetFontHeight( &height ); + float descent = height.descent; + + // We want to be sensitive to the SetAlignment() function. + float left, right; + if( Alignment() == B_ALIGN_RIGHT ) { + left = rect.right - StringWidth( Text() ) + 1; + right = rect.right - 1; + } + else if( Alignment() == B_ALIGN_CENTER ) { + left = rect.left + (rect.Width() / 2) - (StringWidth( Text() ) / 2); + right = left + StringWidth( Text() ) - 2; + } + else { + left = rect.left; + right = left + StringWidth( Text() ) - 2; + } + + // Draw the underline in the requested thickness. + // Note: If the link is disabled, we don't want to draw the underline. + if( IsEnabled() ) { + FillRect( BRect( (float) left, + (float) (rect.bottom - descent), + (float) right, + (float) (rect.bottom - descent + (underlineThickness - 1)) ) ); + } + MovePenTo( BPoint( left, rect.bottom - descent - 1 ) ); + + // Note: DrawString() draws the text at one pixel above the pen's + // current y coordinate. + DrawString( Text() ); +} + + + +void URLView::MessageReceived( BMessage *message ) { + // Is this a message from Tracker in response to our drag-and-drop? + if( message->what == 'DDCP' ) { + // Tracker will send back the name and path of the created file. + // We need to read this information. + entry_ref ref; + message->FindRef( "directory", &ref ); + BEntry entry( &ref ); + BPath path( &entry ); + BString *fullName = new BString( path.Path() ); + fullName->Append( "/" ); + fullName->Append( message->FindString( "name" ) ); + BString *title = new BString( Text() ); + + // Set the new file as a bookmark or as a person as appropriate. + if( IsEmailLink() ) { + CreatePerson( fullName, title ); + } + else CreateBookmark( fullName, title ); + + delete fullName; + delete title; + } +} + + + +void URLView::MouseDown( BPoint point ) { + // If the link isn't enabled, don't do anything. + if( !IsEnabled() ) + return; + + // See which mouse buttons were clicked. + int32 buttons = Window()->CurrentMessage()->FindInt32( "buttons" ); + + // We want to highlight the text if the user clicks on + // the URL. We want to be sure to only register a click + // if the user clicks on the link text itself and not just + // anywhere in the view. + if( GetTextRect().Contains( point ) ) { + SetHighColor( clickColor ); + Redraw(); + + // Set the link as selected and track the mouse. + selected = true; + SetMouseEventMask( B_POINTER_EVENTS ); + + // Remember where the user clicked so we can correctly + // offset the transparent URL if the user drags. + BRect frame = Frame(); + frame.OffsetTo( B_ORIGIN ); + dragOffset = point; + if( Alignment() == B_ALIGN_RIGHT ) { + dragOffset.x -= frame.Width() - StringWidth( Text() ); + } + else if( Alignment() == B_ALIGN_CENTER ) { + dragOffset.x -= (frame.Width() / 2) - (StringWidth( Text() ) / 2); + } + + // Pop up the context menu? + if( buttons == B_SECONDARY_MOUSE_BUTTON ) inPopup = true; + } +} + + + +void URLView::MouseMoved( BPoint point, uint32 transit, + const BMessage *message ) { + + // If the link isn't enabled, don't do anything. + if( !IsEnabled() ) + return; + + // Make sure the window is the active one. + if( !Window()->IsActive() ) return; + + // See which mouse buttons were clicked. + int32 buttons = Window()->CurrentMessage()->FindInt32( "buttons" ); + // Is the user currently dragging the link? (i.e. is a mouse button + // currently down?) + bool alreadyDragging = (buttons != 0); + + switch( transit ) { + case( B_ENTERED_VIEW ): + // Should we set the cursor to the link cursor? + if( GetTextRect().Contains( point ) && !draggedOut ) { + if( !alreadyDragging ) be_app->SetCursor( linkCursor ); + + // Did the user leave and re-enter the view while + // holding down the mouse button? If so, highlight + // the link. + if( selected ) { + SetHighColor( clickColor ); + Redraw(); + } + // Should we hover-highlight the link? + else if( hoverEnabled && !alreadyDragging ) { + if( buttons == 0 ) { + SetHighColor( hoverColor ); + Redraw(); + hovering = true; + } + } + } + break; + + case( B_EXITED_VIEW ): + // We want to restore the link to it normal color and the + // mouse cursor to the normal hand. However, we should only + // set the color and re-draw if it is needed. + if( selected && !draggedOut ) { + be_app->SetCursor( B_HAND_CURSOR ); + SetHighColor( color ); + Redraw(); + + // Is the user drag-and-dropping a bookmark or person? + if( draggable ) { + draggedOut = true; + if( IsEmailLink() ) DoPersonDrag(); + else DoBookmarkDrag(); + } + } + // Is the link currently hover-highlighted? If so, restore + // the normal color now. + else if( hovering && !alreadyDragging ) { + be_app->SetCursor( B_HAND_CURSOR ); + SetHighColor( color ); + Redraw(); + hovering = false; + } + // Change the cursor back to the hand. + else { + be_app->SetCursor( B_HAND_CURSOR ); + } + break; + + case( B_INSIDE_VIEW ): + // The user could either be moving out of the view or + // back into it here, so we must handle both cases. + // In the first case, the cursor is now over the link. + if( GetTextRect().Contains( point ) && !draggedOut ) { + // We only want to change the cursor if not dragging. + if( !alreadyDragging ) be_app->SetCursor( linkCursor ); + if( selected ) { + if( draggable ) { + // If the user moves the mouse more than ten + // pixels, begin the drag. + if( (point.x - dragOffset.x) > 10 || + (dragOffset.x - point.x) > 10 || + (point.y - dragOffset.y) > 10 || + (dragOffset.y - point.y) > 10 ) { + draggedOut = true; + // Draw the appropriate drag object, etc. + if( IsEmailLink() ) DoPersonDrag(); + else DoBookmarkDrag(); + SetHighColor( color ); + Redraw(); + } + } + else { + // Since the link is not draggable, highlight it + // as long as the user holds the button down and + // has the mouse cursor over it (like a standard + // button). + SetHighColor( clickColor ); + Redraw(); + } + } + // The link isn't currently selected? If hover-highlighting + // is enabled, highlight the link. + else if( hoverEnabled && !alreadyDragging ) { + SetHighColor( hoverColor ); + Redraw(); + hovering = true; + } + } + // In this case, the mouse cursor is not over the link, so we + // need to restore the original link color, etc. + else if( !draggedOut ) { + be_app->SetCursor( B_HAND_CURSOR ); + if( selected ) { + SetHighColor( color ); + Redraw(); + + // Is the user dragging the link? + if( draggable ) { + draggedOut = true; + if( IsEmailLink() ) DoPersonDrag(); + else DoBookmarkDrag(); + } + } + // Is the mouse cursor hovering over the link? + else if( hovering ) { + SetHighColor( color ); + Redraw(); + hovering = false; + } + } + break; + } +} + + + +void URLView::MouseUp( BPoint point ) { + // If the link isn't enabled, don't do anything. + if( !IsEnabled() ) + return; + + // Do we want to show the right-click menu? + if( inPopup && GetTextRect().Contains( point ) ) { + BPopUpMenu *popup = CreatePopupMenu(); + // Work around a current bug in Be's popup menus. + point.y = point.y - 6; + + // Display the popup menu. + BMenuItem *selected = popup->Go( ConvertToScreen( point ) , false, true ); + + // Did the user select an item? + if( selected ) { + BString label( selected->Label() ); + // Did the user select the first item? If so, launch the URL. + if( label.FindFirst( "Open" ) != B_ERROR || + label.FindFirst( "Send" ) != B_ERROR || + label.FindFirst( "Connect" ) != B_ERROR ) { + LaunchURL(); + } + // Did the user select the second item? + else if( label.FindFirst( "Copy" ) != B_ERROR ) { + CopyToClipboard(); + } + } + // If not, restore the normal link color. + else { + SetHighColor( color ); + Redraw(); + } + } + + // If the link was clicked on (and not dragged), run the program + // that should handle the URL. + if( selected && GetTextRect().Contains( point ) && + !draggedOut && !inPopup ) { + LaunchURL(); + } + selected = false; + draggedOut = false; + inPopup = false; + + // Should we restore the hovering-highlighted color or the original + // link color? + if( GetTextRect().Contains( point ) && !draggedOut && + !inPopup && hoverEnabled ) { + SetHighColor( hoverColor ); + } + else if( !hovering ) SetHighColor( color ); + Redraw(); +} + + + +void URLView::WindowActivated( bool active ) { + // Be sure that if the user clicks on a link prompting the opening of + // a new window (i.e. launching NetPositive) the URL is not left drawn + // with the hover color. + if( !active ) { + if( IsEnabled() ) { + SetHighColor( color ); + Redraw(); + } + } +} + + + + + +void URLView::AddAttribute( const char *name, const char *value ) { + // Add an attribute (name and corresponding value) to the object + // that will be dragged out (i.e. to fill in Person fields, etc.) + KeyPair *newPair = new KeyPair; + newPair->key = new BString( name ); + newPair->value = new BString( value ); + attributes->AddItem( newPair ); +} + + + +bool URLView::IsEnabled() { + // Return whether or not this link is enabled (and therefore clickable). + return enabled; +} + + + + +void URLView::SetColor( rgb_color color ) { + // Set the normal link color. + this->color = color; + if( IsEnabled() ) { + Window()->Lock(); + SetHighColor( color ); + Redraw(); + Window()->Unlock(); + } +} + + +void URLView::SetColor( uchar red, uchar green, uchar blue, uchar alpha ) { + // Set the normal link color. + rgb_color color; + color.red = red; + color.green = green; + color.blue = blue; + color.alpha = alpha; + SetColor( color ); +} + + +void URLView::SetClickColor( rgb_color color ) { + // Set the link color used when the link is clicked. + clickColor = color; +} + + +void URLView::SetClickColor( uchar red, uchar green, uchar blue, uchar alpha ) { + // Set the link color used when the link is clicked. + rgb_color color; + color.red = red; + color.green = green; + color.blue = blue; + color.alpha = alpha; + SetClickColor( color ); +} + + +void URLView::SetDisabledColor( rgb_color color ) { + // Set the color to draw in when the link is disabled. + disabledColor = color; + Window()->Lock(); + Redraw(); + Window()->Unlock(); +} + + +void URLView::SetDisabledColor( uchar red, uchar green, uchar blue, uchar alpha ) { + // Set the color to draw in when the link is disabled. + rgb_color color; + color.red = red; + color.green = green; + color.blue = blue; + color.alpha = alpha; + SetDisabledColor( color ); +} + + +void URLView::SetDraggable( bool draggable ) { + // Set whether or not this link is draggable. + this->draggable = draggable; +} + + +void URLView::SetEnabled( bool enabled ) { + // Set whether or not the link is enabled (and therefore clickable). + bool redraw = this->enabled != enabled; + this->enabled = enabled; + + if( Window() ) { + Window()->Lock(); + if( !enabled ) + SetHighColor( disabledColor ); + else + SetHighColor( color ); + if( redraw ) + Invalidate(); + Window()->Unlock(); + } +} + + +void URLView::SetHoverColor( rgb_color color ) { + // Set the link color used when the mouse cursor is over it. + hoverColor = color; +} + + +void URLView::SetHoverColor( uchar red, uchar green, uchar blue, uchar alpha ) { + // Set the color to draw in when the link is disabled. + rgb_color color; + color.red = red; + color.green = green; + color.blue = blue; + color.alpha = alpha; + SetHoverColor( color ); +} + + +void URLView::SetHoverEnabled( bool hover ) { + // Set whether or not to hover-highlight the link. + hoverEnabled = hover; +} + + +void URLView::SetIconSize( icon_size iconSize ) { + // Set the size of the icon that will be shown when the link is dragged. + if( iconSize == B_MINI_ICON ) this->iconSize = 16; + else this->iconSize = 32; +} + + +void URLView::SetUnderlineThickness( int thickness ) { + // Set the thickness of the underline in pixels. + underlineThickness = thickness; +} + + +void URLView::SetURL( const char *url ) { + // Set the URL value. + delete this->url; + this->url = new BString( url ); + + // If it's an e-mail link, we want to insert "mailto:" to the front + // if the user did not enter it. + if( IsEmailLink() ) { + if( this->url->FindFirst( "mailto:" ) != 0 ) { + this->url->Prepend( "mailto:" ); + return; + } + } + + // We want to see if the URL is valid. If not, we will disable it. + if( !IsFTPLink() && !IsHTMLLink() ) + SetEnabled( false ); +} + + + + + +void URLView::CopyToClipboard() { + // Copy the URL to the clipboard. + BClipboard clipboard( "system" ); + BMessage *clip = (BMessage *) NULL; + // Get the important URL (i.e. trim off "mailto:", etc.). + BString newclip = GetImportantURL(); + + // Be sure to lock the clipboard first. + if( clipboard.Lock() ) { + clipboard.Clear(); + if( (clip = clipboard.Data()) ) { + clip->AddData( "text/plain", B_MIME_TYPE, newclip.String(), + newclip.Length() + 1 ); + clipboard.Commit(); + } + clipboard.Unlock(); + } +} + + + +void URLView::CreateBookmark( const BString *fullName, const BString *title ) { + // Read the file defined by the path and the title. + BFile *file = new BFile( fullName->String(), B_WRITE_ONLY ); + + // Set the file's MIME type to be a bookmark. + BNodeInfo *nodeInfo = new BNodeInfo( file ); + nodeInfo->SetType( "application/x-vnd.Be-bookmark" ); + delete nodeInfo; + delete file; + + // Add all the attributes, both those inherrent to bookmarks and any + // the developer may have defined using AddAttribute(). + DIR *d; + int fd; + d = fs_open_attr_dir( fullName->String() ); + if( d ) { + fd = open( fullName->String(), O_WRONLY ); + fs_write_attr( fd, "META:title", B_STRING_TYPE, 0, title->String(), title->Length() + 1 ); + fs_write_attr( fd, "META:url", B_STRING_TYPE, 0, url->String(), url->Length() + 1 ); + WriteAttributes( fd ); + close( fd ); + fs_close_attr_dir( d ); + } +} + + +void URLView::CreatePerson( const BString *fullName, const BString *title ) { + // Read the file defined by the path and the title. + BFile *file = new BFile( fullName->String(), B_WRITE_ONLY ); + + // Set the file's MIME type to be a person. + BNodeInfo *nodeInfo = new BNodeInfo( file ); + nodeInfo->SetType( "application/x-person" ); + delete nodeInfo; + delete file; + + // Add all the attributes, both those inherrent to person files and any + // the developer may have defined using AddAttribute(). + DIR *d; + int fd; + d = fs_open_attr_dir( fullName->String() ); + if( d ) { + fd = open( fullName->String(), O_WRONLY ); + fs_write_attr( fd, "META:name", B_STRING_TYPE, 0, title->String(), title->Length() + 1 ); + BString email = GetImportantURL(); + fs_write_attr( fd, "META:email", B_STRING_TYPE, 0, email.String(), email.Length() + 1 ); + WriteAttributes( fd ); + close( fd ); + fs_close_attr_dir( d ); + } +} + + + +BPopUpMenu * URLView::CreatePopupMenu() { + // Create the right-click popup menu. + BPopUpMenu *returnMe = new BPopUpMenu( "URLView Popup", false, false ); + returnMe->SetAsyncAutoDestruct( true ); + + entry_ref app; + + // Set the text of the first item according to the link type. + if( IsEmailLink() ) { + // Find the name of the default e-mail client. + if( be_roster->FindApp( "text/x-email", &app ) == B_OK ) { + BEntry entry( &app ); + BString openLabel( _T("Send e-mail to this address using ") ); + char name[B_FILE_NAME_LENGTH]; + entry.GetName( name ); + openLabel.Append( name ); + returnMe->AddItem( new BMenuItem( openLabel.String(), NULL ) ); + } + } + else if( IsFTPLink() ) { + // Find the name of the default FTP client. + if( be_roster->FindApp( "application/x-vnd.Be.URL.ftp", &app ) == B_OK ) { + BEntry entry( &app ); + BString openLabel( _T("Connect to this server using ") ); + char name[B_FILE_NAME_LENGTH]; + entry.GetName( name ); + openLabel.Append( name ); + returnMe->AddItem( new BMenuItem( openLabel.String(), NULL ) ); + } + } + else { + // Find the name of the default HTML handler (browser). + if( be_roster->FindApp( "text/html", &app ) == B_OK ) { + BEntry entry( &app ); + BString openLabel( _T("Open this link using ") ); + char name[B_FILE_NAME_LENGTH]; + entry.GetName( name ); + openLabel.Append( name ); + returnMe->AddItem( new BMenuItem( openLabel.String(), NULL ) ); + } + } + returnMe->AddItem( new BMenuItem( _T("Copy this link to the clipboard"), NULL ) ); + + return returnMe; +} + + + +void URLView::DoBookmarkDrag() { + // Handle all of the bookmark dragging. This includes setting up + // the drag message and drawing the dragged bitmap. + + // Set up the drag message to support both BTextView dragging (using + // the URL) and file dropping (to Tracker). + BMessage *dragMessage = new BMessage( B_MIME_DATA ); + dragMessage->AddInt32( "be:actions", B_COPY_TARGET ); + dragMessage->AddString( "be:types", "application/octet-stream" ); + dragMessage->AddString( "be:filetypes", "application/x-vnd.Be-bookmark" ); + dragMessage->AddString( "be:type_descriptions", "bookmark" ); + dragMessage->AddString( "be:clip_name", Text() ); + dragMessage->AddString( "be:url", url->String() ); + + // This allows the user to drag the URL into a standard BTextView. + BString link = GetImportantURL(); + dragMessage->AddData( "text/plain", B_MIME_DATA, link.String(), + link.Length() + 1 ); + + // Query for the system's icon for bookmarks. + BBitmap *bookmarkIcon = new BBitmap( BRect( 0, 0, iconSize - 1, + iconSize - 1 ), B_CMAP8 ); + BMimeType mime( "application/x-vnd.Be-bookmark" ); + if( iconSize == 16 ) mime.GetIcon( bookmarkIcon, B_MINI_ICON ); + else mime.GetIcon( bookmarkIcon, B_LARGE_ICON ); + + // Find the size of the bitmap to drag. If the text is bigger than the + // icon, use that size. Otherwise, use the icon's. Center the icon + // vertically in the bitmap. + BRect urlRect = GetURLRect(); + BRect rect = urlRect; + rect.right += iconSize + 4; + if( (rect.bottom - rect.top) < iconSize ) { + int adjustment = (int) ((iconSize - (rect.bottom - rect.top)) / 2) + 1; + rect.top -= adjustment; + rect.bottom += adjustment; + } + + // Make sure the rectangle starts at 0,0. + rect.bottom += 0 - rect.top; + rect.top = 0; + + // Create the bitmap to draw the dragged image in. + BBitmap *dragBitmap = new BBitmap( rect, B_RGBA32, true ); + BView *dragView = new BView( rect, "Drag View", 0, 0 ); + dragBitmap->Lock(); + dragBitmap->AddChild( dragView ); + + BRect frameRect = dragView->Frame(); + + // Make the background of the dragged image transparent. + dragView->SetHighColor( B_TRANSPARENT_COLOR ); + dragView->FillRect( frameRect ); + + // We want 'g's, etc. to go below the underline. When the BeOS can + // do underlining of any font, this code can be removed. + font_height height; + GetFontHeight( &height ); + float descent = height.descent; + + // Find the vertical center of the view so we can vertically + // center everything. + int centerPixel = (int) ((frameRect.bottom - frameRect.top) / 2); + int textCenter = (int) (descent + underlineThickness) + centerPixel; + + // We want to draw everything only half opaque. + dragView->SetDrawingMode( B_OP_ALPHA ); + dragView->SetHighColor( color.red, color.green, color.blue, 128.0 ); + dragView->SetBlendingMode( B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE ); + + // Center the icon in the view. + dragView->MovePenTo( BPoint( frameRect.left, + centerPixel - (iconSize / 2) ) ); + dragView->DrawBitmap( bookmarkIcon ); + + // Draw the text in the same font (size, etc.) as the link view. + // Note: DrawString() draws the text at one pixel above the pen's + // current y coordinate. + BFont font; + GetFont( &font ); + dragView->SetFont( &font ); + dragView->MovePenTo( BPoint( frameRect.left + iconSize + 4, textCenter ) ); + dragView->DrawString( url->String() ); + + // Draw the underline in the requested thickness. + dragView->FillRect( BRect( (float) frameRect.left + iconSize + 4, + (float) (textCenter + 1), + (float) StringWidth( url->String() ) + iconSize + 4, + (float) textCenter + underlineThickness ) ); + + // Be sure to flush the view buffer so everything is drawn. + dragView->Flush(); + dragBitmap->Unlock(); + + // The URL's label is probably not the same size as the URL's + // address, which is what we're going to draw. So horizontally + // offset the bitmap proportionally to where the user clicked + // on the link. + float horiz = dragOffset.x / GetTextRect().Width(); + dragOffset.x = horiz * frameRect.right; + + DragMessage( dragMessage, dragBitmap, B_OP_ALPHA, + BPoint( dragOffset.x, (rect.Height() / 2) + 2 ), this ); + delete dragMessage; + + draggedOut = true; +} + + +void URLView::DoPersonDrag() { + // Handle all of the bookmark dragging. This includes setting up + // the drag message and drawing the dragged bitmap. + + // Set up the drag message to support both BTextView dragging (using + // the e-mail address) and file dropping (to Tracker). + BMessage *dragMessage = new BMessage( B_MIME_DATA ); + dragMessage->AddInt32( "be:actions", B_COPY_TARGET ); + dragMessage->AddString( "be:types", "application/octet-stream" ); + dragMessage->AddString( "be:filetypes", "application/x-person" ); + dragMessage->AddString( "be:type_descriptions", "person" ); + dragMessage->AddString( "be:clip_name", Text() ); + + // This allows the user to drag the e-mail address into a + // standard BTextView. + BString email = GetImportantURL(); + dragMessage->AddData( "text/plain", B_MIME_DATA, email.String(), + email.Length() + 1 ); + + // Query for the system's icon for bookmarks. + BBitmap *personIcon = new BBitmap( BRect( 0, 0, iconSize - 1, + iconSize - 1 ), B_CMAP8 ); + #ifdef ZETA + BMimeType mime( "application/x-vnd.Be-PEPL" ); + #else + BMimeType mime( "application/x-person" ); + #endif + if( iconSize == 16 ) mime.GetIcon( personIcon, B_MINI_ICON ); + else mime.GetIcon( personIcon, B_LARGE_ICON ); + + // Find the size of the bitmap to drag. If the text is bigger than the + // icon, use that size. Otherwise, use the icon's. Center the icon + // vertically in the bitmap. + BRect rect = GetTextRect(); + rect.right += iconSize + 4; + if( (rect.bottom - rect.top) < iconSize ) { + int adjustment = (int) ((iconSize - (rect.bottom - rect.top)) / 2) + 1; + rect.top -= adjustment; + rect.bottom += adjustment; + } + + // Make sure the rectangle starts at 0,0. + rect.bottom += 0 - rect.top; + rect.top = 0; + + // Create the bitmap to draw the dragged image in. + BBitmap *dragBitmap = new BBitmap( rect, B_RGBA32, true ); + BView *dragView = new BView( rect, "Drag View", 0, 0 ); + dragBitmap->Lock(); + dragBitmap->AddChild( dragView ); + + BRect frameRect = dragView->Frame(); + + // Make the background of the dragged image transparent. + dragView->SetHighColor( B_TRANSPARENT_COLOR ); + dragView->FillRect( frameRect ); + + // We want 'g's, etc. to go below the underline. When the BeOS can + // do underlining of any font, this code can be removed. + font_height height; + GetFontHeight( &height ); + float descent = height.descent; + + // Find the vertical center of the view so we can vertically + // center everything. + int centerPixel = (int) ((frameRect.bottom - frameRect.top) / 2); + int textCenter = (int) (descent + underlineThickness) + centerPixel; + + // We want to draw everything only half opaque. + dragView->SetDrawingMode( B_OP_ALPHA ); + dragView->SetHighColor( 0.0, 0.0, 0.0, 128.0 ); + dragView->SetBlendingMode( B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE ); + + // Center the icon in the view. + dragView->MovePenTo( BPoint( frameRect.left, + centerPixel - (iconSize / 2) ) ); + dragView->DrawBitmap( personIcon ); + + // Draw the text in the same font (size, etc.) as the link view. + // Note: DrawString() draws the text at one pixel above the pen's + // current y coordinate. + BFont font; + GetFont( &font ); + dragView->SetFont( &font ); + dragView->MovePenTo( BPoint( frameRect.left + iconSize + 4, textCenter ) ); + dragView->DrawString( Text() ); + + // Be sure to flush the view buffer so everything is drawn. + dragView->Flush(); + dragBitmap->Unlock(); + + // The Person icon adds some width to the bitmap that we are + // going to draw. So horizontally offset the bitmap proportionally + // to where the user clicked on the link. + float horiz = dragOffset.x / GetTextRect().Width(); + dragOffset.x = horiz * frameRect.right; + + DragMessage( dragMessage, dragBitmap, B_OP_ALPHA, + BPoint( dragOffset.x, + (rect.Height() + underlineThickness) / 2 + 2), this ); + delete dragMessage; + + draggedOut = true; +} + + + +BString URLView::GetImportantURL() { + // Return the relevant portion of the URL (i.e. strip off "mailto:" from + // e-mail address URLs). + BString returnMe; + + if( IsEmailLink() ) url->CopyInto( returnMe, 7, url->CountChars() - 6 ); + else url->CopyInto( returnMe, 0, url->CountChars() ); + + return returnMe; +} + + + +BRect URLView::GetTextRect() { + // This function will return a BRect that contains only the text + // and the underline, so the mouse can change and the link will + // be activated only when the mouse is over the text itself, not + // just within the view. + + // Note: We'll use bounding boxes, because they are the most + // accurate, and since the user is interacting with the + // view, off-by-one-pixel errors look bad. + const char *textArray[1]; + textArray[0] = Text(); + + escapement_delta delta; + delta.nonspace = 0; + delta.space = 0; + escapement_delta escapements[1]; + escapements[0] = delta; + + BRect returnMe; + BRect rectArray[1]; + rectArray[0] = returnMe; + + BFont font; + GetFont( &font ); + font.GetBoundingBoxesForStrings( textArray, 1, B_SCREEN_METRIC, escapements, rectArray ); + + BRect frame = Frame(); + frame.OffsetTo( B_ORIGIN ); + returnMe = rectArray[0]; + + // Get the height of the current font. + font_height height; + GetFontHeight( &height ); + float descent = height.descent; + + // Account for rounding of the floats when drawn to avoid + // one-pixel-off errors. + float lowerBound = 0; + if( (((int) descent) * 2) != ((int) (descent * 2)) ) + lowerBound = 1; + + // Adjust the bounding box to reflect where the text is in the view. + returnMe.bottom += 1; + returnMe.OffsetTo( B_ORIGIN ); + float rectHeight = returnMe.Height(); + returnMe.bottom = frame.bottom - descent; + returnMe.top = returnMe.bottom - rectHeight; + returnMe.bottom += 1 + underlineThickness; + returnMe.OffsetBy( 0.0, -(1 + lowerBound) ); + + return returnMe; +} + + +BRect URLView::GetURLRect() { + // This function will return a BRect that contains only the URL + // and the underline, so we can draw it when the user drags. + // We'll use GetFontHeight() instead of bounding boxes here + // because a possible pixel or two off doesn't matter, whereas it + // does when detecting if the user has the cursor over the link. + BRect frame = Frame(); + frame.OffsetTo( B_ORIGIN ); + + // Get the height of the current font. + font_height height; + GetFontHeight( &height ); + + float stringHeight = underlineThickness + height.ascent - 1; + + // Get the rectangle of just the string. + return BRect( frame.left, frame.bottom - stringHeight, + frame.left + StringWidth( url->String() ), + frame.bottom - 1 ); +} + + +bool URLView::IsEmailLink() { + // Is this link an e-mail link? + if( url->FindFirst( "mailto:" ) == 0 ) + return true; + + if( !IsHTMLLink() && !IsFTPLink() && + url->FindFirst( "@" ) != B_ERROR ) { + return true; + } + + return false; +} + + +bool URLView::IsFTPLink() { + // Is this link an FTP link? + return( url->FindFirst( "ftp://" ) == 0 ); +} + + +bool URLView::IsHTMLLink() { + // Is this link an HTML or file link? + return( (url->FindFirst( "http://" ) == 0 ) || + (url->FindFirst( "file://" ) == 0 ) ); +} + + + +void URLView::LaunchURL() { + // Is the URL a mail link or HTTP? + if( IsEmailLink() ) { + // Lock the string buffer and pass it to the mail program. + char *link = url->LockBuffer( url->Length()+1 ); + status_t result = be_roster->Launch( "text/x-email", 1, &link ); + url->UnlockBuffer(); + // Make sure the user has an e-mail program. + if( result != B_NO_ERROR && result != B_ALREADY_RUNNING ) { + BAlert *alert = new BAlert( "E-mail Warning", + "There is no e-mail program on your machine that is configured as the default program to send e-mail.", + "Ok", NULL, NULL, B_WIDTH_AS_USUAL, + B_WARNING_ALERT ); + alert->Go(); + } + } + // Handle an HTTP link. + else if( IsHTMLLink() ) { + // Lock the string buffer and pass it to the web browser. + char *link = url->LockBuffer( url->Length()+1 ); + status_t result = be_roster->Launch( "text/html", 1, &link ); + url->UnlockBuffer(); + // Make sure the user has a web browser. + if( result != B_NO_ERROR && result != B_ALREADY_RUNNING ) { + BAlert *alert = new BAlert( "Web Browser Warning", + "There is no web browser on your machine that is configured as the default program to view web pages.", + "Ok", NULL, NULL, B_WIDTH_AS_USUAL, + B_WARNING_ALERT ); + alert->Go(); + } + } + // Handle an FTP link. + else if( IsFTPLink() ) { + // Lock the string buffer and pass it to the FTP client. + char *link = url->LockBuffer( url->Length()+1 ); + status_t result = be_roster->Launch( "application/x-vnd.Be.URL.ftp", + 1, &link ); + url->UnlockBuffer(); + // Make sure the user has an FTP client. + if( result != B_NO_ERROR && result != B_ALREADY_RUNNING ) { + BAlert *alert = new BAlert( "FTP Warning", + "There is no FTP client on your machine that is configured as the default program to connect to an FTP server.", + "Ok", NULL, NULL, B_WIDTH_AS_USUAL, + B_WARNING_ALERT ); + alert->Go(); + } + } + + // We don't know how to handle anything else. +} + + + +void URLView::Redraw() { + // Redraw the link without flicker. + BRect frame = Frame(); + frame.OffsetTo( B_ORIGIN ); + Draw( frame ); +} + + +void URLView::WriteAttributes( int fd ) { + // Write the developer-defined attributes to the newly-created file. + KeyPair *item; + for( int i = 0; (item = (KeyPair *) attributes->ItemAt(i)); i++ ) { + fs_write_attr( fd, item->key->String(), B_STRING_TYPE, 0, item->value->String(), item->value->Length() + 1 ); + } +} diff --git a/src/URLView.h b/src/URLView.h new file mode 100644 index 0000000..08bec86 --- /dev/null +++ b/src/URLView.h @@ -0,0 +1,141 @@ +/* URLView 2.11 + written by William Kakes of Tall Hill Software. + + This class provides an underlined and clickable BStringView + that will launch the web browser, e-mail program, or FTP client + when clicked on. Other features include hover-highlighting, + right-click menus, and drag-and-drop support. + + You are free to use URLView in your own programs (both open-source + and closed-source) free of charge, but a mention in your read me + file or your program's about box would be appreciated. See + http://www.tallhill.com for current contact information. + + URLView is provided as-is, with no warranties of any kind. If + you use it, you are on your own. +*/ + + + +#ifndef TH_URL_VIEW_H +#define TH_URL_VIEW_H + + + +#include +#include +#include +#include +#include +#include + + + +// This is the link's mouse cursor (a replica of NetPositive's link cursor). +const uint8 url_cursor[] = { 16, 1, 1, 2, + // This is the cursor data. + 0x00, 0x00, 0x38, 0x00, 0x24, 0x00, 0x24, 0x00, + 0x13, 0xe0, 0x12, 0x5c, 0x09, 0x2a, 0x08, 0x01, + 0x3c, 0x21, 0x4c, 0x71, 0x42, 0x71, 0x30, 0xf9, + 0x0c, 0xf9, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, + + // This is the cursor mask. + 0x00, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x3c, 0x00, + 0x1f, 0xe0, 0x1f, 0xfc, 0x0f, 0xfe, 0x0f, 0xff, + 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x3f, 0xff, + 0x0f, 0xff, 0x03, 0xfe, 0x01, 0xf8, 0x00, 0x00, + }; + + + + +// The default link color, blue. +const rgb_color blue = { 0, 0, 255 }; +// The default clicked-link color, red. +const rgb_color red = { 255, 0, 0 }; +// The default link hover color, dark blue. +const rgb_color dark_blue = { 0, 0, 120 }; +// The default disabled color, gray. +const rgb_color gray = { 100, 100, 100 }; + + + +class URLView : public BStringView { + public: + URLView( BRect frame, const char *name, const char *label, const char *url, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW ); + ~URLView(); + + + virtual void AttachedToWindow(); + virtual void Draw( BRect updateRect ); + virtual void MessageReceived( BMessage *message ); + virtual void MouseDown( BPoint point ); + virtual void MouseMoved( BPoint point, uint32 transit, const BMessage *message ); + virtual void MouseUp( BPoint point ); + virtual void WindowActivated( bool active ); + + virtual void AddAttribute( const char *name, const char *value ); + virtual bool IsEnabled(); + virtual void SetColor( rgb_color color ); + virtual void SetColor( uchar red, uchar green, uchar blue, uchar alpha = 255 ); + virtual void SetClickColor( rgb_color color ); + virtual void SetClickColor( uchar red, uchar green, uchar blue, uchar alpha = 255 ); + virtual void SetDisabledColor( rgb_color color ); + virtual void SetDisabledColor( uchar red, uchar green, uchar blue, uchar alpha = 255 ); + virtual void SetDraggable( bool draggable ); + virtual void SetEnabled( bool enabled ); + virtual void SetHoverColor( rgb_color color ); + virtual void SetHoverColor( uchar red, uchar green, uchar blue, uchar alpha = 255 ); + virtual void SetHoverEnabled( bool hover ); + virtual void SetIconSize( icon_size iconSize ); + virtual void SetUnderlineThickness( int thickness ); + virtual void SetURL( const char *url ); + + + private: + void CopyToClipboard(); + void CreateBookmark( const BString *fullName, const BString *title ); + void CreatePerson( const BString *fullName, const BString *title ); + BPopUpMenu *CreatePopupMenu(); + void DoBookmarkDrag(); + void DoPersonDrag(); + BString GetImportantURL(); + BRect GetTextRect(); + BRect GetURLRect(); + bool IsEmailLink(); + bool IsFTPLink(); + bool IsHTMLLink(); + void LaunchURL(); + void Redraw(); + void WriteAttributes( int fd ); + + BString *url; + rgb_color color; + rgb_color clickColor; + rgb_color hoverColor; + rgb_color disabledColor; + bool enabled; + bool hoverEnabled; + bool draggable; + int underlineThickness; + int iconSize; + + bool selected; + bool hovering; + bool draggedOut; + bool inPopup; + const BCursor *linkCursor; + BPoint dragOffset; + BList *attributes; + + typedef struct kp { + BString *key; + BString *value; + } KeyPair; +}; + + + +#endif // TH_URL_VIEW diff --git a/src/YAB.rdef b/src/YAB.rdef new file mode 100644 index 0000000..b91bbe2 --- /dev/null +++ b/src/YAB.rdef @@ -0,0 +1,38 @@ + +resource vector_icon { + $"6E6369660E0500020006023C43C6B9E5E23A85A83CEE414268F44A445900C6D7" + $"F5FF6B94DD03EC66660200060238C5F1BB105D3DFDC23B9CD045487847B50700" + $"FFFFFFFFC1CCFF020006023B3049396B0ABA90833C646E4A101543299500FFFF" + $"FFFFEBEFFF020006023C71E33A0C78BA15E43C7D2149055549455700E3EDFFFF" + $"9EC2FF03FFACAC0200060239D53438FFCBBBC1973C666F4ADC3246DC6C00C1CC" + $"FFFFFFFFFF03003CB0020006023C0AE63B3927BC611E3D03FF4C25624A1A9600" + $"A3043CFFFF90AF03C93B3B030D296402000602BD498B3E1159BF219BBE7D2F4C" + $"1B8F4A331300BD0F0FFFE98484040174100A08325E385E40564E5E545E605058" + $"4C3E510A062E2C2E3E3E454A3C4A2A3A250A042E2C2E3E3E453E320A042E2C3E" + $"324A2A3A250A043E323E454A3C4A2A0A0338423C4D3C440A0622422254325C3E" + $"513E402E3A0A0422422254325C32490A04224232493E402E3A0A043249325C3E" + $"513E400A063E423E544E5C5A505A3F4A390A04C222C20F4E495A3F523C0A043E" + $"42C222C20F523C4A390A054151C08BC8834E5C4E49C22AC2130A053E423E54C0" + $"8BC8834151C22AC2130A044E494E5C5A505A3F110A0D0100000A0001061815FF" + $"01178400040A00010618001501178600040A010107000A080109000A0B010520" + $"20210A050108000A00010A1001178400040A02010D000A0A010E000A0902040F" + $"000A06010B000A0C010C000A0001011001178400040A030102000A040103000A" + $"07010400" +}; + + +resource app_signature "application/x-vnd.yab-app"; + +resource app_version { + major = 1, + middle = 7, + minor = 4, + + variety = B_APPV_FINAL, + internal = 1, + + short_info = "Yab BASIC programming language", + long_info = "Yab allows fast prototyping with simple and clean code. yab contains a large number of BeAPI specific commands for GUI creation and much, much more." +}; + +resource app_flags 1; diff --git a/src/YAB.rdef.rsrc b/src/YAB.rdef.rsrc new file mode 100644 index 0000000..b78cbdd Binary files /dev/null and b/src/YAB.rdef.rsrc differ diff --git a/src/YabBitmapView.cpp b/src/YabBitmapView.cpp new file mode 100644 index 0000000..ce4d526 --- /dev/null +++ b/src/YabBitmapView.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include "YabWindow.h" +#include "YabBitmapView.h" + +YabBitmapView::YabBitmapView(BRect frame, const char *name, uint32 resizingMode, uint32 flags) + : BView(frame, name, resizingMode, flags) +{ + bmp = new BBitmap(BRect(0,0, frame.Width(), frame.Height()), B_RGBA32, true); + BView *myView = new BView(BRect(0,0, frame.Width(), frame.Height()), "canvas", B_FOLLOW_NONE, 0); + bmp->AddChild(myView); + SetDrawingMode(B_OP_COPY); + SetViewColor(0,0,0,255); + mouseMovedInfo = 1; + mouseStateInfo = -1; + prevMouseStateInfo = 0; + mouseX = 0; + mouseY = 0; + mouseLButton = 0; + mouseMButton = 0; + mouseRButton = 0; +} + +YabBitmapView::~YabBitmapView() +{ + delete bmp; +} + +BBitmap* YabBitmapView::GetBitmap() +{ + return bmp; +} + +BView* YabBitmapView::GetBitmapView() +{ + return bmp->FindView("canvas"); +} + +void YabBitmapView::Draw(BRect updateRect) +{ + DrawBitmap(bmp, updateRect, updateRect); +} + +void YabBitmapView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) +{ + BPoint ptCursor; + uint32 uButtons = 0; + GetMouse(&ptCursor, &uButtons, true); + + mouseX = (int)ptCursor.x; + mouseY = (int)ptCursor.y; + if(uButtons & B_PRIMARY_MOUSE_BUTTON) mouseLButton = 1; else mouseLButton = 0; + if(uButtons & B_SECONDARY_MOUSE_BUTTON) mouseRButton = 1; else mouseRButton = 0; + if(uButtons & B_TERTIARY_MOUSE_BUTTON) mouseMButton = 1; else mouseMButton = 0; + + switch(transit) + { + case B_INSIDE_VIEW: + if(prevMouseStateInfo==1) + mouseStateInfo = 0; + else + { + mouseStateInfo = 1; + prevMouseStateInfo = 1; + } + mouseMovedInfo = 0; + break; + case B_ENTERED_VIEW: + mouseStateInfo = 1; + mouseMovedInfo = 0; + break; + case B_OUTSIDE_VIEW: + mouseStateInfo = 2; + mouseMovedInfo = 1; + break; + case B_EXITED_VIEW: + mouseStateInfo = 3; + mouseMovedInfo = 1; + prevMouseStateInfo = 0; + break; + } + BView::MouseMoved(point, transit, message); +} + +void YabBitmapView::MouseDown(BPoint point) +{ + BPoint ptCursor; + uint32 uButtons = 0; + GetMouse(&ptCursor, &uButtons, false); + + mouseX = (int)ptCursor.x; + mouseY = (int)ptCursor.y; + if(uButtons & B_PRIMARY_MOUSE_BUTTON) mouseLButton = 1; else mouseLButton = 0; + if(uButtons & B_SECONDARY_MOUSE_BUTTON) mouseRButton = 1; else mouseRButton = 0; + if(uButtons & B_TERTIARY_MOUSE_BUTTON) mouseMButton = 1; else mouseMButton = 0; + mouseStateInfo = 4; + BView::MouseDown(point); +} + +void YabBitmapView::MouseUp(BPoint point) +{ + BPoint ptCursor; + uint32 uButtons = 0; + GetMouse(&ptCursor, &uButtons, false); + + mouseX = (int)ptCursor.x; + mouseY = (int)ptCursor.y; + if(uButtons & B_PRIMARY_MOUSE_BUTTON) mouseLButton = 1; else mouseLButton = 0; + if(uButtons & B_SECONDARY_MOUSE_BUTTON) mouseRButton = 1; else mouseRButton = 0; + if(uButtons & B_TERTIARY_MOUSE_BUTTON) mouseMButton = 1; else mouseMButton = 0; + mouseStateInfo = 5; + BView::MouseUp(point); +} + diff --git a/src/YabBitmapView.h b/src/YabBitmapView.h new file mode 100644 index 0000000..0561d6b --- /dev/null +++ b/src/YabBitmapView.h @@ -0,0 +1,31 @@ +#ifndef YABBITMAPVIEW_H +#define YABBITMAPVIEW_H + +#include + +class YabBitmapView : public BView +{ + public: + YabBitmapView(BRect frame, const char *name, uint32 resizingMode, uint32 flags); + ~YabBitmapView(); + virtual void Draw(BRect updateRect); + BBitmap* GetBitmap(); + BView* GetBitmapView(); + BBitmap *bmp; + + virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); + virtual void MouseUp(BPoint point); + virtual void MouseDown(BPoint point); + int mouseStateInfo; + int mouseMovedInfo; + int mouseX; + int mouseY; + uint mouseLButton; + uint mouseMButton; + uint mouseRButton; + private: + int prevMouseStateInfo; + +}; + +#endif diff --git a/src/YabControlLook.cpp b/src/YabControlLook.cpp new file mode 100644 index 0000000..af57b39 --- /dev/null +++ b/src/YabControlLook.cpp @@ -0,0 +1,257 @@ +#include +#include +#include "YabControlLook.h" + +YabControlLook::YabControlLook() +{ } + +YabControlLook::~YabControlLook() +{ } + +void YabControlLook::DrawActiveTabBottom(BView* view, BRect& rect, const BRect& updateRect, const rgb_color& base, uint32 flags, uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color edgeShadowColor; + rgb_color edgeLightColor; + rgb_color frameShadowColor; + rgb_color frameLightColor; + rgb_color bevelShadowColor; + rgb_color bevelLightColor; + BGradientLinear fillGradient; + fillGradient.SetStart(rect.LeftBottom() + BPoint(3, -3)); + fillGradient.SetEnd(rect.LeftTop() + BPoint(3, 3)); + + if (flags & B_DISABLED) { + edgeShadowColor = base; + edgeLightColor = base; + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.25); + bevelShadowColor = tint_color(base, 1.07); + bevelLightColor = tint_color(base, 0.8); + fillGradient.AddColor(tint_color(base, 0.85), 0); + fillGradient.AddColor(base, 255); + } else { + edgeShadowColor = tint_color(base, 1.03); + edgeLightColor = tint_color(base, 0.80); + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.30); + bevelShadowColor = tint_color(base, 1.07); + bevelLightColor = tint_color(base, 0.6); + fillGradient.AddColor(tint_color(base, 0.75), 0); + fillGradient.AddColor(tint_color(base, 1.03), 255); + } + + static const float kRoundCornerRadius = 4; + + // left/top corner + BRect cornerRect(rect); + cornerRect.right = cornerRect.left + kRoundCornerRadius; + cornerRect.top = cornerRect.bottom - kRoundCornerRadius; + + BRegion clipping(rect); + clipping.Exclude(cornerRect); + + _DrawRoundCornerLeftBottom(view, cornerRect, updateRect, base, edgeShadowColor, + frameLightColor, bevelLightColor, fillGradient); + + // left/top corner + cornerRect.right = rect.right; + cornerRect.left = cornerRect.right - kRoundCornerRadius; + + clipping.Exclude(cornerRect); + + _DrawRoundCornerRightBottom(view, cornerRect, updateRect, base, edgeShadowColor, + edgeLightColor, frameLightColor, frameShadowColor, bevelLightColor, + bevelShadowColor, fillGradient); + + // rest of frame and fill + view->ConstrainClippingRegion(&clipping); + + _DrawFrame(view, rect, edgeShadowColor, edgeLightColor, edgeLightColor, + edgeShadowColor, + borders & (B_LEFT_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER)); + if ((borders & B_LEFT_BORDER) == 0) + rect.left++; + if ((borders & B_RIGHT_BORDER) == 0) + rect.right--; + + _DrawFrame(view, rect, frameLightColor, frameShadowColor, frameShadowColor, + frameLightColor, B_LEFT_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER); + + _DrawFrame(view, rect, bevelLightColor, bevelShadowColor, bevelShadowColor, + bevelLightColor); + + view->FillRect(rect, fillGradient); + + view->SetHighColor(216,216,216); + view->StrokeLine(BPoint(rect.left, rect.top), BPoint(rect.right, rect.top)); + + view->ConstrainClippingRegion(NULL); +} + +void YabControlLook::DrawInactiveTabBottom(BView* view, BRect& rect,const BRect& updateRect, const rgb_color& base, uint32 flags, uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color edgeShadowColor; + rgb_color edgeLightColor; + rgb_color frameShadowColor; + rgb_color frameLightColor; + rgb_color bevelShadowColor; + rgb_color bevelLightColor; + BGradientLinear fillGradient; + fillGradient.SetStart(rect.LeftBottom() + BPoint(3, -3)); + fillGradient.SetEnd(rect.LeftTop() + BPoint(3, 3)); + + if (flags & B_DISABLED) { + edgeShadowColor = base; + edgeLightColor = base; + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.25); + bevelShadowColor = tint_color(base, 1.07); + bevelLightColor = tint_color(base, 0.8); + fillGradient.AddColor(tint_color(base, 0.85), 0); + fillGradient.AddColor(base, 255); + } else { + edgeShadowColor = tint_color(base, 1.03); + edgeLightColor = tint_color(base, 0.80); + frameShadowColor = tint_color(base, 1.30); + frameLightColor = tint_color(base, 1.30); + bevelShadowColor = tint_color(base, 1.17); + bevelLightColor = tint_color(base, 1.10); + fillGradient.AddColor(tint_color(base, 1.12), 0); + fillGradient.AddColor(tint_color(base, 1.08), 255); + } + + // active tabs stand out at the top, but this is an inactive tab + view->SetHighColor(base); + view->FillRect(BRect(rect.left, rect.bottom - 4, rect.right, rect.bottom)); + rect.bottom -= 4; + + // frame and fill + _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, + edgeLightColor, + borders & (B_LEFT_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER)); + + _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, + frameShadowColor, + borders & (B_LEFT_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER)); + + if (rect.IsValid()) { + _DrawFrame(view, rect, bevelShadowColor, bevelShadowColor, + bevelLightColor, bevelLightColor, B_LEFT_BORDER & ~borders); + } else { + if ((B_LEFT_BORDER & ~borders) != 0) + rect.left++; + } + + view->FillRect(rect, fillGradient); +} + +void +YabControlLook::_DrawRoundCornerLeftBottom(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, const rgb_color& edgeColor, + const rgb_color& frameColor, const rgb_color& bevelColor, + const BGradientLinear& fillGradient) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BRegion clipping(rect); + view->ConstrainClippingRegion(&clipping); + + // background + view->SetHighColor(base); + view->FillRect(rect); + + // outer edge + BRect ellipseRect(rect); + ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; + ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; + + view->SetHighColor(edgeColor); + view->FillEllipse(ellipseRect); + + // frame + ellipseRect.InsetBy(1, 1); + view->SetHighColor(frameColor); + view->FillEllipse(ellipseRect); + + // bevel + ellipseRect.InsetBy(1, 1); + view->SetHighColor(bevelColor); + view->FillEllipse(ellipseRect); + + // fill + ellipseRect.InsetBy(1, 1); + view->FillEllipse(ellipseRect, fillGradient); + + view->ConstrainClippingRegion(NULL); +} + +void +YabControlLook::_DrawRoundCornerRightBottom(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, + const rgb_color& edgeTopColor, const rgb_color& edgeRightColor, + const rgb_color& frameTopColor, const rgb_color& frameRightColor, + const rgb_color& bevelTopColor, const rgb_color& bevelRightColor, + const BGradientLinear& fillGradient) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BRegion clipping(rect); + view->ConstrainClippingRegion(&clipping); + + // background + view->SetHighColor(base); + view->FillRect(rect); + + // outer edge + BRect ellipseRect(rect); + ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; + ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; + + BGradientLinear gradient; + gradient.AddColor(edgeTopColor, 0); + gradient.AddColor(edgeRightColor, 255); + gradient.SetStart(rect.LeftTop()); + gradient.SetEnd(rect.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + + // frame + ellipseRect.InsetBy(1, 1); + rect.right--; + rect.top++; + if (frameTopColor == frameRightColor) { + view->SetHighColor(frameTopColor); + view->FillEllipse(ellipseRect); + } else { + gradient.SetColor(0, frameTopColor); + gradient.SetColor(1, frameRightColor); + gradient.SetStart(rect.LeftTop()); + gradient.SetEnd(rect.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + } + + // bevel + ellipseRect.InsetBy(1, 1); + rect.right--; + rect.top++; + gradient.SetColor(0, bevelTopColor); + gradient.SetColor(1, bevelRightColor); + gradient.SetStart(rect.LeftTop()); + gradient.SetEnd(rect.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + + // fill + ellipseRect.InsetBy(1, 1); + view->FillEllipse(ellipseRect, fillGradient); + + view->ConstrainClippingRegion(NULL); +} + + diff --git a/src/YabControlLook.h b/src/YabControlLook.h new file mode 100644 index 0000000..f45a37b --- /dev/null +++ b/src/YabControlLook.h @@ -0,0 +1,33 @@ +#ifndef YABCONTROLLOOK +#define YABCONTROLLOOK + +#include + +class YabControlLook : public BControlLook +{ + public: + YabControlLook(); + ~YabControlLook(); + + virtual void DrawActiveTabBottom(BView* view, BRect& rect, const BRect& updateRect, const rgb_color& base, uint32 flags = 0, uint32 borders = BControlLook::B_ALL_BORDERS); + virtual void DrawInactiveTabBottom(BView* view, BRect& rect, const BRect& updateRect, const rgb_color& base, uint32 flags = 0, uint32 borders = BControlLook::B_ALL_BORDERS); + void _DrawRoundCornerLeftBottom(BView* view, + BRect& rect, const BRect& updateRect, + const rgb_color& base, + const rgb_color& edgeColor, + const rgb_color& frameColor, + const rgb_color& bevelColor, + const BGradientLinear& fillGradient); + void _DrawRoundCornerRightBottom(BView* view, + BRect& rect, const BRect& updateRect, + const rgb_color& base, + const rgb_color& edgeTopColor, + const rgb_color& edgeRightColor, + const rgb_color& frameTopColor, + const rgb_color& frameRightColor, + const rgb_color& bevelTopColor, + const rgb_color& bevelRightColor, + const BGradientLinear& fillGradient); +}; + +#endif diff --git a/src/YabFilePanel.cpp b/src/YabFilePanel.cpp new file mode 100644 index 0000000..ea022cf --- /dev/null +++ b/src/YabFilePanel.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include "YabFilePanel.h" +#include "YabFilePanelLooper.h" + +BEntry *YabFilePanel::MyFilePanel(const char *name, const char *directory, const char* filename, int mode) +{ + BEntry *myEntry = NULL; + entry_ref ref; + + sem_id semaphore = create_sem(0, "yabfilepanel"); + YabFilePanelLooper *myLooper = new YabFilePanelLooper(semaphore); + myLooper->Run(); + + if(directory) + { + myEntry=new BEntry(directory); + if(myEntry->GetRef(&ref)!=B_OK) + { + myEntry->Unset(); + myEntry->SetTo("/boot/home/"); + myEntry->GetRef(&ref); + } + myEntry->Unset(); + delete myEntry; + } + + BFilePanel *myFilePanel = NULL; + switch(mode) + { + case 0: + myFilePanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(myLooper, myLooper), &ref, B_FILE_NODE, false, NULL, NULL, true, true); + break; + case 1: + myFilePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(myLooper, myLooper), &ref, B_FILE_NODE, false, NULL, NULL, true, true); + if (filename) myFilePanel->SetSaveText(filename); + break; + case 2: + myFilePanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(myLooper, myLooper), &ref, B_DIRECTORY_NODE, false, NULL, NULL, true, true); + break; + case 3: + myFilePanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(myLooper, myLooper), &ref, B_FILE_NODE|B_DIRECTORY_NODE, false, NULL, NULL, true, true); + break; + } + + if(name) myFilePanel->Window()->SetTitle(name); + myFilePanel->Show(); + + bool inloop = true; + while(inloop) + { + while(acquire_sem_etc(semaphore, 1, B_RELATIVE_TIMEOUT, 10000)==B_TIMED_OUT) ; + + myEntry = myLooper->GetChosenFile(); + inloop = false; +/* + if(mode!=2) + inloop = false; + else + { + if(myEntry->IsDirectory()) + inloop = false; + else + { + myFilePanel->Show(); + } + } +*/ + } + myLooper->Lock(); + myLooper->Quit(); + + delete_sem(semaphore); + delete myFilePanel; + return myEntry; +} diff --git a/src/YabFilePanel.h b/src/YabFilePanel.h new file mode 100644 index 0000000..67b633a --- /dev/null +++ b/src/YabFilePanel.h @@ -0,0 +1,10 @@ +#ifndef YABFILEPANEL_H +#define YABFILEPANEL_H + +class YabFilePanel +{ + public: + BEntry *MyFilePanel(const char *name, const char *directory, const char* filename, int panelType); +}; + +#endif diff --git a/src/YabFilePanelLooper.cpp b/src/YabFilePanelLooper.cpp new file mode 100644 index 0000000..08a8994 --- /dev/null +++ b/src/YabFilePanelLooper.cpp @@ -0,0 +1,57 @@ +#include +#include +#include "YabFilePanelLooper.h" + +YabFilePanelLooper::YabFilePanelLooper(sem_id semaphore) : BLooper("YabFilePanelLooper") +{ + myEntry=new BEntry(); + mySemaphore = semaphore; +} + +BEntry *YabFilePanelLooper::GetChosenFile() +{ + return myEntry; +} + +void YabFilePanelLooper::MessageReceived(BMessage *msg) +{ + switch(msg->what) + { + case B_REFS_RECEIVED: + { + entry_ref ref; + if (msg->FindRef("refs", 0, &ref)==B_OK) + myEntry->SetTo(&ref); + else + myEntry->Unset(); + } + break; + + case B_SAVE_REQUESTED: + { + const char *selected; + entry_ref ref; + + if (msg->FindString("name", &selected)!=B_OK) + myEntry->Unset(); + else + { + if (msg->FindRef("directory", 0, &ref)==B_OK) + { + BDirectory *myDirectory = new BDirectory(&ref); + myEntry->SetTo(myDirectory, selected); + myDirectory->Unset(); + delete myDirectory; + } + else + myEntry->Unset(); + } + } + break; + + case B_CANCEL: + release_sem(mySemaphore); + break; + } +} + diff --git a/src/YabFilePanelLooper.h b/src/YabFilePanelLooper.h new file mode 100644 index 0000000..77ebc98 --- /dev/null +++ b/src/YabFilePanelLooper.h @@ -0,0 +1,19 @@ +#ifndef YABFPLOOPER_H +#define YABFPLOOPER_H + +#include +#include +#include + +class YabFilePanelLooper : public BLooper +{ + public: + YabFilePanelLooper(sem_id semaphore); + void MessageReceived(BMessage *msg); + BEntry *GetChosenFile(); + private: + BEntry *myEntry; + sem_id mySemaphore; +}; + +#endif diff --git a/src/YabInterface.cpp b/src/YabInterface.cpp new file mode 100644 index 0000000..5b4481b --- /dev/null +++ b/src/YabInterface.cpp @@ -0,0 +1,10698 @@ +#include "global.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "CalendarControl.h" +#include "YabFilePanel.h" +#include "SplitPane.h" +#include "URLView.h" +#include "Spinner.h" +#include "YabTabView.h" + +#ifdef LIBBSVG + #include +#endif + +#include +#include + +#include "YabInterface.h" +#include "YabWindow.h" +#include "YabView.h" +#include "YabBitmapView.h" +#include "YabList.h" + +#include "YabText.h" +#include "YabMenu.h" +#include "YabStackView.h" +#include "column/YabColumnType.h" +#include "column/ColorTools.h" +#include "column/ColumnListView.h" + + +const uint32 YABBUTTON = 'YBbu'; +const uint32 YABMENU = 'YBme'; +const uint32 YABSUBMENU = 'YBsu'; +const uint32 YABTEXTCONTROL = 'YBtc'; +const uint32 YABCHECKBOX = 'YBcb'; +const uint32 YABRADIOBUTTON = 'YBrb'; +const uint32 YABLISTBOXSELECT = 'YBls'; +const uint32 YABLISTBOXINVOKE = 'YBli'; +const uint32 YABDROPBOX = 'YBdb'; +const uint32 YABSLIDER = 'YBsl'; +const uint32 YABCOLORCONTROL = 'YBco'; +const uint32 YABTREEBOXSELECT = 'YBts'; +const uint32 YABTREEBOXINVOKE = 'YBti'; +const uint32 YABFILEBOXSELECT = 'YBfs'; +const uint32 YABFILEBOXINVOKE = 'YBfi'; +const uint32 YABSHORTCUT = 'YBsh'; + +const uint32 TYPE_YABVIEW = 1; +char * refsRec=(char*)""; + +BCatalog *yabCatalog; + +static bool localize = false; +static bool quitting = false; +static property_info prop_list[] = { + { "YabSendString", {B_SET_PROPERTY, 0}, {B_NAME_SPECIFIER, 0}, "Send a string to MESSAGE$"}, + 0 // terminate list +}; + +const char* _L(const char* text) +{ + if(localize && yabCatalog) + return yabCatalog->GetString(text, NULL); //B_TRANSLATE_CONTEXT); + return text; +} + +/** + * Start the interpreter thread + */ +int32 interpreter(void *data) +{ + int argc,t; + char **argv; + YabInterface *yab; + BList *myData = (BList*)data; + argc = (int)myData->ItemAt(0); + argv = (char**)myData->ItemAt(1); + yab = (YabInterface*)myData->ItemAt(2); + + t = mmain(argc,argv, yab); + return t; +} + +/** + * Constructor sets application directory, spawn the interpreter thread + */ +YabInterface::YabInterface(int argc, char **argv, const char* signature) + :BApplication(signature) +{ + BPath AppDirectory; + + // app directory + app_info appinfo; + + if( GetAppInfo( &appinfo) == B_OK) + { + BEntry ApplicationEntry( &appinfo.ref); + BEntry ApplicationDirectoryEntry; + + if( ApplicationEntry.GetParent( &ApplicationDirectoryEntry) == B_OK) + { + if( AppDirectory.SetTo( &ApplicationDirectoryEntry) == B_OK) + { + strcpy(ApplicationDirectory, AppDirectory.Path()); + // ApplicationDirectory.SetTo(AppDirectory.Path()); + } + } + } + + localMessage = ""; + + BList *myData = new BList(3); + myData->AddItem((void*)argc); + myData->AddItem((void*)argv); + myData->AddItem((void*)this); + myThread = spawn_thread(interpreter,"YabInterpreter",B_NORMAL_PRIORITY,(void*)myData); + if(myThread < B_OK) + { + printf("Can not start thread. Out of memory or maximum thread amount reached.\n"); + printf("Exiting now \n\n"); + exit(1); + } + + if(resume_thread(myThread) < B_OK) + { + printf("Error while starting interpreter!\n"); + printf("Exiting now \n\n"); + exit(1); + } + + viewList = new YabList(); + yabbitmaps = new BList(); + yabcanvas = new BList(); + drawStroking = false; + yabPattern = B_SOLID_HIGH; + yabAlpha = 255; + errorCode = 0; + Roster = NULL; + currentLineNumber = -1; + exiting = false; + + for(int i=0; i<63; i++) + mousemessagebuffer[i] = ' '; + mousemessagebuffer[63] = '\0'; + + myProps = new BPropertyInfo(prop_list); + currentLib = ""; + lastMouseMsg = ""; +} + +YabInterface::~YabInterface() +{ + delete mainFileName; + // delete song; + // delete fopen; + // delete fsave; + delete viewList; + // delete Roster; + delete myProps; + if(yabCatalog) + delete yabCatalog; + while(yabbitmaps->CountItems()>0) + { + int i = 0; + BBitmap *b = (BBitmap*)yabbitmaps->RemoveItem(i); + delete b; + } +} + +/** + * Returns the application directory + */ +const char* YabInterface::GetApplicationDirectory() +{ + return (const char*) ApplicationDirectory; +} + +status_t YabInterface::GetSupportedSuites(BMessage *msg) +{ + msg->AddString("suites", "suite/vnd.yab-YabInterface"); + BPropertyInfo prop_info(prop_list); + msg->AddFlat("messages", &prop_info); + return BApplication::GetSupportedSuites(msg); +} + +BHandler* YabInterface::ResolveSpecifier(BMessage *msg, int32 index, BMessage *spec, int32 form, const char *prop) +{ + if (myProps->FindMatch(msg, index, spec, form, prop) >= 0) + return (BHandler*)this; + return BApplication::ResolveSpecifier(msg, index, spec, form, prop); +} + +void YabInterface::MessageReceived(BMessage *message) +{ + // message->PrintToStream(); + switch(message->what) + { + case B_SET_PROPERTY: + { + BMessage msg; + int32 i,w; + const char *prop; + + if(message->GetCurrentSpecifier(&i, &msg, &w, &prop) != B_BAD_SCRIPT_SYNTAX) + { + BString s; + msg.FindString("name", &s); + localMessage += "_Scripting:"; + localMessage += s; + localMessage +="|"; + } + } + break; + case B_REFS_RECEIVED: + { + entry_ref ref; + if(message->FindRef("refs", 0, &ref)==B_OK) + { + BEntry e(&ref); + BPath path; + e.GetPath(&path); + localMessage += "_RefsReceived:"; + localMessage += path.Path(); + localMessage +="|"; + } + } + break; + default: + BApplication::MessageReceived(message); + break; + } +} + +/** + * The QUIT_REQUESTED message arrived. If the interpreter thread is still active, + * kill it, otherwise exit directly. + */ +bool YabInterface::QuitRequested() +{ + exiting = true; + return true; +} + +void YabInterface::RefsReceived(BMessage *message){ + entry_ref ref; + BString tempstr; + if(message->FindRef("refs", 0, &ref)==B_OK) + { + BEntry e(&ref); + BPath path; + e.GetPath(&path); + tempstr += path.Path(); + refsRec = strdup(tempstr.String()); + } +} + +bool YabInterface::ExitRequested() +{ + status_t exit_val; + thread_info t; + // printf("QUITDEBUG: Exit\n"); + Lock(); + // printf("QUITDEBUG: Locked Ok\n"); + // if(!quitting) + // { + // printf("QUITDEBUG: quitting\n"); + // kill_thread(myThread); + // printf("QUITDEBUG: Kill Thread Ok\n"); + // } + // printf("QUITDEBUG: 1\n"); + + for(int i=0; iLock()) + w->Quit(); + } + + snooze(15000); + // printf("QUITDEBUG: 3\n"); + + + // BMessenger(be_app).SendMessage(new BMessage(B_QUIT_REQUESTED)); + Quit(); + // printf("QUITDEBUG: Quit\n"); + // printf("QUITDEBUG: wait\n"); + // wait_for_thread(myThread, &exit_val); + // get_thread_info(myThread, &t); + // kill_team(t.team); + // printf("QUITDEBUG: Stopped waiting\n"); + Unlock(); + // printf("QUITDEBUG: Unlock\n"); + + exit_thread(B_OK); + + return true; +} + +/** + * Open a window, add the main view. + */ +void YabInterface::OpenWindow(const BRect frame, const char* id, const char* title) +{ + YabWindow* w = new YabWindow(frame,title,id, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS); + YabView* myView = new YabView(w->Bounds(), id, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_NAVIGABLE_JUMP); + w->Lock(); + w->AddChild(myView); + + viewList->AddView(id, myView, TYPE_YABVIEW); + // viewList->PrintOut(); + + // w->Minimize(); + w->SetSizeLimits(10,3000,10,3000); + w->Show(); + w->Unlock(); + w->layout = -1; +} + +int YabInterface::CloseWindow(const char* view) +{ + int tmp = 0; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BView *child, *oldchild; + if(child = myView->ChildAt(0)) + { + while(child) + { + if(is_kind_of(child, YabTabView)) + { + for(int i = 0; i<((YabTabView*)child)->CountTabs(); i++) + { + YabView *t = (YabView*)((YabTabView*)child)->TabAt(i); + RemoveView(t); + viewList->DelView(t->Name()); + } + } + if(is_kind_of(child, YabBitmapView)) + yabcanvas->RemoveItem(child); + + // viewList->PrintOut(); + BView *subchild; + if(subchild = child->ChildAt(0)) + while(subchild) + { + if(is_kind_of(subchild, YabTabView)) + { + for(int i = 0; i<((YabTabView*)subchild)->CountTabs(); i++) + { + YabView *t = (YabView*)((YabTabView*)subchild)->TabAt(i); + RemoveView(t); + viewList->DelView(t->Name()); + } + } + if(viewList->GetView(subchild->Name())) + { + RemoveView(subchild); + viewList->DelView(subchild->Name()); + } + subchild = subchild->NextSibling(); + } + if(viewList->GetView(child->Name())) + { + RemoveView(child); + viewList->DelView(child->Name()); + } + + oldchild = child; + child = child->NextSibling(); + + if(is_kind_of(oldchild, YabView)) + DrawClear(oldchild->Name(), true); + if(is_kind_of(oldchild, BMenuBar)) + { + oldchild->Hide(); + } + oldchild->RemoveSelf(); + delete oldchild; + } + } + if(is_kind_of(myView, YabView)) + DrawClear(myView->Name(), true); + if(is_kind_of(myView, BMenuBar)) + myView->Hide(); + myView->RemoveSelf(); + delete myView; + viewList->DelView(view); + // viewList->PrintOut(); + w->Quit(); + tmp = 1; + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); + + return tmp; +} + +void YabInterface::View(BRect frame, const char* id, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabView *newView = new YabView(frame, id, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_NAVIGABLE_JUMP); + if(w->layout == -1) + newView->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + newView->SetResizingMode(w->layout); + myView->AddChild(newView); + + viewList->AddView(id, newView, TYPE_YABVIEW); + // viewList->PrintOut(); + + newView->Invalidate(); + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::BoxView(BRect frame, const char* id, const char* text, int lineType, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBox *newBox = new BBox(frame, id, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE_JUMP); + font_height fh; + (be_bold_font)->GetHeight(&fh); + float y1 = fh.ascent + fh.descent + fh.leading + 1.0; + YabView *newView = new YabView(BRect(3,y1,frame.Width()-3,frame.Height()-3), id, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE_JUMP); + if(w->layout == -1) + { + newBox->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + newView->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + } + else + { + newBox->SetResizingMode(w->layout); + newView->SetResizingMode(w->layout); + } + newBox->SetLabel(text); + switch(lineType) + { + case 0: newBox->SetBorder(B_NO_BORDER); + break; + case 1: newBox->SetBorder(B_PLAIN_BORDER); + break; + default: newBox->SetBorder(B_FANCY_BORDER); + break; + } + + newBox->AddChild(newView); + myView->AddChild(newBox); + viewList->AddView(id, newView, TYPE_YABVIEW); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::BoxViewSet(const char* id, const char* option, const char* value) +{ + + YabView *myView = NULL; + BString tmpOption(option); + BString tmpValue(value); + BBox *myBox = 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(); + + myBox = cast_as(myView->FindView(id), BBox); + if(myBox) + { + if(tmpOption.IFindFirst("label")!=B_ERROR) + { + myBox->SetLabel(tmpValue); + w->Unlock(); + return; + } + if(tmpOption.IFindFirst("line")!=B_ERROR) + { + if(tmpValue.IFindFirst("0")!=B_ERROR) + { + myBox->SetBorder(B_NO_BORDER); + w->Unlock(); + return; + } + if(tmpValue.IFindFirst("1")!=B_ERROR) + { + myBox->SetBorder(B_PLAIN_BORDER); + w->Unlock(); + return; + } + if(tmpValue.IFindFirst("2")!=B_ERROR) + { + myBox->SetBorder(B_FANCY_BORDER); + w->Unlock(); + return; + } + + } + w->Unlock(); + } + else + w->Unlock(); + Error(id, "BOXVIEW"); + + } + + + } + + + } +} +void YabInterface::Tab(BRect frame, const char* id, const char* mode, const char* view) +{ + tab_orientation side; + BString option(mode); + if(option.IFindFirst("top")!=B_ERROR) + side = B_TAB_TOP; + else if(option.IFindFirst("bottom")!=B_ERROR) + side = B_TAB_BOTTOM; + else ErrorGen("Invalid Option"); + + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + + YabTabView *myTabView = new YabTabView(frame, id); + + if(w->layout == -1) + myTabView->SetResizingMode(B_FOLLOW_ALL); + else + myTabView->SetResizingMode(w->layout); + + myTabView->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE|B_NAVIGABLE_JUMP); + + myTabView->SetOrientation(side); + myTabView->SetTabWidth(B_WIDTH_FROM_LABEL); + + myView->AddChild(myTabView); + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::TabAdd(const char* id, const char* tabname) +{ + YabView *myView = NULL; + YabTabView *myTabView = 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(); + myTabView = cast_as(myView->FindView(id), YabTabView); + if(myTabView) + { + BString t(id); + t << myTabView->CountTabs()+1; + + BRect contentFrame = myTabView->Bounds(); + + YabView *newView = new YabView(contentFrame, t.String(), B_FOLLOW_ALL_SIDES,B_WILL_DRAW|B_NAVIGABLE_JUMP); + viewList->AddView(t.String(), newView, TYPE_YABVIEW); + + myTabView->AddTab(newView, tabname); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TABVIEW"); +} + +void YabInterface::TabDel(const char* id, int num) +{ +/* + YabView *myView = NULL; + #ifdef BUILD_HAIKUTAB + YabTabView *myTabView = NULL; + #else + BTabView *myTabView = NULL; + #endif + + 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(); + #ifdef BUILD_HAIKUTAB + myTabView = cast_as(myView->FindView(id), YabTabView); + #else + myTabView = cast_as(myView->FindView(id), BTabView); + #endif + if(myTabView) + { + if(num-1<0 || num-1>myTabView->CountTabs()) ErrorGen("Invalid tab number"); + BView *child, *oldchild; + if(child = myView->ChildAt(0)) + { + while(child) + { + BView *subchild; + if(subchild = child->ChildAt(0)) + while(subchild) + { + #ifdef BUILD_HAIKUTAB + if(is_kind_of(subchild, YabTabView)) + { + for(int i = 0; i<((YabTabView*)subchild)->CountTabs(); i++) + { + YabView *t = (YabView*)((YabTabView*)subchild)->TabAt(i); + RemoveView(t); + viewList->DelView(t->Name()); + } + } + #endif + if(viewList->GetView(subchild->Name())) + { + RemoveView(subchild); + viewList->DelView(subchild->Name()); + } + subchild = subchild->NextSibling(); + } + if(viewList->GetView(child->Name())) + { + RemoveView(child); + viewList->DelView(child->Name()); + } + + + oldchild = child; + child = child->NextSibling(); + + if(is_kind_of(oldchild, YabView)) + DrawClear(oldchild->Name(), true); + if(is_kind_of(oldchild, BMenuBar)) + { + oldchild->Hide(); + } + oldchild->RemoveSelf(); + delete oldchild; + } + } + if(is_kind_of(myView, YabView)) + DrawClear(myView->Name(), true); + if(is_kind_of(myView, BMenuBar)) + myView->Hide(); + BBox *box = cast_as(myView->Parent(), BBox); + myView->RemoveSelf(); + delete myView; + viewList->DelView(window); + if(box) + { + box->RemoveSelf(); + delete box; + } + #ifdef BUILD_HAIKUTAB + WindowClear(myTabView->ItemAt(num-1)->Name()); + RemoveView(myTabView->ItemAt(num-1)); + #else + WindowClear((myTabView->TabAt(num-1)).GetTargetView().Name()); + #endif + myTabView->RemoveTab(num-1); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TABVIEW"); +*/ +} + + + + + + +void YabInterface::TabSet(const char* id, int num) +{ + YabView *myView = NULL; + YabTabView *myTabView = 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(); + myTabView = cast_as(myView->FindView(id), YabTabView); + if(myTabView) + { + if(num>0 && num<=myTabView->CountTabs()) + myTabView->Select(num-1); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TABVIEW"); +} + +int YabInterface::TabViewGet(const char* id) +{ + int ret = -1; + YabView *myView = NULL; + YabTabView *myTabView = 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(); + myTabView = cast_as(myView->FindView(id), YabTabView); + if(myTabView) + { + ret = myTabView->Selection(); + w->Unlock(); + return ret+1; + } + w->Unlock(); + } + } + } + Error(id, "TABVIEW"); +} + +void YabInterface::Launch(const char* strg) +{ + BString tst(strg); + + entry_ref *ref = new entry_ref(); + BEntry entry(strg); + entry.GetRef(ref); + if(entry.IsDirectory()) + { + BMessage msg, reply; + msg.what = B_REFS_RECEIVED; + msg.AddRef("refs", ref); + BMessenger("application/x-vnd.Be-TRAK").SendMessage(&msg, &reply); + return; + } + + status_t t = be_roster->Launch(ref); + if(t != B_OK) + { + if(tst.FindFirst("http://") != B_ERROR || tst.FindFirst("file://") != B_ERROR || tst.FindFirst("www.") != B_ERROR) + { + char *link = tst.LockBuffer( tst.Length()+1 ); + status_t result = be_roster->Launch( "text/html", 1, &link ); + tst.UnlockBuffer(); + } + } + delete ref; +} + +void YabInterface::CreateButton(BRect frame, const char* id, const char* title, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BButton* myButton = new BButton(frame,id,title,new BMessage(YABBUTTON)); + if(w->layout == -1) + myButton->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + myButton->SetResizingMode(w->layout); + myButton->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + // trick Haiku, resize button again + myButton->ResizeTo(frame.Width(), frame.Height()); + myView->AddChild(myButton); + // viewList->AddView(id, myButton, TYPE_BBUTTON); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +int YabInterface::CreateImage(BPoint coordinates, const char* FileName, const char* window) +{ + BBitmap* myBitmap = NULL; + BFile imageFile; + BPath imagePath; + int ret = 0; + + if(*FileName=='/') + imageFile.SetTo(FileName, B_READ_ONLY); + else + if(!strcmp(ApplicationDirectory,"")) + { + if(imagePath.SetTo((const char*)ApplicationDirectory, FileName)==B_OK) + imageFile.SetTo(imagePath.Path(), B_READ_ONLY); + } + if(imageFile.InitCheck()!=B_OK) + imageFile.SetTo(FileName, B_READ_ONLY); + + if(imageFile.InitCheck()!=B_OK) + return 1; + + Roster = BTranslatorRoster::Default(); + + if(!Roster) + return 2; + + BBitmapStream Stream; + + if(Roster->Translate(&imageFile, NULL, NULL, &Stream, B_TRANSLATOR_BITMAP)GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + t->command = 10; + t->x1 = coordinates.x; t->y1 = coordinates.y; + t->bitmap = myBitmap; + myView->drawList->AddItem(t); + myView->Invalidate(BRect(coordinates.x, coordinates.y, coordinates.x+myBitmap->Bounds().Width(), coordinates.y+myBitmap->Bounds().Height())); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + drawing_mode mode = bview->DrawingMode(); + bview->SetDrawingMode(B_OP_ALPHA); + bview->DrawBitmap(myBitmap, coordinates); + bview->SetDrawingMode(mode); + bview->Sync(); + b->Unlock(); + delete Roster; + delete myBitmap; + return 0; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + drawing_mode mode = bView->DrawingMode(); + bView->SetDrawingMode(B_OP_ALPHA); + bView->DrawBitmap(myBitmap, coordinates); + bView->SetDrawingMode(mode); + bView->Sync(); + b->Unlock(); + + myView->Draw(BRect(coordinates.x, coordinates.y, coordinates.x+myBitmap->Bounds().Width(), coordinates.y+myBitmap->Bounds().Height())); + w->Unlock(); + delete Roster; + delete myBitmap; + return 0; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } + delete Roster; + return 0; +} + +int YabInterface::CreateImage(BRect frame, const char* FileName, const char* window) +{ + int scaling = 0; + if(frame.right == -1) scaling = 1; + if(frame.bottom == -1) scaling = 2; + if(frame.right == -1 && frame.bottom == -1) scaling = 3; + + BBitmap* myBitmap = NULL; + BFile ImageFile; + BPath ImagePath; + int ret = 0; + + if(*FileName=='/') + ImageFile.SetTo(FileName, B_READ_ONLY); + else + if(!strcmp(ApplicationDirectory,"")) + { + if( ImagePath.SetTo((const char*)ApplicationDirectory, FileName) == B_OK) + ImageFile.SetTo(ImagePath.Path(), B_READ_ONLY); + } + + if(ImageFile.InitCheck()!=B_OK) + ImageFile.SetTo(FileName, B_READ_ONLY); + + if(ImageFile.InitCheck()!=B_OK) + return 1; + + Roster = BTranslatorRoster::Default(); + + if(!Roster) + return 2; + + BBitmapStream Stream; + + if(Roster->Translate(&ImageFile, NULL, NULL, &Stream, B_TRANSLATOR_BITMAP) < B_OK) + return 3; + + if(Stream.DetachBitmap(&myBitmap) != B_OK) + return 4; + + BRect newframe; + switch(scaling) + { + case 1: + { + BRect t(myBitmap->Bounds()); + double width; + newframe = frame; + width = (t.right-t.left)*((frame.bottom-frame.top)/(t.bottom-t.top)); + newframe.right = newframe.left+width; + } + break; + case 2: + { + BRect t(myBitmap->Bounds()); + double height; + newframe = frame; + height = (t.bottom-t.top)*((frame.right-frame.left)/(t.right-t.left)); + newframe.bottom = newframe.top+height; + } + break; + case 3: newframe = myBitmap->Bounds(); + break; + default: newframe = frame; + } + + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + t->command = 11; + t->x1 = newframe.left; t->y1 = newframe.top; + t->x2 = newframe.right; t->y2 = newframe.bottom; + t->bitmap = myBitmap; + myView->drawList->AddItem(t); + myView->Invalidate(newframe); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + drawing_mode mode = bview->DrawingMode(); + bview->SetDrawingMode(B_OP_ALPHA); + bview->DrawBitmap(myBitmap, newframe); + bview->SetDrawingMode(mode); + bview->Sync(); + b->Unlock(); + delete Roster; + delete myBitmap; + return 0; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + drawing_mode mode = bView->DrawingMode(); + bView->SetDrawingMode(B_OP_ALPHA); + bView->DrawBitmap(myBitmap, newframe); + bView->SetDrawingMode(mode); + bView->Sync(); + b->Unlock(); + + myView->Draw(newframe); + w->Unlock(); + delete Roster; + delete myBitmap; + return 0; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } + delete Roster; + return 0; +} + +int YabInterface::CreateSVG(BRect frame, const char* FileName, const char* window) +{ +#ifdef LIBBSVG + BPath path; + BString file; + file.SetTo(FileName); + if(FileName[0]!='/') + { + if(!strcmp(ApplicationDirectory,"")) + { + if(path.SetTo((const char*)ApplicationDirectory, FileName) == B_OK) + file.SetTo(path.Path()); + } + } + int ret = 0; + + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); // untested! + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BSVGView *mySVG = new BSVGView(frame,"svgview",0); + mySVG->SetViewColor(myView->ViewColor()); + mySVG->SetScaleToFit(true); + if(w->layout == -1) + mySVG->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + mySVG->SetResizingMode(w->layout); + mySVG->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE); + + if(mySVG->LoadFromFile(file.String())!=B_OK) + ret = 1; + else + myView->AddChild(mySVG); + myView->Invalidate(); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); + return ret; +#else + return 2; +#endif +} + +void YabInterface::StatusBar(BRect frame, const char* id, const char* label1, const char* label2, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BStatusBar *bar = new BStatusBar(frame, id, label1, label2); + bar->SetBarHeight((float)frame.Height()-(be_plain_font)->Size()-5); + if(w->layout == -1) + bar->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + bar->SetResizingMode(w->layout); + myView->AddChild(bar); + bar->Draw(frame); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::StatusBarSet(const char* id, const char* label1, const char* label2, double state) +{ + YabView *myView = NULL; + BStatusBar *myBar = 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(); + myBar = cast_as(myView->FindView(id), BStatusBar); + if(myBar) + { + myBar->Reset(); + myBar->Update((float)state, label1, label2); + w->Unlock(); + return; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + } + Error(id, "STATUSBAR"); +} + +void YabInterface::StatusBarSet(BRect frame, const char* id, const char* view) +{ + // empty! +} + +void YabInterface::StatusBarSet(const char* id, int r, int g, int b) +{ + YabView *myView = NULL; + BStatusBar *myBar = 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(); + myBar = cast_as(myView->FindView(id), BStatusBar); + if(myBar) + { + rgb_color rgb = {r,g,b,255}; + myBar->SetBarColor(rgb); + w->Unlock(); + return; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + } + Error(id, "STATUSBAR"); +} + +void YabInterface::CreateMenu(const char* menuhead, const char* menuitem, const char *shortcut, const char* window) +{ + char myShortcut; + int32 modifiers = 0; + BString t(shortcut); + if(t.Length()>1) + { + myShortcut = shortcut[t.Length()-1]; + if(t.IFindFirst("s")!=B_ERROR && t.IFindFirst("s")GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BMenuBar *menubar; + YabMenu *menu = NULL; + BMenuItem *item = NULL; + w->Lock(); + menubar = cast_as(myView->FindView("menubar"), BMenuBar); + if(menubar == NULL) + { + menubar = new BMenuBar(myView->Bounds(),"menubar"); + myView->AddChild(menubar); + } + for(int i=0; iCountItems(); i++) + if(!strcmp( menubar->ItemAt(i)->Label(), menuhead)) + menu = cast_as(menubar->SubmenuAt(i), YabMenu); + if(menu == NULL) + { + menu = new YabMenu(menuhead); + menubar->AddItem((BMenu*)menu); + } + if(!strcmp(menuitem,"--")) + menu->AddItem(new BSeparatorItem()); + else + menu->AddItem(new BMenuItem(menuitem, new BMessage(YABMENU), myShortcut, modifiers)); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::CreateTextControl(BRect frame, const char* id, const char* label, const char* text, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BTextControl *textControl = new BTextControl(frame, id ,label, text, new BMessage(YABTEXTCONTROL)); + textControl->SetDivider(textControl->StringWidth(label)+5.0); + + if(w) + { + if(w->layout == -1) + textControl->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + textControl->SetResizingMode(w->layout); + } + textControl->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(textControl); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::CreateCheckBox(double x, double y, const char* id, const char* label, int isActivated, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BRect frame(x,y,x+1,y+1); + BCheckBox *checkBox = new BCheckBox(frame, id, label, new BMessage(YABCHECKBOX)); + checkBox->ResizeToPreferred(); + if(isActivated>0) checkBox->SetValue(B_CONTROL_ON); + if(w->layout == -1) + checkBox->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + checkBox->SetResizingMode(w->layout); + checkBox->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(checkBox); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::CreateRadioButton(double x, double y, const char* groupID, const char* label, int isActivated, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BRect frame(x,y,x+1,y+1); + BRadioButton *radio = new BRadioButton(frame, groupID, label, new BMessage(YABRADIOBUTTON)); + radio->ResizeToPreferred(); + if(isActivated>0) radio->SetValue(B_CONTROL_ON); + if(w->layout == -1) + radio->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + radio->SetResizingMode(w->layout); + radio->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(radio); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::CreateListBox(BRect frame, const char* title, int scrollbar, const char* window) +{ + YabView *myView = cast_as(((BView*)viewList->GetView(window)), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + uint32 resizeMode; + + w->Lock(); + + if(scrollbar == 3 || scrollbar == 1) frame.right -= B_V_SCROLL_BAR_WIDTH; + if(scrollbar>2) frame.bottom -= B_H_SCROLL_BAR_HEIGHT; + + BListView *list = new BListView(frame,title); + if(w->layout == -1) + resizeMode = B_FOLLOW_ALL; + else + resizeMode = w->layout; + list->SetResizingMode(resizeMode); + list->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + list->SetSelectionMessage(new BMessage(YABLISTBOXSELECT)); + list->SetInvocationMessage(new BMessage(YABLISTBOXINVOKE)); + switch(scrollbar) + { + case 3: // both + myView->AddChild(new BScrollView("scroll_list", list, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, true, true)); + break; + case 2: // horizontal + myView->AddChild(new BScrollView("scroll_list", list, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, true, false)); + break; + case 0: // none + myView->AddChild(list); + break; + default: // vertical is default + myView->AddChild(new BScrollView("scroll_list", list, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, false, true)); + break; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::CreateDropBox(BRect frame, const char* title, const char* label, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BPopUpMenu *dropmenu = new BPopUpMenu(""); + BMenuField *drop = new BMenuField(frame,title,label, dropmenu, true); + drop->SetDivider(drop->StringWidth(label)+5.0); + if(w->layout == -1) + drop->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + drop->SetResizingMode(w->layout); + drop->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(drop); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::CreateItem(const char* id, const char* item) +{ + YabView *myView = 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(); + BMenuField *myMenuField = cast_as(myView->FindView(id), BMenuField); + if(myMenuField) + { + BPopUpMenu *myPopup = cast_as(myMenuField->Menu(), BPopUpMenu); + if(myPopup) + { + if(!strcmp(item,"--")) + myPopup->AddItem(new BSeparatorItem()); + else + { + BMenuItem *tmp = new BMenuItem(item, new BMessage(YABDROPBOX)); + myPopup->AddItem(tmp); + if(myPopup->CountItems()==1) // first Item + tmp->SetMarked(true); + } + w->Unlock(); + return; + } + } + w->Unlock(); + } + } + } + Error(id, "DROPBOX"); +} + +void YabInterface::RemoveItem(const char* title, const char* item) +{ + YabView *myView = 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(); + BListView *myList = cast_as(myView->FindView(title), BListView); + if(myList) + { + for(int i=0; iCountItems(); i++) + { + BStringItem *stritem = cast_as(myList->ItemAt(i), BStringItem); + if(stritem && !strcmp(stritem->Text(), item)) + { + myList->RemoveItem(i); + w->Unlock(); + return; + } + } + w->Unlock(); + ErrorGen("Item not found"); + } + w->Unlock(); + } + } + } + Error(title, "DROPBOX"); +} + +void YabInterface::ClearItems(const char* title) +{ + YabView *myView = 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(); + BListView *myList = cast_as(myView->FindView(title), BListView); + if(myList) + { + myList->RemoveItems(0,myList->CountItems()); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "DROPBOX"); +} + +void YabInterface::DrawText(BPoint coordinates, const char* text, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + t->command = 0; + t->x1 = coordinates.x; t->y1 = coordinates.y; + t->chardata = strdup(text); + myView->drawList->AddItem(t); + + font_height height; + myView->GetFontHeight(&height); + BRect bbox; + bbox.left = coordinates.x; + bbox.top = coordinates.y - height.ascent; + bbox.right = coordinates.x + myView->StringWidth(text); + bbox.bottom = coordinates.y + height.descent; + + BFont tFont; + myView->GetFont(&tFont); + if(tFont.Rotation() == 0.0 && tFont.Shear() == 90.0) + myView->Invalidate(bbox); + else + myView->Invalidate(); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + bview->DrawString(text, coordinates); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + bView->DrawString(text, coordinates); + bView->Sync(); + b->Unlock(); + + font_height height; + bView->GetFontHeight(&height); + BRect bbox; + bbox.left = coordinates.x; + bbox.top = coordinates.y - height.ascent; + bbox.right = coordinates.x + bView->StringWidth(text); + bbox.bottom = coordinates.y + height.descent; + + myView->Draw(bbox); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::DrawRect(BRect frame, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + if(drawStroking) + t->command = 4; + else + t->command = 5; + t->x1 = frame.left; t->y1 = frame.top; + t->x2 = frame.right; t->y2 = frame.bottom; + t->p = yabPattern; + myView->drawList->AddItem(t); + myView->Invalidate(frame); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + if(drawStroking) + bview->StrokeRect(frame, yabPattern); + else + bview->FillRect(frame, yabPattern); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + if(drawStroking) + bView->StrokeRect(frame, yabPattern); + else + bView->FillRect(frame, yabPattern); + bView->Sync(); + b->Unlock(); + + myView->Draw(frame); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::DrawClear(const char* window, bool isExit) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + rgb_color lowcolor = myView->LowColor(); + rgb_color highcolor = myView->HighColor(); + BFont lastfont; + myView->GetFont(&lastfont); + while(myView->drawList->CountItems()>0) + { + YabDrawing *t = (YabDrawing*)myView->drawList->LastItem(); + myView->drawList->RemoveItem(t); + if(t->command == 0) delete [] t->chardata; + if(t->command == 10 || t->command == 11) delete t->bitmap; + delete t; + } + YabDrawing *t1 = new YabDrawing(); + t1->command = 7; + t1->r = lowcolor.red; t1->g = lowcolor.green; + t1->b = lowcolor.blue; t1->alpha = yabAlpha; + myView->drawList->AddItem(t1); + YabDrawing *t2 = new YabDrawing(); + t2->command = 6; + t2->r = highcolor.red; t2->g = highcolor.green; + t2->b = highcolor.blue; t2->alpha = yabAlpha; + myView->drawList->AddItem(t2); + YabDrawing *t3 = new YabDrawing(); + t3->command = 12; + t3->font = lastfont; + myView->drawList->AddItem(t3); + myView->Invalidate(); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + if(!isExit) Error(window, "VIEW"); +} + +void YabInterface::DrawDot(double x, double y, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + t->command = 1; + t->x1 = x; t->y1 = y; + t->x2 = x; t->y2 = y; + t->p = yabPattern; + myView->drawList->AddItem(t); + myView->Invalidate(BRect(x,y,x,y)); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + bview->StrokeLine(BPoint(x,y), BPoint(x,y), yabPattern); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + bView->StrokeLine(BPoint(x,y), BPoint(x,y), yabPattern); + bView->Sync(); + b->Unlock(); + + myView->Draw(BRect(x,y,x,y)); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::DrawLine(double x1, double y1, double x2, double y2, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + t->command = 1; + t->x1 = x1; t->y1 = y1; + t->x2 = x2; t->y2 = y2; + t->p = yabPattern; + myView->drawList->AddItem(t); + double minx1 = x1Invalidate(BRect(minx1,miny1,minx2,miny2)); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + bview->StrokeLine(BPoint(x1,y1), BPoint(x2,y2), yabPattern); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + bView->StrokeLine(BPoint(x1,y1), BPoint(x2,y2), yabPattern); + bView->Sync(); + b->Unlock(); + + double minx1 = x1Invalidate(BRect(minx1,miny1,minx2,miny2)); + myView->Draw(BRect(minx1,miny1,minx2,miny2)); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::DrawCircle(double x, double y, double r, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + if(drawStroking) + t->command = 2; + else + t->command = 3; + t->x1 = x; t->y1 = y; + t->x2 = r; t->y2 = r; + t->p = yabPattern; + myView->drawList->AddItem(t); + myView->Invalidate(BRect(x-r,y-r,x+r,y+r)); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + if(drawStroking) + bview->StrokeEllipse(BPoint(x,y), r, r, yabPattern); + else + bview->FillEllipse(BPoint(x,y), r, r, yabPattern); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + if(drawStroking) + bView->StrokeEllipse(BPoint(x,y), r, r, yabPattern); + else + bView->FillEllipse(BPoint(x,y), r, r, yabPattern); + bView->Sync(); + b->Unlock(); + + myView->Draw(BRect(x-r,y-r,x+r,y+r)); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::DrawEllipse(double x, double y, double r1, double r2, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + if(drawStroking) + t->command = 2; + else + t->command = 3; + t->x1 = x; t->y1 = y; + t->x2 = r1; t->y2 = r2; + t->p = yabPattern; + myView->drawList->AddItem(t); + myView->Invalidate(BRect(x-r1,y-r2,x+r1,y+r2)); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + if(drawStroking) + bview->StrokeEllipse(BPoint(x,y), r1, r2, yabPattern); + else + bview->FillEllipse(BPoint(x,y), r1, r2, yabPattern); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + if(drawStroking) + bView->StrokeEllipse(BPoint(x,y), r1, r2, yabPattern); + else + bView->FillEllipse(BPoint(x,y), r1, r2, yabPattern); + bView->Sync(); + b->Unlock(); + + myView->Draw(BRect(x-r1,y-r2,x+r1,y+r2)); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::DrawCurve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, const char* window) +{ + double invx1 = x1x2?x1:x2; invx2 = invx2>x3?invx2:x3; invx2 = invx2>x4?invx2:x4; + double invy1 = y1y2?y1:y2; invy2 = invy2>y3?invy2:y3; invy2 = invy2>y4?invy2:y4; + + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabDrawing *t = new YabDrawing(); + if(drawStroking) + t->command = 8; + else + t->command = 9; + t->x1 = x1; t->y1 = y1; + t->x2 = x2; t->y2 = y2; + t->x3 = x3; t->y3 = y3; + t->x4 = x4; t->y4 = y4; + t->p = yabPattern; + myView->drawList->AddItem(t); + myView->Invalidate(BRect(invx1,invy1,invx2,invy2)); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + BPoint p[4]; + p[0].Set(x1,y1); + p[1].Set(x2,y2); + p[2].Set(x3,y3); + p[3].Set(x4,y4); + + if(drawStroking) + { + bview->SetPenSize(1.01); + bview->StrokeBezier(p, yabPattern); + bview->SetPenSize(1.0); + } + else + bview->FillBezier(p, yabPattern); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + BPoint p[4]; + p[0].Set(x1,y1); + p[1].Set(x2,y2); + p[2].Set(x3,y3); + p[3].Set(x4,y4); + + if(drawStroking) + { + bView->SetPenSize(1.01); + bView->StrokeBezier(p, yabPattern); + bView->SetPenSize(1.0); + } + else + bView->FillBezier(p, yabPattern); + bView->Sync(); + b->Unlock(); + + myView->Draw(BRect(invx1,invy1,invx2,invy2)); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::CreateText(double x, double y, const char* id, const char* text, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + double h,b; + b = be_plain_font->StringWidth(text)+1; + h = be_plain_font->Size(); + BStringView *s = new BStringView(BRect(x,y-3,x+b,y+h-3), id, text); + s->ResizeToPreferred(); + if(w->layout == -1) + s->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + s->SetResizingMode(w->layout); + s->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE); + myView->AddChild(s); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::Text2(BRect frame, const char* id, const char* text, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BStringView *s = new BStringView(frame, id, text); + if(w->layout == -1) + s->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + s->SetResizingMode(w->layout); + s->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE); + myView->AddChild(s); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::TextAlign(const char* txt, const char* option) +{ + BString tmp(option); + alignment align; + if(tmp.IFindFirst("align-left")!=B_ERROR) + align = B_ALIGN_LEFT; + else if(tmp.IFindFirst("align-center")!=B_ERROR) + align = B_ALIGN_CENTER; + else if(tmp.IFindFirst("align-right")!=B_ERROR) + align = B_ALIGN_RIGHT; + else + ErrorGen("Unknown option"); + + YabView *myView = NULL; + BStringView *myStringView = 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(); + myStringView = cast_as(myView->FindView(txt), BStringView); + if(myStringView) + { + myStringView->SetAlignment(align); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(txt, "TEXT"); +} + +void YabInterface::Slider(BRect frame, const char* id, const char* title, int min, int max, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BSlider *mySlider = new BSlider(frame, id, title, new BMessage(YABSLIDER), min, max); + if(w->layout == -1) + mySlider->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + mySlider->SetResizingMode(w->layout); + mySlider->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(mySlider); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::Slider(BRect frame, const char* id, const char* title, int min, int max, const char* option, const char* view) +{ + BString tmp(option); + bool thumb = true, orient = true; + if(tmp.IFindFirst("vertical")!=B_ERROR) + orient = false; + if(tmp.IFindFirst("triangle")!=B_ERROR) + thumb = false; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BSlider *mySlider = new BSlider(frame, id, title, new BMessage(YABSLIDER), min, max); + if(w->layout == -1) + mySlider->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + mySlider->SetResizingMode(w->layout); + mySlider->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + if(!orient) + { + mySlider->SetOrientation(B_VERTICAL); + mySlider->SetBarThickness(10); + } + if(!thumb) mySlider->SetStyle(B_TRIANGLE_THUMB); + myView->AddChild(mySlider); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::SetSlider(const char* id, const char* label1, const char* label2) +{ + YabView *myView = NULL; + BSlider *mySlider = 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(); + mySlider = cast_as(myView->FindView(id), BSlider); + if(mySlider) + { + mySlider->SetLimitLabels(label1, label2); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "SLIDER"); +} + +void YabInterface::SetSlider(const char* id, const char* bottomtop, int count) +{ + hash_mark_location location = B_HASH_MARKS_BOTH; + BString tmp(bottomtop); + if(tmp.IFindFirst("none")!=B_ERROR) + location = B_HASH_MARKS_NONE; + if(tmp.IFindFirst("left")!=B_ERROR) + location = B_HASH_MARKS_LEFT; + if(tmp.IFindFirst("right")!=B_ERROR) + location = B_HASH_MARKS_RIGHT; + if(tmp.IFindFirst("top")!=B_ERROR) + location = B_HASH_MARKS_TOP; + if(tmp.IFindFirst("bottom")!=B_ERROR) + location = B_HASH_MARKS_BOTTOM; + YabView *myView = NULL; + BSlider *mySlider = 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(); + mySlider = cast_as(myView->FindView(id), BSlider); + if(mySlider) + { + mySlider->SetHashMarks(location); + mySlider->SetHashMarkCount(count); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "SLIDER"); +} + +void YabInterface::SetSlider(const char* id, const char* part, int r, int g, int b) +{ + bool barcolor = true; + BString tmp(part); + if(tmp.IFindFirst("fillcolor")) + barcolor = false; + + YabView *myView = NULL; + BSlider *mySlider = 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(); + mySlider = cast_as(myView->FindView(id), BSlider); + if(mySlider) + { + rgb_color rgb = {r,g,b,255}; + if(barcolor) + mySlider->SetBarColor(rgb); + else + mySlider->UseFillColor(true,&rgb); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "SLIDER"); +} + +void YabInterface::SetSlider(const char* id, int value) +{ + YabView *myView = NULL; + BSlider *mySlider = 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(); + mySlider = cast_as(myView->FindView(id), BSlider); + if(mySlider) + { + mySlider->SetValue(value); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "SLIDER"); +} + +void YabInterface::SetOption(const char* id, const char* option, const char* value) +{ + bool label = false; + BString tmpOption(option); + if(tmpOption.IFindFirst("label")!=B_ERROR) + label = true; + + if(!label) + ErrorGen("Unknown option"); + + YabView *myView = 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(); + BControl *target = cast_as(myView->FindView(id), BControl); + if(target) + { + target->SetLabel(value); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "CONTROL"); +} + +void YabInterface::SetOption(const char* id, const char* option, int r, int g, int b) +{ + YabView *myView = 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(); + BView *target = myView->FindView(id); + if(target) + { + rgb_color rgb = {r,g,b,0}; + target->SetViewColor(rgb); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "VIEW"); +} + +void YabInterface::SetOption(const char* id, const char* option) +{ + BString tmpOption(option); + if(tmpOption.IFindFirst("auto-resize")==B_ERROR) + ErrorGen("Unknown option"); + + YabView *myView = 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(); + BView *target = myView->FindView(id); + if(target) + { + target->ResizeToPreferred(); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + ErrorGen("View not found"); +} + +void YabInterface::SetOption(const char* id, const char* option, int value) +{ + BString tmpOption(option); + bool isFocus = false; + bool isEnabled = false; + bool isVisible = false; + + if(tmpOption.IFindFirst("enabled")!=B_ERROR) + isEnabled = true; + if(tmpOption.IFindFirst("focus")!=B_ERROR) + isFocus = true; + if(tmpOption.IFindFirst("visible")!=B_ERROR) + isVisible = true; + + if(!isFocus && !isEnabled && !isVisible) + ErrorGen("Unknown option"); + + YabView *myView = 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(); + BView *target = myView->FindView(id); + if(target) + { + if(isEnabled) + { + BControl *myControl = cast_as(target, BControl); + if(myControl) + myControl->SetEnabled(value); + else + { + BMenuField *myMenu = cast_as(target, BMenuField); + if(myMenu) + myMenu->SetEnabled(value); + else + Error(id, "CONTROL or DROPBOX"); + } + } + if(isFocus) + { + target->MakeFocus(value); + } + if(isVisible) + { + BControl *myControl = cast_as(target, BControl); + if(myControl) + { + if(value) + { + if (myControl->IsHidden()) + { + myControl->Show(); + } + } + else + { + if (!myControl->IsHidden()) + { + myControl->Hide(); + } + } + + } + + } + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + ErrorGen("View not found"); +} + +void YabInterface::DropZone(const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + myView->dropZone = true; + else + Error(view, "VIEW"); +} + +void YabInterface::ColorControl(double x, double y, const char* id, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BColorControl *myCControl = new BColorControl(BPoint(x,y), B_CELLS_32x8, 2, id, new BMessage(YABCOLORCONTROL),false); + if(w->layout == -1) + myCControl->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + myCControl->SetResizingMode(w->layout); + myCControl->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(myCControl); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::ColorControl(const char* id, int r, int g, int b) +{ + YabView *myView = NULL; + BColorControl *myCControl = 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(); + myCControl = cast_as(myView->FindView(id), BColorControl); + if(myCControl) + { + rgb_color t = {r,g,b,255}; + myCControl->SetValue(t); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "COLORCONTROL"); +} + +void YabInterface::TextControl(const char* id, const char* text) +{ + YabView *myView = NULL; + BTextControl *myTControl = 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(); + myTControl = cast_as(myView->FindView(id), BTextControl); + if(myTControl) + { + myTControl->SetText(text); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TEXTCONTROL"); +} + +void YabInterface::TextControl(const char* id, int mode) +{ + YabView *myView = NULL; + BTextControl *myTControl = 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(); + myTControl = cast_as(myView->FindView(id), BTextControl); + if(myTControl) + { + BTextView *myTView = myTControl->TextView(); + + switch(mode) + { + case 1: + myTView->HideTyping(true); + break; + + default: + myTView->HideTyping(false); + + break; + } + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TEXTCONTROL"); +} + +void YabInterface::TextControl(const char* id, const char* option, const char* value) +{ + YabView *myView = NULL; + BString tmpOption(option); + BString tmpValue(value); + BTextControl *myTControl = 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(); + int32 x=0; + myTControl = cast_as(myView->FindView(id), BTextControl); + if(myTControl) + { + + BTextView *myTView = myTControl->TextView(); + if(tmpOption.IFindFirst("focus")!=B_ERROR) + { + if(tmpValue.IFindFirst("true")!=B_ERROR) + { + bool focused = true; + int32 ofset=0; + myTControl -> MakeFocus(focused); + myTView-> Select(ofset,ofset); + } + if(tmpValue.IFindFirst("false")!=B_ERROR) + { + bool focused = false; + myTControl -> MakeFocus(focused); + } + } + if(tmpOption.IFindFirst("Curser")!=B_ERROR) + { + const char* str_int = tmpValue.String(); + bool focused = true; + int32 ofset=0; + ofset= atoi(str_int); + myTControl -> MakeFocus(focused); + myTView-> Select(ofset,ofset); + } + if(tmpOption.IFindFirst("type")!=B_ERROR) + { + if(tmpValue.IFindFirst("number")!=B_ERROR) + { + for (x=0;x<48; x++) + { + myTView->DisallowChar(x); + } + for (x=58;x<128; x++) + { + myTView->DisallowChar(x); + } + x=46; + myTView-> AllowChar(x); + } + if(tmpValue.IFindFirst("alphanumeric")!=B_ERROR) + { + for (x=0;x<128; x++) + { + myTView->AllowChar(x); + } + + } + + } + if(tmpOption.IFindFirst("align")!=B_ERROR) + { + if(tmpValue.IFindFirst("right")!=B_ERROR) + { + myTControl->SetAlignment(B_ALIGN_LEFT,B_ALIGN_RIGHT); + } + if(tmpValue.IFindFirst("center")!=B_ERROR) + { + myTControl->SetAlignment(B_ALIGN_LEFT,B_ALIGN_CENTER); + } + if(tmpValue.IFindFirst("left")!=B_ERROR) + { + myTControl->SetAlignment(B_ALIGN_LEFT,B_ALIGN_LEFT); + } + } + if(tmpOption.IFindFirst("length")!=B_ERROR) + { + const char* str_int = tmpValue.String(); + int i = atoi(str_int); + if (i>0) + { + myTView->SetMaxBytes(i); + myTView->SetFontAndColor(be_fixed_font); + } + if (i=0) + { + ErrorGen("Bad length"); + } + } + if(tmpOption.IFindFirst("exclude")!=B_ERROR) + { + int i; + for (i=0; i<= tmpValue.CountChars();i++) + { + x=tmpValue.ByteAt(i); + myTView->DisallowChar(x); + } + } + if(tmpOption.IFindFirst("include")!=B_ERROR) + { + int i; + for (i=0; i<= tmpValue.CountChars();i++) + { + x=tmpValue.ByteAt(i); + myTView->AllowChar(x); + } + } + } + w->Unlock(); + return; + } + w->Unlock(); + } + } +Error(id, "TEXTCONTROL"); +} + +void YabInterface::TextControl(const char* id) +{ + YabView *myView = NULL; + BTextControl *myTControl = 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(); + myTControl = cast_as(myView->FindView(id), BTextControl); + if(myTControl) + { + myTControl->SetText(""); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TEXTCONTROL"); +} + + +void YabInterface::CreateAlert(const char* text, const char* button1, const char* option) +{ + alert_type tmp; + BString typ(option); + tmp = B_EMPTY_ALERT; + if(typ.IFindFirst("info")!=B_ERROR) tmp = B_INFO_ALERT; + else if(typ.IFindFirst("idea")!=B_ERROR) tmp = B_IDEA_ALERT; + else if(typ.IFindFirst("warning")!=B_ERROR) tmp = B_WARNING_ALERT; + else if(typ.IFindFirst("stop")!=B_ERROR) tmp = B_STOP_ALERT; + + (new BAlert("Alert!",text,button1,NULL,NULL,B_WIDTH_AS_USUAL,tmp))->Go(); +} + +const char* YabInterface::LoadFilePanel(const char *mode, const char* title, const char* directory) +{ + int myMode = -1; + BString opt(mode); + if(opt.IFindFirst("Load-File")!=B_ERROR) + myMode = 0; + if(opt.IFindFirst("Save-File")!=B_ERROR) + myMode = 1; + if(opt.IFindFirst("Load-Directory")!=B_ERROR) + myMode = 2; + if(opt.IFindFirst("Load-File-and-Directory")!=B_ERROR) + myMode = 3; + if(myMode == -1) ErrorGen("Invalid Option"); + + YabFilePanel tmp; + BPath path; + BString myTitle(title); + BEntry *entry = tmp.MyFilePanel(myTitle.String(),directory, "", myMode); + entry->GetPath(&path); + if(myMode != 1 && !entry->Exists()) + loadPanel[0] = '\0'; + else + { + if(path.InitCheck() == B_OK) + strcpy(loadPanel,path.Path()); + else + loadPanel[0] = '\0'; + } + + delete entry; + + return (const char*)loadPanel; +} + +const char* YabInterface::SaveFilePanel(const char *mode, const char* title, const char* directory, const char* filename) +{ + int myMode = -1; + BString opt(mode); + if(opt.IFindFirst("Load-File")!=B_ERROR) + myMode = 0; + if(opt.IFindFirst("Save-File")!=B_ERROR) + myMode = 1; + if(opt.IFindFirst("Load-Directory")!=B_ERROR) + myMode = 2; + if(opt.IFindFirst("Load-File-and-Directory")!=B_ERROR) + myMode = 3; + if(myMode == -1) ErrorGen("Invalid Option"); + + YabFilePanel tmp; + BPath path; + BString myTitle(title); + BEntry *entry = tmp.MyFilePanel(myTitle.String(),directory, filename, myMode); + entry->GetPath(&path); + if(myMode != 1 && !entry->Exists()) + loadPanel[0] = '\0'; + else + { + if(path.InitCheck() == B_OK) + strcpy(loadPanel,path.Path()); + else + loadPanel[0] = '\0'; + } + delete entry; + + return (const char*)loadPanel; +} + +void YabInterface::SetLayout(const char* layout, const char* window) +{ + BString tmp(layout); + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + if(tmp.IFindFirst("standard")!=B_ERROR) + w->layout = -1; + else if(tmp.IFindFirst("all")!=B_ERROR) + w->layout = B_FOLLOW_ALL; + else if(tmp.IFindFirst("none")!=B_ERROR) + w->layout = B_FOLLOW_NONE; + else + { + uint32 horizontal, vertical; + if(tmp.IFindFirst("h-center")!=B_ERROR) + horizontal = B_FOLLOW_H_CENTER; + else if((tmp.IFindFirst("left")!=B_ERROR)&&(tmp.IFindFirst("right")!=B_ERROR)) + horizontal = B_FOLLOW_LEFT_RIGHT; + else if(tmp.IFindFirst("right")!=B_ERROR) + horizontal = B_FOLLOW_RIGHT; + else + horizontal = B_FOLLOW_LEFT; + + if(tmp.IFindFirst("v-center")!=B_ERROR) + vertical = B_FOLLOW_V_CENTER; + else if((tmp.IFindFirst("top")!=B_ERROR)&&(tmp.IFindFirst("bottom")!=B_ERROR)) + vertical = B_FOLLOW_TOP_BOTTOM; + else if(tmp.IFindFirst("bottom")!=B_ERROR) + vertical = B_FOLLOW_BOTTOM; + else + vertical = B_FOLLOW_TOP; + w->layout = horizontal|vertical; + } + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::WindowSet(const char* option, const char* value, const char* window) +{ + BString tmp(option); + BString val(value); + uint32 flags = 0; + + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + if(tmp.IFindFirst("Flags")!=B_ERROR) + { + if(val.IFindFirst("Reset")!=B_ERROR) + { + w->SetFlags(0); + w->SetFlags(B_ASYNCHRONOUS_CONTROLS); + } + else + { + flags = w->Flags(); + if(val.IFindFirst("Not-Movable")!=B_ERROR) + flags = flags|B_NOT_MOVABLE; + if(val.IFindFirst("Not-Closable")!=B_ERROR) + flags = flags|B_NOT_CLOSABLE; + if(val.IFindFirst("Not-Zoomable")!=B_ERROR) + flags = flags|B_NOT_ZOOMABLE; + if(val.IFindFirst("Not-Minimizable")!=B_ERROR) + flags = flags|B_NOT_MINIMIZABLE; + if(val.IFindFirst("Not-Resizable")!=B_ERROR) + flags = flags|B_NOT_RESIZABLE; + if(val.IFindFirst("Not-H-Resizable")!=B_ERROR) + flags = flags|B_NOT_H_RESIZABLE; + if(val.IFindFirst("Not-V-Resizable")!=B_ERROR) + flags = flags|B_NOT_V_RESIZABLE; + if(val.IFindFirst("Accept-First-Click")!=B_ERROR) + flags = flags|B_WILL_ACCEPT_FIRST_CLICK; + if(val.IFindFirst("No-Workspace-Activation")!=B_ERROR) + flags = flags|B_NO_WORKSPACE_ACTIVATION; + w->SetFlags(flags|B_ASYNCHRONOUS_CONTROLS); + } + } + else if(tmp.IFindFirst("Look")!=B_ERROR) + { + if(val.IFindFirst("Document")!=B_ERROR) + w->SetLook(B_DOCUMENT_WINDOW_LOOK); + else if(val.IFindFirst("Titled")!=B_ERROR) + w->SetLook(B_TITLED_WINDOW_LOOK); + else if(val.IFindFirst("Floating")!=B_ERROR) + w->SetLook(B_FLOATING_WINDOW_LOOK); + else if(val.IFindFirst("Modal")!=B_ERROR) + w->SetLook(B_MODAL_WINDOW_LOOK); + else if(val.IFindFirst("Bordered")!=B_ERROR) + w->SetLook(B_BORDERED_WINDOW_LOOK); + else if(val.IFindFirst("No-Border")!=B_ERROR) + w->SetLook(B_NO_BORDER_WINDOW_LOOK); + else + ErrorGen("Unknown option"); + } + else if(tmp.IFindFirst("Feel")!=B_ERROR) + { + if(val.IFindFirst("Normal")!=B_ERROR) + w->SetFeel(B_NORMAL_WINDOW_FEEL); + else if(val.IFindFirst("Modal-App")!=B_ERROR) + w->SetFeel(B_MODAL_APP_WINDOW_FEEL); + else if(val.IFindFirst("Modal-All")!=B_ERROR) + w->SetFeel(B_MODAL_ALL_WINDOW_FEEL); + else if(val.IFindFirst("Floating-App")!=B_ERROR) + w->SetFeel(B_FLOATING_APP_WINDOW_FEEL); + else if(val.IFindFirst("Floating-All")!=B_ERROR) + w->SetFeel(B_FLOATING_ALL_WINDOW_FEEL); + else + ErrorGen("Unknown option"); + } + else if(tmp.IFindFirst("Workspace")!=B_ERROR) + { + if(val.IFindFirst("Current")!=B_ERROR) + w->SetWorkspaces(B_CURRENT_WORKSPACE); + else if(val.IFindFirst("All")!=B_ERROR) + w->SetWorkspaces(B_ALL_WORKSPACES); + else if(atoi(val.String()) >= 1) + { + int bit = 1 << atoi(val.String()) - 1; + w->SetWorkspaces(bit); + } + else + ErrorGen("Unknown option"); + } + else if(tmp.IFindFirst("Title")!=B_ERROR) + { + w->SetTitle(value); + } + else + ErrorGen("Unknown option"); + // w->UpdateIfNeeded(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::WindowSet(const char* option, const char* window) +{ + BString tmp(option); + uint32 flags = 0; + + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + if(tmp.IFindFirst("maximize")!=B_ERROR) + w->Zoom(); + else if(tmp.IFindFirst("minimize")!=B_ERROR) + w->Minimize(!w->IsMinimized()); + else if(tmp.IFindFirst("deactivate")!=B_ERROR) + w->Activate(false); + else if(tmp.IFindFirst("activate")!=B_ERROR) + w->Activate(true); + else if(tmp.IFindFirst("disable-updates")!=B_ERROR) + w->DisableUpdates(); + else if(tmp.IFindFirst("enable-updates")!=B_ERROR) + w->EnableUpdates(); + else + ErrorGen("Unknown option"); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::WindowSet(const char* option, int r, int g, int b, const char* window) +{ + BString tmp(option); + if(r>255) r=255; if(r<0) r=0; + if(g>255) g=255; if(g<0) g=0; + if(b>255) b=255; if(b<0) b=0; + + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + if(tmp.IFindFirst("BGColor")!=B_ERROR) + { + myView->SetViewColor(r,g,b,yabAlpha); + myView->Invalidate(); + } + else if(tmp.IFindFirst("HighColor")!=B_ERROR) + { + if(yabAlpha == 255) + myView->SetDrawingMode(B_OP_COPY); + else + myView->SetDrawingMode(B_OP_ALPHA); + myView->SetHighColor(r,g,b,yabAlpha); + YabDrawing *t = new YabDrawing(); + t->command = 6; + t->r = r; t->g = g; + t->b = b; t->alpha = yabAlpha; + myView->drawList->AddItem(t); + } + else if(tmp.IFindFirst("LowColor")!=B_ERROR) + { + if(yabAlpha == 255) + myView->SetDrawingMode(B_OP_COPY); + else + myView->SetDrawingMode(B_OP_ALPHA); + myView->SetLowColor(r,g,b,yabAlpha); + YabDrawing *t = new YabDrawing(); + t->command = 7; + t->r = r; t->g = g; + t->b = b; t->alpha = yabAlpha; + myView->drawList->AddItem(t); + } + else + ErrorGen("Unknown option"); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *bmp = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bView = bmp->FindView(window); + if(bView) + { + if(tmp.IFindFirst("HighColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetHighColor(r,g,b,yabAlpha); + bView->Sync(); + bmp->Unlock(); + return; + } + else if(tmp.IFindFirst("LowColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetLowColor(r,g,b,yabAlpha); + bView->Sync(); + bmp->Unlock(); + return; + } + else + ErrorGen("Unknown option"); + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *bmp = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + if(tmp.IFindFirst("HighColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetHighColor(r,g,b,yabAlpha); + bView->Sync(); + bmp->Unlock(); + w->Unlock(); + return; + } + else if(tmp.IFindFirst("LowColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetLowColor(r,g,b,yabAlpha); + bView->Sync(); + bmp->Unlock(); + w->Unlock(); + return; + } + else + ErrorGen("Unknown option"); + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::WindowSet(const char* option, double x, double y, const char* window) +{ + BString tmp(option); + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + if(tmp.IFindFirst("ResizeTo")!=B_ERROR) + w->ResizeTo(x,y); + else if(tmp.IFindFirst("MoveTo")!=B_ERROR) + w->MoveTo(x,y); + else if(tmp.IFindFirst("MinimumTo")!=B_ERROR) + { + float x1, x2, y1, y2; + w->GetSizeLimits(&x1,&x2,&y1,&y2); + w->SetSizeLimits((float)x,x2,(float)y,y2); + } + else if(tmp.IFindFirst("MaximumTo")!=B_ERROR) + { + float x1, x2, y1, y2; + w->GetSizeLimits(&x1,&x2,&y1,&y2); + w->SetSizeLimits(x1,(float)x,y1,(float)y); + } + else + ErrorGen("Unknown option"); + w->Unlock(); + // w->UpdateIfNeeded(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::WindowClear(const char* window) +{ + bool delMenuBar; + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w && myView->Parent()) + { + w->Lock(); + BView *child, *oldchild; + if(child = myView->ChildAt(0)) + { + while(child) + { + if(is_kind_of(child, YabTabView)) + { + for(int i = 0; i<((YabTabView*)child)->CountTabs(); i++) + { + YabView *t = (YabView*)((YabTabView*)child)->TabAt(i); + RemoveView(t); + viewList->DelView(t->Name()); + } + } + if(is_kind_of(child, YabBitmapView)) + yabcanvas->RemoveItem(child); + BView *subchild; + if(subchild = child->ChildAt(0)) + while(subchild) + { + if(is_kind_of(subchild, YabTabView)) + { + for(int i = 0; i<((YabTabView*)subchild)->CountTabs(); i++) + { + YabView *t = (YabView*)((YabTabView*)subchild)->TabAt(i); + RemoveView(t); + viewList->DelView(t->Name()); + } + } + if(viewList->GetView(subchild->Name())) + { + RemoveView(subchild); + viewList->DelView(subchild->Name()); + } + subchild = subchild->NextSibling(); + } + if(viewList->GetView(child->Name())) + { + RemoveView(child); + viewList->DelView(child->Name()); + } + + + oldchild = child; + child = child->NextSibling(); + + if(is_kind_of(oldchild, YabView)) + DrawClear(oldchild->Name(), true); + if(is_kind_of(oldchild, BMenuBar)) + { + oldchild->Hide(); + } + oldchild->RemoveSelf(); + delete oldchild; + } + } + if(is_kind_of(myView, YabView)) + DrawClear(myView->Name(), true); + if(is_kind_of(myView, BMenuBar)) + myView->Hide(); + BBox *box = cast_as(myView->Parent(), BBox); + myView->RemoveSelf(); + delete myView; + viewList->DelView(window); + if(box) + { + box->RemoveSelf(); + delete box; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::RemoveView(BView *myView) +{ + BView *child, *oldchild; + if(child = myView->ChildAt(0)) + while(child) + { + + if(is_kind_of(child, YabTabView)) + { + for(int i = 0; i<((YabTabView*)child)->CountTabs(); i++) + { + YabView *t = (YabView*)((YabTabView*)child)->TabAt(i); + RemoveView(t); + viewList->DelView(t->Name()); + } + } + if(is_kind_of(child, YabBitmapView)) + yabcanvas->RemoveItem(child); + BView *subchild; + if(subchild = child->ChildAt(0)) + while(subchild) + { + if(is_kind_of(subchild, YabTabView)) + { + for(int i = 0; i<((YabTabView*)subchild)->CountTabs(); i++) + { + YabView *t = (YabView*)((YabTabView*)subchild)->TabAt(i); + RemoveView(t); + viewList->DelView(t->Name()); + } + } + if(viewList->GetView(subchild->Name())) + { + RemoveView(subchild); + viewList->DelView(subchild->Name()); + } + subchild = subchild->NextSibling(); + } + if(viewList->GetView(child->Name())) + { + RemoveView(child); + viewList->DelView(child->Name()); + } + oldchild = child; + child = child->NextSibling(); + + if(is_kind_of(oldchild, YabView)) + DrawClear(oldchild->Name(), true); + if(is_kind_of(oldchild, BMenuBar)) + oldchild->Hide(); + if(is_kind_of(oldchild, BMenuBar)) + { + BMenuBar *b = cast_as(oldchild, BMenuBar); + for(int i=0; iCountItems(); i++) + { + YabMenu *m = (YabMenu*)b->SubmenuAt(i); + if(m) + { + // check for subsubmenus + for(int j=0; jCountItems(); j++) + { + YabMenu *n = (YabMenu*)m->SubmenuAt(j); + if(n) n->MyHide(); + } + m->MyHide(); + // printf("hiden\n"); + } + } + b->Hide(); + } + oldchild->RemoveSelf(); + delete oldchild; + } +} + +void YabInterface::TextEdit(BRect frame, const char* title, int scrollbar, const char* window) +{ + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + uint32 resizeMode; + BRect textframe; + + w->Lock(); + + if(scrollbar == 3 || scrollbar == 1) frame.right -= B_V_SCROLL_BAR_WIDTH; + if(scrollbar>2) frame.bottom -= B_H_SCROLL_BAR_HEIGHT; + + textframe = frame; + textframe.OffsetTo(B_ORIGIN); + + if(w->layout == -1) + resizeMode = B_FOLLOW_ALL; + else + resizeMode = w->layout; + + // BTextView *txtView = new BTextView(frame, title, textframe, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_PULSE_NEEDED|B_NAVIGABLE); + YabText *txtView = new YabText(frame, title, textframe, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_PULSE_NEEDED|B_NAVIGABLE); + txtView->SetWordWrap(true); + // txtView->SetFontAndColor(be_fixed_font); + + switch(scrollbar) + { + case 3: // both + myView->AddChild(new BScrollView("scroll_list", txtView, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, true, true)); + break; + case 2: // horizontal + myView->AddChild(new BScrollView("scroll_list", txtView, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, true, false)); + break; + case 0: // none + myView->AddChild(txtView); + break; + default: // vertical is default + myView->AddChild(new BScrollView("scroll_list", txtView, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, false, true)); + break; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(window, "VIEW"); +} + +void YabInterface::TextAdd(const char* title, const char* text) +{ + YabView *myView = NULL; + YabText *myText = 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + myText->Insert(text); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +void YabInterface::TextSet(const char* title, const char* option) +{ + BString tmp(option); + YabView *myView = NULL; + YabText *myText = 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("Cut")!=B_ERROR) + myText->Cut(be_clipboard); + else if(tmp.IFindFirst("Copy")!=B_ERROR) + { + int32 a,b; + myText->GetSelection(&a, &b); + if(a != b) + myText->Copy(be_clipboard); + } + else if(tmp.IFindFirst("Paste")!=B_ERROR) + myText->Paste(be_clipboard); + else if(tmp.IFindFirst("Clear")!=B_ERROR) + myText->Clear(); + else if(tmp.IFindFirst("Select-All")!=B_ERROR) + myText->SelectAll(); + else if(tmp.IFindFirst("Undo")!=B_ERROR) + myText->Undo(be_clipboard); + // else if(tmp.IFindFirst("Redo")!=B_ERROR) + // ; // myText->Redo(be_clipboard); + else + ErrorGen("Unknown option"); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +void YabInterface::TextSet(const char* title, const char* option, const char* value) +{ + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + BString tmp2(value); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("align")!=B_ERROR) + { + if(tmp2.IFindFirst("left")!=B_ERROR) + myText->SetAlignment(B_ALIGN_LEFT); + else if(tmp2.IFindFirst("center")!=B_ERROR) + myText->SetAlignment(B_ALIGN_CENTER); + else if(tmp2.IFindFirst("right")!=B_ERROR) + myText->SetAlignment(B_ALIGN_RIGHT); + } + else if(tmp.IFindFirst("autocomplete")!=B_ERROR) + myText->AddWord(new BString(value)); + else if(tmp.IFindFirst("font")!=B_ERROR) + { + BFont myFont; + BString opt; + + // Font family + int pos1 = 0; + int pos2 = tmp2.FindFirst(','); + if(pos2 != B_ERROR) + { + tmp2.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + font_family fam; + sprintf((char*)fam, "%s" , opt.String()); + if(myFont.SetFamilyAndFace(fam, B_REGULAR_FACE) == B_OK) + { + myView->SetFont(&myFont, B_FONT_FAMILY_AND_STYLE); + // Font style + pos1 = pos2+1; + pos2 = tmp2.FindFirst(',', pos2+1); + if(pos2 != B_ERROR) + { + tmp2.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + font_style style; + sprintf((char*)style, "%s" , opt.String()); + if(myFont.SetFamilyAndStyle(fam,style) == B_OK) + { + // Font size + pos1 = pos2+1; + pos2 = tmp2.FindFirst(',', pos2+1); + if(pos2 == B_ERROR) pos2 = tmp2.Length(); + tmp2.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + double size = atof(opt.String()); + myFont.SetSize(size); + } + } + } + } + else if(tmp2.IFindFirst("system-plain")!=B_ERROR) + myFont = be_plain_font; + else if(tmp2.IFindFirst("system-fixed")!=B_ERROR) + myFont = be_fixed_font; + else if(tmp2.IFindFirst("system-bold")!=B_ERROR) + myFont = be_bold_font; + + else + ErrorGen("Unknown option"); + int32 start,finish; + myText->GetSelection(&start, &finish); + myText->SelectAll(); + myText->SetFontAndColor(&myFont); + myText->Select(start,finish); + } + else if (tmp.IFindFirst("focus")!=B_ERROR) + { + if (tmp2.IFindFirst("true")!=B_ERROR) + { + bool focused = true; + myText->MakeFocus(focused); + } + else + { + bool focused = false; + myText->MakeFocus(focused); + } + } + else + + ErrorGen("Unknown option"); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +void YabInterface::TextSet(const char* title, const char* option, int value) +{ + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("autocomplete-start")!=B_ERROR) + myText->SetAutoCompleteStart(value-1); + else if(tmp.IFindFirst("has-autocompletion")!=B_ERROR) + myText->HasAutoCompletion((bool)value); + else if(tmp.IFindFirst("autoindent")!=B_ERROR) + myText->SetAutoindent((bool)value); + else if(tmp.IFindFirst("wordwrap")!=B_ERROR) + myText->SetWordWrap((bool)value); + else if(tmp.IFindFirst("editable")!=B_ERROR) + myText->MakeEditable((bool)value); + else if(tmp.IFindFirst("color-case-sensitive")!=B_ERROR) + myText->SetCaseSensitive((bool)value); + else if(tmp.IFindFirst("tabwidth")!=B_ERROR) + myText->SetTabWidth(value); + else if(tmp.IFindFirst("textwidth")!=B_ERROR) + { + // BRect txtframe = myText->TextRect(); + // txtframe.right = txtframe.left + value; + // myText->SetTextRect(txtframe); + myText->SetTextRect(BRect(0,0, value,1)); + // BRect txtbounds = myText->Bounds(); + // myText->FrameResized(txtbounds.Width(), txtbounds.Height()); + BRect bounds(myText->Bounds()); + BScrollBar* horizontalScrollBar = myText->ScrollBar(B_HORIZONTAL); + + // do we have a horizontal scroll bar? + if (horizontalScrollBar != NULL) { + long viewWidth = bounds.IntegerWidth(); + long dataWidth = (long)value; + + long maxRange = dataWidth - viewWidth; + maxRange = max_c(maxRange, 0); + + horizontalScrollBar->SetRange(0, 1000); //(float)maxRange); + // horizontalScrollBar->SetProportion((float)viewWidth / (float)dataWidth); + // horizontalScrollBar->SetSteps(10.0, dataWidth / 10); + // std::cout << "dataWidth: " << dataWidth << " maxrange: " << maxRange << std::endl; + } + + } + else if(tmp.IFindFirst("gotoline")!=B_ERROR) + { + if(value<1) value = 1; + myText->GoToLine(value-1); + myText->ScrollToSelection(); + } + else if(tmp.IFindFirst("select")!=B_ERROR) + { + int start, num; + if(value <= 0) + myText->Select(0,0); + else + { + if(value-1 == 0) + start = 0; + else + start = myText->OffsetAt(value-1); + if(myText->CountLines()>value) + num = myText->OffsetAt(value)-start-1; + else + num = myText->OffsetAt(value)-start; + // num = myText->TextLength()-start; + myText->Select(start,start+num); + myText->ScrollToSelection(); + } + } + else if(tmp.IFindFirst("changed")!=B_ERROR) + myText->SetChanged((bool)value); + else + ErrorGen("Unknown option"); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +void YabInterface::TextColor(const char* title, const char* option, const char* command) +{ + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("Color1")!=B_ERROR) + myText->AddCommand(command,0); + else if(tmp.IFindFirst("Color2")!=B_ERROR) + myText->AddCommand(command,1); + else if(tmp.IFindFirst("Color3")!=B_ERROR) + myText->AddCommand(command,2); + else if(tmp.IFindFirst("Color4")!=B_ERROR) + myText->AddCommand(command,3); + else if(tmp.IFindFirst("char-color")!=B_ERROR) + myText->AddCommand(command,4); + else + ErrorGen("Unknown option"); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +void YabInterface::TextColor(const char* title, const char* option, int r, int g, int b) +{ + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("color1")!=B_ERROR) + myText->SetColors(0,r,g,b); + else if(tmp.IFindFirst("color2")!=B_ERROR) + myText->SetColors(1,r,g,b); + else if(tmp.IFindFirst("color3")!=B_ERROR) + myText->SetColors(2,r,g,b); + else if(tmp.IFindFirst("color4")!=B_ERROR) + myText->SetColors(3,r,g,b); + else if(tmp.IFindFirst("char-color")!=B_ERROR) + myText->SetColors(4,r,g,b); + else if(tmp.IFindFirst("bgcolor")!=B_ERROR) + myText->SetColors(5,r,g,b); + else if(tmp.IFindFirst("textcolor")!=B_ERROR) + myText->SetColors(6,r,g,b); + else + ErrorGen("Unknown option"); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +int YabInterface::TextGet(const char* title, const char* option, const char* option2) +{ + int ret = -1; + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("case-sensitive-find")!=B_ERROR) + { + int32 startOffset, endOffset; + myText->GetSelection(&startOffset, &endOffset); + bool isFinished = false; + int foundOffset, l = myText->TextLength() - endOffset; + char* s; + s = new char[l+1]; + myText->GetText(endOffset, l, s); + BString line(s); + foundOffset = line.FindFirst(option2); + if(foundOffset == B_ERROR) + { + delete s; + s = new char[endOffset]; + myText->GetText(0, endOffset-1, s); + line = s; + foundOffset = line.FindFirst(option2); + } + else + foundOffset += endOffset; + if(foundOffset != B_ERROR) + { + delete s; + myText->Select(foundOffset, foundOffset+strlen(option2)); + myText->ScrollToSelection(); + ret = myText->LineAt(foundOffset)+1; + // myText->GoToLine(myText->LineAt(foundOffset)); + } + } + else if(tmp.IFindFirst("find")!=B_ERROR) + { + int32 startOffset, endOffset; + myText->GetSelection(&startOffset, &endOffset); + // = myText->OffsetAt(myText->CurrentLine()); + bool isFinished = false; + int foundOffset, l = myText->TextLength() - endOffset; + char* s; + s = new char[l+1]; + myText->GetText(endOffset, l, s); + BString line(s); + foundOffset = line.IFindFirst(option2); + if(foundOffset == B_ERROR) + { + delete s; + s = new char[endOffset]; + myText->GetText(0, endOffset-1, s); + line = s; + foundOffset = line.IFindFirst(option2); + } + else + foundOffset += endOffset; + if(foundOffset != B_ERROR) + { + delete s; + myText->Select(foundOffset, foundOffset+strlen(option2)); + myText->ScrollToSelection(); + ret = myText->LineAt(foundOffset)+1; + // myText->GoToLine(myText->LineAt(foundOffset)); + } + } + else + ErrorGen("Unknown option"); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +double YabInterface::TextGet(const char* title, const char* option, int line) +{ + double ret = -1.0; + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("line-width")!=B_ERROR) + ret = myText->LineWidth(line); + else if(tmp.IFindFirst("line-height")!=B_ERROR) + ret = myText->LineHeight(line); + else + ErrorGen("Unknown option"); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +int YabInterface::TextGet(const char* title, const char* option) +{ + int ret = -1; + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("currentline")!=B_ERROR) + ret = myText->CurrentLine()+1; + else if(tmp.IFindFirst("vertical-scrollbar")!=B_ERROR) + { + float f = -1.0; + BScrollView *s = cast_as(myText->Parent(), BScrollView); + if(s) + { + BScrollBar *b = s->ScrollBar(B_VERTICAL); + if(b) f = b->Value(); + else + ErrorGen("TEXTEDIT has no vertical scrollbar"); + } + else + ErrorGen("TEXTEDIT has no vertical scrollbar"); + ret = (int)f; + } + else if(tmp.IFindFirst("horizontal-scrollbar")!=B_ERROR) + { + float f = -1.0; + BScrollView *s = cast_as(myText->Parent(), BScrollView); + if(s) + { + BScrollBar *b = s->ScrollBar(B_HORIZONTAL); + if(b) f = b->Value(); + else + ErrorGen("TEXTEDIT has no horizontal scrollbar"); + } + else + ErrorGen("TEXTEDIT has no horizontal scrollbar"); + ret = (int)f; + } + else if(tmp.IFindFirst("countlines")!=B_ERROR) + ret = myText->CountLines(); + else if(tmp.IFindFirst("textlength")!=B_ERROR) + ret = myText->TextLength(); + else if(tmp.IFindFirst("haschanged")!=B_ERROR) + ret = myText->HasChanged()?1:0; + else if(tmp.IFindFirst("cursor-position")!=B_ERROR) + { + int32 start, end, pos1,pos2; + myText->GetSelection(&start, &end); + ret = end; + } + else + ErrorGen("Unknown option"); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +const char* YabInterface::TextGet(const char* title, int linenum) +{ + YabView *myView = NULL; + YabText *myText = 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + char* ret; + int start, num; + if(linenum-1 == 0) + start = 0; + else + start = myText->OffsetAt(linenum-1); + if(myText->CountLines()>linenum) + num = myText->OffsetAt(linenum)-start-1; + else + num = myText->TextLength()-start; + ret = new char[num+1]; + myText->GetText(start, num, ret); + w->Unlock(); + return (const char*)ret; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +const char* YabInterface::TextGet6(const char* title, const char* option) +{ + YabView *myView = NULL; + YabText *myText = NULL; + BString tmp(option); + + 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(); + myText = cast_as(myView->FindView(title),YabText); + if(myText) + { + if(tmp.IFindFirst("selection")!=B_ERROR) + { + char* ret; + int32 start, finish; + myText->GetSelection(&start, &finish); + if(finish == 0 || (finish-start)<=0) + { + ret = new char[1]; + ret[0] = '\0'; + } + else + { + ret = new char[finish-start+1]; + myText->GetText(start, finish-start, ret); + } + + w->Unlock(); + return (const char*)ret; + } + else + ErrorGen("Unknown option"); + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +double YabInterface::DrawGet(const char* option, const char* txt, const char* view) +{ + double ret = 0; + BString tmp(option); + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + if(tmp.IFindFirst("Text-Width")!=B_ERROR) + ret = myView->StringWidth(txt); + if(tmp.IFindFirst("Max-Text-Height")!=B_ERROR) + { + font_height height; + myView->GetFontHeight(&height); + ret = height.ascent+height.descent; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), view)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + if(tmp.IFindFirst("Text-Width")!=B_ERROR) + ret = bView->StringWidth(txt); + if(tmp.IFindFirst("Max-Text-Height")!=B_ERROR) + { + font_height height; + bView->GetFontHeight(&height); + ret = height.ascent+height.descent; + } + b->Unlock(); + + w->Unlock(); + return ret; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(view, "VIEW or CANVAS"); + } + return ret; +} + +const char* YabInterface::DrawGet(const char* option) +{ + BString t(option); + char* ret; + if(t.IFindFirst("fontfamily")!=B_ERROR) + { + int32 numFamilies = count_font_families(); + ret = new char[numFamilies*(B_FONT_FAMILY_LENGTH + 1)]; + BString tmp(""); + for(int32 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(); + myText = cast_as(myView->FindView(title), YabText); + if(myText) + { + myText->SetText("", 0); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +const char* YabInterface::TextGet(const char* title) +{ + const char* tmp; + YabView *myView = NULL; + YabText *myText = 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(); + myText = cast_as(myView->FindView(title), YabText); + if(myText) + { + tmp = myText->Text(); + w->Unlock(); + return tmp; + } + w->Unlock(); + } + } + } + Error(title, "TEXTEDIT"); +} + +void YabInterface::TreeBox1(BRect frame, const char* id, int scrollbarType, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + uint32 resizeMode; + + w->Lock(); + + if(scrollbarType == 3 || scrollbarType == 1) frame.right -= B_V_SCROLL_BAR_WIDTH; + if(scrollbarType>2) frame.bottom -= B_H_SCROLL_BAR_HEIGHT; + + BOutlineListView *list = new BOutlineListView(frame,id); + if(w->layout == -1) + resizeMode = B_FOLLOW_ALL; + else + resizeMode = w->layout; + list->SetResizingMode(resizeMode); + list->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + list->SetSelectionMessage(new BMessage(YABTREEBOXSELECT)); + list->SetInvocationMessage(new BMessage(YABTREEBOXINVOKE)); + switch(scrollbarType) + { + case 3: // both + myView->AddChild(new BScrollView("scroll_list", list, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, true, true)); + break; + case 2: // horizontal + myView->AddChild(new BScrollView("scroll_list", list, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, true, false)); + break; + case 0: // none + myView->AddChild(list); + break; + default: // vertical is default + myView->AddChild(new BScrollView("scroll_list", list, resizeMode, B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE, false, true)); + break; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::TreeBox2(const char* id, const char* item) +{ + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + myTree->AddItem(new BStringItem(item)); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +void YabInterface::TreeBox3(const char* id, const char* head, const char* item, int isExpanded) +{ + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + for(int i=0; iFullListCountItems(); i++) + { + BStringItem *stritem = (BStringItem*)myTree->FullListItemAt(i); + if(!strcmp(stritem->Text(), head)) + { + BStringItem *tmp = new BStringItem(item); + myTree->AddUnder(tmp,stritem); + if(isExpanded<1) + myTree->Collapse(stritem); + w->Unlock(); + return; + } + } + w->Unlock(); + ErrorGen("Item not found"); + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +void YabInterface::TreeBox4(const char* id) +{ + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + myTree->MakeEmpty(); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +void YabInterface::TreeBox5(const char* id, const char* item) +{ + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + for(int i=0; iFullListCountItems(); i++) + { + BStringItem *stritem = (BStringItem*)myTree->FullListItemAt(i); + if(!strcmp(stritem->Text(), item)) + { + myTree->RemoveItem(i); + w->Unlock(); + return; + } + } + w->Unlock(); + ErrorGen("Item not found"); + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +void YabInterface::TreeBox7(const char* id, int pos) +{ + pos--; + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + if(pos==0) + myTree->DeselectAll(); + else + { + BListItem *item = myTree->FullListItemAt(pos); + if(item) + myTree->Select(myTree->IndexOf(item)); + } + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +void YabInterface::TreeBox8(const char* id, int pos) +{ + pos--; + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + myTree->RemoveItem(pos); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} +void YabInterface::TreeBox9(const char* id, const char* head, const char* item) +{ + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + for(int i=0; iFullListCountItems(); i++) + { + BStringItem *stritem = (BStringItem*)myTree->FullListItemAt(i); + if(!strcmp(stritem->Text(), head)) + { + for(int j=0; iCountItemsUnder(stritem, false); j++) + { + BStringItem *subitem = (BStringItem*)myTree->FullListItemAt(i+j+1); + if(!strcmp(subitem->Text(), item)) + { + myTree->RemoveItem((BListItem*)subitem); + w->Unlock(); + return; + } + } + } + } + w->Unlock(); + ErrorGen("Item not found"); + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +void YabInterface::TreeBox10(const char* id, const char* head) +{ + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + for(int i=0; iFullListCountItems(); i++) + { + BStringItem *stritem = (BStringItem*)myTree->FullListItemAt(i); + if(!strcmp(stritem->Text(), head)) + { + myTree->Expand((BListItem*)stritem); + w->Unlock(); + return; + } + } + w->Unlock(); + ErrorGen("Item not found"); + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} +void YabInterface::TreeBox11(const char* id, const char* head) +{ + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id), BOutlineListView); + if(myTree) + { + for(int i=0; iFullListCountItems(); i++) + { + BStringItem *stritem = (BStringItem*)myTree->FullListItemAt(i); + if(!strcmp(stritem->Text(), head)) + { + myTree->Collapse((BListItem*)stritem); + w->Unlock(); + return; + } + } + w->Unlock(); + ErrorGen("Item not found"); + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +void YabInterface::TreeBox12(const char* id, const char* item, int pos) +{ + if(pos<1) pos = 1; + + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(id),BOutlineListView); + if(myTree) + { + if(pos<=myTree->FullListCountItems()) + { + uint32 outline = (myTree->FullListItemAt(pos-1))->OutlineLevel(); + myTree->AddItem(new BStringItem(item, outline),pos-1); + } + else + myTree->AddItem(new BStringItem(item)); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +const char* YabInterface::TreeboxGet(const char* treebox, int pos) +{ + pos--; + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(treebox), BOutlineListView); + if(myTree) + { + BStringItem *t = (BStringItem*)myTree->FullListItemAt(pos); + if(t) + { + const char* txt = t->Text(); + w->Unlock(); + return txt; + } + } + w->Unlock(); + } + } + } + Error(treebox, "TREEBOX"); +} + +int YabInterface::TreeboxCount(const char* treebox) +{ + int32 ret; + YabView *myView = NULL; + BOutlineListView *myTree = 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(); + myTree = cast_as(myView->FindView(treebox), BOutlineListView); + if(myTree) + { + ret = myTree->FullListCountItems(); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(treebox, "TREEBOX"); +} + +BBitmap* YabInterface::loadImage(const char* FileName) +{ + BBitmap* LogoBitmap = NULL; + BFile ImageFile; + BPath ImagePath; + int ret = 0; + + if( *FileName == '/') + ImageFile.SetTo( FileName, B_READ_ONLY); + else + // App directory. + if(!strcmp(ApplicationDirectory,"")) + { + if( ImagePath.SetTo((const char*)ApplicationDirectory, FileName) == B_OK) + ImageFile.SetTo( ImagePath.Path(), B_READ_ONLY); + } + + if( ImageFile.InitCheck() != B_OK) + ImageFile.SetTo( FileName, B_READ_ONLY); + + if( ImageFile.InitCheck() != B_OK) + return NULL; + + Roster = BTranslatorRoster::Default(); + + if( !Roster) + return NULL; + + BBitmapStream Stream; + + if( Roster->Translate( &ImageFile, NULL, NULL, &Stream, B_TRANSLATOR_BITMAP) < B_OK) + return NULL; + + if( Stream.DetachBitmap( &LogoBitmap) != B_OK) + return NULL; + + + return LogoBitmap; +} + +void YabInterface::ButtonImage(double x,double y, const char* id,const char* enabledon, const char* enabledoff, const char* disabled, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BPicture *pic1 = NULL, *pic2 = NULL, *pic3 = NULL; + BBitmap *bitmap = NULL; + BView *tmpView = new BView(BRect(0,0,1000,1000),"tmp",0, B_WILL_DRAW); + w->AddChild(tmpView); + tmpView->SetDrawingMode(B_OP_ALPHA); + + bitmap = loadImage(enabledon); + tmpView->BeginPicture(new BPicture); + if(bitmap) + { + // drawing_mode mode = myView->DrawingMode(); + // tmpView->SetDrawingMode(B_OP_ALPHA); + tmpView->DrawBitmap(bitmap,bitmap->Bounds()); + // myView->SetDrawingMode(mode); + } + pic1 = tmpView->EndPicture(); + + BRect r; + r.SetLeftTop(BPoint(x,y)); + if(bitmap) + r.SetRightBottom(BPoint(x,y) + bitmap->Bounds().RightBottom()); + else + r.SetRightBottom(BPoint(x,y)); + + bitmap = loadImage(enabledoff); + tmpView->BeginPicture(new BPicture); + if(bitmap) + { + // drawing_mode mode = myView->DrawingMode(); + // tmpView->SetDrawingMode(B_OP_ALPHA); + tmpView->DrawBitmap(bitmap,bitmap->Bounds()); + // myView->SetDrawingMode(mode); + } + pic2 = tmpView->EndPicture(); + + bitmap = loadImage(disabled); + tmpView->BeginPicture(new BPicture); + if(bitmap) tmpView->DrawBitmap(bitmap,bitmap->Bounds()); + pic3 = tmpView->EndPicture(); + + + BPictureButton *myButton = new BPictureButton(r, id, pic2, pic1, new BMessage(YABBUTTON)); + myButton->SetDisabledOff(pic3); + + if(w->layout == -1) + myButton->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + myButton->SetResizingMode(w->layout); + myButton->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(myButton); + tmpView->RemoveSelf(); + delete tmpView; + // delete Roster; + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::CheckboxImage(double x, double y,const char* id,const char* enabledon, const char* enabledoff, const char *disabledon, const char *disabledoff, int isActivated, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BPicture *pic1 = NULL, *pic2 = NULL, *pic3 = NULL, *pic4 = NULL; + BBitmap *bitmap = NULL; + BView *tmpView = new BView(BRect(0,0,1000,1000),"tmp",0, B_WILL_DRAW); + w->AddChild(tmpView); + tmpView->SetDrawingMode(B_OP_ALPHA); + + bitmap = loadImage(enabledon); + tmpView->BeginPicture(new BPicture); + if(bitmap) + { + // drawing_mode mode = myView->DrawingMode(); + // myView->SetDrawingMode(B_OP_ALPHA); + tmpView->DrawBitmap(bitmap,bitmap->Bounds()); + // myView->SetDrawingMode(mode); + } + pic1 = tmpView->EndPicture(); + + BRect r; + r.SetLeftTop(BPoint(x,y)); + if(bitmap) + r.SetRightBottom(BPoint(x,y) + bitmap->Bounds().RightBottom()); + else + r.SetRightBottom(BPoint(x,y)); + + bitmap = loadImage(enabledoff); + tmpView->BeginPicture(new BPicture); + if(bitmap) + { + // drawing_mode mode = myView->DrawingMode(); + // myView->SetDrawingMode(B_OP_ALPHA); + tmpView->DrawBitmap(bitmap,bitmap->Bounds()); + // myView->SetDrawingMode(mode); + } + pic2 = tmpView->EndPicture(); + + bitmap = loadImage(disabledon); + tmpView->BeginPicture(new BPicture); + if(bitmap) + { + // drawing_mode mode = myView->DrawingMode(); + // myView->SetDrawingMode(B_OP_ALPHA); + tmpView->DrawBitmap(bitmap,bitmap->Bounds()); + // myView->SetDrawingMode(mode); + } + pic3 = tmpView->EndPicture(); + + bitmap = loadImage(disabledoff); + tmpView->BeginPicture(new BPicture); + if(bitmap) + { + // drawing_mode mode = myView->DrawingMode(); + // myView->SetDrawingMode(B_OP_ALPHA); + tmpView->DrawBitmap(bitmap,bitmap->Bounds()); + // myView->SetDrawingMode(mode); + } + pic4 = tmpView->EndPicture(); + + BPictureButton *myButton = new BPictureButton(r, id, pic2, pic1, new BMessage(YABCHECKBOX),B_TWO_STATE_BUTTON); + myButton->SetDisabledOn(pic3); + myButton->SetDisabledOff(pic4); + + if(w->layout == -1) + myButton->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + myButton->SetResizingMode(w->layout); + myButton->SetValue(isActivated); + myButton->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(myButton); + tmpView->RemoveSelf(); + delete tmpView; + // delete Roster; + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::CheckboxSet(const char* id, int isActivated) +{ + YabView *myView = NULL; + BCheckBox *myCheckBox = NULL; + BPictureButton *myPicButton = 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(); + myCheckBox = cast_as(myView->FindView(id), BCheckBox); + if(myCheckBox) + { + myCheckBox->SetValue(isActivated); + w->Unlock(); + return; + } + else + { + myPicButton = cast_as(myView->FindView(id), BPictureButton); + if(myPicButton) + { + if(myPicButton->Behavior() == B_TWO_STATE_BUTTON) + { + myPicButton->SetValue(isActivated); + w->Unlock(); + return; + } + } + } + w->Unlock(); + } + } + } + Error(id, "CHECKBOX"); +} + +void YabInterface::RadioSet(const char* id, int isActivated) +{ + YabView *myView = NULL; + BRadioButton *myRadioButton= 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(); + myRadioButton = cast_as(myView->FindView(id), BRadioButton); + if(myRadioButton) + { + myRadioButton->SetValue(isActivated); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "RADIOBUTTON"); +} + +const char* YabInterface::TextControlGet(const char* id) +{ + const char* tmp = NULL; + YabView *myView = NULL; + BTextControl *myTControl = 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(); + myTControl = cast_as(myView->FindView(id), BTextControl); + if(myTControl) + { + tmp = myTControl->Text(); + w->Unlock(); + return tmp; + } + w->Unlock(); + } + } + } + Error(id, "TEXTCONTROL"); +} + +void YabInterface::ToolTips(const char* view, const char* text) +{ + YabView *myView = NULL; + BView *theView = 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(); + theView = w->FindView(view); + if(theView) + { + if(theView->Name()) + { + if(!strcmp(theView->Name(), view)) + { + if(text[0] == '\0') + // tooltip->SetHelp(theView, NULL); + ; + else + theView->SetToolTip(text); + w->Unlock(); + return; + } + } + } + w->Unlock(); + } + } + } + Error(view, "VIEW"); +} + +void YabInterface::ToolTipsColor(const char* color, int r, int g, int b) +{ +/* + BString tmp(color); + rgb_color rgb = {r,g,b}; + if(tmp.IFindFirst("BGColor")!=B_ERROR) + tooltip->SetColor(rgb); + else if(tmp.IFindFirst("TextColor")!=B_ERROR) + tooltip->SetTextColor(rgb); +*/ +} + +void YabInterface::TreeSort(const char* view) +{ + ErrorGen("Sorry, this command is not working yet"); + YabView *myView = NULL; + BOutlineListView *myList = 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(); + myList = cast_as(myView->FindView(view), BOutlineListView); + if(myList) + { + myList->FullListSortItems((int(*)(const BListItem *, const BListItem *))YabInterface::compare); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(view, "TREEBOX"); +} + +void YabInterface::ListSort(const char* view) +{ + YabView *myView = NULL; + BListView *myList = 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(); + myList = cast_as(myView->FindView(view), BListView); + if(myList) + { + myList->SortItems((int(*)(const void*, const void*))YabInterface::compare); + w->Unlock(); + return; + + } + w->Unlock(); + } + } + } + Error(view, "LISTBOX"); +} + +int YabInterface::compare(BListItem **firstArg, BListItem **secondArg) +{ + if(firstArg != NULL && secondArg != NULL) + { + BString item1(((BStringItem*)*firstArg)->Text()); + BString item2(((BStringItem*)*secondArg)->Text()); + if(((BListItem*)*firstArg)->OutlineLevel()!=((BListItem*)*secondArg)->OutlineLevel()) + return 0; + return item1.ICompare(item2); + } + return 0; +} + +void YabInterface::FileBox(BRect frame, const char* id, bool hasHScrollbar, const char* option, const char* view) +{ + BString tmp(option); + + border_style plain = B_PLAIN_BORDER; + if(tmp.IFindFirst("no-border")!=B_ERROR) + plain = B_NO_BORDER; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BColumnListView* myColumnList; + myColumnList = new BColumnListView(frame, id, B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE,plain, hasHScrollbar); + BMessage *msg1, *msg2; + msg1 = new BMessage(YABFILEBOXINVOKE); + msg1->AddPointer("source", myColumnList); + msg2 = new BMessage(YABFILEBOXSELECT); + msg2->AddPointer("source", myColumnList); + myColumnList->SetInvocationMessage(msg1); + myColumnList->SetSelectionMessage(msg2); + myColumnList->SetSortingEnabled(false); + myColumnList->SetSelectionMode(B_SINGLE_SELECTION_LIST); + rgb_color rgb = {195,195,195,255}; + myColumnList->SetColor(B_COLOR_SELECTION, rgb); + + int flags = B_ALLOW_COLUMN_NONE; + if(tmp.IFindFirst("movable")!=B_ERROR) + flags += B_ALLOW_COLUMN_MOVE; + if(tmp.IFindFirst("resizable")!=B_ERROR) + flags += B_ALLOW_COLUMN_RESIZE; + if(tmp.IFindFirst("popup")!=B_ERROR) + flags += B_ALLOW_COLUMN_POPUP; + if(tmp.IFindFirst("removable")!=B_ERROR) + flags += B_ALLOW_COLUMN_REMOVE; + myColumnList->SetColumnFlags((column_flags) flags); + myColumnList->SetLatchWidth(0.0); + myView->AddChild(myColumnList); + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::ColumnBoxAdd(const char* id, int column, int position, int height, const char* text) +{ + YabView *myView = NULL; + BColumnListView *myColumnList = 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(); + myColumnList = cast_as(myView->FindView(id), BColumnListView); + if(myColumnList) + { + BRow *myRow = myColumnList->RowAt(position-1); + if(!myRow) + { + myRow = new BRow(height); + myColumnList->AddRow(myRow, position); + for(int j=0; jCountColumns(); j++) + { + BYabField *myField = new BYabField(""); + myRow->SetField(myField, j); + } + } + + BYabField *myField = (BYabField*)myRow->GetField(column-1); + myField->SetString(text, height); + + myColumnList->Refresh(); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "COLUMNBOX"); +} + +void YabInterface::FileBoxAdd(const char* columnbox, const char* name, int32 pos, double minWidth, double maxWidth, double width, const char* option) +{ + BString tmp(option); + alignment align = B_ALIGN_LEFT; + if(tmp.IFindFirst("align-left")!=B_ERROR) + align = B_ALIGN_LEFT; + if(tmp.IFindFirst("align-center")!=B_ERROR) + align = B_ALIGN_CENTER; + if(tmp.IFindFirst("align-right")!=B_ERROR) + align = B_ALIGN_RIGHT; + YabView *myView = NULL; + BColumnListView *myColumnList = 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(); + myColumnList = cast_as(myView->FindView(columnbox), BColumnListView); + if(myColumnList) + { + BYabColumn *myColumn = new BYabColumn(name,width,maxWidth, minWidth,width, align); + myColumnList->AddColumn(myColumn, pos-1); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(columnbox, "COLUMNBOX"); +} + +void YabInterface::FileBoxClear(const char* columnbox) +{ + YabView *myView = NULL; + BColumnListView *myColumnList = 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(); + myColumnList = cast_as(myView->FindView(columnbox), BColumnListView); + if(myColumnList) + { + myColumnList->Clear(); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(columnbox, "COLUMNBOX"); +} + +void YabInterface::ColumnBoxRemove(const char* columnbox, int position) +{ + YabView *myView = NULL; + BColumnListView *myColumnList = 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(); + myColumnList = cast_as(myView->FindView(columnbox), BColumnListView); + if(myColumnList) + { + BRow *myRow; + myRow = myColumnList->RowAt(position-1); + if(myRow) + { + myColumnList->RemoveRow(myRow); + delete myRow; + } + else + { + w->Unlock(); + ErrorGen("Row not found"); + } + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(columnbox, "COLUMNBOX"); +} + +void YabInterface::ColumnBoxColor(const char* columnbox, const char* option, int r, int g, int b) +{ + YabView *myView = NULL; + BColumnListView *myColumnList = NULL; + BString tmp(option); + ColumnListViewColor col; + if(tmp.IFindFirst("selection-text")!=B_ERROR) + col = B_COLOR_SELECTION_TEXT; + else if(tmp.IFindFirst("non-focus-selection")!=B_ERROR) + col = B_COLOR_NON_FOCUS_SELECTION; + else if(tmp.IFindFirst("selection")!=B_ERROR) + col = B_COLOR_SELECTION; + else if(tmp.IFindFirst("text")!=B_ERROR) + col = B_COLOR_TEXT; + else if(tmp.IFindFirst("row-divider")!=B_ERROR) + col = B_COLOR_ROW_DIVIDER; + else if(tmp.IFindFirst("background")!=B_ERROR) + col = B_COLOR_BACKGROUND; + else + ErrorGen("Invalid option"); + + 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(); + myColumnList = cast_as(myView->FindView(columnbox), BColumnListView); + if(myColumnList) + { + rgb_color rgb = {r,g,b,255}; + myColumnList->SetColor(col, rgb); + myColumnList->Refresh(); + myColumnList->Invalidate(); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(columnbox, "COLUMNBOX"); +} + +void YabInterface::ColumnBoxSelect(const char* columnbox, int position) +{ + YabView *myView = NULL; + BColumnListView *myColumnList = 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(); + myColumnList = cast_as(myView->FindView(columnbox), BColumnListView); + if(myColumnList) + { + if(position == 0) + myColumnList->DeselectAll(); + else + { + myColumnList->AddToSelection(myColumnList->RowAt(position-1)); + myColumnList->ScrollTo(myColumnList->RowAt(position-1)); + } + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(columnbox, "COLUMNBOX"); +} + +const char* YabInterface::ColumnBoxGet(const char* columnbox, int column, int position) +{ + YabView *myView = NULL; + BColumnListView *myColumnList = 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(); + myColumnList = cast_as(myView->FindView(columnbox), BColumnListView); + if(myColumnList) + { + BRow* myRow = myColumnList->RowAt(position-1); + if(myRow) + { + BYabField *myField = cast_as(myRow->GetField(column-1), BYabField); + if(myField) + { + const char* t = myField->String(); + w->Unlock(); + return t; + } + w->Unlock(); + ErrorGen("Column not found"); + } + w->Unlock(); + ErrorGen("Row not found"); + } + w->Unlock(); + } + } + } + Error(columnbox, "COLUMNBOX"); +} + +int YabInterface::ColumnBoxCount(const char* columnbox) +{ + YabView *myView = NULL; + BColumnListView *myColumnList = 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(); + myColumnList = cast_as(myView->FindView(columnbox), BColumnListView); + if(myColumnList) + { + int32 ret = myColumnList->CountRows(); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(columnbox, "COLUMNBOX"); +} + +void YabInterface::ListboxAdd(const char* listbox, const char* item) +{ + YabView *myView = NULL; + BListView *myList = 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(); + myList = cast_as(myView->FindView(listbox), BListView); + // myList = (BListView*)myView->FindView(listbox); + if(myList) + { + myList->AddItem(new BStringItem(item)); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(listbox, "LISTBOX"); +} + +void YabInterface::ListboxAdd(const char* listbox, int pos, const char* item) +{ + YabView *myView = NULL; + BListView *myList = 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(); + myList = cast_as(myView->FindView(listbox), BListView); + if(myList) + { + myList->AddItem(new BStringItem(item), pos-1); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(listbox, "LISTBOX"); +} + +void YabInterface::ListboxSelect(const char* listbox, int pos) +{ + YabView *myView = NULL; + BListView *myList = 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(); + myList = cast_as(myView->FindView(listbox), BListView); + if(myList) + { + if(pos == 0) + myList->DeselectAll(); + else + { + myList->Select(pos-1); + myList->ScrollToSelection(); + } + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(listbox, "LISTBOX"); +} + +void YabInterface::ListboxRemove(const char* listbox, int pos) +{ + YabView *myView = NULL; + BListView *myList = 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(); + myList = cast_as(myView->FindView(listbox), BListView); + if(myList) + { + myList->RemoveItem(pos-1); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(listbox, "LISTBOX"); +} + +const char* YabInterface::ListboxGet(const char* listbox, int pos) +{ + YabView *myView = NULL; + BListView *myList = 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(); + columntext[0] = '\0'; + myList = cast_as(myView->FindView(listbox), BListView); + if(myList) + { + BStringItem *t = cast_as(myList->ItemAt(pos-1), BStringItem); + if(t) + { + const char* txt = t->Text(); + w->Unlock(); + return txt; + } + else + { + w->Unlock(); + ErrorGen("Item not found"); + } + } + w->Unlock(); + } + } + } + Error(listbox, "LISTBOX"); +} + +int YabInterface::ListboxCount(const char* listbox) +{ + int ret = 0; + YabView *myView = NULL; + BListView *myList = 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(); + myList = cast_as(myView->FindView(listbox), BListView); + if(myList) + { + ret = myList->CountItems(); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(listbox, "LISTBOX"); +} + +void YabInterface::DrawSet1(const char* option, const char* window) +{ + BString tmp(option); + + BFont myFont; + BString opt; + + // Font family + int pos1 = 0; + int pos2 = tmp.FindFirst(','); + if(pos2 != B_ERROR) + { + tmp.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + font_family fam; + sprintf((char*)fam, "%s" , opt.String()); + if(myFont.SetFamilyAndFace(fam, B_REGULAR_FACE) == B_OK) + { + // myView->SetFont(&myFont, B_FONT_FAMILY_AND_STYLE); + + // Font style + pos1 = pos2+1; + pos2 = tmp.FindFirst(',', pos2+1); + if(pos2 != B_ERROR) + { + tmp.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + font_style style; + sprintf((char*)style, "%s" , opt.String()); + if(myFont.SetFamilyAndStyle(fam,style) == B_OK) + { + // myView->SetFont(&myFont, B_FONT_FAMILY_AND_STYLE); + + // Font size + pos1 = pos2+1; + pos2 = tmp.FindFirst(',', pos2+1); + if(pos2 == B_ERROR) pos2 = tmp.Length(); + tmp.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + double size = atof(opt.String()); + myFont.SetSize(size); + // myView->SetFont(&myFont, B_FONT_SIZE); + + if(pos2 != tmp.Length()) + { + pos1 = pos2+1; + pos2 = tmp.FindFirst(',', pos2+1); + if(pos2 == B_ERROR) pos2 = tmp.Length(); + tmp.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + if(opt.IFindFirst("bold") != B_ERROR) + myFont.SetFace(B_BOLD_FACE); + else if(opt.IFindFirst("italic") != B_ERROR) + myFont.SetFace(B_ITALIC_FACE); + else if(opt.IFindFirst("regular") != B_ERROR) + myFont.SetFace(B_REGULAR_FACE); + else if(opt.IFindFirst("outlined") != B_ERROR) + myFont.SetFace(B_OUTLINED_FACE); + else if(opt.IFindFirst("strikeout") != B_ERROR) + myFont.SetFace(B_STRIKEOUT_FACE); + else if(opt.IFindFirst("underscore") != B_ERROR) + myFont.SetFace(B_UNDERSCORE_FACE); + + if(pos2 != tmp.Length()) + { + pos1 = pos2 + 1; + pos2 = tmp.FindFirst(',', pos2+1); + if(pos2 == B_ERROR) pos2 = tmp.Length(); + tmp.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + float rotation = atof(opt.String()); + myFont.SetRotation(rotation); + + if(pos2 != tmp.Length()) + { + pos1 = pos2 + 1; + pos2 = tmp.FindFirst(',', pos2+1); + if(pos2 == B_ERROR) pos2 = tmp.Length(); + tmp.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + float shear = atof(opt.String()); + myFont.SetShear(shear); + } + } + + } + + + // Font flags + /*bool looping = true; + while(looping) + { + pos1 = pos2+1; + pos2 = tmp.FindFirst(',', pos2+1); + if(pos2 == B_ERROR) + { + looping = false; + pos2 = tmp.Length(); + } + tmp.CopyInto(opt, pos1, pos2-pos1); + while(opt[0] == ' ') opt.RemoveFirst(" "); + while(opt[opt.Length()-1] == ' ') opt.RemoveLast(" "); + }*/ + } + } + } + } + else if(tmp.IFindFirst("system-plain")!=B_ERROR) + { + myFont = be_plain_font; + // myView->SetFont(&myFont); + } + else if(tmp.IFindFirst("system-fixed")!=B_ERROR) + { + myFont = be_fixed_font; + // myView->SetFont(&myFont); + } + else if(tmp.IFindFirst("system-bold")!=B_ERROR) + { + myFont = be_bold_font; + // myView->SetFont(&myFont); + } + + YabView *myView = cast_as((BView*)viewList->GetView(window), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + myView->SetFont(&myFont); + YabDrawing *t = new YabDrawing(); + t->command = 12; + t->font = myFont; + myView->drawList->AddItem(t); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(window); + if(bview) + { + b->Lock(); + bview->SetFont(&myFont); + bview->Sync(); + b->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), window)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + b->Lock(); + bView->SetFont(&myFont); + bView->Sync(); + b->Unlock(); + + // myView->Draw(myView->Bounds()); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(window, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::DrawSet2(int fillorstroke, const char* mypattern) +{ + BString tmp(mypattern); + if(fillorstroke) drawStroking = true; else drawStroking = false; + if(tmp.IFindFirst("HighSolidFill")!=B_ERROR) + yabPattern = B_SOLID_HIGH; + else if(tmp.IFindFirst("LowSolidFill")!=B_ERROR) + yabPattern = B_SOLID_LOW; + else if(tmp.IFindFirst("CheckeredFill")!=B_ERROR) + yabPattern = B_MIXED_COLORS; + else + { + for(int i = 0; i<8; i++) + if(iGetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + if(opt>0 && opt<5) + { + BRect r = w->Frame(); + switch(opt) + { + case 1: ret = (int)r.LeftTop().x; + break; + case 2: ret = (int)r.LeftTop().y; + break; + case 3: ret = r.IntegerWidth(); + break; + case 4: ret = r.IntegerHeight(); + break; + } + } + if(opt>4) + { + float x1,y1,x2,y2; + w->GetSizeLimits(&x1,&x2,&y1,&y2); + switch(opt) + { + case 5: ret = (int)x1; + break; + case 6: ret = (int)y1; + break; + case 7: ret = (int)x2; + break; + case 8: ret = (int)y2; + break; + } + } + if (opt==9) + { + return true; + } + } + else + { + if (opt==9) + { + return false; + } + else + ErrorGen("Unable to lock window"); + } + } + else + { + if (opt==9) + { + return false; + } + else + Error(view, "VIEW"); + } + return ret; +} + +int YabInterface::ViewGet(const char* view, const char* option) +{ + int opt = 0; + int ret = -1; + BString t(option); + YabView *myView = NULL; + if(t.IFindFirst("position-x")!=B_ERROR) opt = 1; + else if(t.IFindFirst("position-y")!=B_ERROR) opt = 2; + else if(t.IFindFirst("width")!=B_ERROR) opt = 3; + else if(t.IFindFirst("height")!=B_ERROR) opt = 4; + else if(t.IFindFirst("exists")!=B_ERROR) opt = 5; + else if(t.IFindFirst("focused")!=B_ERROR) opt = 6; + else + ErrorGen("Invalid option"); + + 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(); + BView *theView = cast_as(myView->FindView(view), BView); + if(theView) + { + BRect r = theView->Frame(); + switch(opt) + { + case 1: ret = (int)r.LeftTop().x; + break; + case 2: ret = (int)r.LeftTop().y; + break; + case 3: ret = r.IntegerWidth(); + break; + case 4: ret = r.IntegerHeight(); + break; + case 5: ret = true; + break; + case 6: ret = theView->IsFocus(); + break; + } + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + if( opt == 5 ) + ret=false; + else + Error(view, "VIEW"); + + return ret; +} + +void YabInterface::ClipboardCopy(const char* text) +{ + BMessage *clip = (BMessage *)NULL; + + if (be_clipboard->Lock()) + { + be_clipboard->Clear(); + if (clip = be_clipboard->Data()) + { + clip->AddData("text/plain", B_MIME_TYPE, text, strlen(text)); + be_clipboard->Commit(); + } + be_clipboard->Unlock(); + } +} + +int YabInterface::Printer(const char* docname, const char *config, const char* view) +{ + BPrintJob job(docname); + BMessage *setup; + BFile myFile(config, B_READ_ONLY); + + if(myFile.InitCheck()!=B_OK) + { + if(job.ConfigPage()==B_OK) + setup = job.Settings(); + else + { + // (new BAlert(_L("Printer Error!"),_L("Could not setup the printer!"), "Ok"))->Go(); + return 1; + } + } + else + { + setup = new BMessage(); + if(setup->Unflatten(&myFile)!=B_OK) + { + if(job.ConfigPage()==B_OK) + setup = job.Settings(); + else + { + // (new BAlert(_L("Printer Error!"),_L("Could not setup the printer!"), "Ok"))->Go(); + return 1; + } + } + else + if(job.IsSettingsMessageValid(setup)) + job.SetSettings(setup); + else + { + // (new BAlert(_L("Printer Error!"),_L("Could not setup the printer!"), "Ok"))->Go(); + return 2; + } + } + + int32 firstPage, lastPage, nbPages; + BRect printableRect = job.PrintableRect(); + firstPage =0 ;//= job.FirstPage(); Since we aren't calling the set-up print pages, firstpage is always 0 + lastPage = job.LastPage(); + // printf("PRINTER DEBUG Printable BRect %f %f %f %f\n", printableRect.left,printableRect.top, printableRect.right, printableRect.bottom); + YabView *myView = NULL; + BView *newView = 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(); + newView = myView->FindView(view); + w->Unlock(); + if(newView) + break; + } + } + } + + if(!newView) + { + // (new BAlert(_L("Printer Error!"),_L("Could not setup the printer!"), "Ok"))->Go(); + return 3; + } + + + BWindow *w = newView->Window(); + w->Lock(); + + int32 viewHeight = newView->Bounds().IntegerHeight(); + float viewWidth = newView->Bounds().Width(); + if(is_kind_of(newView, YabText)) + viewHeight = (int32)((YabText*)newView)->TextHeight(0, ((YabText*)newView)->CountLines()); + if(is_kind_of(newView, BScrollView)) + { + float a,b; + + if(((BScrollView*)newView)->ScrollBar(B_VERTICAL)) + { + ((BScrollView*)newView)->ScrollBar(B_VERTICAL)->GetRange(&a, &b); + viewHeight = viewHeight + (int32)b; + if(((BScrollView*)newView)->ScrollBar(B_HORIZONTAL)) + viewHeight -= (int32)B_H_SCROLL_BAR_HEIGHT; + } + if(((BScrollView*)newView)->ScrollBar(B_HORIZONTAL)) + { + ((BScrollView*)newView)->ScrollBar(B_HORIZONTAL)->GetRange(&a, &b); + viewWidth = viewWidth + b; + if(((BScrollView*)newView)->ScrollBar(B_VERTICAL)) + viewWidth -= B_V_SCROLL_BAR_WIDTH; + } + + if(((BScrollView*)newView)->ScrollBar(B_VERTICAL)) + newView = ((BScrollView*)newView)->ScrollBar(B_VERTICAL)->Target(); + else + newView = ((BScrollView*)newView)->ScrollBar(B_HORIZONTAL)->Target(); + } + + // printf(" %d %f \n", viewHeight, viewWidth); + int32 printableHeight = printableRect.IntegerHeight(); + float printableWidth = printableRect.Width(); + w->Unlock(); + + int32 maxPages = viewHeight / printableHeight + 1; + if(lastPage>maxPages) + lastPage = maxPages; + nbPages = lastPage - firstPage + 1; + + //printf("PRINTER DEBUG First Page %d Last Page %d \n", firstPage, lastPage); + // printf("PRINTER DEBUG View Height %d Printable Height %d \n", viewHeight, printableHeight); + + if(nbPages<=0) + { + // (new BAlert(_L("Printer Error!"),_L("Could not setup the printer!"), "Ok"))->Go(); + return 4; + } + + job.BeginJob(); + bool can_continue = job.CanContinue(); + + w->Lock(); + + bool hasWordWrap; + float textWidth, textHeight; + + if(is_kind_of(newView, YabText)) + { + int lineheight; + hasWordWrap = ((YabText*)newView)->DoesWordWrap(); + if(!hasWordWrap) ((YabText*)newView)->SetWordWrap(true); + lineheight = (int)((YabText*)newView)->LineHeight(); + textWidth = ((YabText*)newView)->TextRect().Width(); + textHeight = ((YabText*)newView)->TextRect().Height(); + + ((YabText*)newView)->SetTextRect(BRect(0,0,printableWidth, viewHeight)); + + printableHeight -= printableHeight%lineheight; + } + + int32 newHeight; + if(printableHeightSetWordWrap(hasWordWrap); + ((YabText*)newView)->SetTextRect(BRect(0,0,textWidth, textHeight)); + } + + w->Unlock(); + + if(can_continue) + job.CommitJob(); + else + // (new BAlert(_L("Printer Error!"),_L("Could not setup the printer!"), "Ok"))->Go(); + return 5; + return 0; +} + +void YabInterface::PrinterConfig(const char* config) +{ + BPrintJob job(""); + if(job.ConfigPage()==B_OK) + { + BMessage *setup = job.Settings(); + BFile myFile(config, B_WRITE_ONLY|B_CREATE_FILE|B_ERASE_FILE); + if(myFile.InitCheck()==B_OK) + setup->Flatten(&myFile); + } +} + +const char* YabInterface::ClipboardPaste() +{ + const char *text; + int32 textlen; + BString returnstring; + BMessage *clip = (BMessage *)NULL; + + if (be_clipboard->Lock()) + { + BMessage *clip = be_clipboard->Data(); + clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &textlen); + be_clipboard->Unlock(); + if (text != NULL) { + returnstring.SetTo(text, textlen); + } + } + + return returnstring; +} + +int YabInterface::NewAlert(const char* text, const char* button1, const char* button2, const char* button3, const char* option) +{ + alert_type tmp; + BString typ(option); + tmp = B_EMPTY_ALERT; + if(typ.IFindFirst("info")!=B_ERROR) tmp = B_INFO_ALERT; + else if(typ.IFindFirst("idea")!=B_ERROR) tmp = B_IDEA_ALERT; + else if(typ.IFindFirst("warning")!=B_ERROR) tmp = B_WARNING_ALERT; + else if(typ.IFindFirst("stop")!=B_ERROR) tmp = B_STOP_ALERT; + + if(!strcmp(button2,"")) button2 = NULL; + if(!strcmp(button3,"")) button3 = NULL; + + return (new BAlert("Alert!",text,button1,button2,button3,B_WIDTH_AS_USUAL,tmp))->Go() + 1; +} + +void YabInterface::Calendar(double x, double y, const char* id, const char* format, const char* date, const char* view) +{ + int day, month, year, look, myformat; + BString tYear, tMonth, tDay; + BString tDate(date); + tDate.MoveInto(tYear, 6,4); + tDate.MoveInto(tMonth, 3,2); + tDate.MoveInto(tDay, 0,2); + BString tFormat(format); + look = CC_DOT_DIVIDER; + myformat = CC_DD_MM_YYYY_FORMAT; + if(tFormat.FindFirst("/")!=B_ERROR) + look = CC_SLASH_DIVIDER; + else if(tFormat.FindFirst("-")!=B_ERROR) + look = CC_MINUS_DIVIDER; + if(tFormat.IFindFirst("MD")!=B_ERROR) + myformat = CC_MM_DD_YYYY_FORMAT; + + year = atoi(tYear.String()); + if(myformat == CC_MM_DD_YYYY_FORMAT) + { + month = atoi(tDay.String()); + day = atoi(tMonth.String()); + } + else + { + month = atoi(tMonth.String()); + day = atoi(tDay.String()); + } + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + CalendarControl* myCalendar = new CalendarControl(BPoint(x,y),id,day, month, year, myformat, look); + if(w->layout == -1) + myCalendar->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + myCalendar->SetResizingMode(w->layout); + myView->AddChild(myCalendar); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +const char* YabInterface::Calendar(const char* id) +{ + const char* txt; + YabView *myView = NULL; + CalendarControl *myCalendar = 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(); + myCalendar = cast_as(myView->FindView(id), CalendarControl); + if(myCalendar) + { + txt = myCalendar->Text(); + w->Unlock(); + return txt; + } + w->Unlock(); + } + } + } + Error(id, "CALENDAR"); +} + +void YabInterface::Calendar(const char* id, const char* date) +{ + int day, month, year, look, myformat; + BString tYear, tMonth, tDay; + BString tDate(date); + tDate.MoveInto(tYear, 6,4); + tDate.MoveInto(tMonth, 3,2); + tDate.MoveInto(tDay, 0,2); + + YabView *myView = NULL; + CalendarControl *myCalendar = 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(); + myCalendar = cast_as(myView->FindView(id), CalendarControl); + if(myCalendar) + { + myformat = myCalendar->GetFlags(); + year = atoi(tYear.String()); + if(myformat == CC_MM_DD_YYYY_FORMAT) + { + month = atoi(tDay.String()); + day = atoi(tMonth.String()); + } + else + { + month = atoi(tMonth.String()); + day = atoi(tDay.String()); + } + + myCalendar->SetDate(day,month,year); + + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "CALENDAR"); +} + +void YabInterface::Scrollbar(const char* id, int format, const char* view) +{ + YabView *myView = NULL; + BView *myBView = NULL; + if(format != 0) + { + bool hasHor = false, hasVer = false; + if(format>1) hasHor = true; + if(format == 1 || format == 3) hasVer = true; + + 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(); + myBView = myView->FindView(view); + if(myBView) + { + if(myView->RemoveChild(myBView)) + { + BScrollView *myScrollView = new BScrollView(id, myBView, B_FOLLOW_LEFT|B_FOLLOW_TOP, 0, hasHor, hasVer); + if(w->layout == -1) + myScrollView->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + myScrollView->SetResizingMode(w->layout); + myScrollView->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_NAVIGABLE); + myView->AddChild(myScrollView); + myScrollView->SetViewColor(myBView->ViewColor()); + w->Unlock(); + return; + } + } + w->Unlock(); + } + } + } + Error(view, "VIEW"); + } + ErrorGen("Unknown option"); +} + +void YabInterface::ScrollbarSet(const char* scrollview, const char* option, double position) +{ + BString tOption(option); + orientation isHorizontal; + if(tOption.IFindFirst("Vertical Position")!=B_ERROR) isHorizontal = B_VERTICAL; + if(tOption.IFindFirst("Horizontal Position")!=B_ERROR) isHorizontal = B_HORIZONTAL; + if(isHorizontal == B_VERTICAL || isHorizontal == B_HORIZONTAL) + { + YabView *myView = NULL; + BScrollView *myScrollView = 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(); + myScrollView = cast_as((BView*)myView->FindView(scrollview),BScrollView); + if(myScrollView) + { + BScrollBar *myScrollbar = myScrollView->ScrollBar(isHorizontal); + if(myScrollbar) + myScrollbar->SetValue(position); + else + ErrorGen("SCROLLBAR is not valid!"); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(scrollview, "SCROLLBAR"); + } + ErrorGen("Unknown option"); +} + +void YabInterface::ScrollbarSet(const char* scrollview, const char* option) +{ + BString tOption(option); + border_style border; + if(tOption.IFindFirst("no-border")!=B_ERROR) + border = B_NO_BORDER; + else if(tOption.IFindFirst("plain-border")!=B_ERROR) + border = B_PLAIN_BORDER; + else if(tOption.IFindFirst("fancy-border")!=B_ERROR) + border = B_FANCY_BORDER; + else + ErrorGen("Invalid option"); + + YabView *myView = NULL; + BScrollView *myScrollView = 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(); + myScrollView = cast_as((BView*)myView->FindView(scrollview),BScrollView); + if(myScrollView) + { + myScrollView->SetBorder(border); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(scrollview, "SCROLLBAR"); +} + +void YabInterface::ScrollbarSet(const char* scrollview, const char* option, double opt1, double opt2) +{ + BString tOption(option); + orientation isHorizontal; + int isRange = -1; + if(tOption.IFindFirst("Vertical")!=B_ERROR) isHorizontal = B_VERTICAL; + if(tOption.IFindFirst("Horizontal")!=B_ERROR) isHorizontal = B_HORIZONTAL; + if(tOption.IFindFirst("Range")!=B_ERROR) isRange = 1; + if(tOption.IFindFirst("Steps")!=B_ERROR) isRange = 0; + if((isHorizontal == B_VERTICAL || isHorizontal == B_HORIZONTAL) && isRange != -1) + { + YabView *myView = NULL; + BScrollView *myScrollView = 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(); + myScrollView = cast_as((BView*)myView->FindView(scrollview),BScrollView); + if(myScrollView) + { + /* + if(isRange) + { + BRect f(myView->Bounds()); + // printf("%f %f\n", opt1, opt2); + if(isHorizontal == B_HORIZONTAL) + { + f.left = opt1; + f.right = opt2; + } + else + { + f.top = opt1; + f.bottom = opt2; + } + myScrollView->SetDataRect(f); + } + else + { + BScrollBar *myScrollbar = myScrollView->ScrollBar(isHorizontal); + if(myScrollbar) myScrollbar->SetSteps(opt1,opt2); + }*/ + + BScrollBar *myScrollbar = myScrollView->ScrollBar(isHorizontal); + if(isRange == 1) + { + if(myScrollbar) + myScrollbar->SetRange(opt1,opt2); + else + ErrorGen("SCROLLBAR is not valid!"); + } + else + { + if(myScrollbar) + myScrollbar->SetSteps(opt1,opt2); + else + ErrorGen("SCROLLBAR is not valid!"); + } + + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(scrollview, "SCROLLBAR"); + } + ErrorGen("Unknown option"); +} + +double YabInterface::ScrollbarGet(const char* scrollview, const char* option) +{ + BString tOption(option); + orientation isHorizontal; + double res = 0; + if(tOption.IFindFirst("Vertical")!=B_ERROR) isHorizontal = B_VERTICAL; + if(tOption.IFindFirst("Horizontal")!=B_ERROR) isHorizontal = B_HORIZONTAL; + if(isHorizontal == B_VERTICAL || isHorizontal == B_HORIZONTAL) + { + YabView *myView = NULL; + BScrollView *myScrollView = 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(); + myScrollView = (BScrollView*)myView->FindView(scrollview); + if(myScrollView) + { + BScrollBar *myScrollbar = myScrollView->ScrollBar(isHorizontal); + if(myScrollbar) + res = myScrollbar->Value(); + else + ErrorGen("SCROLLBAR is not valid!"); + w->Unlock(); + return res; + } + w->Unlock(); + } + } + } + Error(scrollview, "SCROLLBAR"); + } + ErrorGen("Unknown option"); +} + +void YabInterface::SplitView(BRect frame, const char* id, int isVertical, int style, const char* view) +{ + orientation posture = isVertical>0?B_VERTICAL:B_HORIZONTAL; + + double pos; + + if(posture==B_VERTICAL) + pos = (frame.right-frame.left)/2; + else + pos = (frame.bottom-frame.top)/2; + + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + + BRect frame1(frame); + BRect frame2(frame); + + if(posture==B_VERTICAL) + { + frame1.Set(0,0,pos,frame.bottom-frame.top); + frame2.Set(pos+10,0,frame.right-frame.left, frame.bottom-frame.top); + } + else + { + frame1.Set(0,0,frame.right-frame.left, pos-10); + frame2.Set(0,pos,frame.right-frame.left,frame.bottom-frame.top); + } + + BString t1(id); t1 += "1"; + BString t2(id); t2 += "2"; + + YabView *newView1 = new YabView(frame1, t1.String(), B_FOLLOW_ALL_SIDES,B_WILL_DRAW|B_NAVIGABLE_JUMP); + viewList->AddView(t1.String(), newView1, TYPE_YABVIEW); + + YabView *newView2 = new YabView(frame2, t2.String(), B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_NAVIGABLE_JUMP); + viewList->AddView(t2.String(), newView2, TYPE_YABVIEW); + + SplitPane *mySplit = new SplitPane(frame, id, (BView*)newView1, (BView*)newView2, 0); + if(style) + mySplit->SetBarThickness(10); + else + mySplit->SetBarThickness(5); + mySplit->SetAlignment(posture); + + if(w->layout == -1) + mySplit->SetResizingMode(B_FOLLOW_ALL_SIDES); + else + mySplit->SetResizingMode(w->layout); + + myView->AddChild(mySplit); + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::SplitView(const char* splitView, const char* option, double position) +{ + YabView *myView = NULL; + SplitPane *mySplit = NULL; + BString t(option); + if(t.IFindFirst("Divider")==B_ERROR) + ErrorGen("Unknown option"); + 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(); + mySplit = cast_as(myView->FindView(splitView), SplitPane); + if(mySplit) + { + mySplit->SetBarPosition((int)position); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(splitView, "SPLITVIEW"); +} + +void YabInterface::SplitView(const char* splitView, const char* option, double left, double right) +{ + YabView *myView = NULL; + SplitPane *mySplit = NULL; + BString t(option); + if(t.IFindFirst("MinimumSizes")==B_ERROR) + ErrorGen("Unknown option"); + 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(); + mySplit = cast_as(myView->FindView(splitView), SplitPane); + if(mySplit) + { + mySplit->SetMinSizeOne((int)left); + mySplit->SetMinSizeTwo((int)right); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(splitView, "SPLITVIEW"); +} + +double YabInterface::SplitViewGet(const char* splitView, const char* option) +{ + double ret = -1; + YabView *myView = NULL; + SplitPane *mySplit = NULL; + BString t(option); + if(t.IFindFirst("Divider")==B_ERROR) + ErrorGen("Unknown option"); + 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(); + mySplit = cast_as(myView->FindView(splitView), SplitPane); + if(mySplit) + { + ret = (double)mySplit->GetBarPosition(); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(splitView, "SPLITVIEW"); +} + +void YabInterface::StackViews(BRect frame, const char* id, int number, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView && number<1000) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + + YabStackView *myStackView = new YabStackView(frame, id, number); + if(w->layout == -1) + myStackView->SetResizingMode(B_FOLLOW_ALL); + else + myStackView->SetResizingMode(w->layout); + // myTabView->SetFlags(B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE); + + YabView *newViews[number]; + for(int i=0; iBounds(), t.String(), B_FOLLOW_ALL_SIDES,B_WILL_DRAW|B_NAVIGABLE_JUMP); + viewList->AddView(t.String(), newViews[i], TYPE_YABVIEW); + + } + myStackView->AddViews((BView**)newViews); + + myView->AddChild(myStackView); + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + if(number<1000) Error(view, "VIEW"); + else ErrorGen("Too many views!"); +} + +void YabInterface::StackViews(const char* id, int num) +{ + YabView *myView = NULL; + YabStackView *myStackView = 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(); + myStackView = cast_as(myView->FindView(id), YabStackView); + if(myStackView) + { + myStackView->SelectView(num-1); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "STACKVIEW"); +} + +int YabInterface::StackViewGet(const char* id) +{ + int ret; + YabView *myView = NULL; + YabStackView *myStackView = 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(); + myStackView = cast_as(myView->FindView(id), YabStackView); + if(myStackView) + { + ret = myStackView->CurrentView(); + w->Unlock(); + return ret+1; + } + w->Unlock(); + } + } + } + Error(id, "STACKVIEW"); +} + +void YabInterface::DrawSet3(const char* option, int transparency) +{ + BString t(option); + if(t.IFindFirst("alpha") != B_ERROR) + { + yabAlpha = transparency; + if(yabAlpha<0) yabAlpha = 0; + if(yabAlpha>255) yabAlpha = 255; + } +} + +void YabInterface::TextURL(double x, double y, const char* id, const char* text, const char* url, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + double h,b; + b = be_plain_font->StringWidth(text)+1; + h = be_plain_font->Size() + 1; + URLView *s = new URLView(BRect(x,y,x+b,y+h), id, text, url); + s->SetHoverEnabled(true); + if(w->layout == -1) + s->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + s->SetResizingMode(w->layout); + s->SetFlags(B_WILL_DRAW); + myView->AddChild(s); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::TextURL(const char* id, const char* option, int r, int g, int b) +{ + int opt = 0; + BString t(option); + if(t.IFindFirst("label") != B_ERROR) opt = 1; + if(t.IFindFirst("click") != B_ERROR) opt = 2; + if(t.IFindFirst("mouse-over") != B_ERROR) opt = 3; + + YabView *myView = NULL; + URLView *myURLView = 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(); + myURLView = cast_as(myView->FindView(id), URLView); + if(myURLView) + { + rgb_color col = {r,g,b,255}; + switch(opt) + { + case 1: myURLView->SetColor(col); + break; + case 2: myURLView->SetClickColor(col); + break; + case 3: myURLView->SetHoverColor(col); + break; + default: break; + } + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "TEXTURL"); +} + +void YabInterface::Menu(const char* menuHead, int isRadio, const char* view) +{ + bool radio = isRadio?true:false; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BMenuBar *menubar; + BMenu *menu = NULL; + BMenuItem *item = NULL; + w->Lock(); + + menubar = cast_as(myView->FindView("menubar"), BMenuBar); + if(menubar != NULL) + { + for(int i=0; iCountItems(); i++) + if(!strcmp( menubar->ItemAt(i)->Label(), menuHead)) + { + menu = menubar->SubmenuAt(i); + menu->SetRadioMode(radio); + break; + } + } + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::SubMenu(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* shortcut, const char* view) +{ + char myShortcut; + int32 modifiers = 0; + BString t(shortcut); + if(t.Length()>1) + { + myShortcut = shortcut[t.Length()-1]; + if(t.IFindFirst("s")!=B_ERROR && t.IFindFirst("s")GetView(view), YabView); + + if(!strcmp(menuItem, "--")) + return; + + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BMenuBar *menubar; + YabMenu *menu = NULL; + YabMenu *submenu = NULL; + BMenuItem *item = NULL; + w->Lock(); + menubar = cast_as(myView->FindView("menubar"), BMenuBar); + if(menubar == NULL) + { + menubar = new BMenuBar(myView->Bounds(),"menubar"); + myView->AddChild(menubar); + } + + for(int i=0; iCountItems(); i++) + if(!strcmp( menubar->ItemAt(i)->Label(), menuHead)) + menu = (YabMenu*)menubar->SubmenuAt(i); + + if(menu == NULL) + { + menu = new YabMenu(menuHead); + menubar->AddItem(menu); + } + + int isInMenu = -1; + for(int i=0; iCountItems(); i++) + if(!strcmp(menu->ItemAt(i)->Label(), menuItem)) + { + isInMenu = i; + break; + } + + if(isInMenu == -1) + { + submenu = new YabMenu(menuItem); + menu->AddItem(submenu); + } + else + { + submenu = cast_as(menu->SubmenuAt(isInMenu),YabMenu); + if(submenu == NULL) + { + BMenuItem *myItem = menu->RemoveItem(isInMenu); + delete myItem; + + submenu = new YabMenu(menuItem); + menu->AddItem(submenu, isInMenu); + } + } + + if(!strcmp(subMenuItem,"--")) + submenu->AddItem(new BSeparatorItem()); + else + submenu->AddItem(new BMenuItem(subMenuItem, new BMessage(YABSUBMENU), myShortcut, modifiers)); + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::SubMenu(const char* menuHead, const char* menuItem, int isRadio, const char* view) +{ + bool radio = isRadio?true:false; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BMenuBar *menubar; + BMenu *menu = NULL; + BMenu *submenu = NULL; + BMenuItem *item = NULL; + w->Lock(); + + menubar = cast_as(myView->FindView("menubar"), BMenuBar); + if(menubar != NULL) + { + for(int i=0; iCountItems(); i++) + if(!strcmp( menubar->ItemAt(i)->Label(), menuHead)) + { + menu = menubar->SubmenuAt(i); + for(int j=0; jCountItems(); j++) + if(!strcmp( menu->ItemAt(j)->Label(), menuItem)) + { + submenu = menu->SubmenuAt(j); + if(submenu) + { + submenu->SetRadioMode(radio); + break; + } + } + + if(submenu) break; + } + } + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +int YabInterface::ColorControlGet(const char* colorcontrol, const char* option) +{ + int ret = -1; + int myOption = -1; + BString myString(option); + if(myString.IFindFirst("Red") != B_ERROR) myOption = 0; + if(myString.IFindFirst("Green") != B_ERROR) myOption = 1; + if(myString.IFindFirst("Blue") != B_ERROR) myOption = 2; + + if(myOption<0) ErrorGen("Unknown option"); + + YabView *myView = NULL; + BColorControl *myCControl = NULL; + for(int i=0; iCountItems(); i++) + { + myView = cast_as((BView*)viewList->ItemAt(i), YabView); + if(myView && myOption>-1) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + myCControl = cast_as(myView->FindView(colorcontrol), BColorControl); + if(myCControl) + { + rgb_color t = myCControl->ValueAsColor(); + switch(myOption) + { + case 0: ret = t.red; + break; + case 1: ret = t.green; + break; + case 2: ret = t.blue; + break; + } + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(colorcontrol, "COLORCONTROL"); +} + +int YabInterface::SliderGet(const char* slider) +{ + int ret = -1; + YabView *myView = NULL; + BSlider *mySlider = 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(); + mySlider = cast_as(myView->FindView(slider), BSlider); + if(mySlider) + { + ret = mySlider->Value(); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(slider, "SLIDER"); +} + +void YabInterface::SubMenu3(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* option, const char* view) +{ + int myOption = -1; + BString t(option); + if(t.IFindFirst("disable")!=B_ERROR) myOption = 0; + if(t.IFindFirst("enable")!=B_ERROR) myOption = 1; + if(t.IFindFirst("mark")!=B_ERROR) myOption = 2; + if(t.IFindFirst("plain")!=B_ERROR) myOption = 3; + if(t.IFindFirst("remove")!=B_ERROR) myOption = 4; + + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView && myOption>-1) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BMenuBar *menubar; + BMenu *menu = NULL; + BMenu *submenu = NULL; + BMenuItem *item = NULL; + w->Lock(); + + menubar = cast_as(myView->FindView("menubar"), BMenuBar); + if(menubar) + { + for(int i=0; iCountItems(); i++) + { + if(!strcmp( menubar->ItemAt(i)->Label(), menuHead)) + { + menu = menubar->SubmenuAt(i); + for(int j=0; jCountItems(); j++) + { + if(!strcmp( menu->ItemAt(j)->Label(), menuItem)) + { + submenu = menu->SubmenuAt(j); + if(submenu) + { + for(int k=0; kCountItems(); k++) + { + if(!strcmp( submenu->ItemAt(k)->Label(), subMenuItem)) + { + switch(myOption) + { + case 0: + submenu->ItemAt(k)->SetEnabled(false); + break; + case 1: + submenu->ItemAt(k)->SetEnabled(true); + break; + case 2: + submenu->ItemAt(k)->SetMarked(true); + break; + case 3: + submenu->ItemAt(k)->SetMarked(false); + break; + case 4: + submenu->RemoveItem( submenu->ItemAt(k) ); + if(submenu->CountItems() == 0) { + if(menu->RemoveItem(submenu)) + menu->AddItem(new BMenuItem(menuItem, new BMessage(YABMENU)), j); + } + break; + } + break; + } + } + } + } + } + } + } + } + + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + if(myOption>-1) Error(view, "VIEW"); + else ErrorGen("Unknown option"); +} + +void YabInterface::Menu3(const char* menuHead, const char* menuItem, const char* option,const char* view) +{ + int myOption = -1; + BString t(option); + if(t.IFindFirst("disable")!=B_ERROR) myOption = 0; + if(t.IFindFirst("enable")!=B_ERROR) myOption = 1; + if(t.IFindFirst("mark")!=B_ERROR) myOption = 2; + if(t.IFindFirst("plain")!=B_ERROR) myOption = 3; + if(t.IFindFirst("remove")!=B_ERROR) myOption = 4; + + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView && myOption>-1) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BMenuBar *menubar; + BMenu *menu = NULL; +// BMenuItem *item = NULL; + w->Lock(); + + menubar = cast_as(myView->FindView("menubar"), BMenuBar); + if(menubar != NULL) + { + for(int i=0; iCountItems(); i++) + if(!strcmp( menubar->ItemAt(i)->Label(), menuHead)) + { + menu = menubar->SubmenuAt(i); + for(int j=0; jCountItems(); j++) + if(!strcmp( menu->ItemAt(j)->Label(), menuItem)) + { + switch(myOption) + { + case 0: + menu->ItemAt(j)->SetEnabled(false); + break; + case 1: + menu->ItemAt(j)->SetEnabled(true); + break; + case 2: + menu->ItemAt(j)->SetMarked(true); + break; + case 3: + menu->ItemAt(j)->SetMarked(false); + break; + case 4: + menu->RemoveItem( menu->ItemAt(j) ); + } + break; + } + } + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + if(myOption>-1) Error(view, "VIEW"); + else ErrorGen("Unknown option"); +} + +void YabInterface::SpinControl(double x, double y, const char* id, const char* label, int min, int max, int step, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + Spinner *mySpin = new Spinner(BRect(x,y,x+10,y+10), id, label, min, max, step, NULL); + if(w->layout == -1) + mySpin->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + mySpin->SetResizingMode(w->layout); + myView->AddChild(mySpin); + mySpin->SetViewColor(myView->ViewColor()); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); +} + +void YabInterface::SpinControl(const char* spinControl, int value) +{ + YabView *myView = NULL; + Spinner *mySpin = 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(); + mySpin = cast_as(myView->FindView(spinControl),Spinner); + if(mySpin) + { + mySpin->SetValue(value); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(spinControl, "SPINCONTROL"); +} + +int YabInterface::SpinControlGet(const char *spinControl) +{ + int ret = 0; + YabView *myView = NULL; + Spinner *mySpin = 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(); + mySpin = cast_as(myView->FindView(spinControl),Spinner); + if(mySpin) + { + ret = mySpin->Value(); + w->Unlock(); + return ret; + } + w->Unlock(); + } + } + } + Error(spinControl, "SPINCONTROL"); +} + +const char* YabInterface::PopUpMenu(double x, double y, const char* menuItems, const char* view) +{ + BString t(menuItems); + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + const char* res; + w->Lock(); + BPopUpMenu *returnMe = new BPopUpMenu( "YabPopup", false, false ); + returnMe->SetAsyncAutoDestruct(true); + + int oldi = 0; + for(int i=0; iAddItem(new BSeparatorItem()); + else + returnMe->AddItem(new BMenuItem(_L(j.String()), NULL)); + oldi=i+1; + } + BString j; + t.CopyInto(j,oldi, t.Length()-oldi); + returnMe->AddItem(new BMenuItem(j.String(), NULL)); + + BMenuItem *result = returnMe->Go(myView->ConvertToScreen(BPoint(x,y)), false, true); + if(result) + { + res = result->Label(); + w->Unlock(); + return res; + } + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); + + return ""; +} + +void YabInterface::DropBoxSelect(const char* dropbox, int position) +{ + YabView *myView = 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(); + BMenuField *myMenuField = cast_as(myView->FindView(dropbox), BMenuField); + if(myMenuField) + { + BMenu *myMenu = (BMenu*)myMenuField->Menu(); + if(myMenu) + { + if(position<1) position = 1; + if(position>=myMenu->CountItems()) + position = myMenu->CountItems(); + if(myMenu->CountItems()!=0) + (myMenu->ItemAt(position-1))->SetMarked(true); + w->Unlock(); + return; + } + } + w->Unlock(); + } + } + } + Error(dropbox, "DROPBOX"); +} + +void YabInterface::DropBoxClear(const char* dropbox) +{ + YabView *myView = 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(); + BMenuField *myMenuField = cast_as(myView->FindView(dropbox), BMenuField); + if(myMenuField) + { + BMenu *myMenu = (BMenu*)myMenuField->Menu(); + if(myMenu) + { + while(myMenu->CountItems()>0) + { + BMenuItem *myItem = myMenu->RemoveItem(myMenu->CountItems()-1); + delete myItem; + } + + // bad workaround! Add an empty MenuItem and delete it again + // so that the menu changes + BMenuItem *myItem = new BMenuItem("", NULL); + myMenu->AddItem(myItem); + myItem->SetMarked(true); + myMenu->RemoveItem(myItem); + delete myItem; + + w->Unlock(); + return; + } + } + w->Unlock(); + } + } + } + Error(dropbox, "DROPBOX"); +} + +void YabInterface::DropBoxRemove(const char* dropbox, int position) +{ + YabView *myView = 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(); + BMenuField *myMenuField = cast_as(myView->FindView(dropbox), BMenuField); + if(myMenuField) + { + BMenu *myMenu = (BMenu*)myMenuField->Menu(); + if(myMenu) + { + position --; + if(position<0) position = 0; + if(position>=myMenu->CountItems()) + position = myMenu->CountItems()-1; + + if(myMenu->CountItems()!=0) + { + BMenuItem *myItem = myMenu->ItemAt(position); + if(myItem->IsMarked()) + { + if(myMenu->CountItems()>1 && position>0) + (myMenu->ItemAt(position-1))->SetMarked(true); + else if(myMenu->CountItems()>1 && position == 0) + (myMenu->ItemAt(position+1))->SetMarked(true); + else + { + BMenuItem *myItem = new BMenuItem("", NULL); + myMenu->AddItem(myItem); + myItem->SetMarked(true); + myMenu->RemoveItem(myItem); + delete myItem; + } + + } + myMenu->RemoveItem(myItem); + delete myItem; + } + w->Unlock(); + return; + } + } + w->Unlock(); + } + } + } + Error(dropbox, "DROPBOX"); +} + +int YabInterface::DropBoxCount(const char* dropbox) +{ + int ret = -1; + YabView *myView = 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(); + BMenuField *myMenuField = cast_as(myView->FindView(dropbox), BMenuField); + if(myMenuField) + { + BMenu *myMenu = (BMenu*)myMenuField->Menu(); + if(myMenu) + { + ret = myMenu->CountItems(); + w->Unlock(); + return ret; + } + } + w->Unlock(); + } + } + } + Error(dropbox, "DROPBOX"); +} + +const char* YabInterface::DropBoxGet(const char* dropbox, int position) +{ + YabView *myView = 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(); + BMenuField *myMenuField = cast_as(myView->FindView(dropbox), BMenuField); + if(myMenuField) + { + BMenu *myMenu = (BMenu*)myMenuField->Menu(); + if(myMenu) + { + const char *ret; + position --; + if(position<0) position = 0; + if(position>=myMenu->CountItems()) + position = myMenu->CountItems()-1; + if(myMenu->CountItems()!=0) + { + ret = (myMenu->ItemAt(position))->Label(); + w->Unlock(); + return ret; + } + else + { + w->Unlock(); + return ""; + } + } + } + w->Unlock(); + } + } + } + Error(dropbox, "DROPBOX"); +} + +double YabInterface::MenuHeight() +{ + double ret = -1; + for(int i=0; iLock(); + menubar = cast_as(w->FindView("menubar"), BMenuBar); + if(menubar) + { + ret = menubar->Bounds().bottom - menubar->Bounds().top; + w->Unlock(); + break; + } + w->Unlock(); + } + } + return ret; +} + +double YabInterface::TabHeight() +{ + BFont f = be_plain_font; + font_height fh; + f.GetHeight(&fh); + return fh.ascent + fh.descent + fh.leading + 10.0f; +} + +double YabInterface::ScrollbarWidth() +{ + return B_H_SCROLL_BAR_HEIGHT; +} + +const int YabInterface::IsMouseIn(const char* view) +{ + int t = 2; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + t = myView->mouseMovedInfo; + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); + return 1-t; +} + +const char* YabInterface::GetMouseIn() +{ + snooze(20000); + BString ts; + mousemessagebuffer[0] = '\0'; + + int handled = -1; + YabView *myView = NULL; + + for(int i=0; iIsActive()) + { + w->Lock(); + + BView *view = w->LastMouseMovedView(); + if(!view) + { + w->Unlock(); + break; + } + + if(is_kind_of(view->Parent(), BTextControl)) + view = view->Parent(); + if(is_kind_of(view->Parent(), Spinner)) + view = view->Parent(); + if(is_kind_of(view->Parent(), CalendarControl)) + view = view->Parent(); + if(is_kind_of(view->Parent(), BColorControl)) + view = view->Parent(); + if(is_kind_of(view->Parent(), YabText)) + view = view->Parent(); + if(is_kind_of(view->Parent(), BColumnListView)) + view = view->Parent(); + if(is_kind_of(view, BBox)) + view = view->Parent(); + if(is_kind_of(view, BMenuBar)) + view = view->Parent(); + + BString name = view->Name(); + BPoint coordinates; + uint32 buttons; + + view->GetMouse(&coordinates, &buttons); + + ts << name << ":" << (int)coordinates.x << ":" << (int)coordinates.y << ":"; + if(buttons & B_PRIMARY_MOUSE_BUTTON) + ts << 1 << ":"; + else + ts << 0 << ":"; + if(buttons & B_TERTIARY_MOUSE_BUTTON) + ts << 1 << ":"; + else + ts << 0 << ":"; + if(buttons & B_SECONDARY_MOUSE_BUTTON) + ts << 1; + else + ts << 0; + + w->Unlock(); + } + } + + strcpy(mousemessagebuffer, ts.String()); + return (char*)mousemessagebuffer; +} + +const char* YabInterface::KeyboardMessages(const char* view) +{ + snooze(20000); + keyboardbuffer[0] = '\0'; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BString t(""); + w->Lock(); + // if(!myView->IsFocus()) myView->MakeFocus(true); + if(myView->IsFocus()) + t << myView->pressedKeys; + w->Unlock(); + strcpy(keyboardbuffer, t.String()); + } + else + ErrorGen("Unable to lock window"); + } + else + Error(view, "VIEW"); + return (char*)keyboardbuffer; +} + +const char* YabInterface::GetMouseMessages(const char* view) +{ + snooze(20000); + mousemessagebuffer[0] = '\0'; + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BString t(""); + w->Lock(); + t << myView->mouseX; t += ":"; + t << myView->mouseY; t += ":"; + t << myView->mouseLButton; t += ":"; + t << myView->mouseMButton; t += ":"; + t << myView->mouseRButton; + w->Unlock(); + strcpy(mousemessagebuffer, t.String()); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), view)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BString t(""); + w->Lock(); + t << myView->mouseX; t += ":"; + t << myView->mouseY; t += ":"; + t << myView->mouseLButton; t += ":"; + t << myView->mouseMButton; t += ":"; + t << myView->mouseRButton; + w->Unlock(); + strcpy(mousemessagebuffer, t.String()); + return (char*)mousemessagebuffer; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(view, "VIEW"); + } + return (char*)mousemessagebuffer; +} + +int YabInterface::ThreadKill(const char* option, int id) +{ + int isTeam = -1; + int ret = 0; + BString t(option); + if(t.IFindFirst("teamid")!=B_ERROR) isTeam = 1; + if(t.IFindFirst("threadid")!=B_ERROR) isTeam = 0; + if(isTeam==1) + { + if(kill_team(id)==B_OK) ret = 1; + } + else if(isTeam==0) + { + if(kill_thread(id)==B_OK) ret = 1; + } + else + ErrorGen("Unknown Option"); + + return ret; +} + +int YabInterface::ThreadGet(const char* option, const char* appname) +{ + int isTeam = -1; + int ret = -1; + BString t(option); + if(t.IFindFirst("teamid")!=B_ERROR) isTeam = 1; + if(t.IFindFirst("threadid")!=B_ERROR) isTeam = 0; + if(isTeam==0) + { + ret = find_thread(appname); + if(ret == B_NAME_NOT_FOUND) ret = -1; + } + else if(isTeam==1) + { + int32 cookie=0; + team_info info; + BString t(appname); + while (get_next_team_info(&cookie, &info) == B_OK) + { + if(t.FindFirst(info.args)==B_OK) + { + ret = info.team; + break; + } + } + } + else + ErrorGen("Unknown Option"); + + return ret; +} + +void YabInterface::Bitmap(double w, double h, const char* id) +{ + char *t; + BBitmap *b = new BBitmap(BRect(0,0,w-1,h-1), B_RGBA32, true); + BView *bview = new BView(BRect(0,0,w-1,h-1), id, B_FOLLOW_NONE, 0); + b->AddChild(bview); + t = (char*)b->Bits(); + for(int i=0; iAddItem(b); +} + +int YabInterface::BitmapColor(double x, double y, const char* bitmap, const char* option) +{ + int rgb = 0; + BString tmp(option); + if(tmp.IFindFirst("red")!=B_ERROR) rgb = 1; + else if(tmp.IFindFirst("green")!=B_ERROR) rgb = 2; + else if(tmp.IFindFirst("blue")!=B_ERROR) rgb = 3; + else + ErrorGen("Unknown Option"); + + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(bitmap); + if(bview) + { + int t = b->BytesPerRow()*(int)y + (int)x*4; + unsigned char* bits = (unsigned char*)b->Bits(); + if(t <= b->BitsLength()) + if(rgb == 1) + return (int)bits[t]; + else if(rgb == 2) + return (int)bits[t+1]; + else if(rgb == 3) + return (int)bits[t+2]; + return 0; + } + } + Error(bitmap, "BITMAP"); +} + +void YabInterface::BitmapDraw(double x, double y, const char* bitmap, const char* mode, const char* view) +{ + drawing_mode myMode; + BString tmp(mode); + if(tmp.IFindFirst("copy")!=B_ERROR) + myMode = B_OP_COPY; + else if(tmp.IFindFirst("alpha")!=B_ERROR) + myMode = B_OP_ALPHA; + else + ErrorGen("Unknown option"); + + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(bitmap); + if(bview) + { + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BBitmap *newb = new BBitmap(b->Bounds(), B_RGBA32); + char* newbits = (char*)newb->Bits(); + char* oldbits = (char*)b->Bits(); + for(int j=0; jBitsLength(); j++) + newbits[j] = oldbits[j]; + w->Lock(); + YabDrawing *t = new YabDrawing(); + t->command = 10; + t->x1 = x; t->y1 = y; + t->bitmap = newb; + myView->drawList->AddItem(t); + myView->Invalidate(); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *bb = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bbview = bb->FindView(view); + if(bbview) + { + bb->Lock(); + drawing_mode t = bbview->DrawingMode(); + bbview->SetDrawingMode(myMode); + bbview->DrawBitmap(b, BPoint(x,y)); + bbview->SetDrawingMode(t); + bbview->Sync(); + bb->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), view)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *bb = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + bb->Lock(); + drawing_mode t = bView->DrawingMode(); + bView->SetDrawingMode(myMode); + bView->DrawBitmap(b, BPoint(x,y)); + bView->Sync(); + bView->SetDrawingMode(t); + bb->Unlock(); + + myView->Draw(BRect(x,y,x+b->Bounds().Width(),y+b->Bounds().Height())); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(view, "VIEW, BITMAP or CANVAS"); + } + } + } + Error(bitmap, "BITMAP"); +} + +void YabInterface::BitmapDraw(BRect frame, const char* bitmap, const char* mode, const char* view) +{ + int scaling = 0; + if(frame.right == -1) scaling = 1; + if(frame.bottom == -1) scaling = 2; + if(frame.right == -1 && frame.bottom == -1) scaling = 3; + + drawing_mode myMode; + BString tmp(mode); + if(tmp.IFindFirst("copy")!=B_ERROR) + myMode = B_OP_COPY; + else if(tmp.IFindFirst("alpha")!=B_ERROR) + myMode = B_OP_ALPHA; + else + ErrorGen("Unknown option"); + + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(bitmap); + if(bview) + { + BRect newframe; + switch(scaling) + { + case 1: + { + BRect t(b->Bounds()); + double width; + newframe = frame; + width = (t.right-t.left)*((frame.bottom-frame.top)/(t.bottom-t.top)); + newframe.right = newframe.left+width; + } + break; + case 2: + { + BRect t(b->Bounds()); + double height; + newframe = frame; + height = (t.bottom-t.top)*((frame.right-frame.left)/(t.right-t.left)); + newframe.bottom = newframe.top+height; + } + break; + case 3: newframe = b->Bounds(); + break; + default: newframe = frame; + } + + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + BBitmap *newb = new BBitmap(b->Bounds(), B_RGBA32); + char* newbits = (char*)newb->Bits(); + char* oldbits = (char*)b->Bits(); + for(int j=0; jBitsLength(); j++) + newbits[j] = oldbits[j]; + w->Lock(); + YabDrawing *t = new YabDrawing(); + t->command = 11; + t->x1 = newframe.left; t->y1 = newframe.top; + t->x2 = newframe.right; t->y2 = newframe.bottom; + t->bitmap = newb; + myView->drawList->AddItem(t); + myView->Invalidate(); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *bb = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bbview = bb->FindView(view); + if(bbview) + { + bb->Lock(); + drawing_mode t = bbview->DrawingMode(); + bbview->SetDrawingMode(myMode); + bbview->DrawBitmap(b, newframe); + bbview->SetDrawingMode(t); + bbview->Sync(); + bb->Unlock(); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), view)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *bb = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + bb->Lock(); + drawing_mode t = bView->DrawingMode(); + bView->SetDrawingMode(myMode); + bView->DrawBitmap(b, frame); + bView->Sync(); + bView->SetDrawingMode(t); + bb->Unlock(); + + myView->Draw(newframe); + w->Unlock(); + return; + } + else + ErrorGen("Unable to lock window"); + } + } + Error(view, "VIEW, BITMAP or CANVAS"); + } + } + } + Error(bitmap, "BITMAP"); +} + +void YabInterface::BitmapGet(BRect frame, const char* id, const char* bitmap) +{ + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(bitmap); + if(bview) + { + char *oldbits, *newbits; + BBitmap *newbmp = new BBitmap(BRect(0,0, frame.Width(), frame.Height()), B_RGBA32, true); + BView *newbview = new BView(BRect(0,0, frame.Width(), frame.Height()), id, B_FOLLOW_NONE, 0); + newbmp->AddChild(newbview); + newbits = (char*)newbmp->Bits(); + for(int i=0; iBits(); + b->Lock(); + BRect tframe = bview->Bounds(); + b->Unlock(); + if(frame.top>tframe.bottom || frame.left>tframe.right || frame.bottom>tframe.bottom || frame.right>tframe.right || frame.top<0 || frame.left<0 || frame.right<0 || frame.bottom<0) + ErrorGen("Out of bounds"); + for(int32 j = 0; jBytesPerRow()+k*4+l] = oldbits[(int32)((j+frame.top)*b->BytesPerRow()+(k+frame.left)*4+l)]; + yabbitmaps->AddItem(newbmp); + return; + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), bitmap)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *b = myView->GetBitmap(); + char *oldbits, *newbits; + BBitmap *newbmp = new BBitmap(BRect(0,0, frame.Width(), frame.Height()), B_RGBA32, true); + BView *newbview = new BView(BRect(0,0, frame.Width(), frame.Height()), id, B_FOLLOW_NONE, 0); + newbmp->AddChild(newbview); + newbits = (char*)newbmp->Bits(); + for(int i=0; iBits(); + BRect tframe = myView->Bounds(); + if(frame.top>tframe.bottom || frame.left>tframe.right || frame.bottom>tframe.bottom || frame.right>tframe.right || frame.top<0 || frame.left<0 || frame.right<0 || frame.bottom<0) + ErrorGen("Out of bounds"); + for(int32 j = 0; jBytesPerRow()+k*4+l] = oldbits[(int32)((j+frame.top)*b->BytesPerRow()+(k+frame.left)*4+l)]; + yabbitmaps->AddItem(newbmp); + w->Unlock(); + return; + } + } + } + Error(bitmap, "BITMAP or CANVAS"); +} + +void YabInterface::BitmapGet(double w, const char* id, const char* path) +{ + double h = w; + BRect iFrame = BRect(0, 0, w-1, h-1); + BBitmap *iBitmap = new BBitmap(iFrame, B_CMAP8, true); + BBitmap *fBitmap = new BBitmap(iFrame, B_RGBA32, true); + BView *bview = new BView(iFrame, id, B_FOLLOW_NONE, 0); + fBitmap->AddChild(bview); + + char *b; + b = (char*)fBitmap->Bits(); + for(int i=0; iLock(); + bview->DrawBitmap( iBitmap, iFrame ); + fBitmap->Unlock(); + + delete fNode; + delete iBitmap; + yabbitmaps->AddItem(fBitmap); +} + +void YabInterface::BitmapGetIcon(const char* id, const char* option, const char* path) +{ + BString fString(option); + if( fString.IFindFirst("Path") != B_ERROR ) + { + int w; + int h = w = 32; + BRect iFrame = BRect(0, 0, w-1, h-1); + BBitmap *iBitmap = new BBitmap(iFrame, B_CMAP8, true); + BBitmap *fBitmap = new BBitmap(iFrame, B_RGBA32, true); + BView *bview = new BView(iFrame, id, B_FOLLOW_NONE, 0); + fBitmap->AddChild(bview); + + char *b; + b = (char*)fBitmap->Bits(); + for(int i=0; iLock(); + bview->DrawBitmap( iBitmap, iFrame ); + fBitmap->Unlock(); + + delete fNode; + delete iBitmap; + yabbitmaps->AddItem(fBitmap); + + } + else if( fString.IFindFirst("Mime") != B_ERROR ) + { + int w; + int h = w = 16; + icon_size iType = B_MINI_ICON; + if( fString.IFindFirst("Mime32") != B_ERROR ) + { + h = w = 32; + iType = B_LARGE_ICON; + } + + BRect iFrame = BRect(0, 0, w-1, h-1); + BBitmap *iBitmap = new BBitmap(iFrame, B_CMAP8, true); + BBitmap *fBitmap = new BBitmap(iFrame, B_RGBA32, true); + BView *bview = new BView(iFrame, id, B_FOLLOW_NONE, 0); + fBitmap->AddChild(bview); + + char *b; + b = (char*)fBitmap->Bits(); + for(int i=0; iLock(); + bview->DrawBitmap(iBitmap, iFrame); + bview->Sync(); + fBitmap->Unlock(); + + delete iBitmap; + yabbitmaps->AddItem(fBitmap); + } + else + ErrorGen("Unknown option"); + +} + +void YabInterface::BitmapDrag(const char* bitmap) +{ +} + +void YabInterface::BitmapRemove(const char* bitmap) +{ + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(bitmap); + if(bview) + { + yabbitmaps->RemoveItem(i); + delete b; + return; + } + } + Error(bitmap, "BITMAP"); +} + +void YabInterface::Screenshot(BRect frame, const char* bitmap) +{ + char *t; + int w = (int)frame.Width()-1; + int h = (int)frame.Height()-1; + + BRect area = BRect(0,0,w,h); + BBitmap *fBitmap = new BBitmap(area, B_RGBA32, true); + BView *bview = new BView(area, bitmap, B_FOLLOW_NONE, 0); + BScreen screen(B_MAIN_SCREEN_ID); + fBitmap->AddChild(bview); + + t = (char*)fBitmap->Bits(); + for(int i=0; iAddItem(fBitmap); +} + +int YabInterface::BitmapLoad(const char* FileName, const char* id) +{ + BBitmap* myBitmap = NULL; + BFile imageFile; + BPath imagePath; + int ret = 0; + + if(*FileName=='/') + imageFile.SetTo(FileName, B_READ_ONLY); + else + if(!strcmp(ApplicationDirectory,"")) + { + if(imagePath.SetTo((const char*)ApplicationDirectory, FileName)==B_OK) + imageFile.SetTo(imagePath.Path(), B_READ_ONLY); + } + + if(imageFile.InitCheck()!=B_OK) + imageFile.SetTo(FileName, B_READ_ONLY); + + if(imageFile.InitCheck()!=B_OK) + return 1; + + Roster = BTranslatorRoster::Default(); + + if(!Roster) + return 2; + + BBitmapStream Stream; + + if(Roster->Translate(&imageFile, NULL, NULL, &Stream, B_TRANSLATOR_BITMAP)Bounds(), B_RGBA32, true); + BView *bview = new BView(myBitmap->Bounds(), id, B_FOLLOW_NONE, 0); + b->AddChild(bview); + /* + t = (char*)b->Bits(); + for(int i=0; iLock(); + drawing_mode mode = bview->DrawingMode(); + bview->SetDrawingMode(B_OP_ALPHA); + bview->DrawBitmap(myBitmap, myBitmap->Bounds()); + bview->SetDrawingMode(mode); + bview->Sync(); + b->Unlock(); + + delete Roster; + delete myBitmap; + + yabbitmaps->AddItem(b); + + return 0; +} + +int YabInterface::BitmapGet(const char* id, const char* option) +{ + BString t(option); + bool isWidth = false; + if(t.IFindFirst("height") != B_ERROR) + isWidth = false; + else if(t.IFindFirst("width") != B_ERROR) + isWidth = true; + else + ErrorGen("Unknown option"); + + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(id); + if(bview) + { + BRect r = b->Bounds(); + if(isWidth) + return r.IntegerWidth()+1; + else + return r.IntegerHeight()+1; + } + } + Error(id, "BITMAP"); +} + +int YabInterface::BitmapSave(const char* id, const char* filename, const char* type) +{ + uint32 btype; + BString t(type); + if(t.IFindFirst("png") != B_ERROR) + btype = B_PNG_FORMAT; + else if(t.IFindFirst("jpg") != B_ERROR) + btype = B_JPEG_FORMAT; + else if(t.IFindFirst("tga") != B_ERROR) + btype = B_TGA_FORMAT; + else if(t.IFindFirst("tiff") != B_ERROR) + btype = B_TIFF_FORMAT; + else if(t.IFindFirst("ppm") != B_ERROR) + btype = B_PPM_FORMAT; + else if(t.IFindFirst("bmp") != B_ERROR) + btype = B_BMP_FORMAT; + else + ErrorGen("Unknown type"); + + for(int i=0; iCountItems(); i++) + { + BBitmap *b = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bview = b->FindView(id); + if(bview) + { + BTranslatorRoster *roster = BTranslatorRoster::Default(); + BBitmapStream stream(b); // init with contents of bitmap + BFile file(filename, B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); + if(roster->Translate(&stream, NULL, NULL, &file, btype) != B_OK) + return 1; + else + return 0; + } + } + Error(id, "BITMAP"); +} + +void YabInterface::Canvas(BRect frame, const char* id, const char* view) +{ + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + YabBitmapView *bmpView = new YabBitmapView(frame, id, B_FOLLOW_NONE, B_WILL_DRAW); + if(w->layout == -1) + bmpView->SetResizingMode(B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + else + bmpView->SetResizingMode(w->layout); + myView->AddChild(bmpView); + yabcanvas->AddItem(bmpView); + myView->Invalidate(frame); + w->Unlock(); + return; + } + } + Error(view, "VIEW"); +} + +int YabInterface::Sound(const char* filename) +{ + entry_ref ref; + BEntry entry(filename, true); + + if (entry.InitCheck() == B_OK) + if (entry.GetRef(&ref) == B_OK) + return play_sound(&ref, true, false, true); + return -1; +} + +void YabInterface::SoundStop(int32 id) +{ + stop_sound(id); +} + +void YabInterface::SoundWait(int32 id) +{ + wait_for_sound(id); +} + +void YabInterface::SetOption(const char* id, const char* option, double x, double y) +{ + BString tmp(option); + YabView *myView = 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(); + BView *theView = cast_as(myView->FindView(id), BView); + if(theView) + { + if(tmp.IFindFirst("ResizeTo")!=B_ERROR) + theView->ResizeTo(x,y); + else if(tmp.IFindFirst("ResizeBy")!=B_ERROR) + theView->ResizeBy(x,y); + else if(tmp.IFindFirst("MoveTo")!=B_ERROR) + theView->MoveTo(x,y); + else if(tmp.IFindFirst("MoveBy")!=B_ERROR) + theView->MoveBy(x,y); + else + ErrorGen("Unknown option"); + theView->Invalidate(); + w->Unlock(); + return; + } + w->Unlock(); + } + } + } + Error(id, "VIEW"); +} + +void YabInterface::DrawSet(const char* option, const char* color,const char* view) +{ + BString tmp(option); + BString colstr(color); + rgb_color col; + if(colstr.IFindFirst("Panel-Background-Color")!=B_ERROR) + col = ui_color(B_PANEL_BACKGROUND_COLOR); + else if(colstr.IFindFirst("Panel-Text-Color")!=B_ERROR) + { + col = ui_color(B_PANEL_TEXT_COLOR); + } + else if(colstr.IFindFirst("Panel-Link-Color")!=B_ERROR) + { + col.red = 0; col.green = 0; col.blue = 255; + } + else if(colstr.IFindFirst("Menu-Background-Color")!=B_ERROR) + col = ui_color(B_MENU_BACKGROUND_COLOR); + else if(colstr.IFindFirst("Menu-Selection-Background-Color")!=B_ERROR) + col = ui_color(B_MENU_SELECTION_BACKGROUND_COLOR); + else if(colstr.IFindFirst("Menu-Item-Text-Color")!=B_ERROR) + col = ui_color(B_MENU_ITEM_TEXT_COLOR); + else if(colstr.IFindFirst("Menu-Selected-Item-Text-Color")!=B_ERROR) + col = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); + else if(colstr.IFindFirst("Keyboard-Navigation-Color")!=B_ERROR) + col = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + else if(colstr.IFindFirst("Jan-Favorite-Color")!=B_ERROR) + { + col.red = 220; col.green = 220; col.blue = 250; + } + else + ErrorGen("Invalid color"); + if(colstr.IFindFirst("Lighten-1-Tint")!=B_ERROR) + col = tint_color(col, B_LIGHTEN_1_TINT); + else if(colstr.IFindFirst("Lighten-2-Tint")!=B_ERROR) + col = tint_color(col, B_LIGHTEN_2_TINT); + else if(colstr.IFindFirst("Lighten-Max-Tint")!=B_ERROR) + col = tint_color(col, B_LIGHTEN_MAX_TINT); + else if(colstr.IFindFirst("Darken-1-Tint")!=B_ERROR) + col = tint_color(col, B_DARKEN_1_TINT); + else if(colstr.IFindFirst("Darken-2-Tint")!=B_ERROR) + col = tint_color(col, B_DARKEN_2_TINT); + else if(colstr.IFindFirst("Darken-3-Tint")!=B_ERROR) + col = tint_color(col, B_DARKEN_3_TINT); + else if(colstr.IFindFirst("Darken-4-Tint")!=B_ERROR) + col = tint_color(col, B_DARKEN_4_TINT); + else if(colstr.IFindFirst("Darken-Max-Tint")!=B_ERROR) + col = tint_color(col, B_DARKEN_MAX_TINT); + else if(colstr.IFindFirst("Disabled-Label-Tint")!=B_ERROR) + col = tint_color(col, B_DISABLED_LABEL_TINT); + else if(colstr.IFindFirst("Disabled-Mark-Tint")!=B_ERROR) + col = tint_color(col, B_DISABLED_MARK_TINT); + else if(colstr.IFindFirst("Highlight-Background-Tint")!=B_ERROR) + col = tint_color(col, B_HIGHLIGHT_BACKGROUND_TINT); + col.alpha = yabAlpha; + + YabView *myView = cast_as((BView*)viewList->GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + if(tmp.IFindFirst("BGColor")!=B_ERROR) + { + myView->SetViewColor(col); + myView->Invalidate(); + } + else if(tmp.IFindFirst("HighColor")!=B_ERROR) + { + if(yabAlpha == 255) + myView->SetDrawingMode(B_OP_COPY); + else + myView->SetDrawingMode(B_OP_ALPHA); + myView->SetHighColor(col); + YabDrawing *t = new YabDrawing(); + t->command = 6; + t->r = col.red; t->g = col.green; + t->b = col.blue; t->alpha = yabAlpha; + myView->drawList->AddItem(t); + } + else if(tmp.IFindFirst("LowColor")!=B_ERROR) + { + if(yabAlpha == 255) + myView->SetDrawingMode(B_OP_COPY); + else + myView->SetDrawingMode(B_OP_ALPHA); + myView->SetLowColor(col); + YabDrawing *t = new YabDrawing(); + t->command = 7; + t->r = col.red; t->g = col.green; + t->b = col.blue; t->alpha = yabAlpha; + myView->drawList->AddItem(t); + } + else + ErrorGen("Unknown option"); + w->Unlock(); + } + else + ErrorGen("Unable to lock window"); + } + else + { + for(int i=0; iCountItems(); i++) + { + BBitmap *bmp = (BBitmap*)yabbitmaps->ItemAt(i); + BView *bView = bmp->FindView(view); + if(bView) + { + if(tmp.IFindFirst("HighColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetHighColor(col); + bView->Sync(); + bmp->Unlock(); + return; + } + else if(tmp.IFindFirst("LowColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetLowColor(col); + bView->Sync(); + bmp->Unlock(); + return; + } + else + ErrorGen("Unknown option"); + } + } + for(int i=0; iCountItems(); i++) + { + YabBitmapView *myView = (YabBitmapView*)yabcanvas->ItemAt(i); + if(!strcmp(myView->Name(), view)) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BBitmap *bmp = myView->GetBitmap(); + BView *bView = myView->GetBitmapView(); + if(tmp.IFindFirst("HighColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetHighColor(col); + bView->Sync(); + bmp->Unlock(); + w->Unlock(); + return; + } + else if(tmp.IFindFirst("LowColor")!=B_ERROR) + { + bmp->Lock(); + if(yabAlpha == 255) + bView->SetDrawingMode(B_OP_COPY); + else + bView->SetDrawingMode(B_OP_ALPHA); + bView->SetLowColor(col); + bView->Sync(); + bmp->Unlock(); + w->Unlock(); + return; + } + else + ErrorGen("Unknown option"); + } + else + ErrorGen("Unable to lock window"); + } + } + Error(view, "VIEW, BITMAP or CANVAS"); + } +} + +void YabInterface::Treebox13(const char* id,const char* option, int pos) +{ +} + +int YabInterface::TreeboxGetOpt(const char* id, const char* option, int pos) +{ +} + +int YabInterface::ListboxGetNum(const char* id) +{ + YabView *myView = NULL; + BListView *myList = 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(); + myList = cast_as(myView->FindView(id), BListView); + if(myList) + { + int32 t = myList->CurrentSelection(); + w->Unlock(); + return t+1; + } + w->Unlock(); + } + } + } + Error(id, "LISTBOX"); +} + +int YabInterface::DropboxGetNum(const char* id) +{ + YabView *myView = 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(); + BMenuField *myMenuField = cast_as(myView->FindView(id), BMenuField); + if(myMenuField) + { + BMenu *myMenu = (BMenu*)myMenuField->Menu(); + if(myMenu) + { + int32 ret; + ret = myMenu->IndexOf(myMenu->FindMarked()); + w->Unlock(); + return ret; + } + } + w->Unlock(); + } + } + } + Error(id, "DROPBOX"); +} + +int YabInterface::TreeboxGetNum(const char* id) +{ + YabView *myView = NULL; + BOutlineListView *myList = 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(); + myList = cast_as(myView->FindView(id), BOutlineListView); + if(myList) + { + int32 t = myList->FullListCurrentSelection(); + w->Unlock(); + return t+1; + } + w->Unlock(); + } + } + } + Error(id, "TREEBOX"); +} + +int YabInterface::ColumnboxGetNum(const char* id) +{ + YabView *myView = NULL; + BColumnListView *myList = 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(); + myList = cast_as(myView->FindView(id), BColumnListView); + if(myList) + { + int32 t = myList->IndexOf(myList->CurrentSelection()); + w->Unlock(); + return t+1; + } + w->Unlock(); + } + } + } + Error(id, "COLUMNBOX"); +} + +void YabInterface::Attribute1(const char* type, const char* name, const char* value, const char* filename) +{ + + // fix to work properly with string and bool types. + BNode node(filename); + if(node.InitCheck() != B_OK) + ErrorGen("Attribute file not found!"); + BString tempvalue(value); + + + type_code typecode; + BString typeStr(type); + if(typeStr.IFindFirst("string")!=B_ERROR) + { + int32 x = tempvalue.Length(); + typecode = B_STRING_TYPE; + x++; + node.WriteAttr(name, typecode, 0, value, x); + } + else if(typeStr.IFindFirst("mime")!=B_ERROR) + { + int32 x = tempvalue.Length(); + typecode = B_MIME_STRING_TYPE; + x++; + node.WriteAttr(name, typecode, 0, value, x); + } + else if(typeStr.IFindFirst("bool")!=B_ERROR) + { + typecode = B_BOOL_TYPE; + int32 x=1; + char str[1]; + str[0]=1; + const char* tf = str; + if (tempvalue.IFindFirst("false") !=B_ERROR) + tf=""; + node.WriteAttr(name, typecode, 0, tf, x); + } + + + else if(typeStr.IFindFirst("int")!=B_ERROR) + { + int32 x = tempvalue.Length(); + typecode = B_INT32_TYPE; + node.WriteAttr(name, typecode, 0, value, x); + } + + + else if(typeStr.IFindFirst("double")!=B_ERROR) + { + int32 x = tempvalue.Length(); + typecode = B_DOUBLE_TYPE; + node.WriteAttr(name, typecode, 0, value, x); + } + else if(typeStr.IFindFirst("float")!=B_ERROR) + { + int32 x = tempvalue.Length(); + typecode = B_FLOAT_TYPE; + node.WriteAttr(name, typecode, 0, value, x); + } + else if(typeStr.IFindFirst("long")!=B_ERROR) + { + int32 x = tempvalue.Length(); + typecode = B_INT64_TYPE; + node.WriteAttr(name, typecode, 0, value, x); + } + else + ErrorGen("Unknown attribute type!"); + + + +} + +void YabInterface::AttributeClear(const char* name, const char* filename) +{ + BNode node(filename); + if(node.InitCheck() != B_OK) + ErrorGen("Attribute file not found!"); + node.RemoveAttr(name); +} + +const char* YabInterface::AttributeGet1(const char* name, const char* filename) +{ + BString tempname(name); + BNode node(filename); + if(node.InitCheck() != B_OK) + ErrorGen("Attribute file not found!"); + if (tempname.Length() >0) + { + attr_info attr; + if(node.GetAttrInfo(name, &attr) != B_OK) + ErrorGen("Attribute not found!"); + + int size = attr.size; + if(size>32568) + size = 32568; + if(node.ReadAttr(name,attr.type, 0, attrbuffer, size) == 0) + return ""; + + if (attr.type == B_BOOL_TYPE) + { + int x = 0; + if (attrbuffer[0] == x) + { + return "false"; + } + else + { + return "true"; + } + } + + return (char*)attrbuffer; + } + else + { + BString List=""; + BString sp=" | "; + BString Attrtype; + char buf[B_ATTR_NAME_LENGTH]; + while (node.GetNextAttrName(buf) == B_OK) + { + attr_info attr; + if(node.GetAttrInfo(buf, &attr) != B_OK) + ErrorGen("Attribute not found!"); + uint32 attrtype; + attrtype=attr.type; + switch(attrtype) + { + case B_BOOL_TYPE: + Attrtype="Bool"; + break; + case B_STRING_TYPE: + Attrtype = "String"; + break; + case B_MIME_STRING_TYPE: + Attrtype = "Mime"; + break; + case B_INT32_TYPE: + Attrtype = "Int"; + break; + case B_DOUBLE_TYPE: + Attrtype = "Double"; + break; + case B_FLOAT_TYPE: + Attrtype = "Float"; + break; + case B_INT64_TYPE: + Attrtype = "Long"; + break; + default: + Attrtype = "Unsupported"; + break; + } + + + List << buf << sp << Attrtype << sp; + } + + + return List.String(); + + } +} + +double YabInterface::AttributeGet2(const char* name, const char* filename) +{ + BNode node(filename); + if(node.InitCheck() != B_OK) + ErrorGen("Attribute file not found!"); + + attr_info attr; + if(node.GetAttrInfo(name, &attr) != B_OK) + ErrorGen("Attribute not found!"); + int size = attr.size; + if(size>32568) + size = 32568; + if(node.ReadAttr(name,attr.type, 0, attrbuffer, size) == 0) + return 0.0; + if (attr.type == B_BOOL_TYPE) + { + int x = 0; + if (attrbuffer[0] == x) + { + return 0.0; + } + else + { + return 1.0; + } + } + + + if(node.ReadAttr(name, 0, 0, attrbuffer, size) == 0) + return 0.0; + return atof((char*)attrbuffer); +} +void YabInterface::ShortCut(const char* view, const char* key, const char* msg) +{ + char myShortcut; + int32 modifiers = 0; + BString t(key); + if(t.Length()>1) + { + myShortcut = key[t.Length()-1]; + if(t.IFindFirst("s")!=B_ERROR && t.IFindFirst("s")GetView(view), YabView); + if(myView) + { + YabWindow *w = cast_as(myView->Window(), YabWindow); + if(w) + { + w->Lock(); + BMessage *mesg = new BMessage(YABSHORTCUT); + mesg->AddString("shortcut", msg); + w->AddShortcut(myShortcut, modifiers, mesg); + w->Unlock(); + return; + } + } + Error(view,"VIEW"); +} + +int YabInterface::IsComputerOn() +{ + return is_computer_on(); +} + +void YabInterface::MouseSet(const char* opt) +{ + BString t(opt); + if(t.IFindFirst("Hide")!=B_ERROR) + HideCursor(); + else if(t.IFindFirst("Show")!=B_ERROR) + ShowCursor(); + else if(t.IFindFirst("Obscure")!=B_ERROR) + ObscureCursor(); + else ErrorGen("Unknown option"); +} + +const char* YabInterface::GetMessageString() +{ + snooze(20000); + BString tmp(""); + if(exiting) + { + tmp += "_QuitRequested|"; + exiting = false; + } + tmp += localMessage; + localMessage = ""; + for(int i=0; iTitle(), "_TOOLTIPWINDOW") && strcmp(WindowAt(i)->Title(), "_CALENDARWINDOW")) + + + YabWindow *w = cast_as(WindowAt(i), YabWindow); + if(w) + { + + w->Sync(); + if(w->Lock()) + { + tmp += w->getMessages(); + if (w->WActivated==1) + { + tmp+=w->idString; + tmp+=":_Activated|"; + w->WActivated=-1; + } + if (w->WActivated==0) + { + tmp+=w->idString; + tmp+=":_Deactivated|"; + w->WActivated=-1; + } +// if (w->WFrameMoved==1) +// { +// w->WFrameMoved=-1; +// tmp+=w->Name(); +// tmp+=":_FrameMoved:"; +// tmp << w->Wpx; +// tmp+=":"; +// tmp << w->Wpy; +// tmp+="|"; +// } +// if (w->WFrameResized==1) +// { +// w->WFrameResized=-1; +// tmp+=w->Name(); +// tmp+=":_FrameResized:"; +// tmp << w->Wpw; +// tmp+=":"; +// tmp << w->Wph; +// tmp+="|"; +// } + w->Unlock(); + } + } + } + + + YabView *myView = 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(); + if (myView->CountChildren()) + { + for (int o=0; oCountChildren(); o++) + { + if (dynamic_cast(myView->ChildAt(o))) + { + YabTabView *target = dynamic_cast(myView->ChildAt(o)); + if (target) + { + if (target->FocusChanged!=target->OldTabView) + { + tmp+=target->Name(); + tmp+=":_TabChanged:"; + tmp+=target->Name(); + tmp << target->FocusChanged; + tmp+="|"; + target->OldTabView=target->FocusChanged; + } + + } + } + + } + } + w->Unlock(); + } + } + } + if(tmp.Length()>32766) + tmp.Remove(32767, tmp.Length()-32766); + strcpy(messagebuffer, tmp.String()); + return (char*)messagebuffer; +} + +int YabInterface::MessageSend(const char* app, const char* msg) +{ + BMessage message, reply; + status_t result; + + // set the command constant + message.what = B_SET_PROPERTY; + + // construct the specifier stack + message.AddSpecifier("YabSendString", msg); // B_NAME_SPECIFIER + + // send the message and fetch the result + result = BMessenger(app).SendMessage(&message, &reply); + if(result == B_OK) return 0; + if(result == B_BAD_PORT_ID) return 1; + if(result == B_WOULD_BLOCK) return 2; + if(result == B_TIMED_OUT) return 3; + return 4; +} + +void YabInterface::SetLocalize(const char* path) +{ + if(yabCatalog) + delete yabCatalog; + //yabCatalog = new BCatalog(path); +} + +const int YabInterface::GetErrorCode() +{ + return errorCode; +} + +void YabInterface::KillThread(int code) +{ + errorCode = code; + quitting = true; + ExitRequested(); + // BMessenger(be_app).SendMessage(new BMessage(B_QUIT_REQUESTED)); + // while(1){} +} + +void YabInterface::Error(const char* id, const char* type) +{ + fprintf(stderr, "---Error in %s, line %d: \"%s\" is not of type %s\n", currentLib.String(), currentLineNumber, id, type); + fprintf(stderr,"---Error: Program stopped due to an error \n"); + KillThread(-1); + // while(1){} +} + +void YabInterface::ErrorGen(const char* msg) +{ + fprintf(stderr, "---Error in %s, line %d: %s\n", currentLib.String(), currentLineNumber, msg); + fprintf(stderr,"---Error: Program stopped due to an error \n"); + KillThread(-1); + // while(1){} +} + +void YabInterface::SetCurrentLineNumber(int line, const char* libname) +{ + currentLineNumber = line; + if(!strcmp(libname, "main")) + currentLib = mainFileName; + else + currentLib = libname; +} + +void YabInterface::SetMainFileName(const char* name) +{ + mainFileName = strdup(name); +} + +/** + * C interface functions + */ + +const char* yi_GetApplicationDirectory(YabInterface *yab) +{ + return yab->GetApplicationDirectory(); +} + +void yi_OpenWindow(double x1,double y1,double x2,double y2, const char* id, const char* title, YabInterface* yab) +{ + yab->OpenWindow(BRect(x1,y1,x2,y2), id, _L(title)); +} + +int yi_CloseWindow(const char* view, YabInterface* yab) +{ + return yab->CloseWindow(view); +} + +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); +} + +int yi_CreateImage(double x,double y,const char* imagefile, const char* window, YabInterface* yab) +{ + return yab->CreateImage(BPoint(x,y),imagefile,window); +} + +int yi_CreateImage2(double x1,double y1,double x2,double y2,const char* imagefile, const char* window, YabInterface* yab) +{ + return yab->CreateImage(BRect(x1,y1,x2,y2),imagefile,window); +} + +int yi_CreateSVG(double x1,double y1,double x2,double y2,const char* imagefile, const char* window, YabInterface* yab) +{ + return yab->CreateSVG(BRect(x1,y1,x2,y2),imagefile,window); +} + +void yi_CreateMenu(const char* menuhead, const char* menuitem, const char *shortcut, const char* window, YabInterface* yab) +{ + yab->CreateMenu(_L(menuhead),_L(menuitem),shortcut,window); +} + +void yi_CreateTextControl(double x1, double y1, double x2, double y2, const char* id, const char* label, const char* text, const char* window, YabInterface *yab) +{ + yab->CreateTextControl(BRect(x1,y1,x2,y2),id,_L(label),_L(text),window); +} + +void yi_CreateCheckBox(double x, double y, const char* id, const char* label, int isActivated, const char* window, YabInterface *yab) +{ + yab->CreateCheckBox(x,y,id,_L(label),isActivated,window); +} + +void yi_CreateRadioButton(double x, double y, const char* groupID, const char* label, int isActivated, const char* window, YabInterface *yab) +{ + yab->CreateRadioButton(x,y,groupID,_L(label),isActivated,window); +} + +void yi_CreateListBox(double x1, double y1, double x2, double y2, const char* title, int scrollbar, const char* window, YabInterface *yab) +{ + yab->CreateListBox(BRect(x1,y1,x2,y2),title,scrollbar,window); +} + +void yi_CreateDropBox(double x1, double y1, double x2, double y2, const char* title, const char* label, const char* window, YabInterface *yab) +{ + yab->CreateDropBox(BRect(x1,y1,x2,y2),title,_L(label), window); +} + +void yi_CreateItem(const char* id,const char* item, YabInterface *yab) +{ + yab->CreateItem(id,_L(item)); +} + +void yi_RemoveItem(const char* title,const char* item, YabInterface *yab) +{ + yab->RemoveItem(title,_L(item)); +} + +void yi_ClearItems(const char* title, YabInterface *yab) +{ + yab->ClearItems(title); +} + +void yi_DrawText(double x, double y, const char* text, const char* window, YabInterface* yab) +{ + yab->DrawText(BPoint(x,y), _L(text), window); +} + +void yi_DrawRect(double x1, double y1, double x2, double y2, const char* window, YabInterface* yab) +{ + yab->DrawRect(BRect(x1,y1,x2,y2),window); +} + +void yi_DrawClear(const char* window, YabInterface* yab) +{ + yab->DrawClear(window, false); +} + +void yi_CreateAlert(const char* text, const char* button1, const char* type, YabInterface* yab) +{ + yab->CreateAlert(_L(text),_L(button1),type); +} + +void yi_CreateText(double x, double y, const char* id, const char* text, const char* window, YabInterface* yab) +{ + yab->CreateText(x,y,id,_L(text),window); +} + +void yi_Text2(double x1, double y1, double x2, double y2, const char* id, const char* text, const char* window, YabInterface* yab) +{ + yab->Text2(BRect(x1,y1,x2,y2),id,_L(text),window); +} + +void yi_TextAlign(const char* txt, const char *option, YabInterface *yab) +{ + yab->TextAlign(txt, option); +} + +void yi_Translate(char* text, char result[]) +{ + if(yabCatalog) + { + result[0] = '\0'; + strcpy(result,yabCatalog->GetString(text, NULL)); + } + else + strcpy(result,text); +} + +void yi_MenuTranslate(char* text, char result[]) +{ + if(yabCatalog) + { + result[0] = '\0'; + const char* token; + const char delimiters[] = ":"; + + token = strtok(text, delimiters); + while(token!=NULL) + { + strcat(result,yabCatalog->GetString(token, NULL)); //B_TRANSLATE_CONTEXT)); + token = strtok(NULL, delimiters); + if(token!=NULL) strcat(result,":"); + } + } + else + strcpy(result,text); +} + +void yi_SetLocalize() +{ + localize = true; +} + +void yi_StopLocalize() +{ + localize = false; +} + +void yi_SetLocalize2(const char* , YabInterface *yab) +{ + localize = true; + //yab->SetLocalize(path); +} + +const char* yi_LoadFilePanel(const char* mode, const char* title, const char* directory, YabInterface *yab) +{ + return yab->LoadFilePanel(mode, _L(title), directory); +} + +const char* yi_SaveFilePanel(const char* mode, const char* title, const char* directory, const char*filename, YabInterface *yab) +{ + return yab->SaveFilePanel(mode, _L(title), directory, filename); +} + +void yi_SetLayout(const char* layout, const char* window, YabInterface *yab) +{ + yab->SetLayout(layout, window); +} + +void yi_WindowSet1(const char* option, const char* value, const char* window, YabInterface *yab) +{ + yab->WindowSet(option, value, window); +} + +void yi_WindowSet2(const char* option, int r, int g, int b, const char* window, YabInterface *yab) +{ + yab->WindowSet(option, r, g, b, window); +} + +void yi_WindowSet3(const char* option, double x, double y, const char* window, YabInterface *yab) +{ + yab->WindowSet(option,x,y, window); +} + +void yi_WindowSet4(const char* option, const char* window, YabInterface *yab) +{ + yab->WindowSet(option, window); +} + +void yi_WindowClear(const char* window, YabInterface *yab) +{ + yab->WindowClear(window); +} + +void yi_TextEdit(double x1, double y1, double x2, double y2, const char* title, int scrollbar, const char* window, YabInterface *yab) +{ + yab->TextEdit(BRect(x1,y1,x2,y2), title, scrollbar, window); +} + +void yi_TextAdd(const char* title, const char* text, YabInterface *yab) +{ + yab->TextAdd(title,text); +} + +void yi_TextSet(const char* title, const char* option, YabInterface *yab) +{ + yab->TextSet(title,option); +} + +void yi_TextSet2(const char* title, const char* option, int value, YabInterface *yab) +{ + yab->TextSet(title,option,value); +} + +void yi_TextSet3(const char* title, const char* option, const char* value, YabInterface *yab) +{ + yab->TextSet(title,option,value); +} + +void yi_TextColor1(const char* title, const char* option, const char* command, YabInterface *yab) +{ + yab->TextColor(title,option,command); +} + +void yi_TextColor2(const char* title, const char* option, int r, int g, int b, YabInterface *yab) +{ + yab->TextColor(title,option,r,g,b); +} + +int yi_TextGet2(const char* title, const char* option, YabInterface *yab) +{ + return yab->TextGet(title,option); +} + +const char* yi_TextGet3(const char* title, int linenum, YabInterface *yab) +{ + return yab->TextGet(title,linenum); +} + +double yi_TextGet4(const char* title, const char* option, int linenum, YabInterface *yab) +{ + return yab->TextGet(title,option,linenum); +} + +int yi_TextGet5(const char* title, const char* option, const char* option2, YabInterface *yab) +{ + return yab->TextGet(title,option,option2); +} + +const char* yi_TextGet6(const char* title, const char* option, YabInterface *yab) +{ + return yab->TextGet6(title, option); +} + +void yi_TextClear(const char* title, YabInterface *yab) +{ + yab->TextClear(title); +} + +const char* yi_TextGet(const char* title, YabInterface *yab) +{ + return yab->TextGet(title); +} + +void yi_DrawSet1(const char* option, const char* window, YabInterface *yab) +{ + return yab->DrawSet1(option, window); +} + +void yi_DrawSet2(int fillorstroke, const char* mypattern, YabInterface *yab) +{ + return yab->DrawSet2(fillorstroke, mypattern); +} + +void yi_View(double x1, double y1, double x2, double y2, const char* id, const char* view, YabInterface *yab) +{ + yab->View(BRect(x1,y1,x2,y2), id, view); +} + +void yi_BoxView(double x1, double y1, double x2, double y2, const char* id, const char* text, int lineType, const char* view, YabInterface *yab) +{ + yab->BoxView(BRect(x1,y1,x2,y2), id, _L(text), lineType, view); +} + +void yi_BoxViewSet(const char* id, const char* option,const char* value, YabInterface *yab) +{ + yab->BoxViewSet(id, option,value); +} + + +void yi_Tab(double x1, double y1, double x2, double y2, const char* id, const char* names, const char* view, YabInterface *yab) +{ + yab->Tab(BRect(x1,y1,x2,y2), id, names, view); +} + +void yi_TabSet(const char* id, int num, YabInterface *yab) +{ + yab->TabSet(id, num); +} + +void yi_TabAdd(const char* id, const char* tabname, YabInterface *yab) +{ + yab->TabAdd(id, _L(tabname)); +} + +void yi_TabDel(const char* id, int num, YabInterface *yab) +{ + yab->TabDel(id, num); +} + +int yi_TabViewGet(const char* id, YabInterface *yab) +{ + return yab->TabViewGet(id); +} + +void yi_DrawDot(double x, double y, const char* window, YabInterface *yab) +{ + yab->DrawDot(x,y, window); +} + +void yi_DrawLine(double x1, double y1, double x2, double y2, const char* window, YabInterface *yab) +{ + yab->DrawLine(x1,y1,x2,y2, window); +} + +void yi_DrawCircle(double x, double y, double r, const char* window, YabInterface *yab) +{ + yab->DrawCircle(x,y,r, window); +} + +void yi_DrawEllipse(double x, double y, double r1, double r2, const char* window, YabInterface *yab) +{ + yab->DrawEllipse(x,y,r1,r2, window); +} + +void yi_DrawCurve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, const char* window, YabInterface *yab) +{ + yab->DrawCurve(x1,y1,x2,y2,x3,y3,x4,y4, window); +} + +void yi_Slider1(double x1, double y1, double x2, double y2, const char* id, const char* title, int min, int max, const char* view, YabInterface *yab) +{ + yab->Slider(BRect(x1,y1,x2,y2), id, _L(title), min, max, view); +} + +void yi_Slider2(double x1, double y1, double x2, double y2, const char* id, const char* title, int min, int max, const char* option, const char* view, YabInterface *yab) +{ + yab->Slider(BRect(x1,y1,x2,y2), id, _L(title), min, max, option, view); +} + +void yi_SetSlider1(const char* id, const char* label1, const char* label2, YabInterface *yab) +{ + yab->SetSlider(id, _L(label1), _L(label2)); +} + +void yi_SetSlider2(const char* id, const char* bottomtop, int count, YabInterface *yab) +{ + yab->SetSlider(id, bottomtop, count); +} + +void yi_SetSlider3(const char* id, const char* part, int r, int g, int b, YabInterface *yab) +{ + yab->SetSlider(id, part, r,g,b); +} + +void yi_SetSlider4(const char* id, int value, YabInterface *yab) +{ + yab->SetSlider(id, value); +} + +void yi_SetOption1(const char* id, const char* option, const char* value, YabInterface *yab) +{ + yab->SetOption(id,option,value); +} + +void yi_SetOption2(const char* id, const char* option, int r, int g, int b, YabInterface *yab) +{ + yab->SetOption(id,option,r,g,b); +} + +void yi_SetOption3(const char* id, const char* option, double x, double y, YabInterface *yab) +{ + yab->SetOption(id,option,x,y); +} + +void yi_SetOption4(const char* id, const char* option, YabInterface *yab) +{ + yab->SetOption(id,option); +} + +void yi_SetOption5(const char* id, const char* option, int value, YabInterface *yab) +{ + yab->SetOption(id,option,value); +} + +void yi_DropZone(const char* view, YabInterface *yab) +{ + yab->DropZone(view); +} + +void yi_ColorControl1(double x, double y, const char* id, const char* view, YabInterface* yab) +{ + yab->ColorControl(x,y,id,view); +} + +void yi_ColorControl2(const char* id, int r, int g, int b, YabInterface* yab) +{ + yab->ColorControl(id,r,g,b); +} + +void yi_TextControl2(const char* id, const char* text, YabInterface* yab) +{ + yab->TextControl(id,_L(text)); +} + +void yi_TextControl3(const char* id, int mode, YabInterface* yab) +{ + yab->TextControl(id,mode); +} + +void yi_TextControl5(const char* id, YabInterface* yab) +{ + yab->TextControl(id); +} + +void yi_TextControl4(const char* id, const char* option, const char* value, YabInterface* yab) +{ + yab->TextControl(id,option,value); +} + +void yi_TreeBox1(double x1, double y1, double x2, double y2, const char* id, int scrollbarType, const char* view, YabInterface* yab) +{ + yab->TreeBox1(BRect(x1,y1,x2,y2), id, scrollbarType, view); +} + +void yi_TreeBox2(const char* id, const char* item, YabInterface* yab) +{ + yab->TreeBox2(id,_L(item)); +} + +void yi_TreeBox3(const char* id, const char* head, const char* item, int isExpanded, YabInterface* yab) +{ + yab->TreeBox3(id,_L(head),_L(item),isExpanded); +} + +void yi_TreeBox4(const char* id, YabInterface* yab) +{ + yab->TreeBox4(id); +} + +void yi_TreeBox5(const char* id, const char* item, YabInterface* yab) +{ + yab->TreeBox5(id,_L(item)); +} + +void yi_TreeBox7(const char* id, int pos, YabInterface* yab) +{ + yab->TreeBox7(id,pos); +} + +void yi_TreeBox8(const char* id, int pos, YabInterface* yab) +{ + yab->TreeBox8(id,pos); +} + +void yi_TreeBox9(const char* id, const char* head, const char* item, YabInterface* yab) +{ + yab->TreeBox9(id,_L(head), _L(item)); +} + +void yi_TreeBox10(const char* id, const char* head, YabInterface* yab) +{ + yab->TreeBox10(id,_L(head)); +} + +void yi_TreeBox11(const char* id, const char* head, YabInterface* yab) +{ + yab->TreeBox11(id,_L(head)); +} + +void yi_TreeBox12(const char* id, const char* item, int pos, YabInterface* yab) +{ + yab->TreeBox12(id,_L(item), pos); +} + +const char* yi_TreeboxGet(const char* treebox, int pos, YabInterface *yab) +{ + return yab->TreeboxGet(treebox, pos); +} + +int yi_TreeboxCount(const char* treebox, YabInterface *yab) +{ + return yab->TreeboxCount(treebox); +} + +void yi_ButtonImage(double x,double y,const char* id,const char* enabledon, const char* enabledoff, const char *disabled, const char* view, YabInterface *yab) +{ + yab->ButtonImage(x,y, id, enabledon, enabledoff, disabled, view); +} + +void yi_CheckboxImage(double x,double y,const char* id,const char* enabledon, const char* enabledoff, const char *disabledon, const char *disabledoff, int isActivated, const char* view, YabInterface *yab) +{ + yab->CheckboxImage(x,y, id, enabledon, enabledoff, disabledon, disabledoff, isActivated, view); +} + +void yi_CheckboxSet(const char* id, int isActivated, YabInterface* yab) +{ + yab->CheckboxSet(id, isActivated); +} + +void yi_RadioSet(const char* id, int isActivated, YabInterface* yab) +{ + yab->RadioSet(id, isActivated); +} + +void yi_ToolTip(const char* view, const char* text, YabInterface *yab) +{ + yab->ToolTips(view,_L(text)); +} + +void yi_ToolTipColor(const char* color, int r, int g, int b, YabInterface *yab) +{ + yab->ToolTipsColor(color,r,g,b); +} + +void yi_TreeSort(const char* view, YabInterface *yab) +{ + yab->TreeSort(view); +} + +void yi_ListSort(const char* view, YabInterface *yab) +{ + yab->ListSort(view); +} + +void yi_FileBox(double x1, double y1, double x2, double y2, const char* id, int scrollbartype, const char *option, const char* view, YabInterface *yab) +{ + yab->FileBox(BRect(x1,y1,x2,y2), id, scrollbartype, option, view); +} + +void yi_FileBoxAdd2(const char* columnbox, const char* name, int pos, double maxWidth, double minWidth, double width, const char* option, YabInterface *yab) +{ + yab->FileBoxAdd(columnbox, _L(name), pos, maxWidth, minWidth, width, option); +} + +void yi_FileBoxClear(const char* view, YabInterface *yab) +{ + yab->FileBoxClear(view); +} + +void yi_ColumnBoxAdd(const char* id, int column, int position, int height, const char* item, YabInterface *yab) +{ + yab->ColumnBoxAdd(id, column, position, height, _L(item)); +} + +void yi_ColumnBoxSelect(const char *columnbox, int position, YabInterface *yab) +{ + yab->ColumnBoxSelect(columnbox, position); +} + +void yi_ColumnBoxRemove(const char *columnbox, int position, YabInterface *yab) +{ + yab->ColumnBoxRemove(columnbox, position); +} + +void yi_ColumnBoxColor(const char *columnbox, const char* option, int r, int g, int b, YabInterface *yab) +{ + yab->ColumnBoxColor(columnbox, option, r,g,b); +} + +const char* yi_ColumnBoxGet(const char *columnbox, int column, int position, YabInterface *yab) +{ + return yab->ColumnBoxGet(columnbox, column, position); +} + +int yi_ColumnBoxCount(const char *columnbox, YabInterface *yab) +{ + return yab->ColumnBoxCount(columnbox); +} + +const char* yi_TextControlGet(const char* id, YabInterface* yab) +{ + return yab->TextControlGet(id); +} + +int yi_DeskbarPosition(YabInterface *yab) +{ + return yab->DeskbarParam("position"); +} + +int yi_DeskbarExpanded(YabInterface *yab) +{ + return yab->DeskbarParam("expanded"); +} + +int yi_DeskbarWidth(YabInterface *yab) +{ + return yab->DeskbarParam("width"); +} + +int yi_DeskbarHeight(YabInterface *yab) +{ + return yab->DeskbarParam("height"); +} + +int yi_DeskbarX(YabInterface *yab) +{ + return yab->DeskbarParam("x"); +} + +int yi_DeskbarY(YabInterface *yab) +{ + return yab->DeskbarParam("y"); +} + +int yi_DesktopWidth(YabInterface *yab) +{ + return yab->DesktopParam(true); +} + +int yi_DesktopHeight(YabInterface *yab) +{ + return yab->DesktopParam(false); +} + +int yi_WindowGet(const char* view, const char* option, YabInterface *yab) +{ + return yab->WindowGet(view,option); +} + +int yi_ViewGet(const char* view, const char* option, YabInterface *yab) //vasper +{ + return yab->ViewGet(view,option); +} + +void yi_ClipboardCopy(const char* text, YabInterface *yab) +{ + yab->ClipboardCopy(text); +} + +int yi_Printer(const char* docname, const char *view, const char* config, YabInterface *yab) +{ + return yab->Printer(docname, view,config); +} + +void yi_PrinterConfig(const char* config, YabInterface *yab) +{ + yab->PrinterConfig(config); +} + +const char* yi_ClipboardPaste(YabInterface *yab) +{ + return yab->ClipboardPaste(); +} + +int yi_NewAlert(const char* text, const char* button1, const char* button2, const char* button3, const char* option, YabInterface *yab) +{ + return yab->NewAlert(_L(text), _L(button1), _L(button2), _L(button3), option); +} + +void yi_Calendar1(double x, double y, const char* id, const char* format, const char* date, const char* view, YabInterface *yab) +{ + yab->Calendar(x,y, id, format, date, view); +} + +const char* yi_Calendar2(const char* id, YabInterface *yab) +{ + return yab->Calendar(id); +} + +void yi_Calendar3(const char* id, const char* date, YabInterface *yab) +{ + yab->Calendar(id, date); +} + +const char* yi_ListboxGet(const char* listbox, int pos, YabInterface *yab) +{ + return yab->ListboxGet(listbox, pos); +} + +int yi_ListboxCount(const char* listbox, YabInterface *yab) +{ + return yab->ListboxCount(listbox); +} + +void yi_ListboxAdd1(const char* listbox, const char* item, YabInterface *yab) +{ + yab->ListboxAdd(listbox,_L(item)); +} + +void yi_ListboxAdd2(const char* listbox, int pos, const char* item, YabInterface *yab) +{ + yab->ListboxAdd(listbox, pos, _L(item)); +} + +void yi_ListboxSelect(const char* listbox, int pos, YabInterface *yab) +{ + yab->ListboxSelect(listbox,pos); +} + +void yi_ListboxRemove(const char* listbox, int pos, YabInterface *yab) +{ + yab->ListboxRemove(listbox,pos); +} + +void yi_Scrollbar(const char* id, int format, const char* view, YabInterface *yab) +{ + yab->Scrollbar(id, format, view); +} + +void yi_ScrollbarSet1(const char* scrollview, const char* option, double position, YabInterface *yab) +{ + yab->ScrollbarSet(scrollview, option, position); +} + +void yi_ScrollbarSet2(const char* scrollview, const char* option, double opt1, double opt2, YabInterface *yab) +{ + yab->ScrollbarSet(scrollview, option, opt1, opt2); +} + +void yi_ScrollbarSet3(const char* scrollview, const char* option, YabInterface *yab) +{ + yab->ScrollbarSet(scrollview, option); +} + +double yi_ScrollbarGet(const char* scrollview, const char* option, YabInterface *yab) +{ + return yab->ScrollbarGet(scrollview, option); +} + +void yi_SplitView1(double x1,double y1,double x2,double y2, const char* id, int isVertical, int style, const char* view, YabInterface *yab) +{ + yab->SplitView(BRect(x1,y1,x2,y2), id, isVertical, style, view); +} + +void yi_SplitView2(const char* splitView, const char* option, double position, YabInterface *yab) +{ + yab->SplitView(splitView, option, position); +} + +void yi_SplitView3(const char* splitView, const char* option, double left, double right, YabInterface *yab) +{ + yab->SplitView(splitView, option, left, right); +} + +double yi_SplitViewGet(const char* splitView, const char* option, YabInterface *yab) +{ + return yab->SplitViewGet(splitView, option); +} + +void yi_StackView1(double x1,double y1,double x2,double y2, const char* id, int number, const char* view, YabInterface *yab) +{ + yab->StackViews(BRect(x1,y1,x2,y2), id, number, view); +} + +void yi_StackView2(const char* stackView, int num, YabInterface *yab) +{ + yab->StackViews(stackView, num); +} + +int yi_StackViewGet(const char* stackView, YabInterface *yab) +{ + return yab->StackViewGet(stackView); +} + +void yi_DrawSet3(const char* option, int transparency, YabInterface *yab) +{ + yab->DrawSet3(option, transparency); +} + +extern void yi_TextURL1(double x, double y, const char* id, const char* text, const char* url, const char* view, YabInterface *yab) +{ + yab->TextURL(x,y, id, _L(text), url, view); +} + +void yi_TextURL2(const char* id, const char* option, int r, int g, int b, YabInterface *yab) +{ + yab->TextURL(id, option, r,g,b); +} + +void yi_Menu2(const char* menuHead, int isRadio, const char* view, YabInterface *yab) +{ + yab->Menu(_L(menuHead), isRadio, view); +} + +void yi_SubMenu1(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* modifiers, const char* view, YabInterface *yab) +{ + yab->SubMenu(_L(menuHead), _L(menuItem), _L(subMenuItem), modifiers, view); +} + +void yi_SubMenu2(const char* menuHead, const char* menuItem, int isRadio, const char* view, YabInterface *yab) +{ + yab->SubMenu(_L(menuHead), _L(menuItem), isRadio, view); +} + +void yi_SpinControl1(double x, double y, const char* id, const char* label, int min, int max, int step, const char* view, YabInterface *yab) +{ + yab->SpinControl(x,y, id, _L(label), min, max, step, view); +} + +void yi_SpinControl2(const char* spinControl, int value, YabInterface *yab) +{ + yab->SpinControl(spinControl, value); +} + +int yi_SpinControlGet(const char *spinControl, YabInterface *yab) +{ + return yab->SpinControlGet(spinControl); +} + +const char* yi_PopUpMenu(double x, double y, const char* menuItems, const char* view, YabInterface *yab) +{ + return yab->PopUpMenu(x,y,menuItems,view); +} + +void yi_DropBoxSelect(const char* dropbox, int position, YabInterface *yab) +{ + yab->DropBoxSelect(dropbox, position); +} + +void yi_DropBoxClear(const char* dropbox, YabInterface *yab) +{ + yab->DropBoxClear(dropbox); +} + +void yi_DropBoxRemove(const char* dropbox, int position, YabInterface *yab) +{ + yab->DropBoxRemove(dropbox,position); +} + +int yi_DropBoxCount(const char* dropbox, YabInterface *yab) +{ + return yab->DropBoxCount(dropbox); +} + +const char* yi_DropBoxGet(const char* dropbox, int position, YabInterface *yab) +{ + return yab->DropBoxGet(dropbox, position); +} + +int yi_ColorControlGet(const char* colorcontrol, const char* option, YabInterface *yab) +{ + return yab->ColorControlGet(colorcontrol, option); +} + +int yi_SliderGet(const char* slider, YabInterface *yab) +{ + return yab->SliderGet(slider); +} + +double yi_DrawGet1(const char* option, const char* txt, const char* view, YabInterface *yab) +{ + return yab->DrawGet(option, txt, view); +} + +double yi_DrawGet2(const char* option, const char* view, YabInterface *yab) +{ + return yab->DrawGet(option, "", view); +} + +const char* yi_DrawGet3(const char* option, YabInterface *yab) +{ + return yab->DrawGet(option); +} + +void yi_SubMenu3(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* option, const char* view, YabInterface *yab) +{ + yab->SubMenu3(_L(menuHead), _L(menuItem), _L(subMenuItem), option, view); +} + +void yi_Menu3(const char* menuHead, const char* menuItem, const char* option,const char* view, YabInterface *yab) +{ + yab->Menu3(_L(menuHead), _L(menuItem), option, view); +} + +double yi_MenuHeight(YabInterface *yab) +{ + return yab->MenuHeight(); +} + +double yi_TabHeight(YabInterface *yab) +{ + return yab->TabHeight(); +} + +double yi_ScrollbarWidth(YabInterface *yab) +{ + return yab->ScrollbarWidth(); +} + +void yi_exit(int code, YabInterface *yab) +{ + yab->KillThread(code); +} + +const int yi_IsMouseIn(const char* view, YabInterface *yab) +{ + return yab->IsMouseIn(view); +} + +const char* yi_GetMouseIn(YabInterface *yab) +{ + return yab->GetMouseIn(); +} + + +const char* yi_KeyboardMessages(const char* view, YabInterface* yab) +{ + return yab->KeyboardMessages(view); +} + +const char* yi_GetMouseMessages(const char* view, YabInterface* yab) +{ + return yab->GetMouseMessages(view); +} + +const char* yi_CheckMessages(YabInterface* yab) +{ + return yab->GetMessageString(); +} + +int yi_MessageSend(const char* app, const char* msg,YabInterface* yab) +{ + return yab->MessageSend(app,msg); +} + +int yi_ThreadKill(const char* option, int id,YabInterface* yab) +{ + return yab->ThreadKill(option, id); +} + +int yi_ThreadGet(const char* option, const char* appname,YabInterface* yab) +{ + return yab->ThreadGet(option, appname); +} + +void yi_SetCurrentLineNumber(int line, const char* libname, YabInterface* yab) +{ + yab->SetCurrentLineNumber(line, libname); +} + +void yi_SetMainFileName(const char* name, YabInterface* yab) +{ + yab->SetMainFileName(name); +} + +void yi_beep() +{ + beep(); +} + +void yi_Bitmap(double w, double h, const char* id,YabInterface* yab) +{ + yab->Bitmap(w,h,id); +} + +int yi_BitmapColor(double x, double y, const char* id, const char* option, YabInterface *yab) +{ + yab->BitmapColor(x,y, id, option); +} + +void yi_BitmapDraw(double x, double y, const char* bitmap, const char* mode, const char* view,YabInterface* yab) +{ + yab->BitmapDraw(x,y, bitmap, mode, view); +} + +void yi_BitmapDraw2(double x1, double y1, double x2, double y2, const char* bitmap, const char* mode, const char* view,YabInterface* yab) +{ + yab->BitmapDraw(BRect(x1,y1,x2,y2), bitmap, mode, view); +} + +void yi_BitmapGet(double x1, double y1, double x2, double y2, const char* id, const char* bitmap, YabInterface* yab) +{ + yab->BitmapGet(BRect(x1,y1,x2,y2), id, bitmap); +} + +void yi_BitmapGet2(double w, const char* id, const char* path, YabInterface* yab) +{ + yab->BitmapGet(w, id, path); +} + +int yi_BitmapGetNum(const char* id, const char* option, YabInterface* yab) +{ + yab->BitmapGet(id, option); +} + +int yi_BitmapLoad(const char* filename, const char* bitmap, YabInterface* yab) +{ + yab->BitmapLoad(filename, bitmap); +} + +void yi_BitmapGetIcon(const char* id, const char* option, const char* path, YabInterface* yab) +{ + yab->BitmapGetIcon(id, option, path); +} + +void yi_BitmapDrag(const char* bitmap,YabInterface* yab) +{ + yab->BitmapDrag(bitmap); +} + +void yi_BitmapRemove(const char* bitmap,YabInterface* yab) +{ + yab->BitmapRemove(bitmap); +} + +void yi_Screenshot(double x1, double y1, double x2, double y2, const char* bitmap, YabInterface *yab) +{ + return yab->Screenshot(BRect(x1,y1,x2,y2), bitmap); +} + +int yi_BitmapSave(const char* id, const char* filename, const char* type, YabInterface* yab) +{ + return yab->BitmapSave(id, filename, type); //, type); +} + +void yi_Canvas(double x1, double y1, double x2, double y2, const char* id, const char* view, YabInterface *yab) +{ + yab->Canvas(BRect(x1,y1,x2,y2), id,view); +} + +int yi_Sound(const char* filename, YabInterface* yab) +{ + return yab->Sound(filename); +} + +void yi_SoundStop(int id, YabInterface* yab) +{ + yab->SoundStop(id); +} + +void yi_SoundWait(int id, YabInterface* yab) +{ + yab->SoundWait(id); +} + +void yi_ShortCut(const char* view, const char* key, const char* msg, YabInterface *yab) +{ + yab->ShortCut(view,key,msg); +} + +int yi_IsComputerOn(YabInterface *yab) +{ + return yab->IsComputerOn(); +} + +void yi_DrawSet4(const char* option, const char* color,const char* view, YabInterface* yab) +{ + yab->DrawSet(option, color, view); +} + +void yi_Treebox13(const char* id,const char* option, int pos, YabInterface* yab) +{ + yab->Treebox13(id, option, pos); +} + +int yi_TreeboxGetOpt(const char* id, const char* option, int pos, YabInterface* yab) +{ + return yab->TreeboxGetOpt(id, option, pos); +} + +int yi_ListboxGetNum(const char* id, YabInterface* yab) +{ + return yab->ListboxGetNum(id); +} + +int yi_DropboxGetNum(const char* id, YabInterface* yab) +{ + return yab->DropboxGetNum(id); +} + +int yi_TreeboxGetNum(const char* id, YabInterface* yab) +{ + return yab->TreeboxGetNum(id); +} + +int yi_ColumnboxGetNum(const char* id, YabInterface* yab) +{ + return yab->ColumnboxGetNum(id); +} + +int yi_DrawGet4(double x, double y, const char* option, const char* view, YabInterface* yab) +{ + return yab->DrawGet(BPoint(x,y),option,view); +} + +void yi_MouseSet(const char* opt, YabInterface *yab) +{ + yab->MouseSet(opt); +} + +void yi_StatusBar(double x1, double y1, double x2, double y2, const char* id, const char* label1, const char* label2, const char* view, YabInterface *yab) +{ + yab->StatusBar(BRect(x1, y1, x2, y2), id, label1, label2, view); +} + +void yi_StatusBarSet(const char* id, const char* label1, const char* label2, double state, YabInterface *yab) +{ + yab->StatusBarSet(id, label1, label2, state); +} + +void yi_StatusBarSet2(double x1, double y1, double x2, double y2, const char* id, const char* view, YabInterface *yab) +{ + yab->StatusBarSet(BRect(x1, y1, x2, y2), id, view); +} + +void yi_StatusBarSet3(const char* id, int r, int g, int b, YabInterface *yab) +{ + yab->StatusBarSet(id, r, g, b); +} + +void yi_Launch(const char* strg, YabInterface *yab) +{ + yab->Launch(strg); +} + +void yi_Attribute1(const char* type, const char* name, const char* value, const char* filename, YabInterface* yab) +{ + yab->Attribute1(type, name, value, filename); +} + +void yi_AttributeClear(const char* name, const char* filename, YabInterface* yab) +{ + yab->AttributeClear(name, filename); +} + +const char* yi_AttributeGet1(const char* name, const char* filename, YabInterface* yab) +{ + return yab->AttributeGet1(name, filename); +} + +double yi_AttributeGet2(const char* name, const char* filename, YabInterface* yab) +{ + return yab->AttributeGet2(name, filename); +} diff --git a/src/YabInterface.h b/src/YabInterface.h new file mode 100644 index 0000000..859ca07 --- /dev/null +++ b/src/YabInterface.h @@ -0,0 +1,523 @@ +#ifndef YABINTERFACE_H +#define YABINTERFACE_H + +#ifdef __cplusplus + #include + #include + #include + #include + #include + #include + #include + #include + #include "YabList.h" + #include "global.h" + #include "config.h" + + class YabInterface : public BApplication + { + public: + YabInterface(int argc, char** argv, const char* signature); + ~YabInterface(); + + status_t GetSupportedSuites(BMessage *msg); + BHandler *ResolveSpecifier(BMessage *msg, int32 index, BMessage *spec, int32 form, const char *prop); + const char* GetApplicationDirectory(); + void OpenWindow(const BRect frame, const char* id, const char* title); + int CloseWindow(const char* view); + void MessageReceived(BMessage *message); + bool QuitRequested(); + bool ExitRequested(); + void CreateButton(BRect frame, const char* id, const char* title, const char* window); + int CreateImage(BPoint coordinates, const char* imagefile, const char* window); + int CreateImage(BRect frame, const char* imagefile, const char* window); + int CreateSVG(BRect frame, const char* imagefile, const char* window); + void DrawText(BPoint coordinates, const char* text, const char* window); + void DrawRect(BRect frame, const char* window); + void DrawClear(const char* window, bool isExit); + void CreateAlert(const char* text, const char* button1, const char* option); + void CreateMenu(const char* menuhead, const char* menuitem, const char *shortcut, const char* window); + void CreateTextControl(BRect frame, const char *id, const char* label, const char* text, const char* window); + void CreateCheckBox(double x, double y, const char *id, const char* label, int isActivated, const char* window); + void CreateRadioButton(double x, double y, const char* groupID, const char* label, int isActivated, const char* window); + void CreateListBox(BRect frame, const char* title, int scrollbar, const char* window); + void CreateDropBox(BRect frame, const char* title, const char* label, const char* window); + void CreateItem(const char* id, const char* item); + void RemoveItem(const char* title, const char* item); + void ClearItems(const char* title); + void CreateText(double x, double y, const char *id, const char* text, const char* window); + void Text2(BRect frame, const char *id, const char* text, const char* window); + void TextAlign(const char* txt, const char *option); + const char* LoadFilePanel(const char* mode, const char* title, const char* directory); + const char* SaveFilePanel(const char* mode, const char* title, const char* directory, const char*filename); + void SetLayout(const char* layout, const char* window); + void WindowSet(const char* option, const char* value, const char* window); + void WindowSet(const char* option, int r, int g, int b, const char* window); + void WindowSet(const char* option, double x, double y, const char* window); + void WindowSet(const char* option, const char* window); + void WindowClear(const char* window); + void TextEdit(BRect frame, const char* title, int scrollbar, const char* window); + void TextAdd(const char* title, const char* text); + void TextSet(const char* title, const char* option); + void TextSet(const char* title, const char* option, int value); + void TextSet(const char* title, const char* option, const char* value); + void TextColor(const char* title, const char* option, const char* command); + void TextColor(const char* title, const char* option, int r, int g, int b); + void TextClear(const char* title); + const char* TextGet(const char* title); + const char* TextGet(const char* title, int linenum); + const char* TextGet6(const char* title, const char* option); + int TextGet(const char* title, const char* option); + double TextGet(const char* title, const char* option, int line); + int TextGet(const char* title, const char* option, const char* option2); + void DrawSet1(const char* option, const char* window); + void DrawSet2(int fillorstroke, const char* mypattern); + void View(BRect frame, const char* id, const char* view); + void BoxView(BRect frame, const char* id, const char* text, int lineType, const char* view); + void BoxViewSet(const char* id, const char* option, const char* value); + void Tab(BRect frame, const char* id, const char* names, const char* view); + void TabSet(const char* id, int num); + void TabAdd(const char* id, const char* name); + void TabDel(const char* id, int num); + int TabViewGet(const char* id); + void DrawDot(double x, double y, const char* window); + void DrawLine(double x1, double y1, double x2, double y2, const char* window); + void DrawCircle(double x, double y, double r, const char* window); + void DrawEllipse(double x, double y, double r1, double r2, const char* window); + void DrawCurve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, const char* window); + void Slider(BRect frame, const char* id, const char* title, int min, int max, const char* view); + void Slider(BRect frame, const char* id, const char* title, int min, int max, const char* option, const char* view); + void SetSlider(const char* id, const char* label1, const char* label2); + void SetSlider(const char* id, const char* bottomtop, int count); + void SetSlider(const char* id, const char* part, int r, int g, int b); + void SetSlider(const char* id, int value); + void SetOption(const char* id, const char* option, const char* value); + void SetOption(const char* id, const char* option, int r, int g, int b); + void SetOption(const char* id, const char* option, double x, double y); + void SetOption(const char* id, const char* option); + void SetOption(const char* id, const char* option, int value); + void DropZone(const char* view); + void ColorControl(double x, double y, const char* id, const char* view); + void ColorControl(const char* id, int r, int g, int b); + void TextControl(const char* id, const char* text); + void TextControl(const char* id, int mode); + void TextControl(const char* id, const char* option, const char* value); + void TextControl(const char* id); + void TreeBox1(BRect frame, const char* id, int scrollbarType, const char* view); + void TreeBox2(const char* id, const char* item); + void TreeBox3(const char* id, const char* head, const char* item, int isExpanded); + void TreeBox4(const char* id); + void TreeBox5(const char* id, const char* item); + void TreeBox7(const char* id, int pos); + void TreeBox8(const char* id, int pos); + void TreeBox9(const char* id, const char* head, const char* item); + void TreeBox10(const char* id, const char* head); + void TreeBox11(const char* id, const char* head); + void TreeBox12(const char* id, const char* item, int pos); + void Launch(const char* strg); + const char* TreeboxGet(const char* treebox, int pos); + int TreeboxCount(const char* treebox); + void ButtonImage(double x, double y,const char* id,const char* enabledon, const char* enabledoff, const char* disabled, const char* view); + void CheckboxImage(double x, double y,const char* id,const char* enabledon, const char* enabledoff, const char *disabledon, const char *disabledoff, int isActivated, const char* view); + void CheckboxSet(const char* id, int isActivated); + void RadioSet(const char* id, int isActivated); + void ToolTips(const char* view, const char* text); + void ToolTipsColor(const char* color, int r, int g, int b); + void TreeSort(const char* view); + void ListSort(const char* view); + void FileBox(BRect frame, const char* id, bool scrollbartype, const char* option, const char* view); + void FileBoxAdd(const char* id, const char* name, int32 pos, double maxWidth, double minWidth, double width, const char* option); + void FileBoxClear(const char* view); + void ColumnBoxAdd(const char* id, int column, int position, int height, const char* item); + void ColumnBoxSelect(const char *columnbox, int position); + void ColumnBoxRemove(const char *columnbox, int position); + void ColumnBoxColor(const char *columnbox, const char* option, int r, int g, int b); + int Printer(const char* docname, const char *view, const char* config); + void PrinterConfig(const char* config); + void Calendar(double x, double y, const char* id, const char* format, const char* date, const char* view); + const char* Calendar(const char* id); + void Calendar(const char* id, const char* date); + void MouseSet(const char* opt); + void Scrollbar(const char* id, int format, const char* view); + void ScrollbarSet(const char* scrollview, const char* option, double position); + void ScrollbarSet(const char* scrollview, const char* option, double opt1, double opt2); + void ScrollbarSet(const char* scrollview, const char* option); + double ScrollbarGet(const char* scrollview, const char* option); + const char* ListboxGet(const char* listbox, int pos); + int ListboxCount(const char* listbox); + void ListboxAdd(const char* listbox, const char* item); + void ListboxAdd(const char* listbox, int pos, const char* item); + void ListboxSelect(const char* listbox, int pos); + void ListboxRemove(const char* listbox, int pos); + void SplitView(BRect frame, const char* id, int isVertical, int style, const char* view); + void SplitView(const char* splitView, const char* option, double position); + void SplitView(const char* splitView, const char* option, double left, double right); + double SplitViewGet(const char* splitView, const char* option); + void StackViews(BRect frame, const char* id, int number, const char* view); + void StackViews(const char* stackView, int num); + int StackViewGet(const char* stackView); + void DrawSet3(const char* option, int transparency); + void TextURL(double x, double y, const char* id, const char* text, const char* url, const char* view); + void TextURL(const char* id, const char* option, int r, int g, int b); + void Menu(const char* menuHead, int isRadio, const char* view); + void SubMenu(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* modifiers, const char* view); + void SubMenu(const char* menuHead, const char* menuItem, int isRadio, const char* view); + void SpinControl(double x, double y, const char* id, const char* label, int min, int max, int step, const char* view); + void SpinControl(const char* spinControl, int value); + int SpinControlGet(const char *spinControl); + const char* PopUpMenu(double x, double y, const char* menuItems, const char* view); + void DropBoxSelect(const char* dropbox, int position); + void DropBoxClear(const char* dropbox); + void DropBoxRemove(const char* dropbox, int position); + int DropBoxCount(const char* dropbox); + const char* DropBoxGet(const char* dropbox, int position); + int ColorControlGet(const char* colorcontrol, const char* option); + int SliderGet(const char* slider); + void SubMenu3(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* option, const char* view); + void Menu3(const char* menuHead, const char* menuItem, const char* option,const char* view); + double ScrollbarWidth(); + double MenuHeight(); + double TabHeight(); + const char* ColumnBoxGet(const char *columnbox, int column, int position); + int ColumnBoxCount(const char *columnbox); + const char* TextControlGet(const char* id); + int WindowGet(const char* view, const char* option); + int ViewGet(const char* view, const char* option); //vasper + double DrawGet(const char* option, const char* txt, const char* view); + int DrawGet(BPoint coord, const char* option, const char* view); + const char* DrawGet(const char* option); + void ClipboardCopy(const char* text); + const char* ClipboardPaste(); + int DeskbarParam(const char* option); + int DesktopParam(bool isWidth); + int NewAlert(const char* text, const char* button1, const char* button2, const char* button3, const char* option); + int ThreadKill(const char* option, int id); + int ThreadGet(const char* option, const char* appname); + const int IsMouseIn(const char* view); + const char* GetMouseIn(); + const char* GetMouseMessages(const char* view); + const char* KeyboardMessages(const char* view); + const char* GetMessageString(); + int MessageSend(const char* app, const char* msg); + void SetLocalize(const char* path); + void Bitmap(double w, double h, const char* id); + int BitmapColor(double x, double y, const char* id, const char* option); + void BitmapDraw(double x, double y, const char* bitmap, const char* mode, const char* view); + void BitmapDraw(BRect frame, const char* bitmap, const char* mode, const char* view); + void BitmapGet(BRect frame, const char* id, const char* bitmap); + void BitmapGet(double w, const char* id, const char* path); + int BitmapGet(const char* id, const char* option); + int BitmapLoad(const char* id, const char* option); + void BitmapGetIcon(const char* id, const char* option, const char* path); + void BitmapDrag(const char* bitmap); + void BitmapRemove(const char* bitmap); + void Screenshot(BRect frame, const char* bitmap); + int BitmapSave(const char* id, const char* filename, const char* type); + void Canvas(BRect frame, const char* id, const char* view); + int Sound(const char* filename); + void SoundStop(int32 id); + void SoundWait(int32 id); + int IsComputerOn(); + void ShortCut(const char* view, const char* key, const char* msg); + void DrawSet(const char* option, const char* color,const char* view); + void Treebox13(const char* id,const char* option, int pos); + int TreeboxGetOpt(const char* id, const char* option, int pos); + int ListboxGetNum(const char* id); + int DropboxGetNum(const char* id); + int TreeboxGetNum(const char* id); + int ColumnboxGetNum(const char* id); + void Attribute1(const char* type, const char* name, const char* value, const char* filename); + void AttributeClear(const char* name, const char* filename); + const char* AttributeGet1(const char* name, const char* filename); + double AttributeGet2(const char* name, const char* filename); + + const int GetErrorCode(); + void Error(const char* id, const char* type); + void ErrorGen(const char* msg); + void SetCurrentLineNumber(int line, const char* libname); + void SetMainFileName(const char* name); + void KillThread(int code); + void StatusBar(BRect frame, const char* id, const char* label1, const char* label2, const char* view); + void StatusBarSet(const char* id, const char* label1, const char* label2, double state); + void StatusBarSet(BRect frame, const char* id, const char* view); + void StatusBarSet(const char* id, int r, int g, int b); + void RefsReceived(BMessage *message); + + private: + void RemoveView(BView* myView); + void GetMMsgInfo(BString &t, int mouseStateInfo, int mouseLButton, int mouseMButton, int mouseRButton, int x, int y, const char* name); + BBitmap* loadImage(const char* name); + static int compare(BListItem **firstArg, BListItem **secondArg); + + BTranslatorRoster *Roster; + char ApplicationDirectory[1024]; + char loadPanel[1280]; + char columntext[4096]; + char mousemessagebuffer[64]; + char keyboardbuffer[27]; + char messagebuffer[32567]; + char attrbuffer[32567]; + char mouseoverbuffer[256]; + BFilePanel *fopen, *fsave; + thread_id myThread; + int errorCode; + bool drawStroking; + int yabAlpha; + pattern yabPattern; + YabList *viewList; + int currentLineNumber; + const char* mainFileName; + bool exiting; + BPropertyInfo *myProps; + BString localMessage; + BString currentLib; + BList *yabbitmaps; + BList *yabcanvas; + BString lastMouseMsg; + }; +#else + typedef + struct YabInterface + YabInterface; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mmain(int argc, char** argv, YabInterface* yab); /* ANSI C prototypes */ +extern const char* yi_GetApplicationDirectory(YabInterface *yab); +extern void yi_OpenWindow(double x1,double y1,double x2,double y2, const char* id, const char* title, YabInterface* yab); +extern int yi_CloseWindow(const char* view, YabInterface* yab); +extern void yi_CreateButton(double x1,double y1,double x2,double y2, const char* id, const char* title, const char* window, YabInterface* yab); +extern int yi_CreateImage(double x,double y,const char* imagefile, const char* window, YabInterface* yab); +extern int yi_CreateImage2(double x1,double y1,double x2, double y2,const char* imagefile, const char* window, YabInterface* yab); +extern int yi_CreateSVG(double x1,double y1,double x2, double y2,const char* imagefile, const char* window, YabInterface* yab); +extern void yi_CreateMenu(const char* menuhead, const char* menuitem, const char *shortcut, const char* window, YabInterface* yab); +extern void yi_CreateTextControl(double x1, double y1, double x2, double y2, const char *id, const char* label, const char* text, const char* window, YabInterface *yab); +extern void yi_CreateCheckBox(double x, double y, const char *id, const char* label, int isActivated, const char* window, YabInterface *yab); +extern void yi_CreateRadioButton(double x, double y, const char* groupID, const char* label, int isActivated, const char* window, YabInterface *yab); +extern void yi_CreateListBox(double x1,double y1,double x2,double y2, const char* title, int scrollbar, const char* window, YabInterface *yab); +extern void yi_CreateDropBox(double x1, double y1,double x2,double y2, const char* title,const char* label, const char* window, YabInterface *yab); +extern void yi_CreateItem(const char* id,const char* item, YabInterface *yab); +extern void yi_RemoveItem(const char* title,const char* item, YabInterface *yab); +extern void yi_ClearItems(const char* title, YabInterface *yab); +extern void yi_DrawText(double x, double y, const char* text, const char* window, YabInterface* yab); +extern void yi_DrawRect(double x1, double y1, double x2, double y2, const char* window, YabInterface* yab); +extern void yi_DrawClear(const char* window, YabInterface* yab); +extern void yi_CreateAlert(const char* text, const char* button1, const char* type, YabInterface* yab); +extern void yi_CreateText(double x, double y, const char *id, const char* text, const char* window, YabInterface *yab); +extern void yi_Text2(double x1, double y1, double x2, double y2, const char *id, const char* text, const char* window, YabInterface *yab); +extern void yi_TextAlign(const char* txt, const char *option, YabInterface *yab); +extern void yi_Translate(char* text, char result[]); +extern void yi_MenuTranslate(char* text, char result[]); +extern void yi_SetLocalize(); +extern void yi_StopLocalize(); +extern const char* yi_LoadFilePanel(const char* mode, const char* title, const char* directory, YabInterface* yab); +extern const char* yi_SaveFilePanel(const char* mode, const char* title, const char* directory, const char*filename, YabInterface* yab); +extern void yi_SetLayout(const char* layout, const char* window, YabInterface *yab); +extern void yi_WindowSet1(const char* option, const char* value, const char* window, YabInterface *yab); +extern void yi_WindowSet2(const char* option, int r, int g, int b, const char* window, YabInterface *yab); +extern void yi_WindowSet3(const char* option, double x, double y, const char* window, YabInterface *yab); +extern void yi_WindowSet4(const char* option, const char* window, YabInterface *yab); +extern void yi_WindowClear(const char* window, YabInterface *yab); +extern void yi_TextEdit(double x1, double y1, double x2, double y2, const char* title, int scrollbar, const char* window, YabInterface *yab); +extern void yi_TextAdd(const char* title, const char* text, YabInterface *yab); +extern void yi_TextSet(const char* title, const char* option, YabInterface *yab); +extern void yi_TextClear(const char* title, YabInterface *yab); +extern const char* yi_TextGet(const char* title, YabInterface *yab); +extern const char* yi_TextGet3(const char* title, int linenum, YabInterface *yab); +extern const char* yi_TextGet6(const char* title, const char* option, YabInterface *yab); +extern double yi_TextGet4(const char* title, const char* option, int line, YabInterface *yab); +extern int yi_TextGet5(const char* title, const char* option, const char* option2, YabInterface *yab); +extern void yi_TextSet2(const char* title, const char* option, int value, YabInterface *yab); +extern void yi_TextSet3(const char* title, const char* option, const char* value, YabInterface *yab); +extern void yi_TextColor1(const char* title, const char* option, const char* command, YabInterface *yab); +extern void yi_TextColor2(const char* title, const char* option, int r, int g, int b, YabInterface *yab); +extern int yi_TextGet2(const char* title, const char* option, YabInterface *yab); +extern void yi_DrawSet1(const char* option, const char* window, YabInterface *yab); +extern void yi_DrawSet2(int fillorstroke, const char* mypattern, YabInterface *yab); +extern void yi_View(double x1, double y1, double x2, double y2, const char* id, const char* view, YabInterface *yab); +extern void yi_BoxView(double x1, double y1, double x2, double y2, const char* id, const char* text, int lineType, const char* view, YabInterface *yab); +extern void yi_BoxViewSet(const char* id, const char* option, const char* value, YabInterface *yab); +extern void yi_Tab(double x1, double y1, double x2, double y2, const char* id, const char* names, const char* view, YabInterface *yab); +extern void yi_TabSet(const char* id, int num, YabInterface *yab); +extern void yi_TabAdd(const char* id, const char* name, YabInterface *yab); +extern void yi_TabDel(const char* id, int num, YabInterface *yab); +extern int yi_TabViewGet(const char* id, YabInterface *yab); +extern void yi_DrawDot(double x, double y, const char* window, YabInterface *yab); +extern void yi_DrawLine(double x1, double y1, double x2, double y2, const char* window, YabInterface *yab); +extern void yi_DrawCircle(double x, double y, double r, const char* window, YabInterface *yab); +extern void yi_DrawEllipse(double x, double y, double r1, double r2, const char* window, YabInterface *yab); +extern void yi_DrawCurve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, const char* window, YabInterface *yab); +extern void yi_Slider1(double x1, double y1, double x2, double y2, const char* id, const char* title, int min, int max, const char* view, YabInterface *yab); +extern void yi_Slider2(double x1, double y1, double x2, double y2, const char* id, const char* title, int min, int max, const char* option, const char* view, YabInterface *yab); +extern void yi_SetSlider1(const char* id, const char* label1, const char* label2, YabInterface *yab); +extern void yi_SetSlider2(const char* id, const char* bottomtop, int count, YabInterface *yab); +extern void yi_SetSlider3(const char* id, const char* part, int r, int g, int b, YabInterface *yab); +extern void yi_SetSlider4(const char* id, int value, YabInterface *yab); +extern void yi_SetOption1(const char* id, const char* option, const char* value, YabInterface *yab); +extern void yi_SetOption2(const char* id, const char* option, int r, int g, int b, YabInterface *yab); +extern void yi_SetOption3(const char* id, const char* option, double x, double y, YabInterface *yab); +extern void yi_SetOption4(const char* id, const char* option, YabInterface *yab); +extern void yi_SetOption5(const char* id, const char* option, int value, YabInterface *yab); +extern void yi_DropZone(const char* view, YabInterface *yab); +extern void yi_ColorControl1(double x, double y, const char* id, const char* view, YabInterface* yab); +extern void yi_ColorControl2(const char* id, int r, int g, int b, YabInterface* yab); +extern void yi_TextControl2(const char* id, const char* text, YabInterface* yab); +extern void yi_TextControl3(const char* id, int mode, YabInterface* yab); +extern void yi_TextControl5(const char* id, YabInterface* yab); +extern void yi_TextControl4(const char* id, const char* option, const char* value, YabInterface* yab); +extern void yi_TreeBox1(double x1, double y1, double x2, double y2, const char* id, int scrollbarType, const char* view, YabInterface* yab); +extern void yi_TreeBox2(const char* id, const char* item, YabInterface* yab); +extern void yi_TreeBox3(const char* id, const char* head, const char* item, int isExpanded, YabInterface* yab); +extern void yi_TreeBox4(const char* id, YabInterface* yab); +extern void yi_TreeBox5(const char* id, const char* item, YabInterface* yab); +extern void yi_TreeBox7(const char* id, int pos, YabInterface* yab); +extern void yi_TreeBox8(const char* id, int pos, YabInterface* yab); +extern void yi_TreeBox9(const char* id, const char* head, const char* item, YabInterface* yab); +extern void yi_TreeBox10(const char* id, const char* head, YabInterface* yab); +extern void yi_TreeBox11(const char* id, const char* head, YabInterface* yab); +extern void yi_TreeBox12(const char* id, const char* item, int pos, YabInterface* yab); +extern const char* yi_TreeboxGet(const char* treebox, int pos, YabInterface* yab); +extern int yi_TreeboxCount(const char* treebox, YabInterface* yab); +extern void yi_ButtonImage(double x,double y,const char* id,const char* enabledon, const char* enabledoff, const char* disabled, const char* view, YabInterface *yab); +extern void yi_CheckboxImage(double x,double y,const char* id,const char* enabledon, const char* enabledoff, const char *disabledon, const char *disabledoff, int isActivated, const char* view, YabInterface *yab); +extern void yi_CheckboxSet(const char* id, int isActivated, YabInterface* yab); +extern void yi_RadioSet(const char* id, int isActivated, YabInterface* yab); +extern const char* yi_TextControlGet(const char* id, YabInterface* yab); +extern void yi_ToolTip(const char* view, const char* text, YabInterface *yab); +extern void yi_ToolTipColor(const char* color, int r, int g, int b, YabInterface *yab); +extern void yi_TreeSort(const char* view, YabInterface *yab); +extern void yi_ListSort(const char* view, YabInterface *yab); +extern void yi_FileBox(double x1, double y1, double x2, double y2, const char* id, int scrollbartype, const char* option, const char* view, YabInterface *yab); +extern void yi_FileBoxAdd2(const char* id, const char* name, int pos, double maxWidth, double minWidth, double width, const char* option, YabInterface *yab); +extern void yi_FileBoxClear(const char* view, YabInterface *yab); +extern void yi_ColumnBoxAdd(const char* id, int column, int position, int height, const char* item, YabInterface *yab); +extern void yi_ColumnBoxSelect(const char *columnbox, int position, YabInterface *yab); +extern void yi_ColumnBoxRemove(const char *columnbox, int position, YabInterface *yab); +extern void yi_ColumnBoxColor(const char *columnbox, const char* option, int r, int g, int b, YabInterface *yab); +extern int yi_Printer(const char* docname, const char *view, const char* config, YabInterface *yab); +extern void yi_PrinterConfig(const char* config, YabInterface *yab); +extern const char* yi_ColumnBoxGet(const char *columnbox, int column, int position, YabInterface *yab); +extern int yi_ColumnBoxCount(const char *columnbox, YabInterface *yab); +extern int yi_DeskbarPosition(YabInterface *yab); +extern int yi_DeskbarExpanded(YabInterface *yab); +extern int yi_DeskbarWidth(YabInterface *yab); +extern int yi_DeskbarHeight(YabInterface *yab); +extern int yi_DeskbarX(YabInterface *yab); +extern int yi_DeskbarY(YabInterface *yab); +extern int yi_DesktopWidth(YabInterface *yab); +extern int yi_DesktopHeight(YabInterface *yab); +extern int yi_WindowGet(const char* view, const char* option, YabInterface *yab); +extern int yi_ViewGet(const char* view, const char* option, YabInterface *yab); //vasper +extern void yi_ClipboardCopy(const char* text, YabInterface *yab); +extern const char* yi_ClipboardPaste(YabInterface *yab); +extern int yi_NewAlert(const char* text, const char* button1, const char* button2, const char* button3, const char* option, YabInterface *yab); +extern void yi_Calendar1(double x, double y, const char* id, const char* format, const char* date, const char* view, YabInterface *yab); +extern const char* yi_Calendar2(const char* id, YabInterface *yab); +extern void yi_Calendar3(const char* id, const char* date, YabInterface *yab); +extern void yi_MouseSet(const char* opt, YabInterface *yab); +extern void yi_Scrollbar(const char* id, int format, const char* view, YabInterface *yab); +extern void yi_ScrollbarSet1(const char* scrollview, const char* option, double position, YabInterface *yab); +extern void yi_ScrollbarSet2(const char* scrollview, const char* option, double opt1, double opt2, YabInterface *yab); +extern void yi_ScrollbarSet3(const char* scrollview, const char* option, YabInterface *yab); +extern double yi_ScrollbarGet(const char* scrollview, const char* option, YabInterface *yab); +extern const char* yi_ListboxGet(const char* listbox, int pos, YabInterface *yab); +extern int yi_ListboxCount(const char* listbox, YabInterface *yab); +extern void yi_ListboxAdd1(const char* listbox, const char* item, YabInterface *yab); +extern void yi_ListboxAdd2(const char* listbox, int pos, const char* item, YabInterface *yab); +extern void yi_ListboxSelect(const char* listbox, int pos, YabInterface *yab); +extern void yi_ListboxRemove(const char* listbox, int pos, YabInterface *yab); +extern void yi_SplitView1(double x1,double y1,double x2,double y2, const char* id, int isVertical, int style, const char* view, YabInterface *yab); +extern void yi_SplitView2(const char* splitView, const char* option, double position, YabInterface *yab); +extern void yi_SplitView3(const char* splitView, const char* option, double left, double right, YabInterface *yab); +extern double yi_SplitViewGet(const char* splitView, const char* option, YabInterface *yab); +extern void yi_StackView1(double x1,double y1,double x2,double y2, const char* id, int number, const char* view, YabInterface *yab); +extern void yi_StackView2(const char* stackView, int num, YabInterface *yab); +extern int yi_StackViewGet(const char* stackView, YabInterface *yab); +extern void yi_DrawSet3(const char* option, int transparency, YabInterface *yab); +extern void yi_TextURL1(double x, double y, const char* id, const char* text, const char* url, const char* view, YabInterface *yab); +extern void yi_TextURL2(const char* id, const char* option, int r, int g, int b, YabInterface *yab); +extern void yi_Menu2(const char* menuHead, int isRadio, const char* view, YabInterface *yab); +extern void yi_SubMenu1(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* modifiers, const char* view, YabInterface *yab); +extern void yi_SubMenu2(const char* menuHead, const char* menuItem, int isRadio, const char* view, YabInterface *yab); +extern void yi_SpinControl1(double x, double y, const char* id, const char* label, int min, int max, int step, const char* view, YabInterface *yab); +extern void yi_SpinControl2(const char* spinControl, int value, YabInterface *yab); +extern int yi_SpinControlGet(const char *spinControl, YabInterface *yab); +extern const char* yi_PopUpMenu(double x, double y, const char* menuItems, const char* view, YabInterface *yab); +extern void yi_DropBoxSelect(const char* dropbox, int position, YabInterface *yab); +extern void yi_DropBoxClear(const char* dropbox, YabInterface *yab); +extern void yi_DropBoxRemove(const char* dropbox, int position, YabInterface *yab); +extern int yi_DropBoxCount(const char* dropbox, YabInterface *yab); +extern const char* yi_DropBoxGet(const char* dropbox, int position, YabInterface *yab); +extern int yi_ColorControlGet(const char* colorcontrol, const char* option, YabInterface *yab); +extern int yi_SliderGet(const char* slider, YabInterface *yab); +extern void yi_SubMenu3(const char* menuHead, const char* menuItem, const char* subMenuItem, const char* option, const char* view, YabInterface *yab); +extern void yi_Menu3(const char* menuHead, const char* menuItem, const char* option,const char* view, YabInterface *yab); +extern double yi_MenuHeight(YabInterface *yab); +extern double yi_TabHeight(YabInterface *yab); +extern double yi_ScrollbarWidth(YabInterface *yab); +extern double yi_DrawGet1(const char* option, const char* txt, const char* view, YabInterface* yab); +extern double yi_DrawGet2(const char* option, const char* view, YabInterface* yab); +extern const char* yi_DrawGet3(const char* option, YabInterface* yab); +extern int yi_DrawGet4(double x, double y, const char* option, const char* view, YabInterface* yab); +extern void yi_exit(int code, YabInterface *yab); +extern void yi_Launch(const char* strg, YabInterface *yab); +extern const int yi_IsMouseIn(const char* view, YabInterface* yab); +extern const char* yi_GetMouseIn(YabInterface* yab); +extern const char* yi_GetMouseMessages(const char* view, YabInterface* yab); +extern const char* yi_KeyboardMessages(const char* view, YabInterface* yab); +extern const char* yi_CheckMessages(YabInterface* yab); +extern int yi_MessageSend(const char* app, const char* msg,YabInterface* yab); +extern int yi_ThreadKill(const char* option, int id,YabInterface* yab); +extern int yi_ThreadGet(const char* option, const char* appname,YabInterface* yab); +extern void yi_Bitmap(double w, double h, const char* id,YabInterface* yab); +extern int yi_BitmapColor(double x, double y, const char* id, const char* option, YabInterface *yab); +extern void yi_BitmapDraw(double x, double y, const char* bitmap, const char* mode, const char* view,YabInterface* yab); +extern void yi_BitmapDraw2(double x1, double y1, double x2, double y2, const char* bitmap, const char* mode, const char* view,YabInterface* yab); +extern void yi_BitmapGet(double x1, double y1, double x2, double y2, const char* id, const char* bitmap,YabInterface* yab); +extern void yi_BitmapGet2(double w, const char* id, const char* path, YabInterface* yab); +extern void yi_BitmapGetIcon(const char* id, const char* option, const char* path, YabInterface* yab); +extern int yi_BitmapGetNum(const char* id, const char* option, YabInterface* yab); +extern int yi_BitmapLoad(const char* filename, const char* bitmap, YabInterface* yab); +extern void yi_BitmapDrag(const char* bitmap,YabInterface* yab); +extern void yi_BitmapRemove(const char* bitmap,YabInterface* yab); +extern void yi_Screenshot(double x1, double y1, double x2, double y2, const char* bitmap, YabInterface* yab); +extern int yi_BitmapSave(const char* id, const char* filename, const char* type, YabInterface* yab); +extern void yi_Canvas(double x1, double y1, double x2, double y2, const char* id, const char* view, YabInterface *yab); +extern int yi_Sound(const char* filename, YabInterface* yab); +extern void yi_SoundStop(int id, YabInterface* yab); +extern void yi_SoundWait(int id, YabInterface* yab); +extern int yi_IsComputerOn(YabInterface* yab); +extern void yi_ShortCut(const char* view, const char* key, const char* msg, YabInterface* yab); +extern void yi_DrawSet4(const char* option, const char* color,const char* view, YabInterface* yab); +extern void yi_Treebox13(const char* id,const char* option, int pos, YabInterface* yab); +extern int yi_TreeboxGetOpt(const char* id, const char* option, int pos, YabInterface* yab); +extern int yi_ListboxGetNum(const char* id, YabInterface* yab); +extern int yi_DropboxGetNum(const char* id, YabInterface* yab); +extern int yi_TreeboxGetNum(const char* id, YabInterface* yab); +extern int yi_ColumnboxGetNum(const char* id, YabInterface* yab); +extern void yi_SetLocalize2(const char* path, YabInterface* yab); +extern void yi_SetCurrentLineNumber(int line, const char* libname, YabInterface* yab); +extern void yi_SetMainFileName(const char* name, YabInterface* yab); +extern void yi_beep(); +extern void yi_StatusBar(double x1, double y1, double x2, double y2, const char* id, const char* label1, const char* label2, const char* view, YabInterface* yab); +extern void yi_StatusBarSet(const char* id, const char* label1, const char* label2, double state, YabInterface* yab); +extern void yi_StatusBarSet2(double x1, double y1, double x2, double y2, const char* id, const char* view, YabInterface* yab); +extern void yi_StatusBarSet3(const char* id, int r, int g, int b, YabInterface* yab); +extern void yi_Attribute1(const char* type, const char* name, const char* value, const char* filename, YabInterface* yab); +extern void yi_AttributeClear(const char* name, const char* filename, YabInterface* yab); +extern const char* yi_AttributeGet1(const char* name, const char* filename, YabInterface* yab); +extern double yi_AttributeGet2(const char* name, const char* filename, YabInterface* yab); +extern char* refsRec; //refs received + +#ifdef LOCALIZE +const char* _L(const char* text); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*YABINTERFACE_H*/ diff --git a/src/YabList.cpp b/src/YabList.cpp new file mode 100644 index 0000000..cc2e95c --- /dev/null +++ b/src/YabList.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include "YabList.h" +#include + +YabList::YabList() +{ + idList = new BList(1); + viewList = new BList(1); + typeList = new BList(1); +} + +YabList::~YabList() +{ + DelAll(); + delete idList; + delete viewList; + delete typeList; +} + +int YabList::ViewNum(const char* id) +{ + int tmp=-1; + if(id) + { + for(int i=0; iCountItems(); i++) + if(!strcmp(id, ((BString*)(idList->ItemAt(i)))->String() )) + { + tmp = i; + break; + } + } + return tmp; +} + +void YabList::AddView(const char* id, const BView* view, int type) +{ + idList->AddItem((void*)new BString(id)); + viewList->AddItem((void*)view); + typeList->AddItem((void*)type); +} + +void YabList::DelView(const char* id) +{ + int i = ViewNum(id); + if(i!=-1) + { + idList->RemoveItem(i); + viewList->RemoveItem(i); + typeList->RemoveItem(i); + } +} + +void YabList::DelAll() +{ + idList->MakeEmpty(); + viewList->MakeEmpty(); + typeList->MakeEmpty(); +} + +const void* YabList::GetView(const char* id) +{ + int t = ViewNum(id); + if(t>=0) + return viewList->ItemAt(t); + else + return NULL; +} + +const int YabList::GetType(const char* id) +{ + return (int)typeList->ItemAt(ViewNum(id)); +} + +const int YabList::CountItems() +{ + return typeList->CountItems(); +} + +const void* YabList::ItemAt(int i) +{ + return viewList->ItemAt(i); +} + +void YabList::PrintOut() +{ + printf("\n"); + for(int i=0; iCountItems(); i++) + printf("\t%s\n", ((BString*)(idList->ItemAt(i)))->String() ); + printf("\n"); +} diff --git a/src/YabList.h b/src/YabList.h new file mode 100644 index 0000000..e2c1740 --- /dev/null +++ b/src/YabList.h @@ -0,0 +1,27 @@ +#ifndef YABLIST_H +#define YABLIST_H + +#include +#include + +class YabList +{ +public: + YabList(); + ~YabList(); + void AddView(const char* id, const BView* view, int type); + void DelView(const char* id); + void DelAll(); + const void* GetView(const char* id); + const int GetType(const char* id); + const int CountItems(); + const void* ItemAt(int i); + void PrintOut(); +private: + int ViewNum(const char* id); + BList* idList; + BList* viewList; + BList* typeList; +}; + +#endif diff --git a/src/YabMain.cpp b/src/YabMain.cpp new file mode 100644 index 0000000..a5fc934 --- /dev/null +++ b/src/YabMain.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include "YabInterface.h" + +char t[1024]; +const char* readSignature(int argc, char** argv) +{ + BString tmp("application/x-vnd.yab-app"); + /* Do not make changes above this comment without changing yab-IDE + to compensate for these changes.*/ + for(int i=1; iRun(); + ret = yabInterface->GetErrorCode(); + delete yabInterface; + return ret; +} diff --git a/src/YabMenu.h b/src/YabMenu.h new file mode 100644 index 0000000..0bdc0d3 --- /dev/null +++ b/src/YabMenu.h @@ -0,0 +1,17 @@ +#ifndef YABMENU_H +#define YABMENU_H + +class YabMenu : public BMenu +{ +public: + YabMenu(const char* name) : BMenu(name) + { + } + + void MyHide() + { + Hide(); + } +}; + +#endif diff --git a/src/YabStackView.cpp b/src/YabStackView.cpp new file mode 100644 index 0000000..6a1f36c --- /dev/null +++ b/src/YabStackView.cpp @@ -0,0 +1,50 @@ +// #include +#include "YabStackView.h" + + +YabStackView::YabStackView(BRect frame, const char *name, int32 number_of_views, uint32 resizingMode, uint32 flags, const BFont *labelFont) : BView(frame, name, resizingMode, flags) +{ + myViews = new BView*[number_of_views]; + // init + for(int i=0; i < number_of_views; i++) + { + myViews[i] = NULL; + } + myCurrent = 0; + myBounds = Bounds(); + myNumOfViews = number_of_views; +} + +YabStackView::~YabStackView() +{ + delete[] myViews; +} + +void YabStackView::AddViews(BView** stackedViews) +{ + for(int32 i = 0; i < myNumOfViews; i++) + { + myViews[i] = stackedViews[i]; + if(i != myCurrent) myViews[i]->Hide(); + AddChild(myViews[i]); + } +} + + +void YabStackView::SelectView(int32 index) +{ + if(index != myCurrent && index >= 0 && index < myNumOfViews) + { + Invalidate(myBounds); + myViews[myCurrent]->Hide(); + myCurrent = index; + Invalidate(myBounds); + myViews[myCurrent]->Show(); + } +} + +int32 YabStackView::CurrentView() +{ + return myCurrent; +} + diff --git a/src/YabStackView.h b/src/YabStackView.h new file mode 100644 index 0000000..531d293 --- /dev/null +++ b/src/YabStackView.h @@ -0,0 +1,23 @@ +#ifndef YAB_STACKVIEW_H_ +#define YAB_STACKVIEW_H_ + +#include + +class YabStackView : public BView +{ + public: + YabStackView(BRect frame, const char *name, int32 number_of_views, uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, uint32 flags = B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS, const BFont *labelFont = be_plain_font); + ~YabStackView(); + + void AddViews(BView** stackedViews); + int32 CurrentView(); + virtual void SelectView(int32 index); + + private: + BView** myViews; + int32 myCurrent; + BRect myBounds; + int32 myNumOfViews; +}; + +#endif diff --git a/src/YabTabView.cpp b/src/YabTabView.cpp new file mode 100644 index 0000000..3b4f231 --- /dev/null +++ b/src/YabTabView.cpp @@ -0,0 +1,543 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2005, Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: YabTabView.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Modified by Jan Bungeroth (jan@be-logos.org) +// Description: YabTabView provides the framework for containing and +// managing groups of BView objects. Modified for *sane* +// view handling (they stay connected to the window). +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include +#include +#include "YabControlLook.h" +#include "YabTabView.h" + +#define X_OFFSET 0.0f + +YabTabView::YabTabView(BRect frame, const char* name, button_width width, uint32 resizingMode, uint32 flags) + : BView(frame, name, resizingMode, flags) +{ + fTabList = new BList; + fTabNames = new BList; + + fTabWidthSetting = width; + fSelection = 0; + fFocus = -1; + fTabOffset = 0.0f; + + rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR); + + SetViewColor(color); + SetLowColor(color); + + font_height fh; + GetFontHeight(&fh); + fTabHeight = fh.ascent + fh.descent + fh.leading + 8.0f; + +/* + if (layouted) { + BGroupLayout* layout = new(std::nothrow) BGroupLayout(B_HORIZONTAL); + if (layout) { + layout->SetInsets(3.0, 3.0 + TabHeight() - 1, 3.0, 3.0); + SetLayout(layout); + } + + fContainerView = new BView("view container", B_WILL_DRAW); + fContainerView->SetLayout(new(std::nothrow) BCardLayout()); + } else { + */ + BRect bounds = Bounds(); + + bounds.top += TabHeight(); + bounds.InsetBy(3.0f, 3.0f); + + fContainerView = new BView(bounds, "view container", B_FOLLOW_ALL, + B_WILL_DRAW); +// } + + fContainerView->SetViewColor(color); + fContainerView->SetLowColor(color); + + AddChild(fContainerView); + FocusChanged = 1; + OldTabView = 1; + + fTabOrientation = B_TAB_TOP; +} + +YabTabView::~YabTabView() +{ + for(int i=0; iRemoveItem(i); + } + + delete fTabList; + delete fTabNames; +} + +void YabTabView::AddTab(BView *tabView, const char* label) +{ + if(tabView) + { + tabView->Hide(); + fContainerView->AddChild(tabView); + Invalidate(); + if(CountTabs() == 0) tabView->Show(); + + + fTabList->AddItem(tabView); + fTabNames->AddItem(new BString(label)); + } +} + +BView* YabTabView::RemoveTab(int32 index) +{ + if(index < 0 || index >= CountTabs()) + return NULL; + + BView *tab = (BView*)fTabList->RemoveItem(index); + delete (BString*)fTabNames->RemoveItem(index); + + if (index <= fSelection && fSelection != 0) + fSelection--; + + Select(fSelection); + + if (fFocus == CountTabs() - 1) + SetFocusTab(fFocus, false); + else + SetFocusTab(fFocus, true); + + return tab; +} + +int32 YabTabView::CountTabs() const +{ + return fTabList->CountItems(); +} + +int32 YabTabView::Selection() const +{ + return fSelection; +} + +void YabTabView::Select(int32 index) +{ + if (index < 0 || index >= CountTabs()) + index = Selection(); + + BView *tab = TabAt(Selection()); + if (tab) + { + Invalidate(); + tab->Hide(); + } + + tab = TabAt(index); + if (tab) + { + if (index != 0 && !Bounds().Contains(TabFrame(index))){ + if (!Bounds().Contains(TabFrame(index).LeftTop())) + fTabOffset += TabFrame(index).left - Bounds().left - 20.0f; + else + fTabOffset += TabFrame(index).right - Bounds().right + 20.0f; + } + + + Invalidate(); + tab->Show(); + fSelection = index; + FocusChanged = index+1; + } + +} + +void YabTabView::MakeFocus(bool focused) +{ + BView::MakeFocus(focused); + + SetFocusTab(Selection(), focused); +} + +int32 YabTabView::FocusTab() const +{ + return fFocus; +} + +void YabTabView::SetFocusTab(int32 tab, bool focused) +{ + + if (tab >= CountTabs()) + tab = 0; + + if (tab < 0) + tab = CountTabs() - 1; + + if (focused) { + if (tab == fFocus) + return; + + if (fFocus != -1){ + if (TabAt (fFocus) != NULL) + TabAt(fFocus)->MakeFocus(false); + Invalidate(TabFrame(fFocus)); + } + if (TabAt(tab) != NULL){ + TabAt(tab)->MakeFocus(true); + Invalidate(TabFrame(tab)); + fFocus = tab; + } + } else if (fFocus != -1) { + TabAt(fFocus)->MakeFocus(false); + Invalidate(TabFrame(fFocus)); + fFocus = -1; + } +} + +BView* YabTabView::TabAt(int32 index) +{ + if(index < 0 || index >= CountTabs()) + return NULL; + + return (BView*)fTabList->ItemAt(index); +} + +const char* YabTabView::GetTabName(int32 index) const +{ + if(index < 0 || index >= CountTabs()) + return NULL; + + return ((BString*)fTabNames->ItemAt(index))->String(); +} + +void YabTabView::KeyDown(const char *bytes, int32 numBytes) +{ + if (IsHidden()) + return; + + switch (bytes[0]) { + case B_DOWN_ARROW: + case B_LEFT_ARROW: { + int32 focus = fFocus - 1; + if (focus < 0) + focus = CountTabs() - 1; + SetFocusTab(focus, true); + FocusChanged = 1; + break; + } + + case B_UP_ARROW: + case B_RIGHT_ARROW: { + int32 focus = fFocus + 1; + if (focus >= CountTabs()) + focus = 0; + SetFocusTab(focus, true); + FocusChanged = 1; + break; + } + + case B_RETURN: + case B_SPACE: + Select(FocusTab()); + break; + + default: + BView::KeyDown(bytes, numBytes); + } +} + +void YabTabView::MouseDown(BPoint point) +{ + if (fTabOrientation == B_TAB_TOP && point.y > fTabHeight) + return; + if (fTabOrientation == B_TAB_BOTTOM && point.y < Bounds().bottom-fTabHeight) + return; + + for (int32 i = 0; i < CountTabs(); i++) { + if (TabFrame(i).Contains(point) && i != Selection()) { + Select(i); + fFocus = -1; + return; + } + } + + BView::MouseDown(point); +} + +BRect YabTabView::TabFrame(int32 tab_index) const +{ + float width = 100.0; + float height = fTabHeight;; + BRect tabFrame(Bounds()); + switch (fTabWidthSetting) { + case B_WIDTH_FROM_LABEL: + { + float x = 0.0; + for (int32 i = 0; i < tab_index; i++){ + x += StringWidth(GetTabName(i)) + 20.0; + } + + if(fTabOrientation == B_TAB_TOP) + tabFrame.Set(x, 0.0, x + StringWidth(GetTabName(tab_index)) + 20.0, height); + else + tabFrame.Set(x, tabFrame.bottom - height, x + StringWidth(GetTabName(tab_index)) + 20.0, tabFrame.bottom); + return tabFrame; + } + + case B_WIDTH_FROM_WIDEST: + width = 0.0; + for (int32 i = 0; i < CountTabs(); i++) { + float tabWidth = StringWidth(GetTabName(i)) + 20.0; + if (tabWidth > width) + width = tabWidth; + } + // fall through + + case B_WIDTH_AS_USUAL: + default: + if(fTabOrientation == B_TAB_TOP) + tabFrame.Set(tab_index * width, 0.0, tab_index * width + width, height); + else + tabFrame.Set(tab_index * width, tabFrame.bottom - height, tab_index * width + width, tabFrame.bottom); + return tabFrame; + } +} + +void YabTabView::SetTabWidth(button_width width) +{ + fTabWidthSetting = width; + + Invalidate(); +} + +button_width YabTabView::TabWidth() const +{ + return fTabWidthSetting; +} + +void YabTabView::SetTabHeight(float height) +{ + if (fTabHeight == height) + return; + + fContainerView->MoveBy(0.0f, height - fTabHeight); + fContainerView->ResizeBy(0.0f, height - fTabHeight); + + fTabHeight = height; + + Invalidate(); +} + + +float YabTabView::TabHeight() +{ + return fTabHeight; +} + + +BView *YabTabView::ContainerView() +{ + return fContainerView; +} + +void YabTabView::Draw(BRect updateRect) +{ + // DrawBox(DrawTabs()); +// SetHighColor(223,223,223); +// StrokeLine(BPoint(Bounds().left, Bounds().bottom-TabHeight()-2), BPoint(Bounds().right, Bounds().bottom-TabHeight()-2)); + DrawBox(TabFrame(fSelection)); + DrawTabs(); + + if (IsFocus() && fFocus != -1) + { + DrawFocusMark(TabFrame(fFocus), fFocus); + // Invalidate(TabFrame(fFocus)); + } +} + + +BRect YabTabView::DrawTabs() +{ + float left = 0; + + for (int32 i = 0; i < CountTabs(); i++) { + BRect tabFrame = TabFrame(i); + DrawTab(tabFrame, i, i == fSelection ? B_TAB_FRONT : (i == 0) ? B_TAB_FIRST : B_TAB_ANY, i + 1 != fSelection); + + left = tabFrame.right; + } + + BRect frame(Bounds()); + if (left < frame.right) { + frame.left = left; + if(fTabOrientation == B_TAB_TOP) + frame.bottom = fTabHeight; + else + frame.top = frame.bottom - fTabHeight; + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 borders = BControlLook::B_TOP_BORDER + | BControlLook::B_BOTTOM_BORDER | BControlLook::B_RIGHT_BORDER; + if (left == 0) + borders |= BControlLook::B_LEFT_BORDER; + if(fTabOrientation == B_TAB_TOP) + be_control_look->DrawInactiveTab(this, frame, frame, base, 0, borders); + else + fYabControlLook.DrawInactiveTabBottom(this, frame, frame, base, 0, borders); + } + + if (fSelection < CountTabs()) + return TabFrame(fSelection); + + return BRect(); +} + +void YabTabView::DrawLabel(int32 current, BRect frame) +{ + BString label = GetTabName(current); + if (label == NULL) + return; + + float frameWidth = frame.Width(); + float width = StringWidth(label.String()); + font_height fh; + + if (width > frameWidth) { + BFont font; + GetFont(&font); + font.TruncateString(&label, B_TRUNCATE_END, frameWidth); + width = frameWidth; + font.GetHeight(&fh); + } else { + GetFontHeight(&fh); + } + + SetDrawingMode(B_OP_OVER); + SetHighColor(ui_color(B_CONTROL_TEXT_COLOR)); + DrawString(label.String(), + BPoint((frame.left + frame.right - width) / 2.0, + (frame.top + frame.bottom - fh.ascent - fh.descent) / 2.0 + + fh.ascent)); +} + + +void YabTabView::DrawTab(BRect frame, int32 current, tab_position position, bool full) +{ + + BView *owner = this; + rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR); + +// uint32 borders = BControlLook::B_RIGHT_BORDER +// | BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; +// if (frame.left == owner->Bounds().left) +// borders |= BControlLook::B_LEFT_BORDER; +// be_control_look->DrawButtonFrame(owner, frame, frame, +// no_tint, 0, borders); +// if (position == B_TAB_FRONT) +// no_tint = tint_color(no_tint, B_DARKEN_2_TINT); +// be_control_look->DrawButtonBackground(owner, frame, frame, no_tint); + + uint32 borders = BControlLook::B_TOP_BORDER + | BControlLook::B_BOTTOM_BORDER; + if (frame.left == owner->Bounds().left) + borders |= BControlLook::B_LEFT_BORDER; + if (frame.right == owner->Bounds().right) + borders |= BControlLook::B_RIGHT_BORDER; + + if (position == B_TAB_FRONT) { + if(fTabOrientation == B_TAB_TOP) + { + frame.bottom += 1; + be_control_look->DrawActiveTab(owner, frame, frame, no_tint, 0, borders); + } + else + { + frame.top -= 1; + fYabControlLook.DrawActiveTabBottom(owner, frame, frame, no_tint, 0, borders); + } + } else { + if(fTabOrientation == B_TAB_TOP) + be_control_look->DrawInactiveTab(owner, frame, frame, no_tint, 0, borders); + else + fYabControlLook.DrawInactiveTabBottom(owner, frame, frame, no_tint, 0, borders); + } + + DrawLabel(current, frame); + return; + +} + +void YabTabView::DrawFocusMark(BRect frame, int32 current) +{ + float width = StringWidth(GetTabName(current)); + + SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); + + float offset = (fSelection == current) ? 3 : 2; + StrokeLine(BPoint((frame.left + frame.right - width) / 2.0, + frame.bottom - offset), + BPoint((frame.left + frame.right + width) / 2.0, + frame.bottom - offset)); +} + +void YabTabView::DrawBox(BRect selTabRect) +{ + BRect rect(Bounds()); + if(fTabOrientation == B_TAB_TOP) + rect.top = selTabRect.bottom; + else + rect.bottom -= selTabRect.Height(); + +// BRegion clipping(Bounds()); +// selTabRect.left += 2; +// selTabRect.right -= 2; +// clipping.Exclude(selTabRect); +// ConstrainClippingRegion(&clipping); + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + be_control_look->DrawGroupFrame(this, rect, rect, base); + +// ConstrainClippingRegion(NULL); + +} + +void YabTabView::SetOrientation(tab_orientation side) +{ + if(fTabOrientation != side) + if(side == B_TAB_BOTTOM) + fContainerView->MoveTo(3.0, 3.0); + else + fContainerView->MoveTo(3.0, TabHeight()); + fTabOrientation = side; +} + +tab_orientation YabTabView::Orientation() +{ + return fTabOrientation; +} + diff --git a/src/YabTabView.h b/src/YabTabView.h new file mode 100644 index 0000000..d858b1e --- /dev/null +++ b/src/YabTabView.h @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: YabTabView.h +// Author: Marc Flerackers (mflerackers@androme.be) +// Jan Bungeroth (jan@be-logos.org) +// Description: YabTabView provides the framework for containing and +// managing groups of BView objects. +//------------------------------------------------------------------------------ + +#ifndef YABTAB_VIEW_H +#define YABTAB_VIEW_H + +// Standard Includes ----------------------------------------------------------- + +#include +#include "YabControlLook.h" + +// Local Defines --------------------------------------------------------------- +enum tab_position { + B_TAB_FIRST = 999, + B_TAB_FRONT, + B_TAB_ANY +}; + +enum tab_orientation { + B_TAB_TOP = 0, + B_TAB_BOTTOM +}; + +// YabTabView class ------------------------------------------------------------------ +class YabTabView : public BView +{ +public: + YabTabView(BRect frame, const char *name, + button_width width = B_WIDTH_AS_USUAL, + uint32 resizingMode = B_FOLLOW_ALL, + uint32 flags = B_FULL_UPDATE_ON_RESIZE | + B_WILL_DRAW | B_NAVIGABLE_JUMP | + B_FRAME_EVENTS | B_NAVIGABLE); + ~YabTabView(); + +virtual void KeyDown(const char *bytes, int32 numBytes); +virtual void MouseDown(BPoint point); + +virtual void Select(int32 tab); + int32 Selection() const; + +virtual void MakeFocus(bool focused = true); +virtual void SetFocusTab(int32 tab, bool focused); + int32 FocusTab() const; + +virtual void Draw(BRect updateRect); +virtual BRect DrawTabs(); +virtual void DrawBox(BRect selTabRect); +virtual BRect TabFrame(int32 tab_index) const; +virtual void DrawFocusMark(BRect frame, int32 current); +virtual void DrawLabel(int32 current, BRect frame); +virtual void DrawTab(BRect frame, int32 current, tab_position position, bool full); +virtual const char* GetTabName(int32 index) const; + +virtual void AddTab(BView *target, const char* tabname); +virtual BView *RemoveTab(int32 tabIndex); + +virtual BView *TabAt ( int32 tab_index ); +virtual void SetTabWidth(button_width width); +button_width TabWidth() const; + + void SetOrientation(tab_orientation side); + tab_orientation Orientation(); + +virtual void SetTabHeight(float height); + float TabHeight(); + + BView *ContainerView(); + + int32 CountTabs() const; + int32 FocusChanged; + int32 OldTabView; + +private: + BList *fTabList; + BList *fTabNames; + BView *fContainerView; + button_width fTabWidthSetting; + float fTabWidth; + float fTabHeight; + int32 fSelection; + int32 fInitialSelection; + int32 fFocus; + float fTabOffset; + tab_orientation fTabOrientation; + YabControlLook fYabControlLook; +}; +//------------------------------------------------------------------------------ + +#endif diff --git a/src/YabText.cpp b/src/YabText.cpp new file mode 100644 index 0000000..20a245c --- /dev/null +++ b/src/YabText.cpp @@ -0,0 +1,920 @@ +#include +#include "YabText.h" + +const uint32 YABTEXT_ANALYSE = 'YTan'; +const uint32 YABTEXT_FILECHANGED = 'YTfc'; +const uint32 YABTEXT_PARSE_LINE = 'YTpl'; +const uint32 YABTEXT_UNDO_HIGHLIGHTING = 'YTuh'; + +const rgb_color Blue = {0,0,255,255}; +const rgb_color Red = {255,0,0,255}; +const rgb_color Grey = {185,185,185,255}; +const rgb_color Green = {0,200,000,255}; +const rgb_color Magenta = {200,0,255,255}; + +YabText::YabText(BRect frame, const char* name, BRect textRect, uint32 resizeMode, uint32 flags) + : BTextView(frame, name, textRect, resizeMode, flags) +{ + isCaseSensitive = false; + hasChanged = false; + + // Standard definitions + bgcolor.blue = bgcolor.red = bgcolor.green = bgcolor.alpha = 255; // background + textcolor.blue = textcolor.red = textcolor.green = 0; textcolor.alpha = 255; + + generic_cmd_color = Blue; + format_cmd_color = Red; + special_cmd_color = Green; + comment_color = Grey; + punc_symbol_color = Magenta; + + SetStylable(true); + // BFont myFont(be_fixed_font); + // myFontSize = 12; + // f = myFont; + // f.SetSize(myFontSize); + // SetFontAndColor(0,1,&f,B_FONT_ALL,&textcolor); + + SearchOffset = 0; + SetDoesUndo(true); + + hasAutoCompletion = true; + words = new BList(0); + number_of_letters = 3; + isJapanese = false; +} + +YabText::~YabText() +{ + BString *anItem; + for ( int32 i = 0; (anItem = (BString*)words->ItemAt(i)); i++ ) + delete anItem; + delete words; +} + +void YabText::AddWord(BString *word) +{ + words->AddItem((void*)word); +} + +void YabText::HasAutoCompletion(bool flag) +{ + hasAutoCompletion = flag; +} + +void YabText::SetAutoCompleteStart(int num) +{ + number_of_letters = num; +} + +void YabText::AddCommand(const char* command, int colorGroup) +{ + switch(colorGroup) + { + case 0: generic_matches.push_back(command); + break; + case 1: green_matches.push_back(command); + break; + case 2: purple_matches.push_back(command); + break; + case 3: comment_matches.push_back(command); + break; + case 4: punctuation.push_back(command[0]); + break; + default: + break; + } +} + +void YabText::SetColors(int id, int r, int g, int b) +{ + switch(id) + { + case 0: generic_cmd_color.red = r; + generic_cmd_color.green = g; + generic_cmd_color.blue = b; + ParseAll(0,TextLength()-1,true); + break; + case 1: format_cmd_color.red = r; + format_cmd_color.green = g; + format_cmd_color.blue = b; + ParseAll(0,TextLength()-1,true); + break; + case 2: special_cmd_color.red = r; + special_cmd_color.green = g; + special_cmd_color.blue = b; + ParseAll(0,TextLength()-1,true); + break; + case 3: comment_color.red = r; + comment_color.green = g; + comment_color.blue = b; + ParseAll(0,TextLength()-1,true); + break; + case 4: punc_symbol_color.red = r; + punc_symbol_color.green = g; + punc_symbol_color.blue = b; + ParseAll(0,TextLength()-1,true); + break; + case 5: SetViewColor(r,g,b); + Invalidate(); + break; + case 6: { + textcolor.red = r; + textcolor.green = g; + textcolor.blue = b; + BFont default_font; + GetFontAndColor(0, &default_font); + // BFont default_font(be_fixed_font); + // default_font.SetSize(myFontSize); + SetFontAndColor(0,TextLength()-1,&default_font,B_FONT_ALL,&textcolor); + ParseAll(0,TextLength()-1,true); + } + break; + default: + break; + } +} + +void YabText::AttachedToWindow() +{ + SetViewColor(bgcolor); + SetColorSpace(B_RGB32); + BTextView::AttachedToWindow(); +} + +void YabText::Select(int32 start,int32 finish) +{ + BTextView::Select(start,finish); +} + +int32 YabText::CountPhysicalLines() +{ + return BTextView::CountLines(); +} + +void YabText::KeyDown(const char* bytes, int32 numBytes) +{ + isAutoComplete = false; + bool shouldBeChanged = true; + bool passon = true; + switch(bytes[0]) + { + case B_ENTER: + { + //update previous line on enter + BMessage msg(YABTEXT_PARSE_LINE); + int32 start,finish; + GetSelection(&start,&finish); + if(msg.AddInt32("start",start) == B_OK && msg.AddInt32("finish",finish) == B_OK) + { + BMessenger msgr(this); + msgr.SendMessage(&msg); + } + } + break; + case B_LEFT_ARROW: + { + shouldBeChanged = false; + if(modifiers() & B_CONTROL_KEY) + { + passon = false; + int32 startoffset, endoffset; + GetSelection(&startoffset, &endoffset); + bool inloop = true; + while(inloop) + { + startoffset--; + if(startoffset < 0) + { + if(modifiers() & B_SHIFT_KEY) + Select(0,endoffset); + else + Select(0,0); + ScrollToSelection(); + inloop = false; + } + else + { + char tmp = ByteAt(startoffset); + + if(tmp == ' ' || tmp == ':' || tmp == '/' || tmp == '\n' || tmp == '.' || tmp == '(' || tmp == ')' || tmp == '"' || tmp == '\t' || tmp == '-' || tmp == '+' || tmp == '*' || tmp == '^' || tmp == ',' || tmp == ';' || tmp == '=' || tmp == '\r') + { + if(modifiers() & B_SHIFT_KEY) + Select(startoffset,endoffset); + else + Select(startoffset,startoffset); + ScrollToSelection(); + inloop = false; + } + } + + } + + } + } + break; + case B_RIGHT_ARROW: + { + shouldBeChanged = false; + int cur = CurrentLine(); + if(modifiers() & B_CONTROL_KEY) + { + // passon = false; + int32 startoffset, endoffset; + GetSelection(&startoffset, &endoffset); + bool inloop = true; + while(inloop) + { + endoffset++; + if(endoffset > TextLength() ) + { + if(modifiers() & B_SHIFT_KEY) + Select(startoffset,endoffset); + else + Select(endoffset, endoffset); + ScrollToSelection(); + inloop = false; + } + else + { + char tmp = ByteAt(endoffset); + int a = LineAt(endoffset); + + if(tmp == ' ' || tmp == ':' || tmp == '/' || tmp == '\n' || tmp == '.' || tmp == '(' || tmp == ')' || tmp == '"' || tmp == '\t' || tmp == '-' || tmp == '+' || tmp == '*' || tmp == '^' || tmp == ',' || tmp == ';' || tmp == '=' || tmp == '\r' || a!=cur) + { + if(a!=cur) endoffset --; + if(modifiers() & B_SHIFT_KEY) + Select(startoffset,endoffset); + else + Select(endoffset,endoffset); + ScrollToSelection(); + inloop = false; + } + } + + } + + } + } + break; + case B_UP_ARROW: + case B_DOWN_ARROW: + case B_PAGE_UP: + case B_PAGE_DOWN: + case B_HOME: + case B_END: + case B_INSERT: + case B_FUNCTION_KEY: + case B_ESCAPE: + shouldBeChanged = false; + break; + case B_BACKSPACE: + { + int32 a,b; + GetSelection(&a, &b); + if(a == b && a == 0) shouldBeChanged = false; + } + break; + case B_DELETE: + { + int32 a,b; + GetSelection(&a, &b); + if(a == b && a == TextLength()) shouldBeChanged = false; + } + break; + } + + if(shouldBeChanged && !hasChanged) hasChanged = true; + + if(passon) BTextView::KeyDown(bytes,numBytes); + + if(isAutoComplete) + { + Select(autoOffset, autoEnd); + } +} + +int YabText::FindFirstOnLine(char c,int offset,int eol) +{ + for(int i=offset;i sols; + std::vector eols; + FillSolEol(sols,eols,0,TextLength()-1); + + for(int i=0;i= sols[i] && offset <= eols[i]) + return i; + } + return -1; +} + +void YabText::FillSolEol(std::vector& s,std::vector& e,int start,int finish) +{ + int i=start; + int text_length = TextLength(); + for(i=start;i>=0;i--) + { + if(ByteAt(i) == '\n') + { + break; + } + } + start=i+1; + + i = finish; + for(i=finish;i CountLines()) index = CountLines(); + +// if(index < 0 || index > CountLines() || TextLength() <= 0) +// return; + + std::vector eols; + std::vector sols; + + FillSolEol(sols,eols,0,TextLength()-1); + Select(sols[index],eols[index]); +}*/ + +int32 YabText::CountLines() +{ + std::vector eols; + std::vector sols; + FillSolEol(sols,eols,0,TextLength()-1); + return eols.size(); +} + +void YabText::ParseAll(int start,int finish,bool IsInteractive) +{ + // BFont font(be_fixed_font); + // font.SetSize(myFontSize); + BFont default_font; + GetFontAndColor(0, &default_font); + + int text_length = TextLength(); + if(text_length > 0) + { + std::vector eols; + std::vector sols; + FillSolEol(sols,eols,start,finish); + + int i; + int size; + /* + if(!IsInteractive) + { + size = text_length; + std::vector colorVec(size,textcolor); + + for(i=0;i offsets; + offsets.push_back(0); + + for(i=1;icount = offset_size; + for(i=0;iruns[i].color=colorVec[offsets[i]]; + tra->runs[i].font=font; + tra->runs[i].offset=offsets[i]; + } + SetRunArray(0,text_length-1,tra); + } + else + {*/ + for(i=0;i colorVec(size,textcolor); + + for(int k=0;k 0) + if(!isJapanese) SetFontAndColor(plStart,plStart+plLength,&default_font,B_FONT_ALL,&colorVec[i-sol-1]); +} + +void YabText::ParseLine(int sol,int eol,std::vector& colorVec)//,std::vector& colorVec) +{ + int i; + int offset = sol; + int pos; + int text_length = TextLength(); + //assert(sol >=0 && eol >=0 && sol < text_length && eol < text_length); + //Setup some defaults.... + /* + TwoColorPlateau('\'',sol,eol,comment_color,colorVec);//,displaced);//-displaced + TwoColorPlateau('`',sol,eol,comment_color,colorVec);//,displaced); + TwoColorPlateau('\\',sol,eol,comment_color,colorVec);//,displaced);*/ + + for(i=sol;i= 0 && ByteAt(i-1) == '\\') + { + colorVec[i-1] = punc_symbol_color; + } + + colorVec[i] = punc_symbol_color; + + } + else if(ByteAt(i) == '&' || ByteAt(i) == '{' || ByteAt(i) == '}')// + { + if(i-1 >= 0 && ByteAt(i-1) == '\\') + { + colorVec[i-1] = punc_symbol_color; + } + + colorVec[i] = punc_symbol_color; + + } + else if(ByteAt(i) == '$') + { + if(i-1 >= 0 && ByteAt(i-1) == '\\') + { + colorVec[i-1] = textcolor; + colorVec[i] = textcolor; + } + } + else if(ByteAt(i) == '\\' && i+1 < eol) + { + if(ByteAt(i+1) == '#') + { + colorVec[i] = punc_symbol_color; + colorVec[i+1] = punc_symbol_color; + }else if(ByteAt(i+1) == '\'' || ByteAt(i+1) == '`') + { + colorVec[i] = textcolor; + colorVec[i+1] = textcolor; + } + } + /*if(toupper((char)ByteAt(i)) == 'B') + { + if(i+3 < eol && toupper((char)ByteAt(i+1)) == 'E' && + toupper((char)ByteAt(i+2)) == 'O' && toupper((char)ByteAt(i+3)) == 'S') + { + colorVec[i] = Blue; + colorVec[i+1] = Red; + } + else if(i+4 < eol && toupper((char)ByteAt(i+1)) == 'E' && + toupper((char)ByteAt(i+2)) == 'T' && toupper((char)ByteAt(i+3)) == 'E' + && toupper((char)ByteAt(i+3)) == 'X') + { + colorVec[i] = Blue; + colorVec[i+1] = Red; + } + }*/ + } + offset = sol; + while((pos = FindFirstOnLine('%',offset,eol))>= 0 && offset < eol) + { + + if(pos - 1 >= 0 && ByteAt(pos-1) == '\\') + { + colorVec[pos-1] = punc_symbol_color; + colorVec[pos] = punc_symbol_color; + } + else + { + for(i=pos;i& colorVec) +{ + int i; + for(i=sol;i='0' && (char)ByteAt(j)<='9')) + // if(ByteAt(j)>32) + { + match << (char)ByteAt(j); + } + else + break; + } + if((match.Length() > 0) && (i==sol || !isalpha(ByteAt(i-1)))) + { + if(Contains(green_matches,match)) + { + for(int k=i;k=0) + { + if(ByteAt(myOffset) == ' ' || ByteAt(myOffset) == '\n' || ByteAt(myOffset) == '\t') + break; + myOffset --; + } + + if(offset-myOffset>number_of_letters) + { + for(int i=myOffset+1; iItemAt(i)); i++ ) + { + if(anItem->Compare(itext, offset-myOffset+length-1) == 0) + { + autoOffset = offset + 1; + isAutoComplete = true; + BString sleepy(anItem->String()); + sleepy.CopyInto(replace, offset-myOffset-1, anItem->Length()); + length = replace.Length(); + autoEnd = anItem->Length()+myOffset+1; + break; + } + + } + } + } + BTextView::InsertText(replace.String(),length,offset,NULL); + + if(text[0] != B_ENTER) + { + BMessage msg(YABTEXT_ANALYSE); + if(msg.AddInt32("offset",offset)==B_OK && msg.AddInt32("length",length)==B_OK) + //&& msg.AddString("text",text) == B_OK) + { + BMessenger msgr(this); + msgr.SendMessage(&msg); + } + } +} + +void YabText::DeleteText(int32 start, int32 finish) +{ + BMessage msg(YABTEXT_ANALYSE); + if(msg.AddInt32("start",start)==B_OK && msg.AddInt32("finish",finish)==B_OK) + { + BMessenger msgr(this); + msgr.SendMessage(&msg); + } + BTextView::DeleteText(start,finish); + +} + +void YabText::SetText(const char* text,int32 length,const text_run_array* runs ) +{ + hasChanged = true; + BTextView::SetText(text,length,runs); + // ParseAll(0,length-1,false); +} + +void YabText::UpdateColors() +{ + SetFontAndColor(0,TextLength(),&f,B_FONT_ALL,&textcolor); + ParseAll(0,TextLength()-1,true); + //const char* text = Text(); + //Delete(0,TextLength()-1); + //SetText(text,strlen(text));//,TextLength()-1); +} + +void YabText::UpdateFontSize() +{ + f.SetSize(myFontSize); + SetFontAndColor(0,TextLength(),&f,B_FONT_ALL,&textcolor); + ParseAll(0,TextLength()-1,true); +} + +void YabText::SetText(BFile* file,int32 offset,int32 length,const text_run_array* runs ) +{ + hasChanged = true; + BTextView::SetText(file,offset,length,runs); + // ParseAll(offset,length-1,false); +} + +bool YabText::Contains(std::vector& v,BString s) +{ + for(int i=0;iwhat) + { + case B_INPUT_METHOD_EVENT: + { + int32 be_op; + if(msg->FindInt32("be:opcode", &be_op) == B_OK) + { + if(be_op == B_INPUT_METHOD_STARTED) isJapanese = true; + if(be_op == B_INPUT_METHOD_STOPPED) isJapanese = false; + } + BTextView::MessageReceived(msg); + } + break; + case YABTEXT_UNDO_HIGHLIGHTING: + { + int32 start,finish; + if(msg->FindInt32("start",&start)==B_OK && msg->FindInt32("finish",&finish)==B_OK) + { + Select(start,finish); + } + }break; + + case YABTEXT_PARSE_LINE: + { + int32 start,finish; + if(msg->FindInt32("start",&start)==B_OK && msg->FindInt32("finish",&finish)==B_OK) + { + int32 sel_start,sel_finish; + GetSelection(&sel_start,&sel_finish); + ParseAll(min(sel_start,start),max(sel_finish,finish),true); + } + }break; + case YABTEXT_ANALYSE: + { + int32 start,finish; + if(msg->FindInt32("start",&start)==B_OK && msg->FindInt32("finish",&finish)==B_OK) + { + ParseAll(start,finish,true); + } + + int32 offset,length; + if(msg->FindInt32("offset",&offset)==B_OK + && msg->FindInt32("length",&length)==B_OK) + { + GetSelection(&start,&finish); + ParseAll(offset,finish,true); + } + + }break; + /* + case B_CUT: + case B_COPY: + case B_PASTE: + { + BMessage msg(UPDATE_CLIPBOARD_MENU_STATUS); + BMessenger msgr(Window()); + msgr.SendMessage(&msg); + }*/ + default: + BTextView::MessageReceived(msg); + + } +} + +/* +void YabText::LoadFile (entry_ref *ref) +{ + if (ref == NULL) { + return; + } + + BFile file(ref, B_READ_ONLY); + if (file.InitCheck() != B_OK) { + return; + } + + off_t length; + file.GetSize(&length); + if (length == 0) { + return; + } + + SetText (&file, 0, length); +}*/ + +bool YabText::HasChanged() +{ + return hasChanged; +} + +void YabText::SetChanged(bool changed) +{ + hasChanged = changed; +} + +bool YabText::IsCaseSensitive() +{ + return isCaseSensitive; +} + +void YabText::SetCaseSensitive(bool caseSensitive) +{ + isCaseSensitive = caseSensitive; +} diff --git a/src/YabText.h b/src/YabText.h new file mode 100644 index 0000000..97effac --- /dev/null +++ b/src/YabText.h @@ -0,0 +1,90 @@ +#ifndef YABTEXT_H +#define YABTEXT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class YabText : public BTextView +{ + public: + YabText(BRect frame, const char* name, BRect textRect, uint32 resizeMode, uint32 flags); + ~YabText(); + void AddCommand(const char* command, int colorGroup); + virtual void AttachedToWindow(); + virtual void Select(int32 start,int32 finish); + void SetColors(int, int, int, int); + int32 CountPhysicalLines(); //? + virtual void KeyDown(const char* bytes, int32 numBytes); + int FindFirstOnLine(char c,int offset,int eol); + int32 OffsetAtIndex(int32 index);// const; + int32 LineAt(int32 offset);// const; + void FillSolEol(std::vector& s,std::vector& e,int start,int finish); + // void GoToLine(int32 index); + int32 CountLines(); + void ParseAll(int start,int finish,bool IsInteractive); + void IParseLine(int sol,int eol); // TODO! + void ParseLine(int sol,int eol,std::vector& colorVec); // TODO! + void ICheckWordLists(int sol,int eol,std::vector& colorVec); + void SetText(const char* text,int32 length,const text_run_array* runs = NULL); + void UpdateColors(); + void UpdateFontSize(); + void SetText(BFile* file,int32 offset,int32 length,const text_run_array* runs = NULL); + bool Contains(std::vector& v,BString s); + // virtual bool CanEndLine(int32 offset); + // void LoadFile(entry_ref *ref); + virtual void MessageReceived(BMessage* msg); + + bool HasChanged(); + void SetChanged(bool changed); + bool IsCaseSensitive(); + void SetCaseSensitive(bool caseSensitive); + + void SetNormalFocus(); + void SetAttachedFocus(); + + void AddWord(BString *word); + void SetAutoCompleteStart(int num); + void HasAutoCompletion(bool flag); + + int SearchOffset; + + private: + bool isCaseSensitive, hasChanged, isJapanese; + int myFontSize; + rgb_color bgcolor; + rgb_color textcolor, punc_symbol_color, comment_color, ignore_color; + rgb_color format_cmd_color, special_cmd_color, generic_cmd_color; + BFont f; + + std::vector green_matches; + std::vector purple_matches; + std::vector generic_matches; + std::vector comment_matches; + std::vector punctuation; + + BList *words; + bool hasAutoCompletion, isAutoComplete; + int32 autoOffset, autoEnd; + int number_of_letters; + + bool min(int32 a, int32 b) + { + return (a<=b?a:b); + }; + bool max(int32 a, int32 b) + { + return (a>=b?a:b); + }; + + protected: + virtual void InsertText(const char* text,int32 length,int32 offset,const text_run_array* runner); + virtual void DeleteText(int32 start, int32 finish); +}; +#endif diff --git a/src/YabToolTip.cpp b/src/YabToolTip.cpp new file mode 100644 index 0000000..d1b9523 --- /dev/null +++ b/src/YabToolTip.cpp @@ -0,0 +1,138 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +// #include +#include +#include + +#include "ToolTip.h" + +class MouseToolTip : public BToolTip { +public: + MouseToolTip() + { + fView = new MouseView(); + SetSticky(true); + } + + virtual ~MouseToolTip() + { + delete fView; + } + + virtual BView* View() const + { + return fView; + } + +private: + BStringView* fView; +}; + + +class ImmediateView : public BStringView { +public: + ImmediateView(const char* name, const char* label) + : + BStringView(name, label) + { + SetToolTip("Easy but immediate!"); + ToolTip()->SetSticky(true); + } + + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) + { + if (transit == B_ENTERED_VIEW) + ShowToolTip(ToolTip()); + } +}; + + +class Window : public BWindow { +public: + Window(); + + virtual bool QuitRequested(); +}; + + +class Application : public BApplication { +public: + Application(); + + virtual void ReadyToRun(); +}; + + +// #pragma mark - + + +Window::Window() + : + BWindow(BRect(100, 100, 520, 430), "ToolTip-Test", + B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS) +{ + BView* simple = new BStringView("1", "Simple Tool Tip"); + simple->SetToolTip("This is a really\nsimple tool tip!"); + + BView* custom = new BStringView("2", "Custom Tool Tip"); + custom->SetToolTip(new CustomToolTip()); + + BView* changing = new BStringView("3", "Changing Tool Tip"); + changing->SetToolTip(new ChangingToolTip()); + + BView* mouse = new BStringView("3", "Mouse Tool Tip (sticky)"); + mouse->SetToolTip(new MouseToolTip()); + + BView* immediate = new ImmediateView("3", "Immediate Tool Tip (sticky)"); + + BLayoutBuilder::Group<>(this, B_VERTICAL) + .Add(simple) + .Add(custom) + .Add(changing) + .Add(mouse) + .Add(immediate); +} + + +bool +Window::QuitRequested() +{ + be_app->PostMessage(B_QUIT_REQUESTED); + return true; +} + + +// #pragma mark - + + +Application::Application() + : BApplication("application/x-vnd.haiku-tooltiptest") +{ +} + + +void +Application::ReadyToRun() +{ + BWindow *window = new Window(); + window->Show(); +} + + +// #pragma mark - + + +int +main(int argc, char **argv) +{ + Application app; + + app.Run(); + return 0; +} + diff --git a/src/YabView.cpp b/src/YabView.cpp new file mode 100644 index 0000000..1706156 --- /dev/null +++ b/src/YabView.cpp @@ -0,0 +1,335 @@ +#include +#include +#include +#include +#include +#include "YabWindow.h" +#include "YabView.h" + +YabView::YabView(BRect frame, const char *name, uint32 resizingMode, uint32 flags) + : BView(frame, name, resizingMode, flags) +{ +/* + SetViewColor(216,216,216,255); + SetLowColor(216,216,216,255); + SetHighColor(0,0,0,255); + */ + + rgb_color b1 = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color b2 = {0,0,0,255}; + + SetViewColor(b1); + SetLowColor(b1); + SetHighColor(b2); + + drawList = new BList(1); + + YabDrawing *t = new YabDrawing(); + t->command = 6; + t->r = 0; t->g = 0; + t->b = 0; t->alpha = 255; + drawList->AddItem(t); + + YabDrawing *t2 = new YabDrawing(); + t2->command = 7; + t2->r = b1.red; t2->g = b1.green; + t2->b = b1.blue; t2->alpha = 255; + drawList->AddItem(t2); + + mouseMovedInfo = 1; + mouseStateInfo = -1; + prevMouseStateInfo = 0; + + mouseX = 0; + mouseY = 0; + mouseLButton = 0; + mouseMButton = 0; + mouseRButton = 0; + dropZone = false; + pressedKeys.SetTo(""); + SetDrawingMode(B_OP_COPY); +} + +YabView::~YabView() +{ + while(drawList->CountItems()>0) + { + YabDrawing *t = (YabDrawing*)drawList->LastItem(); + drawList->RemoveItem(t); + if(t->command == 0) delete [] t->chardata; + delete t; + } + delete drawList; +} + +void YabView::MessageReceived(BMessage *msg) +{ + entry_ref ref; + switch (msg->what) + { + case B_SIMPLE_DATA: + { + if(dropZone) + { + BString tmp(""); + int32 count; + uint32 type; + const char* name; + int i =0; + + while(msg->FindRef("refs", i, &ref) == B_OK) + { + BEntry dropEntry(&ref); + BPath tmpDirectory; + dropEntry.GetPath(&tmpDirectory); + tmp << Name(); + tmp << ":_Dropped"; + tmp << ":" << tmpDirectory.Path(); + tmp << "|"; + i++; + } + YabWindow *yabWin = (YabWindow*)Window(); + yabWin->dropMsg.SetTo(tmp); + } + else + BView::MessageReceived(msg); + } + break; + default: + BView::MessageReceived(msg); + break; + } +} + +void YabView::Draw(BRect updateRect) +{ + SetFont(be_plain_font); + updateRect = Bounds(); + for(int i=0; iCountItems(); i++) + { + YabDrawing *e = (YabDrawing*)drawList->ItemAt(i); + switch(e->command) + { + case 0: DrawString(e->chardata, BPoint(e->x1, e->y1)); + break; + case 1: StrokeLine(BPoint(e->x1,e->y1),BPoint(e->x2,e->y2), e->p); + break; + case 2: StrokeEllipse(BPoint(e->x1,e->y1), e->x2, e->y2, e->p); + break; + case 3: FillEllipse(BPoint(e->x1,e->y1), e->x2, e->y2, e->p); + break; + case 4: StrokeRect(BRect(e->x1,e->y1,e->x2,e->y2), e->p); + break; + case 5: FillRect(BRect(e->x1,e->y1,e->x2,e->y2), e->p); + break; + case 6: { + if(e->alpha == 255) + SetDrawingMode(B_OP_COPY); + else + SetDrawingMode(B_OP_ALPHA); + SetHighColor(e->r,e->g,e->b,e->alpha); + } + break; + case 7: { + if(e->alpha == 255) + SetDrawingMode(B_OP_COPY); + else + SetDrawingMode(B_OP_ALPHA); + SetLowColor(e->r,e->g,e->b,e->alpha); + } + break; + case 8: { + BPoint p[4]; + p[0].Set(e->x1,e->y1); + p[1].Set(e->x2,e->y2); + p[2].Set(e->x3,e->y3); + p[3].Set(e->x4,e->y4); + SetPenSize(1.01); + StrokeBezier(p, e->p); + SetPenSize(1.0); + } + break; + case 9: { + BPoint p[4]; + p[0].Set(e->x1,e->y1); + p[1].Set(e->x2,e->y2); + p[2].Set(e->x3,e->y3); + p[3].Set(e->x4,e->y4); + SetPenSize(2.0); + FillBezier(p, e->p); + SetPenSize(1.0); + } + break; + case 10: { + drawing_mode mode = DrawingMode(); + if(IsPrinting()) + SetDrawingMode(B_OP_COPY); + else + SetDrawingMode(B_OP_ALPHA); + DrawBitmap(e->bitmap, BPoint(e->x1, e->y1)); + SetDrawingMode(mode); + } + break; + case 11: { + drawing_mode mode = DrawingMode(); + if(IsPrinting()) + SetDrawingMode(B_OP_COPY); + else + SetDrawingMode(B_OP_ALPHA); + DrawBitmap(e->bitmap, BRect(e->x1, e->y1, e->x2, e->y2)); + SetDrawingMode(mode); + } + break; + case 12: { + // SetFont(&e->font, B_FONT_FAMILY_AND_STYLE); + // SetFont(&e->font, B_FONT_SIZE); + SetFont(&e->font, B_FONT_ALL); + } + break; + } + } +} + +void YabView::MouseDown(BPoint point) +{ + BPoint ptCursor; + uint32 uButtons = 0; + GetMouse(&ptCursor, &uButtons, false); + + mouseX = (int)ptCursor.x; + mouseY = (int)ptCursor.y; + if(uButtons & B_PRIMARY_MOUSE_BUTTON) mouseLButton = 1; else mouseLButton = 0; + if(uButtons & B_SECONDARY_MOUSE_BUTTON) mouseRButton = 1; else mouseRButton = 0; + if(uButtons & B_TERTIARY_MOUSE_BUTTON) mouseMButton = 1; else mouseMButton = 0; + mouseStateInfo = 4; + BView::MouseDown(point); +} + +void YabView::MouseUp(BPoint point) +{ + BPoint ptCursor; + uint32 uButtons = 0; + GetMouse(&ptCursor, &uButtons, false); + + mouseX = (int)ptCursor.x; + mouseY = (int)ptCursor.y; + if(uButtons & B_PRIMARY_MOUSE_BUTTON) mouseLButton = 1; else mouseLButton = 0; + if(uButtons & B_SECONDARY_MOUSE_BUTTON) mouseRButton = 1; else mouseRButton = 0; + if(uButtons & B_TERTIARY_MOUSE_BUTTON) mouseMButton = 1; else mouseMButton = 0; + mouseStateInfo = 5; + BView::MouseUp(point); +} + +void YabView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) +{ + BPoint ptCursor; + uint32 uButtons = 0; + GetMouse(&ptCursor, &uButtons, true); + + mouseX = (int)ptCursor.x; + mouseY = (int)ptCursor.y; + if(uButtons & B_PRIMARY_MOUSE_BUTTON) mouseLButton = 1; else mouseLButton = 0; + if(uButtons & B_SECONDARY_MOUSE_BUTTON) mouseRButton = 1; else mouseRButton = 0; + if(uButtons & B_TERTIARY_MOUSE_BUTTON) mouseMButton = 1; else mouseMButton = 0; + + switch(transit) + { + case B_INSIDE_VIEW: + if(prevMouseStateInfo==1) + mouseStateInfo = 0; + else + { + mouseStateInfo = 1; + prevMouseStateInfo = 1; + } + mouseMovedInfo = 0; + break; + case B_ENTERED_VIEW: + mouseStateInfo = 1; + mouseMovedInfo = 0; + break; + case B_OUTSIDE_VIEW: + mouseStateInfo = 2; + mouseMovedInfo = 1; + break; + case B_EXITED_VIEW: + mouseStateInfo = 3; + mouseMovedInfo = 1; + prevMouseStateInfo = 0; + break; + } + + BView::MouseMoved(point, transit, message); +} + +void YabView::KeyDown(const char *bytes, int32 numBytes) +{ + BMessage *msg = Window()->CurrentMessage(); + if(msg) + { + pressedKeys.SetTo(""); + int32 key, modifiers; + msg->FindInt32("key", &key); + msg->FindInt32("modifiers", &modifiers); + if(modifiers&B_CONTROL_KEY) pressedKeys << "ctrl-"; + if(modifiers&B_COMMAND_KEY) pressedKeys << "command-"; + if(modifiers&B_OPTION_KEY) pressedKeys << "option-"; + if(modifiers&B_SHIFT_KEY) pressedKeys << "shift-"; + switch(bytes[0]) + { + case B_BACKSPACE: pressedKeys << "backspace"; break; + case B_ENTER: pressedKeys << "enter"; break; + case B_TAB: pressedKeys << "tab"; break; + case B_ESCAPE: pressedKeys << "esc"; break; + case B_LEFT_ARROW: pressedKeys << "left"; break; + case B_RIGHT_ARROW: pressedKeys << "right"; break; + case B_UP_ARROW: pressedKeys << "up"; break; + case B_DOWN_ARROW: pressedKeys << "down"; break; + case B_INSERT: pressedKeys << "insert"; break; + case B_DELETE: pressedKeys << "del"; break; + case B_HOME: pressedKeys << "home"; break; + case B_END: pressedKeys << "end"; break; + case B_PAGE_UP: pressedKeys << "pageup"; break; + case B_PAGE_DOWN: pressedKeys << "pagedown"; break; + case B_FUNCTION_KEY: + { + switch(key) + { + case B_F1_KEY: pressedKeys << "f1"; break; + case B_F2_KEY: pressedKeys << "f2"; break; + case B_F3_KEY: pressedKeys << "f3"; break; + case B_F4_KEY: pressedKeys << "f4"; break; + case B_F5_KEY: pressedKeys << "f5"; break; + case B_F6_KEY: pressedKeys << "f6"; break; + case B_F7_KEY: pressedKeys << "f7"; break; + case B_F8_KEY: pressedKeys << "f8"; break; + case B_F9_KEY: pressedKeys << "f9"; break; + case B_F10_KEY: pressedKeys << "f10"; break; + case B_F11_KEY: pressedKeys << "f11"; break; + case B_F12_KEY: pressedKeys << "f12"; break; + case B_PRINT_KEY: pressedKeys << "print"; break; + case B_SCROLL_KEY: pressedKeys << "scroll"; break; + case B_PAUSE_KEY: pressedKeys << "pause"; break; + default: + pressedKeys.SetTo(bytes); + break; + } + } + break; + default: + pressedKeys.SetTo(bytes); + break; + } + } + else + pressedKeys.SetTo(bytes); + + if(bytes[0]!=B_TAB) BView::KeyDown(bytes,numBytes); +} + +void YabView::KeyUp(const char *bytes, int32 numBytes) +{ + pressedKeys.SetTo(""); + BView::KeyUp(bytes,numBytes); +} + diff --git a/src/YabView.h b/src/YabView.h new file mode 100644 index 0000000..6976ee6 --- /dev/null +++ b/src/YabView.h @@ -0,0 +1,44 @@ +#ifndef YABVIEW_H +#define YABVIEW_H + +#include +#include + +struct YabDrawing +{ + int command; + double x1,y1,x2,y2,x3,y3,x4,y4; + int r,g,b,alpha; + const char* chardata; + pattern p; + BBitmap *bitmap; + BFont font; +}; + +class YabView : public BView +{ + public: + YabView(BRect frame, const char *name, uint32 resizingMode, uint32 flags); + ~YabView(); + virtual void MessageReceived(BMessage *msg); + virtual void Draw(BRect updateRect); + virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); + virtual void MouseUp(BPoint point); + virtual void MouseDown(BPoint point); + virtual void KeyUp(const char *bytes, int32 numBytes); + virtual void KeyDown(const char *bytes, int32 numBytes); + BList *drawList; + int mouseMovedInfo; + int mouseStateInfo; + int mouseX; + int mouseY; + uint mouseLButton; + uint mouseMButton; + uint mouseRButton; + bool dropZone; + BString pressedKeys; + private: + int prevMouseStateInfo; +}; + +#endif diff --git a/src/YabWindow.cpp b/src/YabWindow.cpp new file mode 100644 index 0000000..e23873c --- /dev/null +++ b/src/YabWindow.cpp @@ -0,0 +1,361 @@ +#include "global.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "YabWindow.h" +#include "column/ColumnListView.h" + +const uint32 YABBUTTON = 'YBbu'; +const uint32 YABMENU = 'YBme'; +const uint32 YABSUBMENU = 'YBsu'; +const uint32 YABTEXTCONTROL = 'YBtc'; +const uint32 YABCHECKBOX = 'YBcb'; +const uint32 YABRADIOBUTTON = 'YBrb'; +const uint32 YABLISTBOXSELECT = 'YBls'; +const uint32 YABLISTBOXINVOKE = 'YBli'; +const uint32 YABDROPBOX = 'YBdb'; +const uint32 YABSLIDER = 'YBsl'; +const uint32 YABCOLORCONTROL = 'YBco'; +const uint32 YABTREEBOXSELECT = 'YBts'; +const uint32 YABTREEBOXINVOKE = 'YBti'; +const uint32 YABFILEBOXSELECT = 'YBfs'; +const uint32 YABFILEBOXINVOKE = 'YBfi'; +const uint32 YABSPINCONTROL = 'YBsp'; +const uint32 YABSHORTCUT = 'YBsh'; + +YabWindow::YabWindow(BRect frame, const char* title, const char* id, window_look winlook, window_feel winfeel, uint32 flags) + : BWindow (frame, title, winlook, winfeel, flags) +{ + messageString.SetTo(""); + idString.SetTo(id); + showing = 1; + dropMsg.SetTo(""); + WActivated=-1; + WFrameMoved=-1; + WFrameResized=-1; +} + +YabWindow::~YabWindow() +{ +} + +void YabWindow::WindowActivated(bool state) +{ + if (state) + WActivated=1; + else + WActivated=0; +} + +void YabWindow::FrameMoved(BPoint new_position) +{ + WFrameMoved=1; + Wpx=(int)new_position.x; + Wpy=(int)new_position.y; +} + +void YabWindow::FrameResized(float new_width, float new_height) +{ + WFrameResized=1; + Wph=(int)new_height; + Wpw=(int)new_width; +} + +void YabWindow::MessageReceived(BMessage *message) +{ + // if(message) message->PrintToStream(); + switch(message->what) + { + case YABBUTTON: + { + BString tmpMessage(""); + BButton *myButtonPressed; + message->FindPointer("source",(void **) &myButtonPressed); + tmpMessage += myButtonPressed->Name(); + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABMENU: + { + BString tmpMessage(""); + BMenuItem *mySelectedMenu; + message->FindPointer("source",(void **) &mySelectedMenu); + BMenu *myMenu = mySelectedMenu->Menu(); + tmpMessage += ((BMenuBar*)myMenu->Supermenu())->Parent()->Name(); + tmpMessage += ":"; + tmpMessage += myMenu->Name(); + tmpMessage += ":"; + tmpMessage += mySelectedMenu->Label(); + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABSUBMENU: + { + BString tmpMessage(""); + BMenuItem *mySelectedMenu; + message->FindPointer("source",(void **) &mySelectedMenu); + BMenu *myMenu = mySelectedMenu->Menu(); + tmpMessage += ((BMenuBar*)myMenu->Supermenu()->Supermenu())->Parent()->Name(); + tmpMessage += ":"; + tmpMessage += myMenu->Supermenu()->Name(); + tmpMessage += ":"; + tmpMessage += myMenu->Name(); + tmpMessage += ":"; + tmpMessage += mySelectedMenu->Label(); + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABTEXTCONTROL: + { + BString tmpMessage(""); + BTextControl *myTextControl; + message->FindPointer("source",(void **) &myTextControl); + tmpMessage += myTextControl->Name(); + tmpMessage += ":"; + tmpMessage += myTextControl->Text(); + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABCHECKBOX: + { + BString tmpMessage(""); + BCheckBox *myCheckBox; + message->FindPointer("source",(void **) &myCheckBox); + tmpMessage += myCheckBox->Name(); + tmpMessage += ":"; + if(myCheckBox->Value()==B_CONTROL_ON) + tmpMessage += "ON|"; + else + tmpMessage += "OFF|"; + messageString += tmpMessage; + } + break; + case YABRADIOBUTTON: + { + BString tmpMessage(""); + BRadioButton *myRadioButton; + message->FindPointer("source",(void **) &myRadioButton); + tmpMessage += myRadioButton->Name(); + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABLISTBOXINVOKE: + { + BListView *myList; + message->FindPointer("source",(void **) &myList); + int i = myList->CurrentSelection(); + if(i>=0) + { + BString tmpMessage(""); + tmpMessage += myList->Name(); + tmpMessage += ":_Invoke:"; + // tmpMessage += ((BStringItem*)(myList->ItemAt(i)))->Text(); + tmpMessage << i+1; + tmpMessage += "|"; + messageString += tmpMessage; + } + } + break; + case YABLISTBOXSELECT: + { + BListView *myList; + message->FindPointer("source",(void **) &myList); + int i = myList->CurrentSelection(); + if(i>=0) + { + BString tmpMessage(""); + tmpMessage += myList->Name(); + tmpMessage += ":_Select:"; + // tmpMessage += ((BStringItem*)(myList->ItemAt(i)))->Text(); + tmpMessage << i+1; + tmpMessage += "|"; + messageString += tmpMessage; + } + } + break; + case YABDROPBOX: + { + BString tmpMessage(""); + BMenuItem *myMenuItem; + message->FindPointer("source",(void **) &myMenuItem); + tmpMessage += (myMenuItem->Menu())->Supermenu()->Parent()->Name(); + tmpMessage += ":"; + tmpMessage += myMenuItem->Label(); + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABSLIDER: + { + BString tmpMessage(""); + BSlider *mySlider; + message->FindPointer("source",(void **) &mySlider); + tmpMessage += mySlider->Name(); + tmpMessage += ":"; + tmpMessage << mySlider->Value(); + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABCOLORCONTROL: + { + rgb_color col; + BString tmpMessage(""); + BColorControl *myCControl; + message->FindPointer("source",(void **) &myCControl); + tmpMessage += myCControl->Name(); + tmpMessage += ":"; + col = myCControl->ValueAsColor(); + tmpMessage << col.red << ":" << col.green << ":" << col.blue; + tmpMessage += "|"; + messageString += tmpMessage; + } + break; + case YABTREEBOXINVOKE: + { + BOutlineListView *myList; + message->FindPointer("source",(void **) &myList); + int i = myList->FullListCurrentSelection(); + if(i>=0) + { + BString tmpMessage(""); + const char* txt = ((BStringItem*)(myList->FullListItemAt(i)))->Text(); + tmpMessage += myList->Name(); + tmpMessage += ":_Invoke:"; + tmpMessage << i+1; + /* + int n = tmpMessage.Length(); + BListItem *superitem = myList->Superitem(myList->FullListItemAt(i)); + while(superitem) + { + BString t(""); + t << ((BStringItem*)superitem)->Text() << ":"; + tmpMessage.Insert(t,n); + superitem = myList->Superitem(superitem); + } + tmpMessage += txt;*/ + tmpMessage += "|"; + messageString += tmpMessage; + } + } + break; + case YABTREEBOXSELECT: + { + BOutlineListView *myList; + message->FindPointer("source",(void **) &myList); + int i = myList->FullListCurrentSelection(); + if(i>=0) + { + BString tmpMessage(""); + const char* txt = ((BStringItem*)(myList->FullListItemAt(i)))->Text(); + tmpMessage += myList->Name(); + tmpMessage += ":_Select:"; + tmpMessage << i+1; + /* + int n = tmpMessage.Length(); + BListItem *superitem = myList->Superitem(myList->FullListItemAt(i)); + while(superitem) + { + BString t(""); + t << ((BStringItem*)superitem)->Text() << ":"; + tmpMessage.Insert(t,n); + superitem = myList->Superitem(superitem); + } + tmpMessage += txt;*/ + tmpMessage += "|"; + messageString += tmpMessage; + } + } + break; + case YABFILEBOXSELECT: + { + BColumnListView *myList; + message->FindPointer("source",(void **) &myList); + BRow *myRow = NULL; + if(myList) myRow = myList->CurrentSelection(); + if(myRow) + { + // if(!myList->IsFocus()) myList->MakeFocus(); + BString tmpMessage(""); + tmpMessage += myList->Name(); + tmpMessage += ":_Select:"; + tmpMessage << myList->IndexOf(myRow)+1; + tmpMessage += "|"; + messageString += tmpMessage; + } + } + break; + case YABFILEBOXINVOKE: + { + BColumnListView *myList; + message->FindPointer("source",(void **) &myList); + BRow *myRow = NULL; + if(myList) myRow = myList->CurrentSelection(); + if(myRow) + { + // if(!myList->IsFocus()) myList->MakeFocus(); + BString tmpMessage(""); + tmpMessage += myList->Name(); + tmpMessage += ":_Invoke:"; + tmpMessage << myList->IndexOf(myRow)+1; + tmpMessage += "|"; + messageString += tmpMessage; + } + } + break; + case YABSHORTCUT: + { + const char* myMsg; + if(message->FindString("shortcut", &myMsg) == B_OK) + { + messageString += myMsg; + messageString += "|"; + } + } + break; + default: + BWindow::MessageReceived(message); + break; + } +} + +const BString YabWindow::getMessages() +{ + BString tmp(messageString); + tmp += dropMsg; + messageString.SetTo(""); + dropMsg.SetTo(""); + return (const BString)tmp; +} + +bool YabWindow::QuitRequested() +{ + messageString += idString; + messageString += ":_QuitRequested|"; + return false; +} + +bool YabWindow::IsPaper(uint8* a) +{ + if(a[32] != 0) return true; + return false; +} + diff --git a/src/YabWindow.h b/src/YabWindow.h new file mode 100644 index 0000000..cb1c360 --- /dev/null +++ b/src/YabWindow.h @@ -0,0 +1,38 @@ +#ifndef YABWINDOW_H +#define YABWINDOW_H + +#include +#include +#include +#include +#include +#include + +class YabWindow : public BWindow +{ + public: + YabWindow(BRect frame, const char* title, const char* id, window_look winlook, window_feel winfeel, uint32 flags); + ~YabWindow(); + virtual void MessageReceived(BMessage *message); + virtual bool QuitRequested(); + const BString getMessages(); + virtual void WindowActivated(bool state); + virtual void FrameMoved(BPoint new_position); + virtual void FrameResized(float new_width, float new_height); + int layout; + int showing; + int WActivated; + int WFrameResized; + int Wpx; + int Wpy; + int Wph; + int Wpw; + int WFrameMoved; + BString dropMsg; + BString idString; + private: + bool IsPaper(uint8* a); + BString messageString; +}; + +#endif diff --git a/src/column/ColorTools.cpp b/src/column/ColorTools.cpp new file mode 100644 index 0000000..e4aea31 --- /dev/null +++ b/src/column/ColorTools.cpp @@ -0,0 +1,110 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/******************************************************************************* +/ +/ File: ColorTools.cpp +/ +/ Description: Additional experimental color manipulation functions. +/ +/ Copyright 2000, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#include "ColorTools.h" + +#if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI + +namespace BExperimental { + +#if DEBUG +#define DB_INLINE +#else +#define DB_INLINE inline +#endif + +static DB_INLINE void mix_color_func(rgb_color* target, const rgb_color other, uint8 amount) +{ + target->red = (uint8)( ((int16(other.red)-int16(target->red))*amount)/255 + + target->red ); + target->green = (uint8)( ((int16(other.green)-int16(target->green))*amount)/255 + + target->green ); + target->blue = (uint8)( ((int16(other.blue)-int16(target->blue))*amount)/255 + + target->blue ); + target->alpha = (uint8)( ((int16(other.alpha)-int16(target->alpha))*amount)/255 + + target->alpha ); +} + +static DB_INLINE void blend_color_func(rgb_color* target, const rgb_color other, uint8 amount) +{ + const uint8 alphaMix = (uint8)( ((int16(other.alpha)-int16(255-target->alpha))*amount)/255 + + (255-target->alpha) ); + target->red = (uint8)( ((int16(other.red)-int16(target->red))*alphaMix)/255 + + target->red ); + target->green = (uint8)( ((int16(other.green)-int16(target->green))*alphaMix)/255 + + target->green ); + target->blue = (uint8)( ((int16(other.blue)-int16(target->blue))*alphaMix)/255 + + target->blue ); + target->alpha = (uint8)( ((int16(other.alpha)-int16(target->alpha))*amount)/255 + + target->alpha ); +} + +static DB_INLINE void disable_color_func(rgb_color* target, const rgb_color background) +{ + blend_color_func(target, background, 255-70); +} + +// -------------------------------------------------------------------------- + +rgb_color mix_color(rgb_color color1, rgb_color color2, uint8 amount) +{ + mix_color_func(&color1, color2, amount); + return color1; +} + +rgb_color blend_color(rgb_color color1, rgb_color color2, uint8 amount) +{ + blend_color_func(&color1, color2, amount); + return color1; +} + +rgb_color disable_color(rgb_color color, rgb_color background) +{ + disable_color_func(&color, background); + return color; +} + +} + +#endif diff --git a/src/column/ColorTools.h b/src/column/ColorTools.h new file mode 100644 index 0000000..ac33d18 --- /dev/null +++ b/src/column/ColorTools.h @@ -0,0 +1,107 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/******************************************************************************* +/ +/ File: ColorTools.h +/ +/ Description: Additional experimental color manipulation functions. +/ +/ Copyright 2000, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLOR_TOOLS_H +#define _COLOR_TOOLS_H + +#include + +#if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI + +namespace BExperimental { + +// Comparison operators. + +inline bool operator==(const rgb_color c1, const rgb_color c2) +{ + return (*((uint32*)&c1)) == (*((uint32*)&c2)); +} + +inline bool operator!=(const rgb_color c1, const rgb_color c2) +{ + return (*((uint32*)&c1)) != (*((uint32*)&c2)); +} + +// Color creation. + +#ifndef HAIKU + +inline rgb_color make_color(uint8 red, uint8 green, uint8 blue, uint8 alpha=255) +{ + rgb_color c; + c.red = red; + c.green = green; + c.blue = blue; + c.alpha = alpha; + return c; +} + +#endif + +// Mix two colors together, ignoring their relative alpha channels. +// If amount is 0, the result is color1; if 255, the result is color2; +// if another value, it is somewhere in-between. The resulting alpha +// channel is mixed exactly like the other color channels. +rgb_color mix_color(rgb_color color1, rgb_color color2, uint8 amount); + +// Blend two colors together, weighting by their relative alpha channels. +// The resulting color is the same as mix_color(), except that the amount +// used from color1 and color2's color channels is dependent on that color's +// alpha channel. For example, if color1.alpha is 0 and color2.alpha is +// 255, the resulting red, green, and blue values will be the same as those +// in color2, regardless of 'amount'. +rgb_color blend_color(rgb_color color1, rgb_color color2, uint8 amount); + +// Return a color that is the disabled representation of 'color' when drawn +// on a solid color 'background'. +rgb_color disable_color(rgb_color color, rgb_color background); + +} // namespace BExperimental + +using namespace BExperimental; + +#endif + +#endif diff --git a/src/column/ColumnListView.cpp b/src/column/ColumnListView.cpp new file mode 100644 index 0000000..150e3c4 --- /dev/null +++ b/src/column/ColumnListView.cpp @@ -0,0 +1,4887 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/******************************************************************************* +/ +/ File: ColumnListView.cpp +/ +/ Description: Experimental multi-column list view. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ By Jeff Bush +/ +*******************************************************************************/ + +#include "ColumnListView.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ColorTools.h" +#include "ObjectList.h" + +#define DOUBLE_BUFFERED_COLUMN_RESIZE 1 +#define SMART_REDRAW 1 +#define DRAG_TITLE_OUTLINE 1 +#define CONSTRAIN_CLIPPING_REGION 1 +#define LOWER_SCROLLBAR 0 + +namespace BPrivate { + +static const unsigned char kResizeCursorData[] = { + 16, 1, 8, 8, + 0x03, 0xc0, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x1a, 0x58, 0x2a, 0x54, 0x4a, 0x52, 0x8a, 0x51, + 0x8a, 0x51, 0x4a, 0x52, 0x2a, 0x54, 0x1a, 0x58, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xc0, + + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, + 0x1b, 0xd8, 0x3b, 0xdc, 0x7b, 0xde, 0xfb, 0xdf, + 0xfb, 0xdf, 0x7b, 0xde, 0x3b, 0xdc, 0x1b, 0xd8, + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0 +}; + +static const unsigned char kMaxResizeCursorData[] = { + 16, 1, 8, 8, + 0x03, 0xc0, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x1a, 0x40, 0x2a, 0x40, 0x4a, 0x40, 0x8a, 0x40, + 0x8a, 0x40, 0x4a, 0x40, 0x2a, 0x40, 0x1a, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xc0, + + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, + 0x1b, 0xc0, 0x3b, 0xc0, 0x7b, 0xc0, 0xfb, 0xc0, + 0xfb, 0xc0, 0x7b, 0xc0, 0x3b, 0xc0, 0x1b, 0xc0, + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0 +}; + +static const unsigned char kMinResizeCursorData[] = { + 16, 1, 8, 8, + 0x03, 0xc0, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x58, 0x02, 0x54, 0x02, 0x52, 0x02, 0x51, + 0x02, 0x51, 0x02, 0x52, 0x02, 0x54, 0x02, 0x58, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xc0, + + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, + 0x03, 0xd8, 0x03, 0xdc, 0x03, 0xde, 0x03, 0xdf, + 0x03, 0xdf, 0x03, 0xde, 0x03, 0xdc, 0x03, 0xd8, + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0 +}; + +static const unsigned char kColumnMoveCursorData[] = { + 16, 1, 8, 8, + 0x01, 0x80, 0x02, 0x40, 0x04, 0x20, 0x08, 0x10, + 0x1e, 0x78, 0x2a, 0x54, 0x4e, 0x72, 0x80, 0x01, + 0x80, 0x01, 0x4e, 0x72, 0x2a, 0x54, 0x1e, 0x78, + 0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x01, 0x80, + + 0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, + 0x1f, 0xf8, 0x3b, 0xdc, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x3b, 0xdc, 0x1f, 0xf8, + 0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80 +}; + +static const unsigned char kDownSortArrow8x8[] = { + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff +}; + +static const unsigned char kUpSortArrow8x8[] = { + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff +}; + +static const unsigned char kDownSortArrow8x8Invert[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff +}; + +static const unsigned char kUpSortArrow8x8Invert[] = { + 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const float kTintedLineTint = 0.7 * B_NO_TINT + 0.3 * B_DARKEN_1_TINT; + +static const float kTitleHeight = 16.0; +static const float kLatchWidth = 0.0; //5.0; + + +static const rgb_color kColor[B_COLOR_TOTAL] = +{ + {236, 236, 236, 255}, // B_COLOR_BACKGROUND + { 0, 0, 0, 255}, // B_COLOR_TEXT + {148, 148, 148, 255}, // B_COLOR_ROW_DIVIDER + {190, 190, 190, 255}, // B_COLOR_SELECTION + { 0, 0, 0, 255}, // B_COLOR_SELECTION_TEXT + {200, 200, 200, 255}, // B_COLOR_NON_FOCUS_SELECTION + {180, 180, 180, 180}, // B_COLOR_EDIT_BACKGROUND + { 0, 0, 0, 255}, // B_COLOR_EDIT_TEXT + {215, 215, 215, 255}, // B_COLOR_HEADER_BACKGROUND + { 0, 0, 0, 255}, // B_COLOR_HEADER_TEXT + { 0, 0, 0, 255}, // B_COLOR_SEPARATOR_LINE + { 0, 0, 0, 255}, // B_COLOR_SEPARATOR_BORDER +}; + +static const int32 kMaxDepth = 1024; +static const float kLeftMargin = kLatchWidth; +static const float kRightMargin = kLatchWidth; +static const float kOutlineLevelIndent = kLatchWidth; +static const float kColumnResizeAreaWidth = 10.0; +static const float kRowDragSensitivity = 5.0; +static const float kDoubleClickMoveSensitivity = 4.0; +static const float kSortIndicatorWidth = 9.0; +static const float kDropHighlightLineHeight = 2.0; + +static const uint32 kToggleColumn = 'BTCL'; + +class BRowContainer : public BObjectList +{ +}; + +class TitleView : public BView { + typedef BView _inherited; +public: + TitleView(BRect frame, OutlineView* outlineView, + BList* visibleColumns, BList* sortColumns, + BColumnListView* masterView, + uint32 resizingMode); + virtual ~TitleView(); + + void ColumnAdded(BColumn* column); + void ColumnResized(BColumn* column, float oldWidth); + void SetColumnVisible(BColumn* column, bool visible); + + virtual void Draw(BRect updateRect); + virtual void ScrollTo(BPoint where); + virtual void MessageReceived(BMessage* message); + virtual void MouseDown(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + virtual void MouseUp(BPoint where); + virtual void FrameResized(float width, float height); + + void MoveColumn(BColumn* column, int32 index); + void SetColumnFlags(column_flags flags); + + void SetEditMode(bool state) + { fEditMode = state; } + +private: + void GetTitleRect(BColumn* column, BRect* _rect); + int32 FindColumn(BPoint where, float* _leftEdge); + void FixScrollBar(bool scrollToFit); + void DragSelectedColumn(BPoint where); + void ResizeSelectedColumn(BPoint where, + bool preferred = false); + void ComputeDragBoundries(BColumn* column, + BPoint where); + void DrawTitle(BView* view, BRect frame, + BColumn* column, bool depressed); + + float _VirtualWidth() const; + + OutlineView* fOutlineView; + BList* fColumns; + BList* fSortColumns; +// float fColumnsWidth; + BRect fVisibleRect; + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + BBitmap* fDrawBuffer; + BView* fDrawBufferView; +#endif + + enum { + INACTIVE, + RESIZING_COLUMN, + PRESSING_COLUMN, + DRAG_COLUMN_INSIDE_TITLE, + DRAG_COLUMN_OUTSIDE_TITLE + } fCurrentState; + + BPopUpMenu* fColumnPop; + BColumnListView* fMasterView; + bool fEditMode; + int32 fColumnFlags; + + // State information for resizing/dragging + BColumn* fSelectedColumn; + BRect fSelectedColumnRect; + bool fResizingFirstColumn; + BPoint fClickPoint; // offset within cell + float fLeftDragBoundry; + float fRightDragBoundry; + BPoint fCurrentDragPosition; + + + BBitmap* fUpSortArrow; + BBitmap* fDownSortArrow; + + BCursor* fResizeCursor; + BCursor* fMinResizeCursor; + BCursor* fMaxResizeCursor; + BCursor* fColumnMoveCursor; +}; + +class OutlineView : public BView { + typedef BView _inherited; +public: + OutlineView(BRect, BList* visibleColumns, + BList* sortColumns, + BColumnListView* listView); + virtual ~OutlineView(); + + virtual void Draw(BRect); + const BRect& VisibleRect() const; + + void RedrawColumn(BColumn* column, float leftEdge, + bool isFirstColumn); + void StartSorting(); + float GetColumnPreferredWidth(BColumn* column); + + void AddRow(BRow*, int32 index, BRow* TheRow); + BRow* CurrentSelection(BRow* lastSelected) const; + void ToggleFocusRowSelection(bool selectRange); + void ToggleFocusRowOpen(); + void ChangeFocusRow(bool up, bool updateSelection, + bool addToCurrentSelection); + void MoveFocusToVisibleRect(); + void ExpandOrCollapse(BRow* parent, bool expand); + void RemoveRow(BRow*); + BRowContainer* RowList(); + void UpdateRow(BRow*); + bool FindParent(BRow* row, BRow** _parent, + bool* _isVisible); + int32 IndexOf(BRow* row); + void Deselect(BRow*); + void AddToSelection(BRow*); + void DeselectAll(); + BRow* FocusRow() const; + void SetFocusRow(BRow* row, bool select); + BRow* FindRow(float ypos, int32* _indent, + float* _top); + bool FindRect(const BRow* row, BRect* _rect); + void ScrollTo(const BRow* row); + + void Clear(); + void SetSelectionMode(list_view_type type); + list_view_type SelectionMode() const; + void SetMouseTrackingEnabled(bool); + void FixScrollBar(bool scrollToFit); + void SetEditMode(bool state) + { fEditMode = state; } + + virtual void FrameResized(float width, float height); + virtual void ScrollTo(BPoint where); + virtual void MouseDown(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + virtual void MouseUp(BPoint where); + virtual void MessageReceived(BMessage* message); + +private: + bool SortList(BRowContainer* list, bool isVisible); + static int32 DeepSortThreadEntry(void* outlineView); + void DeepSort(); + void SelectRange(BRow* start, BRow* end); + int32 CompareRows(BRow* row1, BRow* row2); + void AddSorted(BRowContainer* list, BRow* row); + void RecursiveDeleteRows(BRowContainer* list, + bool owner); + void InvalidateCachedPositions(); + bool FindVisibleRect(BRow* row, BRect* _rect); + + BList* fColumns; + BList* fSortColumns; + float fItemsHeight; + BRowContainer fRows; + BRect fVisibleRect; + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + BBitmap* fDrawBuffer; + BView* fDrawBufferView; +#endif + + BRow* fFocusRow; + BRect fFocusRowRect; + BRow* fRollOverRow; + + BRow fSelectionListDummyHead; + BRow* fLastSelectedItem; + BRow* fFirstSelectedItem; + + thread_id fSortThread; + int32 fNumSorted; + bool fSortCancelled; + + enum CurrentState { + INACTIVE, + LATCH_CLICKED, + ROW_CLICKED, + DRAGGING_ROWS + }; + + CurrentState fCurrentState; + + + BColumnListView* fMasterView; + list_view_type fSelectionMode; + bool fTrackMouse; + BField* fCurrentField; + BRow* fCurrentRow; + BColumn* fCurrentColumn; + bool fMouseDown; + BRect fFieldRect; + int32 fCurrentCode; + bool fEditMode; + + // State information for mouse/keyboard interaction + BPoint fClickPoint; + bool fDragging; + int32 fClickCount; + BRow* fTargetRow; + float fTargetRowTop; + BRect fLatchRect; + float fDropHighlightY; + + friend class RecursiveOutlineIterator; +}; + +class RecursiveOutlineIterator { +public: + RecursiveOutlineIterator( + BRowContainer* container, + bool openBranchesOnly = true); + + BRow* CurrentRow() const; + int32 CurrentLevel() const; + void GoToNext(); + +private: + struct { + BRowContainer* fRowSet; + int32 fIndex; + int32 fDepth; + } fStack[kMaxDepth]; + + int32 fStackIndex; + BRowContainer* fCurrentList; + int32 fCurrentListIndex; + int32 fCurrentListDepth; + bool fOpenBranchesOnly; +}; + +} // namespace BPrivate + + +using namespace BPrivate; + + +BField::BField() +{ +} + + +BField::~BField() +{ +} + + +// #pragma mark - + + +void +BColumn::MouseMoved(BColumnListView* /*parent*/, BRow* /*row*/, + BField* /*field*/, BRect /*field_rect*/, BPoint/*point*/, + uint32 /*buttons*/, int32 /*code*/) +{ +} + + +void +BColumn::MouseDown(BColumnListView* /*parent*/, BRow* /*row*/, + BField* /*field*/, BRect /*field_rect*/, BPoint /*point*/, + uint32 /*buttons*/) +{ +} + + +void +BColumn::MouseUp(BColumnListView* /*parent*/, BRow* /*row*/, BField* /*field*/) +{ +} + + +// #pragma mark - + + +BRow::BRow(float height) + : + fChildList(NULL), + fIsExpanded(false), + fHeight(height), + fNextSelected(NULL), + fPrevSelected(NULL), + fParent(NULL), + fList(NULL) +{ +} + + +BRow::~BRow() +{ + while (true) { + BField* field = (BField*) fFields.RemoveItem(0L); + if (field == 0) + break; + + delete field; + } +} + + +bool +BRow::HasLatch() const +{ + return fChildList != 0; +} + + +int32 +BRow::CountFields() const +{ + return fFields.CountItems(); +} + + +BField* +BRow::GetField(int32 index) +{ + return (BField*)fFields.ItemAt(index); +} + + +const BField* +BRow::GetField(int32 index) const +{ + return (const BField*)fFields.ItemAt(index); +} + + +void +BRow::SetField(BField* field, int32 logicalFieldIndex) +{ + if (fFields.ItemAt(logicalFieldIndex) != 0) + delete (BField*)fFields.RemoveItem(logicalFieldIndex); + + if (NULL != fList) { + ValidateField(field, logicalFieldIndex); + BRect inv; + fList->GetRowRect(this, &inv); + fList->Invalidate(inv); + } + + fFields.AddItem(field, logicalFieldIndex); +} + + +float +BRow::Height() const +{ + return fHeight; +} + + +bool +BRow::IsExpanded() const +{ + return fIsExpanded; +} + + +void +BRow::ValidateFields() const +{ + for (int32 i = 0; i < CountFields(); i++) + ValidateField(GetField(i), i); +} + + +void +BRow::ValidateField(const BField* field, int32 logicalFieldIndex) const +{ + // The Fields may be moved by the user, but the logicalFieldIndexes + // do not change, so we need to map them over when checking the + // Field types. + BColumn* col = NULL; + int32 items = fList->CountColumns(); + for (int32 i = 0 ; i < items; ++i) { + col = fList->ColumnAt(i); + if( col->LogicalFieldNum() == logicalFieldIndex ) + break; + } + + if (NULL == col) { + BString dbmessage("\n\n\tThe parent BColumnListView does not have " + "\n\ta BColumn at the logical field index "); + dbmessage << logicalFieldIndex << ".\n\n"; + printf(dbmessage.String()); + } else { + if (!col->AcceptsField(field)) { + BString dbmessage("\n\n\tThe BColumn of type "); + dbmessage << typeid(*col).name() << "\n\tat logical field index " + << logicalFieldIndex << "\n\tdoes not support the " + "field type " + << typeid(*field).name() << ".\n\n"; + debugger(dbmessage.String()); + } + } +} + + +// #pragma mark - + + +BColumn::BColumn(float width, float minWidth, float maxWidth, alignment align) + : + fWidth(width), + fMinWidth(minWidth), + fMaxWidth(maxWidth), + fVisible(true), + fList(0), + fShowHeading(true), + fAlignment(align) +{ +} + + +BColumn::~BColumn() +{ +} + + +float +BColumn::Width() const +{ + return fWidth; +} + + +void +BColumn::SetWidth(float width) +{ + fWidth = width; +} + + +float +BColumn::MinWidth() const +{ + return fMinWidth; +} + + +float +BColumn::MaxWidth() const +{ + return fMaxWidth; +} + + +void +BColumn::DrawTitle(BRect, BView*) +{ +} + + +void +BColumn::DrawField(BField*, BRect, BView*) +{ +} + + +int +BColumn::CompareFields(BField*, BField*) +{ + return 0; +} + + +void +BColumn::GetColumnName(BString* into) const +{ + *into = "(Unnamed)"; +} + + +float +BColumn::GetPreferredWidth(BField* field, BView* parent) const +{ + return fWidth; +} + + +bool +BColumn::IsVisible() const +{ + return fVisible; +} + + +void +BColumn::SetVisible(bool visible) +{ + if (fList && (fVisible != visible)) + fList->SetColumnVisible(this, visible); +} + + +bool +BColumn::ShowHeading() const +{ + return fShowHeading; +} + + +void +BColumn::SetShowHeading(bool state) +{ + fShowHeading = state; +} + + +alignment +BColumn::Alignment() const +{ + return fAlignment; +} + + +void +BColumn::SetAlignment(alignment align) +{ + fAlignment = align; +} + + +bool +BColumn::WantsEvents() const +{ + return fWantsEvents; +} + + +void +BColumn::SetWantsEvents(bool state) +{ + fWantsEvents = state; +} + + +int32 +BColumn::LogicalFieldNum() const +{ + return fFieldID; +} + + +bool +BColumn::AcceptsField(const BField*) const +{ + return true; +} + + +// #pragma mark - + + +BColumnListView::BColumnListView(BRect rect, const char* name, + uint32 resizingMode, uint32 flags, border_style border, + bool showHorizontalScrollbar) + : + BView(rect, name, resizingMode, + flags | B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE), + fStatusView(NULL), + fSelectionMessage(NULL), + fSortingEnabled(true), + fLatchWidth(kLatchWidth), + fBorderStyle(border) +{ + _Init(showHorizontalScrollbar); +} + + +BColumnListView::BColumnListView(const char* name, uint32 flags, + border_style border, bool showHorizontalScrollbar) + : + BView(name, flags | B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE), + fStatusView(NULL), + fSelectionMessage(NULL), + fSortingEnabled(true), + fLatchWidth(kLatchWidth), + fBorderStyle(border) +{ + _Init(showHorizontalScrollbar); +} + + +BColumnListView::~BColumnListView() +{ + while (BColumn* column = (BColumn*)fColumns.RemoveItem(0L)) + delete column; +} + + +bool +BColumnListView::InitiateDrag(BPoint, bool) +{ + return false; +} + + +void +BColumnListView::MessageDropped(BMessage*, BPoint) +{ +} + + +void +BColumnListView::ExpandOrCollapse(BRow* row, bool Open) +{ + fOutlineView->ExpandOrCollapse(row, Open); +} + + +status_t +BColumnListView::Invoke(BMessage* message) +{ + if (message == 0) + message = Message(); + + return BInvoker::Invoke(message); +} + + +void +BColumnListView::ItemInvoked() +{ + Invoke(); +} + + +void +BColumnListView::SetInvocationMessage(BMessage* message) +{ + SetMessage(message); +} + + +BMessage* +BColumnListView::InvocationMessage() const +{ + return Message(); +} + + +uint32 +BColumnListView::InvocationCommand() const +{ + return Command(); +} + + +BRow* +BColumnListView::FocusRow() const +{ + return fOutlineView->FocusRow(); +} + + +void +BColumnListView::SetFocusRow(int32 Index, bool Select) +{ + SetFocusRow(RowAt(Index), Select); +} + + +void +BColumnListView::SetFocusRow(BRow* row, bool Select) +{ + fOutlineView->SetFocusRow(row, Select); +} + + +void +BColumnListView::SetMouseTrackingEnabled(bool Enabled) +{ + fOutlineView->SetMouseTrackingEnabled(Enabled); +} + + +list_view_type +BColumnListView::SelectionMode() const +{ + return fOutlineView->SelectionMode(); +} + + +void +BColumnListView::Deselect(BRow* row) +{ + fOutlineView->Deselect(row); +} + + +void +BColumnListView::AddToSelection(BRow* row) +{ + fOutlineView->AddToSelection(row); +} + + +void +BColumnListView::DeselectAll() +{ + fOutlineView->DeselectAll(); +} + + +BRow* +BColumnListView::CurrentSelection(BRow* lastSelected) const +{ + return fOutlineView->CurrentSelection(lastSelected); +} + + +void +BColumnListView::SelectionChanged() +{ + if (fSelectionMessage) + Invoke(fSelectionMessage); +} + + +void +BColumnListView::SetSelectionMessage(BMessage* message) +{ + if (fSelectionMessage == message) + return; + + delete fSelectionMessage; + fSelectionMessage = message; +} + + +BMessage* +BColumnListView::SelectionMessage() +{ + return fSelectionMessage; +} + + +uint32 +BColumnListView::SelectionCommand() const +{ + if (fSelectionMessage) + return fSelectionMessage->what; + + return 0; +} + + +void +BColumnListView::SetSelectionMode(list_view_type mode) +{ + fOutlineView->SetSelectionMode(mode); +} + + +void +BColumnListView::SetSortingEnabled(bool enabled) +{ + fSortingEnabled = enabled; + fSortColumns.MakeEmpty(); + fTitleView->Invalidate(); // Erase sort indicators +} + + +bool +BColumnListView::SortingEnabled() const +{ + return fSortingEnabled; +} + + +void +BColumnListView::SetSortColumn(BColumn* column, bool add, bool ascending) +{ + if (!SortingEnabled()) + return; + + if (!add) + fSortColumns.MakeEmpty(); + + if (!fSortColumns.HasItem(column)) + fSortColumns.AddItem(column); + + column->fSortAscending = ascending; + fTitleView->Invalidate(); + fOutlineView->StartSorting(); +} + + +void +BColumnListView::ClearSortColumns() +{ + fSortColumns.MakeEmpty(); + fTitleView->Invalidate(); // Erase sort indicators +} + + +void +BColumnListView::AddStatusView(BView* view) +{ + BRect bounds = Bounds(); + float width = view->Bounds().Width(); + if (width > bounds.Width() / 2) + width = bounds.Width() / 2; + + fStatusView = view; + + Window()->BeginViewTransaction(); + fHorizontalScrollBar->ResizeBy(-(width + 1), 0); + fHorizontalScrollBar->MoveBy((width + 1), 0); + AddChild(view); + + BRect viewRect(bounds); + viewRect.right = width; + viewRect.top = viewRect.bottom - B_H_SCROLL_BAR_HEIGHT; + if (fBorderStyle == B_PLAIN_BORDER) + viewRect.OffsetBy(1, -1); + else if (fBorderStyle == B_FANCY_BORDER) + viewRect.OffsetBy(2, -2); + + view->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); + view->ResizeTo(viewRect.Width(), viewRect.Height()); + view->MoveTo(viewRect.left, viewRect.top); + Window()->EndViewTransaction(); +} + + +BView* +BColumnListView::RemoveStatusView() +{ + if (fStatusView) { + float width = fStatusView->Bounds().Width(); + Window()->BeginViewTransaction(); + fStatusView->RemoveSelf(); + fHorizontalScrollBar->MoveBy(-width, 0); + fHorizontalScrollBar->ResizeBy(width, 0); + Window()->EndViewTransaction(); + } + + BView* view = fStatusView; + fStatusView = 0; + return view; +} + + +void +BColumnListView::AddColumn(BColumn* column, int32 logicalFieldIndex) +{ + ASSERT(column != NULL); + + column->fList = this; + column->fFieldID = logicalFieldIndex; + + // sanity check. If there is already a field with this ID, remove it. + for (int32 index = 0; index < fColumns.CountItems(); index++) { + BColumn* existingColumn = (BColumn*) fColumns.ItemAt(index); + if (existingColumn && existingColumn->fFieldID == logicalFieldIndex) { + RemoveColumn(existingColumn); + break; + } + } + + if (column->Width() < column->MinWidth()) + column->SetWidth(column->MinWidth()); + else if (column->Width() > column->MaxWidth()) + column->SetWidth(column->MaxWidth()); + + fColumns.AddItem((void*) column); + fTitleView->ColumnAdded(column); +} + + +void +BColumnListView::MoveColumn(BColumn* column, int32 index) +{ + ASSERT(column != NULL); + fTitleView->MoveColumn(column, index); +} + + +void +BColumnListView::RemoveColumn(BColumn* column) +{ + if (fColumns.HasItem(column)) { + SetColumnVisible(column, false); + if (Window() != NULL) + Window()->UpdateIfNeeded(); + fColumns.RemoveItem(column); + } +} + + +int32 +BColumnListView::CountColumns() const +{ + return fColumns.CountItems(); +} + + +BColumn* +BColumnListView::ColumnAt(int32 field) const +{ + return (BColumn*) fColumns.ItemAt(field); +} + + +BColumn* +BColumnListView::ColumnAt(BPoint point) const +{ + float left = MAX(kLeftMargin, LatchWidth()); + + for (int i = 0; BColumn* column = (BColumn*)fColumns.ItemAt(i); i++) { + if (!column->IsVisible()) + continue; + + float right = left + column->Width(); + if (point.x >= left && point.x <= right) + return column; + + left = right + 1; + } + + return NULL; +} + + +void +BColumnListView::SetColumnVisible(BColumn* column, bool visible) +{ + fTitleView->SetColumnVisible(column, visible); +} + + +void +BColumnListView::SetColumnVisible(int32 index, bool isVisible) +{ + BColumn* column = ColumnAt(index); + if (column) + column->SetVisible(isVisible); +} + + +bool +BColumnListView::IsColumnVisible(int32 index) const +{ + BColumn* column = ColumnAt(index); + if (column) + return column->IsVisible(); + + return false; +} + + +void +BColumnListView::SetColumnFlags(column_flags flags) +{ + fTitleView->SetColumnFlags(flags); +} + + +void +BColumnListView::ResizeColumnToPreferred(int32 index) +{ + BColumn* column = ColumnAt(index); + if (column == NULL) + return; + + // get the preferred column width + float width = fOutlineView->GetColumnPreferredWidth(column); + + // set it + float oldWidth = column->Width(); + column->SetWidth(width); + + fTitleView->ColumnResized(column, oldWidth); + fOutlineView->Invalidate(); +} + + +void +BColumnListView::ResizeAllColumnsToPreferred() +{ + int32 count = CountColumns(); + for (int32 i = 0; i < count; i++) + ResizeColumnToPreferred(i); +} + + +const BRow* +BColumnListView::RowAt(int32 Index, BRow* parentRow) const +{ + if (parentRow == 0) + return fOutlineView->RowList()->ItemAt(Index); + + return parentRow->fChildList ? parentRow->fChildList->ItemAt(Index) : NULL; +} + + +BRow* +BColumnListView::RowAt(int32 Index, BRow* parentRow) +{ + if (parentRow == 0) + return fOutlineView->RowList()->ItemAt(Index); + + return parentRow->fChildList ? parentRow->fChildList->ItemAt(Index) : 0; +} + + +const BRow* +BColumnListView::RowAt(BPoint point) const +{ + float top; + int32 indent; + return fOutlineView->FindRow(point.y, &indent, &top); +} + + +BRow* +BColumnListView::RowAt(BPoint point) +{ + float top; + int32 indent; + return fOutlineView->FindRow(point.y, &indent, &top); +} + + +bool +BColumnListView::GetRowRect(const BRow* row, BRect* outRect) const +{ + return fOutlineView->FindRect(row, outRect); +} + + +bool +BColumnListView::FindParent(BRow* row, BRow** _parent, bool* _isVisible) const +{ + return fOutlineView->FindParent(row, _parent, _isVisible); +} + + +int32 +BColumnListView::IndexOf(BRow* row) +{ + return fOutlineView->IndexOf(row); +} + + +int32 +BColumnListView::CountRows(BRow* parentRow) const +{ + if (parentRow == 0) + return fOutlineView->RowList()->CountItems(); + if (parentRow->fChildList) + return parentRow->fChildList->CountItems(); + else + return 0; +} + + +void +BColumnListView::AddRow(BRow* row, BRow* parentRow) +{ + AddRow(row, -1, parentRow); +} + + +void +BColumnListView::AddRow(BRow* row, int32 index, BRow* parentRow) +{ + row->fChildList = 0; + row->fList = this; + row->ValidateFields(); + fOutlineView->AddRow(row, index, parentRow); +} + + +void +BColumnListView::RemoveRow(BRow* row) +{ + fOutlineView->RemoveRow(row); + row->fList = NULL; +} + + +void +BColumnListView::UpdateRow(BRow* row) +{ + fOutlineView->UpdateRow(row); +} + + +void +BColumnListView::ScrollTo(const BRow* row) +{ + fOutlineView->ScrollTo(row); +} + + +void +BColumnListView::ScrollTo(BPoint point) +{ + fOutlineView->ScrollTo(point); +} + + +void +BColumnListView::Clear() +{ + fOutlineView->Clear(); +} + + +void +BColumnListView::SetFont(const BFont* font, uint32 mask) +{ + // This method is deprecated. + fOutlineView->SetFont(font, mask); + fTitleView->SetFont(font, mask); +} + + +void +BColumnListView::SetFont(ColumnListViewFont font_num, const BFont* font, + uint32 mask) +{ + switch (font_num) { + case B_FONT_ROW: + fOutlineView->SetFont(font, mask); + break; + + case B_FONT_HEADER: + fTitleView->SetFont(font, mask); + break; + + default: + ASSERT(false); + break; + } +} + + +void +BColumnListView::GetFont(ColumnListViewFont font_num, BFont* font) const +{ + switch (font_num) { + case B_FONT_ROW: + fOutlineView->GetFont(font); + break; + + case B_FONT_HEADER: + fTitleView->GetFont(font); + break; + + default: + ASSERT(false); + break; + } +} + + +void +BColumnListView::SetColor(ColumnListViewColor color_num, const rgb_color color) +{ + if ((int)color_num < 0) { + ASSERT(false); + color_num = (ColumnListViewColor) 0; + } + + if ((int)color_num >= (int)B_COLOR_TOTAL) { + ASSERT(false); + color_num = (ColumnListViewColor) (B_COLOR_TOTAL - 1); + } + + fColorList[color_num] = color; +} + + +rgb_color +BColumnListView::Color(ColumnListViewColor color_num) const +{ + if ((int)color_num < 0) { + ASSERT(false); + color_num = (ColumnListViewColor) 0; + } + + if ((int)color_num >= (int)B_COLOR_TOTAL) { + ASSERT(false); + color_num = (ColumnListViewColor) (B_COLOR_TOTAL - 1); + } + + return fColorList[color_num]; +} + + +void +BColumnListView::SetHighColor(rgb_color color) +{ + BView::SetHighColor(color); +// fOutlineView->Invalidate(); // Redraw things with the new color + // Note that this will currently cause + // an infinite loop, refreshing over and over. + // A better solution is needed. +} + + +void +BColumnListView::SetSelectionColor(rgb_color color) +{ + fColorList[B_COLOR_SELECTION] = color; +} + + +void +BColumnListView::SetBackgroundColor(rgb_color color) +{ + fColorList[B_COLOR_BACKGROUND] = color; + fOutlineView->Invalidate(); // Repaint with new color +} + + +void +BColumnListView::SetEditColor(rgb_color color) +{ + fColorList[B_COLOR_EDIT_BACKGROUND] = color; +} + + +const rgb_color +BColumnListView::SelectionColor() const +{ + return fColorList[B_COLOR_SELECTION]; +} + + +const rgb_color +BColumnListView::BackgroundColor() const +{ + return fColorList[B_COLOR_BACKGROUND]; +} + + +const rgb_color +BColumnListView::EditColor() const +{ + return fColorList[B_COLOR_EDIT_BACKGROUND]; +} + + +BPoint +BColumnListView::SuggestTextPosition(const BRow* row, + const BColumn* inColumn) const +{ + BRect rect; + GetRowRect(row, &rect); + if (inColumn) { + float leftEdge = MAX(kLeftMargin, LatchWidth()); + for (int index = 0; index < fColumns.CountItems(); index++) { + BColumn* column = (BColumn*) fColumns.ItemAt(index); + if (!column->IsVisible()) + continue; + + if (column == inColumn) { + rect.left = leftEdge; + rect.right = rect.left + column->Width(); + break; + } + + leftEdge += column->Width() + 1; + } + } + + font_height fh; + fOutlineView->GetFontHeight(&fh); + float baseline = floor(rect.top + fh.ascent + + (rect.Height()+1-(fh.ascent+fh.descent))/2); + return BPoint(rect.left + 8, baseline); +} + + +void +BColumnListView::SetLatchWidth(float width) +{ + fLatchWidth = width; + Invalidate(); +} + + +float +BColumnListView::LatchWidth() const +{ + return fLatchWidth; +} + +void +BColumnListView::DrawLatch(BView* view, BRect rect, LatchType position, BRow*) +{ + const int32 rectInset = 4; + + view->SetHighColor(0, 0, 0); + + // Make Square + int32 sideLen = rect.IntegerWidth(); + if (sideLen > rect.IntegerHeight()) + sideLen = rect.IntegerHeight(); + + // Make Center + int32 halfWidth = rect.IntegerWidth() / 2; + int32 halfHeight = rect.IntegerHeight() / 2; + int32 halfSide = sideLen / 2; + + float left = rect.left + halfWidth - halfSide; + float top = rect.top + halfHeight - halfSide; + + BRect itemRect(left, top, left + sideLen, top + sideLen); + + // Why it is a pixel high? I don't know. + itemRect.OffsetBy(0, -1); + + itemRect.InsetBy(rectInset, rectInset); + + // Make it an odd number of pixels wide, the latch looks better this way + if ((itemRect.IntegerWidth() % 2) == 1) { + itemRect.right += 1; + itemRect.bottom += 1; + } + + switch (position) { + case B_OPEN_LATCH: + view->StrokeRect(itemRect); + view->StrokeLine( + BPoint(itemRect.left + 2, + (itemRect.top + itemRect.bottom) / 2), + BPoint(itemRect.right - 2, + (itemRect.top + itemRect.bottom) / 2)); + break; + + case B_PRESSED_LATCH: + view->StrokeRect(itemRect); + view->StrokeLine( + BPoint(itemRect.left + 2, + (itemRect.top + itemRect.bottom) / 2), + BPoint(itemRect.right - 2, + (itemRect.top + itemRect.bottom) / 2)); + view->StrokeLine( + BPoint((itemRect.left + itemRect.right) / 2, + itemRect.top + 2), + BPoint((itemRect.left + itemRect.right) / 2, + itemRect.bottom - 2)); + view->InvertRect(itemRect); + break; + + case B_CLOSED_LATCH: + view->StrokeRect(itemRect); + view->StrokeLine( + BPoint(itemRect.left + 2, + (itemRect.top + itemRect.bottom) / 2), + BPoint(itemRect.right - 2, + (itemRect.top + itemRect.bottom) / 2)); + view->StrokeLine( + BPoint((itemRect.left + itemRect.right) / 2, + itemRect.top + 2), + BPoint((itemRect.left + itemRect.right) / 2, + itemRect.bottom - 2)); + break; + + case B_NO_LATCH: + // No drawing + break; + } +} + + +void +BColumnListView::MakeFocus(bool isFocus) +{ + if (fBorderStyle != B_NO_BORDER) { + // Redraw focus marks around view + Invalidate(); + fHorizontalScrollBar->SetBorderHighlighted(isFocus); + fVerticalScrollBar->SetBorderHighlighted(isFocus); + } + + BView::MakeFocus(isFocus); +} + + +void +BColumnListView::MessageReceived(BMessage* message) +{ + // Propagate mouse wheel messages down to child, so that it can + // scroll. Note we have done so, so we don't go into infinite + // recursion if this comes back up here. + if (message->what == B_MOUSE_WHEEL_CHANGED) { + bool handled; + if (message->FindBool("be:clvhandled", &handled) != B_OK) { + message->AddBool("be:clvhandled", true); + fOutlineView->MessageReceived(message); + return; + } + } + + BView::MessageReceived(message); +} + + +void +BColumnListView::KeyDown(const char* bytes, int32 numBytes) +{ + char c = bytes[0]; + switch (c) { + case B_RIGHT_ARROW: + case B_LEFT_ARROW: + { + float minVal, maxVal; + fHorizontalScrollBar->GetRange(&minVal, &maxVal); + float smallStep, largeStep; + fHorizontalScrollBar->GetSteps(&smallStep, &largeStep); + float oldVal = fHorizontalScrollBar->Value(); + float newVal = oldVal; + + if (c == B_LEFT_ARROW) + newVal -= smallStep; + else if (c == B_RIGHT_ARROW) + newVal += smallStep; + + if (newVal < minVal) + newVal = minVal; + else if (newVal > maxVal) + newVal = maxVal; + + fHorizontalScrollBar->SetValue(newVal); + break; + } + + case B_DOWN_ARROW: + fOutlineView->ChangeFocusRow(false, + (modifiers() & B_CONTROL_KEY) == 0, + (modifiers() & B_SHIFT_KEY) != 0); + break; + + case B_UP_ARROW: + fOutlineView->ChangeFocusRow(true, + (modifiers() & B_CONTROL_KEY) == 0, + (modifiers() & B_SHIFT_KEY) != 0); + break; + + case B_PAGE_UP: + case B_PAGE_DOWN: + { + float minValue, maxValue; + fVerticalScrollBar->GetRange(&minValue, &maxValue); + float smallStep, largeStep; + fVerticalScrollBar->GetSteps(&smallStep, &largeStep); + float currentValue = fVerticalScrollBar->Value(); + float newValue = currentValue; + + if (c == B_PAGE_UP) + newValue -= largeStep; + else + newValue += largeStep; + + if (newValue > maxValue) + newValue = maxValue; + else if (newValue < minValue) + newValue = minValue; + + fVerticalScrollBar->SetValue(newValue); + + // Option + pgup or pgdn scrolls and changes the selection. + if (modifiers() & B_OPTION_KEY) + fOutlineView->MoveFocusToVisibleRect(); + + break; + } + + case B_ENTER: + Invoke(); + break; + + case B_SPACE: + fOutlineView->ToggleFocusRowSelection( + (modifiers() & B_SHIFT_KEY) != 0); + break; + + case '+': + fOutlineView->ToggleFocusRowOpen(); + break; + + default: + BView::KeyDown(bytes, numBytes); + } +} + + +void +BColumnListView::AttachedToWindow() +{ + if (!Messenger().IsValid()) + SetTarget(Window()); + + if (SortingEnabled()) fOutlineView->StartSorting(); +} + + +void +BColumnListView::WindowActivated(bool active) +{ + fOutlineView->Invalidate(); + // Focus and selection appearance changes with focus + + Invalidate(); // Redraw focus marks around view + BView::WindowActivated(active); +} + + +void +BColumnListView::Draw(BRect updateRect) +{ + BRect rect = Bounds(); + + if (be_control_look != NULL) { + uint32 flags = 0; + if (IsFocus() && Window()->IsActive()) + flags |= BControlLook::B_FOCUSED; + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + + BRect verticalScrollBarFrame; + if (!fVerticalScrollBar->IsHidden()) + verticalScrollBarFrame = fVerticalScrollBar->Frame(); + BRect horizontalScrollBarFrame; + if (!fHorizontalScrollBar->IsHidden()) + horizontalScrollBarFrame = fHorizontalScrollBar->Frame(); + + if (fBorderStyle == B_NO_BORDER) { + // We still draw the left/top border, but not focused. + // The scrollbars cannot be displayed without frame and + // it looks bad to have no frame only along the left/top + // side. + rgb_color borderColor = tint_color(base, B_DARKEN_2_TINT); + SetHighColor(borderColor); + StrokeLine(BPoint(rect.left, rect.bottom), + BPoint(rect.left, rect.top)); + StrokeLine(BPoint(rect.left + 1, rect.top), + BPoint(rect.right, rect.top)); + } + + be_control_look->DrawScrollViewFrame(this, rect, updateRect, + verticalScrollBarFrame, horizontalScrollBarFrame, + base, fBorderStyle, flags); + + return; + } + + BRect cornerRect(rect.right - B_V_SCROLL_BAR_WIDTH, + rect.bottom - B_H_SCROLL_BAR_HEIGHT, rect.right, rect.bottom); + if (fBorderStyle == B_PLAIN_BORDER) { + BView::SetHighColor(0, 0, 0); + StrokeRect(rect); + cornerRect.OffsetBy(-1, -1); + } else if (fBorderStyle == B_FANCY_BORDER) { + bool isFocus = IsFocus() && Window()->IsActive(); + + if (isFocus) { + // TODO: Need to find focus color programatically + BView::SetHighColor(0, 0, 190); + } else + BView::SetHighColor(255, 255, 255); + + StrokeRect(rect); + if (!isFocus) + BView::SetHighColor(184, 184, 184); + else + BView::SetHighColor(152, 152, 152); + + rect.InsetBy(1,1); + StrokeRect(rect); + cornerRect.OffsetBy(-2, -2); + } + + BView::SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + // fills lower right rect between scroll bars + FillRect(cornerRect); +} + + +void +BColumnListView::SaveState(BMessage* msg) +{ + msg->MakeEmpty(); + + for (int32 i = 0; BColumn* col = (BColumn*)fColumns.ItemAt(i); i++) { + msg->AddInt32("ID",col->fFieldID); + msg->AddFloat("width", col->fWidth); + msg->AddBool("visible", col->fVisible); + } + + msg->AddBool("sortingenabled", fSortingEnabled); + + if (fSortingEnabled) { + for (int32 i = 0; BColumn* col = (BColumn*)fSortColumns.ItemAt(i); + i++) { + msg->AddInt32("sortID", col->fFieldID); + msg->AddBool("sortascending", col->fSortAscending); + } + } +} + + +void +BColumnListView::LoadState(BMessage* msg) +{ + int32 id; + for (int i = 0; msg->FindInt32("ID", i, &id) == B_OK; i++) { + for (int j = 0; BColumn* column = (BColumn*)fColumns.ItemAt(j); j++) { + if (column->fFieldID == id) { + // move this column to position 'i' and set its attributes + MoveColumn(column, i); + float width; + if (msg->FindFloat("width", i, &width) == B_OK) + column->SetWidth(width); + bool visible; + if (msg->FindBool("visible", i, &visible) == B_OK) + column->SetVisible(visible); + } + } + } + bool b; + if (msg->FindBool("sortingenabled", &b) == B_OK) { + SetSortingEnabled(b); + for (int k = 0; msg->FindInt32("sortID", k, &id) == B_OK; k++) { + for (int j = 0; BColumn* column = (BColumn*)fColumns.ItemAt(j); + j++) { + if (column->fFieldID == id) { + // add this column to the sort list + bool value; + if (msg->FindBool("sortascending", k, &value) == B_OK) + SetSortColumn(column, true, value); + } + } + } + } +} + + +void +BColumnListView::SetEditMode(bool state) +{ + fOutlineView->SetEditMode(state); + fTitleView->SetEditMode(state); +} + + +void +BColumnListView::Refresh() +{ + if (LockLooper()) { + Invalidate(); + fOutlineView->FixScrollBar (true); + fOutlineView->Invalidate(); + Window()->UpdateIfNeeded(); + UnlockLooper(); + } +} + + +BSize +BColumnListView::MinSize() +{ + BSize size; + size.width = 100; + size.height = kTitleHeight + 4 * B_H_SCROLL_BAR_HEIGHT; + if (!fHorizontalScrollBar->IsHidden()) + size.height += fHorizontalScrollBar->Frame().Height() + 1; + // TODO: Take border size into account + + return BLayoutUtils::ComposeSize(ExplicitMinSize(), size); +} + + +BSize +BColumnListView::PreferredSize() +{ + BSize size = MinSize(); + size.height += ceilf(be_plain_font->Size()) * 20; + + int32 count = CountColumns(); + if (count > 0) { + // return MinSize().width if there are no columns. + size.width = 40.0f; + for (int32 i = 0; i < count; i++) { + BColumn* column = ColumnAt(i); + if (column != NULL) + size.width += fOutlineView->GetColumnPreferredWidth(column); + } + } + + return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size); +} + + +BSize +BColumnListView::MaxSize() +{ + BSize size(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size); +} + + +void +BColumnListView::InvalidateLayout(bool descendants) +{ + BView::InvalidateLayout(descendants); +} + + +void +BColumnListView::DoLayout() +{ + if (!(Flags() & B_SUPPORTS_LAYOUT)) + return; + + BRect titleRect; + BRect outlineRect; + BRect vScrollBarRect; + BRect hScrollBarRect; + _GetChildViewRects(Bounds(), !fHorizontalScrollBar->IsHidden(), + titleRect, outlineRect, vScrollBarRect, hScrollBarRect); + + fTitleView->MoveTo(titleRect.LeftTop()); + fTitleView->ResizeTo(titleRect.Width(), titleRect.Height()); + + fOutlineView->MoveTo(outlineRect.LeftTop()); + fOutlineView->ResizeTo(outlineRect.Width(), outlineRect.Height()); + + fVerticalScrollBar->MoveTo(vScrollBarRect.LeftTop()); + fVerticalScrollBar->ResizeTo(vScrollBarRect.Width(), + vScrollBarRect.Height()); + + fHorizontalScrollBar->MoveTo(hScrollBarRect.LeftTop()); + fHorizontalScrollBar->ResizeTo(hScrollBarRect.Width(), + hScrollBarRect.Height()); + + fOutlineView->FixScrollBar(true); +} + + +void +BColumnListView::_Init(bool showHorizontalScrollbar) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + + BRect bounds(Bounds()); + if (bounds.Width() <= 0) + bounds.right = 100; + if (bounds.Height() <= 0) + bounds.bottom = 100; + + for (int i = 0; i < (int)B_COLOR_TOTAL; i++) + fColorList[i] = kColor[i]; + + BRect titleRect; + BRect outlineRect; + BRect vScrollBarRect; + BRect hScrollBarRect; + _GetChildViewRects(bounds, showHorizontalScrollbar, titleRect, outlineRect, + vScrollBarRect, hScrollBarRect); + + fOutlineView = new OutlineView(outlineRect, &fColumns, &fSortColumns, this); + AddChild(fOutlineView); + + + fTitleView = new TitleView(titleRect, fOutlineView, &fColumns, + &fSortColumns, this, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); + AddChild(fTitleView); + + fVerticalScrollBar = new BScrollBar(vScrollBarRect, "vertical_scroll_bar", + fOutlineView, 0.0, bounds.Height(), B_VERTICAL); + AddChild(fVerticalScrollBar); + + fHorizontalScrollBar = new BScrollBar(hScrollBarRect, + "horizontal_scroll_bar", fTitleView, 0.0, bounds.Width(), B_HORIZONTAL); + AddChild(fHorizontalScrollBar); + + if (!showHorizontalScrollbar) + fHorizontalScrollBar->Hide(); + + fOutlineView->FixScrollBar(true); +} + + +void +BColumnListView::_GetChildViewRects(const BRect& bounds, + bool showHorizontalScrollbar, BRect& titleRect, BRect& outlineRect, + BRect& vScrollBarRect, BRect& hScrollBarRect) +{ + titleRect = bounds; + titleRect.bottom = titleRect.top + kTitleHeight; +#if !LOWER_SCROLLBAR + titleRect.right -= B_V_SCROLL_BAR_WIDTH; +#endif + + outlineRect = bounds; + outlineRect.top = titleRect.bottom + 1.0; + outlineRect.right -= B_V_SCROLL_BAR_WIDTH; + if (showHorizontalScrollbar) + outlineRect.bottom -= B_H_SCROLL_BAR_HEIGHT; + + vScrollBarRect = bounds; +#if LOWER_SCROLLBAR + vScrollBarRect.top += kTitleHeight; +#endif + + vScrollBarRect.left = vScrollBarRect.right - B_V_SCROLL_BAR_WIDTH; + if (showHorizontalScrollbar) + vScrollBarRect.bottom -= B_H_SCROLL_BAR_HEIGHT; + + hScrollBarRect = bounds; + hScrollBarRect.top = hScrollBarRect.bottom - B_H_SCROLL_BAR_HEIGHT; + hScrollBarRect.right -= B_V_SCROLL_BAR_WIDTH; + + // Adjust stuff so the border will fit. + if (fBorderStyle == B_PLAIN_BORDER || fBorderStyle == B_NO_BORDER) { + titleRect.InsetBy(1, 0); + titleRect.OffsetBy(0, 1); + outlineRect.InsetBy(1, 1); + } else if (fBorderStyle == B_FANCY_BORDER) { + titleRect.InsetBy(2, 0); + titleRect.OffsetBy(0, 2); + outlineRect.InsetBy(2, 2); + + vScrollBarRect.OffsetBy(-1, 0); +#if LOWER_SCROLLBAR + vScrollBarRect.top += 2; + vScrollBarRect.bottom -= 1; +#else + vScrollBarRect.InsetBy(0, 1); +#endif + hScrollBarRect.OffsetBy(0, -1); + hScrollBarRect.InsetBy(1, 0); + } +} + + +// #pragma mark - + + +TitleView::TitleView(BRect rect, OutlineView* horizontalSlave, + BList* visibleColumns, BList* sortColumns, BColumnListView* listView, + uint32 resizingMode) + : + BView(rect, "title_view", resizingMode, B_WILL_DRAW | B_FRAME_EVENTS), + fOutlineView(horizontalSlave), + fColumns(visibleColumns), + fSortColumns(sortColumns), +// fColumnsWidth(0), + fVisibleRect(rect.OffsetToCopy(0, 0)), + fCurrentState(INACTIVE), + fColumnPop(NULL), + fMasterView(listView), + fEditMode(false), + fColumnFlags(B_ALLOW_COLUMN_MOVE | B_ALLOW_COLUMN_RESIZE + | B_ALLOW_COLUMN_POPUP | B_ALLOW_COLUMN_REMOVE) +{ + SetViewColor(B_TRANSPARENT_COLOR); + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + // xxx this needs to be smart about the size of the backbuffer. + BRect doubleBufferRect(0, 0, 600, 35); + fDrawBuffer = new BBitmap(doubleBufferRect, B_RGB32, true); + fDrawBufferView = new BView(doubleBufferRect, "double_buffer_view", + B_FOLLOW_ALL_SIDES, 0); + fDrawBuffer->Lock(); + fDrawBuffer->AddChild(fDrawBufferView); + fDrawBuffer->Unlock(); +#endif + + fUpSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_CMAP8); + fDownSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_CMAP8); + + fUpSortArrow->SetBits((const void*) kUpSortArrow8x8, 64, 0, B_CMAP8); + fDownSortArrow->SetBits((const void*) kDownSortArrow8x8, 64, 0, B_CMAP8); + + fResizeCursor = new BCursor(kResizeCursorData); + fMinResizeCursor = new BCursor(kMinResizeCursorData); + fMaxResizeCursor = new BCursor(kMaxResizeCursorData); + fColumnMoveCursor = new BCursor(kColumnMoveCursorData); + + FixScrollBar(true); +} + + +TitleView::~TitleView() +{ + delete fColumnPop; + fColumnPop = NULL; + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + delete fDrawBuffer; +#endif + delete fUpSortArrow; + delete fDownSortArrow; + + delete fResizeCursor; + delete fMaxResizeCursor; + delete fMinResizeCursor; + delete fColumnMoveCursor; +} + + +void +TitleView::ColumnAdded(BColumn* column) +{ +// fColumnsWidth += column->Width(); + FixScrollBar(false); + Invalidate(); +} + + +void +TitleView::ColumnResized(BColumn* column, float oldWidth) +{ +// fColumnsWidth += column->Width() - oldWidth; + FixScrollBar(false); + Invalidate(); +} + + +void +TitleView::SetColumnVisible(BColumn* column, bool visible) +{ + if (column->fVisible == visible) + return; + + // If setting it visible, do this first so we can find its position + // to invalidate. If hiding it, do it last. + if (visible) + column->fVisible = visible; + + BRect titleInvalid; + GetTitleRect(column, &titleInvalid); + + // Now really set the visibility + column->fVisible = visible; + +// if (visible) +// fColumnsWidth += column->Width(); +// else +// fColumnsWidth -= column->Width(); + + BRect outlineInvalid(fOutlineView->VisibleRect()); + outlineInvalid.left = titleInvalid.left; + titleInvalid.right = outlineInvalid.right; + + Invalidate(titleInvalid); + fOutlineView->Invalidate(outlineInvalid); +} + + +void +TitleView::GetTitleRect(BColumn* findColumn, BRect* _rect) +{ + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + int32 numColumns = fColumns->CountItems(); + for (int index = 0; index < numColumns; index++) { + BColumn* column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (column == findColumn) { + _rect->Set(leftEdge, 0, leftEdge + column->Width(), + fVisibleRect.bottom); + return; + } + + leftEdge += column->Width() + 1; + } + + TRESPASS(); +} + + +int32 +TitleView::FindColumn(BPoint position, float* _leftEdge) +{ + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + int32 numColumns = fColumns->CountItems(); + for (int index = 0; index < numColumns; index++) { + BColumn* column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (leftEdge > position.x) + break; + + if (position.x >= leftEdge + && position.x <= leftEdge + column->Width()) { + *_leftEdge = leftEdge; + return index; + } + + leftEdge += column->Width() + 1; + } + + return 0; +} + + +void +TitleView::FixScrollBar(bool scrollToFit) +{ + BScrollBar* hScrollBar = ScrollBar(B_HORIZONTAL); + if (hScrollBar == NULL) + return; + + float virtualWidth = _VirtualWidth(); + + if (virtualWidth > fVisibleRect.Width()) { + hScrollBar->SetProportion(fVisibleRect.Width() / virtualWidth); + + // Perform the little trick if the user is scrolled over too far. + // See OutlineView::FixScrollBar for a more in depth explanation + float maxScrollBarValue = virtualWidth - fVisibleRect.Width(); + if (scrollToFit || hScrollBar->Value() <= maxScrollBarValue) { + hScrollBar->SetRange(0.0, maxScrollBarValue); + hScrollBar->SetSteps(50, fVisibleRect.Width()); + } + } else if (hScrollBar->Value() == 0.0) { + // disable scroll bar. + hScrollBar->SetRange(0.0, 0.0); + } +} + + +void +TitleView::DragSelectedColumn(BPoint position) +{ + float invalidLeft = fSelectedColumnRect.left; + float invalidRight = fSelectedColumnRect.right; + + float leftEdge; + int32 columnIndex = FindColumn(position, &leftEdge); + fSelectedColumnRect.OffsetTo(leftEdge, 0); + + MoveColumn(fSelectedColumn, columnIndex); + + fSelectedColumn->fVisible = true; + ComputeDragBoundries(fSelectedColumn, position); + + // Redraw the new column position + GetTitleRect(fSelectedColumn, &fSelectedColumnRect); + invalidLeft = MIN(fSelectedColumnRect.left, invalidLeft); + invalidRight = MAX(fSelectedColumnRect.right, invalidRight); + + Invalidate(BRect(invalidLeft, 0, invalidRight, fVisibleRect.bottom)); + fOutlineView->Invalidate(BRect(invalidLeft, 0, invalidRight, + fOutlineView->VisibleRect().bottom)); + + DrawTitle(this, fSelectedColumnRect, fSelectedColumn, true); +} + + +void +TitleView::MoveColumn(BColumn* column, int32 index) +{ + fColumns->RemoveItem((void*) column); + + if (-1 == index) { + // Re-add the column at the end of the list. + fColumns->AddItem((void*) column); + } else { + fColumns->AddItem((void*) column, index); + } +} + + +void +TitleView::SetColumnFlags(column_flags flags) +{ + fColumnFlags = flags; +} + + +void +TitleView::ResizeSelectedColumn(BPoint position, bool preferred) +{ + float minWidth = fSelectedColumn->MinWidth(); + float maxWidth = fSelectedColumn->MaxWidth(); + + float oldWidth = fSelectedColumn->Width(); + float originalEdge = fSelectedColumnRect.left + oldWidth; + if (preferred) { + float width = fOutlineView->GetColumnPreferredWidth(fSelectedColumn); + fSelectedColumn->SetWidth(width); + } else if (position.x > fSelectedColumnRect.left + maxWidth) + fSelectedColumn->SetWidth(maxWidth); + else if (position.x < fSelectedColumnRect.left + minWidth) + fSelectedColumn->SetWidth(minWidth); + else + fSelectedColumn->SetWidth(position.x - fSelectedColumnRect.left - 1); + + float dX = fSelectedColumnRect.left + fSelectedColumn->Width() + - originalEdge; + if (dX != 0) { + float columnHeight = fVisibleRect.Height(); + BRect originalRect(originalEdge, 0, 1000000.0, columnHeight); + BRect movedRect(originalRect); + movedRect.OffsetBy(dX, 0); + + // Update the size of the title column + BRect sourceRect(0, 0, fSelectedColumn->Width(), columnHeight); + BRect destRect(sourceRect); + destRect.OffsetBy(fSelectedColumnRect.left, 0); + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + fDrawBuffer->Lock(); + DrawTitle(fDrawBufferView, sourceRect, fSelectedColumn, false); + fDrawBufferView->Sync(); + fDrawBuffer->Unlock(); + + CopyBits(originalRect, movedRect); + DrawBitmap(fDrawBuffer, sourceRect, destRect); +#else + CopyBits(originalRect, movedRect); + DrawTitle(this, destRect, fSelectedColumn, false); +#endif + + // Update the body view + BRect slaveSize = fOutlineView->VisibleRect(); + BRect slaveSource(originalRect); + slaveSource.bottom = slaveSize.bottom; + BRect slaveDest(movedRect); + slaveDest.bottom = slaveSize.bottom; + fOutlineView->CopyBits(slaveSource, slaveDest); + fOutlineView->RedrawColumn(fSelectedColumn, fSelectedColumnRect.left, + fResizingFirstColumn); + +// fColumnsWidth += dX; + + // Update the cursor + if (fSelectedColumn->Width() == minWidth) + SetViewCursor(fMinResizeCursor, true); + else if (fSelectedColumn->Width() == maxWidth) + SetViewCursor(fMaxResizeCursor, true); + else + SetViewCursor(fResizeCursor, true); + + ColumnResized(fSelectedColumn, oldWidth); + } +} + + +void +TitleView::ComputeDragBoundries(BColumn* findColumn, BPoint) +{ + float previousColumnLeftEdge = -1000000.0; + float nextColumnRightEdge = 1000000.0; + + bool foundColumn = false; + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + int32 numColumns = fColumns->CountItems(); + for (int index = 0; index < numColumns; index++) { + BColumn* column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (column == findColumn) { + foundColumn = true; + continue; + } + + if (foundColumn) { + nextColumnRightEdge = leftEdge + column->Width(); + break; + } else + previousColumnLeftEdge = leftEdge; + + leftEdge += column->Width() + 1; + } + + float rightEdge = leftEdge + findColumn->Width(); + + fLeftDragBoundry = MIN(previousColumnLeftEdge + findColumn->Width(), + leftEdge); + fRightDragBoundry = MAX(nextColumnRightEdge, rightEdge); +} + + +void +TitleView::DrawTitle(BView* view, BRect rect, BColumn* column, bool depressed) +{ + BRect drawRect; + rgb_color borderColor = mix_color( + fMasterView->Color(B_COLOR_HEADER_BACKGROUND), + make_color(0, 0, 0), 128); + rgb_color backgroundColor; + + rgb_color bevelHigh; + rgb_color bevelLow; + // Want exterior borders to overlap. + if (be_control_look == NULL) { + rect.right += 1; + drawRect = rect; + drawRect.InsetBy(2, 2); + if (depressed) { + backgroundColor = mix_color( + fMasterView->Color(B_COLOR_HEADER_BACKGROUND), + make_color(0, 0, 0), 64); + bevelHigh = mix_color(backgroundColor, make_color(0, 0, 0), 64); + bevelLow = mix_color(backgroundColor, make_color(255, 255, 255), + 128); + drawRect.left++; + drawRect.top++; + } else { + backgroundColor = fMasterView->Color(B_COLOR_HEADER_BACKGROUND); + bevelHigh = mix_color(backgroundColor, make_color(255, 255, 255), + 192); + bevelLow = mix_color(backgroundColor, make_color(0, 0, 0), 64); + drawRect.bottom--; + drawRect.right--; + } + } else { + drawRect = rect; + } + + font_height fh; + GetFontHeight(&fh); + + float baseline = floor(drawRect.top + fh.ascent + + (drawRect.Height() + 1 - (fh.ascent + fh.descent)) / 2); + + if (be_control_look != NULL) { + BRect bgRect = rect; + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + view->SetHighColor(tint_color(base, B_DARKEN_2_TINT)); + view->StrokeLine(bgRect.LeftBottom(), bgRect.RightBottom()); + + bgRect.bottom--; + bgRect.right--; + + if (depressed) + base = tint_color(base, B_DARKEN_1_TINT); + + be_control_look->DrawButtonBackground(view, bgRect, rect, base, 0, + BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER); + + view->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_DARKEN_2_TINT)); + view->StrokeLine(rect.RightTop(), rect.RightBottom()); + + } else { + + view->SetHighColor(borderColor); + view->StrokeRect(rect); + view->BeginLineArray(4); + view->AddLine(BPoint(rect.left + 1, rect.top + 1), + BPoint(rect.right - 1, rect.top + 1), bevelHigh); + view->AddLine(BPoint(rect.left + 1, rect.top + 1), + BPoint(rect.left + 1, rect.bottom - 1), bevelHigh); + view->AddLine(BPoint(rect.right - 1, rect.top + 1), + BPoint(rect.right - 1, rect.bottom - 1), bevelLow); + view->AddLine(BPoint(rect.left + 2, rect.bottom-1), + BPoint(rect.right - 1, rect.bottom - 1), bevelLow); + view->EndLineArray(); + + view->SetHighColor(backgroundColor); + view->SetLowColor(backgroundColor); + + view->FillRect(rect.InsetByCopy(2, 2)); + } + + // If no column given, nothing else to draw. + if (!column) + return; + + view->SetHighColor(fMasterView->Color(B_COLOR_HEADER_TEXT)); + + BFont font; + GetFont(&font); + view->SetFont(&font); + + int sortIndex = fSortColumns->IndexOf(column); + if (sortIndex >= 0) { + // Draw sort notation. + BPoint upperLeft(drawRect.right - kSortIndicatorWidth, baseline); + + if (fSortColumns->CountItems() > 1) { + char str[256]; + sprintf(str, "%d", sortIndex + 1); + const float w = view->StringWidth(str); + upperLeft.x -= w; + + view->SetDrawingMode(B_OP_COPY); + view->MovePenTo(BPoint(upperLeft.x + kSortIndicatorWidth, + baseline)); + view->DrawString(str); + } + + float bmh = fDownSortArrow->Bounds().Height()+1; + + view->SetDrawingMode(B_OP_OVER); + + if (column->fSortAscending) { + BPoint leftTop(upperLeft.x, drawRect.top + (drawRect.IntegerHeight() + - fDownSortArrow->Bounds().IntegerHeight()) / 2); + view->DrawBitmapAsync(fDownSortArrow, leftTop); + } else { + BPoint leftTop(upperLeft.x, drawRect.top + (drawRect.IntegerHeight() + - fUpSortArrow->Bounds().IntegerHeight()) / 2); + view->DrawBitmapAsync(fUpSortArrow, leftTop); + } + + upperLeft.y = baseline - bmh + floor((fh.ascent + fh.descent - bmh) / 2); + if (upperLeft.y < drawRect.top) + upperLeft.y = drawRect.top; + + // Adjust title stuff for sort indicator + drawRect.right = upperLeft.x - 2; + } + + if (drawRect.right > drawRect.left) { +#if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion(drawRect); + view->PushState(); + view->ConstrainClippingRegion(&clipRegion); +#endif + view->MovePenTo(BPoint(drawRect.left + 8, baseline)); + view->SetDrawingMode(B_OP_OVER); + view->SetHighColor(fMasterView->Color(B_COLOR_HEADER_TEXT)); + column->DrawTitle(drawRect, view); + +#if CONSTRAIN_CLIPPING_REGION + view->PopState(); +#endif + } +} + + +float +TitleView::_VirtualWidth() const +{ + float width = 0.0f; + + int32 count = fColumns->CountItems(); + for (int32 i = 0; i < count; i++) { + BColumn* column = reinterpret_cast(fColumns->ItemAt(i)); + width += column->Width(); + } + + return width + MAX(kLeftMargin, + fMasterView->LatchWidth()) + kRightMargin * 2; +} + + +void +TitleView::Draw(BRect invalidRect) +{ + float columnLeftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + for (int32 columnIndex = 0; columnIndex < fColumns->CountItems(); + columnIndex++) { + + BColumn* column = (BColumn*) fColumns->ItemAt(columnIndex); + if (!column->IsVisible()) + continue; + + if (columnLeftEdge > invalidRect.right) + break; + + if (columnLeftEdge + column->Width() >= invalidRect.left) { + BRect titleRect(columnLeftEdge, 0, + columnLeftEdge + column->Width(), fVisibleRect.Height()); + DrawTitle(this, titleRect, column, + (fCurrentState == DRAG_COLUMN_INSIDE_TITLE + && fSelectedColumn == column)); + } + + columnLeftEdge += column->Width() + 1; + } + + + // Bevels for right title margin + if (columnLeftEdge <= invalidRect.right) { + BRect titleRect(columnLeftEdge, 0, Bounds().right + 2, + fVisibleRect.Height()); + DrawTitle(this, titleRect, NULL, false); + } + + // Bevels for left title margin + if (invalidRect.left < MAX(kLeftMargin, fMasterView->LatchWidth())) { + BRect titleRect(0, 0, MAX(kLeftMargin, fMasterView->LatchWidth()) - 1, + fVisibleRect.Height()); + DrawTitle(this, titleRect, NULL, false); + } + +#if DRAG_TITLE_OUTLINE + // (Internal) Column Drag Indicator + if (fCurrentState == DRAG_COLUMN_INSIDE_TITLE) { + BRect dragRect(fSelectedColumnRect); + dragRect.OffsetTo(fCurrentDragPosition.x - fClickPoint.x, 0); + if (dragRect.Intersects(invalidRect)) { + SetHighColor(0, 0, 255); + StrokeRect(dragRect); + } + } +#endif +} + + +void +TitleView::ScrollTo(BPoint position) +{ + fOutlineView->ScrollBy(position.x - fVisibleRect.left, 0); + fVisibleRect.OffsetTo(position.x, position.y); + + // Perform the little trick if the user is scrolled over too far. + // See OutlineView::ScrollTo for a more in depth explanation + float maxScrollBarValue = _VirtualWidth() - fVisibleRect.Width(); + BScrollBar* hScrollBar = ScrollBar(B_HORIZONTAL); + float min, max; + hScrollBar->GetRange(&min, &max); + if (max != maxScrollBarValue && position.x > maxScrollBarValue) + FixScrollBar(true); + + _inherited::ScrollTo(position); +} + + +void +TitleView::MessageReceived(BMessage* message) +{ + if (message->what == kToggleColumn) { + int32 num; + if (message->FindInt32("be:field_num", &num) == B_OK) { + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn* column = (BColumn*) fColumns->ItemAt(index); + if (!column) + continue; + if (column->LogicalFieldNum() == num) + column->SetVisible(!column->IsVisible()); + } + } + return; + } else { + BView::MessageReceived(message); + } +} + + +void +TitleView::MouseDown(BPoint position) +{ + if(fEditMode) + return; + + int32 buttons = 1; + Window()->CurrentMessage()->FindInt32("buttons", &buttons); + if (buttons == B_SECONDARY_MOUSE_BUTTON + && (fColumnFlags & B_ALLOW_COLUMN_POPUP)) { + // Right mouse button -- bring up menu to show/hide columns. + if (!fColumnPop) fColumnPop = new BPopUpMenu("Columns", false, false); + fColumnPop->RemoveItems(0, fColumnPop->CountItems(), true); + BMessenger me(this); + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn* column = (BColumn*) fColumns->ItemAt(index); + if (!column) continue; + BString name; + column->GetColumnName(&name); + BMessage* msg = new BMessage(kToggleColumn); + msg->AddInt32("be:field_num", column->LogicalFieldNum()); + BMenuItem* it = new BMenuItem(name.String(), msg); + it->SetMarked(column->IsVisible()); + it->SetTarget(me); + fColumnPop->AddItem(it); + } + BPoint screenPosition = ConvertToScreen(position); + BRect sticky(screenPosition, screenPosition); + sticky.InsetBy(-5, -5); + fColumnPop->Go(ConvertToScreen(position), true, false, sticky, true); + return; + } + + fResizingFirstColumn = true; + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn* column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (leftEdge > position.x + kColumnResizeAreaWidth / 2) + break; + + // Check for resizing a column + float rightEdge = leftEdge + column->Width(); + + if (column->ShowHeading()) { + if (position.x > rightEdge - kColumnResizeAreaWidth / 2 + && position.x < rightEdge + kColumnResizeAreaWidth / 2 + && column->MaxWidth() > column->MinWidth() + && (fColumnFlags & B_ALLOW_COLUMN_RESIZE)) { + + int32 clicks = 0; + Window()->CurrentMessage()->FindInt32("clicks", &clicks); + if (clicks == 2) { + ResizeSelectedColumn(position, true); + fCurrentState = INACTIVE; + break; + } + fCurrentState = RESIZING_COLUMN; + fSelectedColumn = column; + fSelectedColumnRect.Set(leftEdge, 0, rightEdge, + fVisibleRect.Height()); + fClickPoint = BPoint(position.x - rightEdge - 1, + position.y - fSelectedColumnRect.top); + SetMouseEventMask(B_POINTER_EVENTS, + B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); + break; + } + + fResizingFirstColumn = false; + + // Check for clicking on a column. + if (position.x > leftEdge && position.x < rightEdge) { + fCurrentState = PRESSING_COLUMN; + fSelectedColumn = column; + fSelectedColumnRect.Set(leftEdge, 0, rightEdge, + fVisibleRect.Height()); + DrawTitle(this, fSelectedColumnRect, fSelectedColumn, true); + fClickPoint = BPoint(position.x - fSelectedColumnRect.left, + position.y - fSelectedColumnRect.top); + SetMouseEventMask(B_POINTER_EVENTS, + B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); + break; + } + } + leftEdge = rightEdge + 1; + } +} + + +void +TitleView::MouseMoved(BPoint position, uint32 transit, + const BMessage* dragMessage) +{ + if (fEditMode) + return; + + // Handle column manipulation + switch (fCurrentState) { + case RESIZING_COLUMN: + ResizeSelectedColumn(position - BPoint(fClickPoint.x, 0)); + break; + + case PRESSING_COLUMN: { + if (abs((int32)(position.x - (fClickPoint.x + + fSelectedColumnRect.left))) > kColumnResizeAreaWidth + || abs((int32)(position.y - (fClickPoint.y + + fSelectedColumnRect.top))) > kColumnResizeAreaWidth) { + // User has moved the mouse more than the tolerable amount, + // initiate a drag. + if (transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW) { + if(fColumnFlags & B_ALLOW_COLUMN_MOVE) { + fCurrentState = DRAG_COLUMN_INSIDE_TITLE; + ComputeDragBoundries(fSelectedColumn, position); + SetViewCursor(fColumnMoveCursor, true); +#if DRAG_TITLE_OUTLINE + BRect invalidRect(fSelectedColumnRect); + invalidRect.OffsetTo(position.x - fClickPoint.x, 0); + fCurrentDragPosition = position; + Invalidate(invalidRect); +#endif + } + } else { + if(fColumnFlags & B_ALLOW_COLUMN_REMOVE) { + // Dragged outside view + fCurrentState = DRAG_COLUMN_OUTSIDE_TITLE; + fSelectedColumn->SetVisible(false); + BRect dragRect(fSelectedColumnRect); + + // There is a race condition where the mouse may have + // moved by the time we get to handle this message. + // If the user drags a column very quickly, this + // results in the annoying bug where the cursor is + // outside of the rectangle that is being dragged + // around. Call GetMouse with the checkQueue flag set + // to false so we can get the most recent position of + // the mouse. This minimizes this problem (although + // it is currently not possible to completely eliminate + // it). + uint32 buttons; + GetMouse(&position, &buttons, false); + dragRect.OffsetTo(position.x - fClickPoint.x, + position.y - dragRect.Height() / 2); + BeginRectTracking(dragRect, B_TRACK_WHOLE_RECT); + } + } + } + + break; + } + + case DRAG_COLUMN_INSIDE_TITLE: { + if (transit == B_EXITED_VIEW + && (fColumnFlags & B_ALLOW_COLUMN_REMOVE)) { + // Dragged outside view + fCurrentState = DRAG_COLUMN_OUTSIDE_TITLE; + fSelectedColumn->SetVisible(false); + BRect dragRect(fSelectedColumnRect); + + // See explanation above. + uint32 buttons; + GetMouse(&position, &buttons, false); + + dragRect.OffsetTo(position.x - fClickPoint.x, + position.y - fClickPoint.y); + BeginRectTracking(dragRect, B_TRACK_WHOLE_RECT); + } else if (position.x < fLeftDragBoundry + || position.x > fRightDragBoundry) { + DragSelectedColumn(position - BPoint(fClickPoint.x, 0)); + } + +#if DRAG_TITLE_OUTLINE + // Set up the invalid rect to include the rect for the previous + // position of the drag rect, as well as the new one. + BRect invalidRect(fSelectedColumnRect); + invalidRect.OffsetTo(fCurrentDragPosition.x - fClickPoint.x, 0); + if (position.x < fCurrentDragPosition.x) + invalidRect.left -= fCurrentDragPosition.x - position.x; + else + invalidRect.right += position.x - fCurrentDragPosition.x; + + fCurrentDragPosition = position; + Invalidate(invalidRect); +#endif + break; + } + + case DRAG_COLUMN_OUTSIDE_TITLE: + if (transit == B_ENTERED_VIEW) { + // Drag back into view + EndRectTracking(); + fCurrentState = DRAG_COLUMN_INSIDE_TITLE; + fSelectedColumn->SetVisible(true); + DragSelectedColumn(position - BPoint(fClickPoint.x, 0)); + } + + break; + + case INACTIVE: + // Check for cursor changes if we are over the resize area for + // a column. + BColumn* resizeColumn = 0; + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn* column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (leftEdge > position.x + kColumnResizeAreaWidth / 2) + break; + + float rightEdge = leftEdge + column->Width(); + if (position.x > rightEdge - kColumnResizeAreaWidth / 2 + && position.x < rightEdge + kColumnResizeAreaWidth / 2 + && column->MaxWidth() > column->MinWidth()) { + resizeColumn = column; + break; + } + + leftEdge = rightEdge + 1; + } + + // Update the cursor + if (resizeColumn) { + if (resizeColumn->Width() == resizeColumn->MinWidth()) + SetViewCursor(fMinResizeCursor, true); + else if (resizeColumn->Width() == resizeColumn->MaxWidth()) + SetViewCursor(fMaxResizeCursor, true); + else + SetViewCursor(fResizeCursor, true); + } else + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, true); + break; + } +} + + +void +TitleView::MouseUp(BPoint position) +{ + if (fEditMode) + return; + + switch (fCurrentState) { + case RESIZING_COLUMN: + ResizeSelectedColumn(position - BPoint(fClickPoint.x, 0)); + fCurrentState = INACTIVE; + FixScrollBar(false); + break; + + case PRESSING_COLUMN: { + if (fMasterView->SortingEnabled()) { + if (fSortColumns->HasItem(fSelectedColumn)) { + if ((modifiers() & B_CONTROL_KEY) == 0 + && fSortColumns->CountItems() > 1) { + fSortColumns->MakeEmpty(); + fSortColumns->AddItem(fSelectedColumn); + } + + fSelectedColumn->fSortAscending + = !fSelectedColumn->fSortAscending; + } else { + if ((modifiers() & B_CONTROL_KEY) == 0) + fSortColumns->MakeEmpty(); + + fSortColumns->AddItem(fSelectedColumn); + fSelectedColumn->fSortAscending = true; + } + + fOutlineView->StartSorting(); + } + + fCurrentState = INACTIVE; + Invalidate(); + break; + } + + case DRAG_COLUMN_INSIDE_TITLE: + fCurrentState = INACTIVE; + +#if DRAG_TITLE_OUTLINE + Invalidate(); // xxx Can make this smaller +#else + Invalidate(fSelectedColumnRect); +#endif + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, true); + break; + + case DRAG_COLUMN_OUTSIDE_TITLE: + fCurrentState = INACTIVE; + EndRectTracking(); + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, true); + break; + + default: + ; + } +} + + +void +TitleView::FrameResized(float width, float height) +{ + fVisibleRect.right = fVisibleRect.left + width; + fVisibleRect.bottom = fVisibleRect.top + height; + FixScrollBar(true); +} + + +// #pragma mark - + + +OutlineView::OutlineView(BRect rect, BList* visibleColumns, BList* sortColumns, + BColumnListView* listView) + : + BView(rect, "outline_view", B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_FRAME_EVENTS), + fColumns(visibleColumns), + fSortColumns(sortColumns), + fItemsHeight(0.0), + fVisibleRect(rect.OffsetToCopy(0, 0)), + fFocusRow(0), + fRollOverRow(0), + fLastSelectedItem(0), + fFirstSelectedItem(0), + fSortThread(B_BAD_THREAD_ID), + fCurrentState(INACTIVE), + fMasterView(listView), + fSelectionMode(B_MULTIPLE_SELECTION_LIST), + fTrackMouse(false), + fCurrentField(0), + fCurrentRow(0), + fCurrentColumn(0), + fMouseDown(false), + fCurrentCode(B_OUTSIDE_VIEW), + fEditMode(false), + fDragging(false), + fClickCount(0), + fDropHighlightY(-1) +{ + SetViewColor(B_TRANSPARENT_COLOR); + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + // TODO: This needs to be smart about the size of the buffer. + // Also, the buffer can be shared with the title's buffer. + BRect doubleBufferRect(0, 0, 600, 35); + fDrawBuffer = new BBitmap(doubleBufferRect, B_RGB32, true); + fDrawBufferView = new BView(doubleBufferRect, "double_buffer_view", + B_FOLLOW_ALL_SIDES, 0); + fDrawBuffer->Lock(); + fDrawBuffer->AddChild(fDrawBufferView); + fDrawBuffer->Unlock(); +#endif + + FixScrollBar(true); + fSelectionListDummyHead.fNextSelected = &fSelectionListDummyHead; + fSelectionListDummyHead.fPrevSelected = &fSelectionListDummyHead; +} + + +OutlineView::~OutlineView() +{ +#if DOUBLE_BUFFERED_COLUMN_RESIZE + delete fDrawBuffer; +#endif + + Clear(); +} + + +void +OutlineView::Clear() +{ + DeselectAll(); + // Make sure selection list doesn't point to deleted rows! + RecursiveDeleteRows(&fRows, false); + Invalidate(); + fItemsHeight = 0.0; + FixScrollBar(true); +} + + +void +OutlineView::SetSelectionMode(list_view_type mode) +{ + DeselectAll(); + fSelectionMode = mode; +} + + +list_view_type +OutlineView::SelectionMode() const +{ + return fSelectionMode; +} + + +void +OutlineView::Deselect(BRow* row) +{ + if (row == NULL) + return; + + if (row->fNextSelected != 0) { + row->fNextSelected->fPrevSelected = row->fPrevSelected; + row->fPrevSelected->fNextSelected = row->fNextSelected; + row->fNextSelected = 0; + row->fPrevSelected = 0; + Invalidate(); + } +} + + +void +OutlineView::AddToSelection(BRow* row) +{ + if (row == NULL) + return; + + if (row->fNextSelected == 0) { + if (fSelectionMode == B_SINGLE_SELECTION_LIST) + DeselectAll(); + + row->fNextSelected = fSelectionListDummyHead.fNextSelected; + row->fPrevSelected = &fSelectionListDummyHead; + row->fNextSelected->fPrevSelected = row; + row->fPrevSelected->fNextSelected = row; + + BRect invalidRect; + if (FindVisibleRect(row, &invalidRect)) + Invalidate(invalidRect); + } +} + + +void +OutlineView::RecursiveDeleteRows(BRowContainer* list, bool isOwner) +{ + if (list == NULL) + return; + + while (true) { + BRow* row = list->RemoveItemAt(0L); + if (row == 0) + break; + + if (row->fChildList) + RecursiveDeleteRows(row->fChildList, true); + + delete row; + } + + if (isOwner) + delete list; +} + + +void +OutlineView::RedrawColumn(BColumn* column, float leftEdge, bool isFirstColumn) +{ + // TODO: Remove code duplication (private function which takes a view + // pointer, pass "this" in non-double buffered mode)! + // Watch out for sourceRect versus destRect though! + if (!column) + return; + + font_height fh; + GetFontHeight(&fh); + float line = 0.0; + bool tintedLine = true; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + line += iterator.CurrentRow()->Height() + 1, iterator.GoToNext()) { + + BRow* row = iterator.CurrentRow(); + float rowHeight = row->Height(); + if (line > fVisibleRect.bottom) + break; + tintedLine = !tintedLine; + + if (line + rowHeight >= fVisibleRect.top) { +#if DOUBLE_BUFFERED_COLUMN_RESIZE + BRect sourceRect(0, 0, column->Width(), rowHeight); +#endif + BRect destRect(leftEdge, line, leftEdge + column->Width(), + line + rowHeight); + + rgb_color highColor; + rgb_color lowColor; + if (row->fNextSelected != 0) { + if (fEditMode) { + highColor = fMasterView->Color(B_COLOR_EDIT_BACKGROUND); + lowColor = fMasterView->Color(B_COLOR_EDIT_BACKGROUND); + } else { + highColor = fMasterView->Color(B_COLOR_SELECTION); + lowColor = fMasterView->Color(B_COLOR_SELECTION); + } + } else { + highColor = fMasterView->Color(B_COLOR_BACKGROUND); + lowColor = fMasterView->Color(B_COLOR_BACKGROUND); + } + if (tintedLine) + lowColor = tint_color(lowColor, kTintedLineTint); + + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + fDrawBuffer->Lock(); + + fDrawBufferView->SetHighColor(highColor); + fDrawBufferView->SetLowColor(lowColor); + + BFont font; + GetFont(&font); + fDrawBufferView->SetFont(&font); + fDrawBufferView->FillRect(sourceRect, B_SOLID_LOW); + + if (isFirstColumn) { + // If this is the first column, double buffer drawing the latch + // too. + destRect.left += iterator.CurrentLevel() * kOutlineLevelIndent + - fMasterView->LatchWidth(); + sourceRect.left += iterator.CurrentLevel() * kOutlineLevelIndent + - fMasterView->LatchWidth(); + + LatchType pos = B_NO_LATCH; + if (row->HasLatch()) + pos = row->fIsExpanded ? B_OPEN_LATCH : B_CLOSED_LATCH; + + BRect latchRect(sourceRect); + latchRect.right = latchRect.left + fMasterView->LatchWidth(); + fMasterView->DrawLatch(fDrawBufferView, latchRect, pos, row); + } + + BField* field = row->GetField(column->fFieldID); + if (field) { + BRect fieldRect(sourceRect); + if (isFirstColumn) + fieldRect.left += fMasterView->LatchWidth(); + + #if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion(fieldRect); + fDrawBufferView->PushState(); + fDrawBufferView->ConstrainClippingRegion(&clipRegion); + #endif + fDrawBufferView->SetHighColor(fMasterView->Color( + row->fNextSelected ? B_COLOR_SELECTION_TEXT + : B_COLOR_TEXT)); + float baseline = floor(fieldRect.top + fh.ascent + + (fieldRect.Height() + 1 - (fh.ascent+fh.descent)) / 2); + fDrawBufferView->MovePenTo(fieldRect.left + 8, baseline); + column->DrawField(field, fieldRect, fDrawBufferView); + #if CONSTRAIN_CLIPPING_REGION + fDrawBufferView->PopState(); + #endif + } + + if (fFocusRow == row && !fEditMode && fMasterView->IsFocus() + && Window()->IsActive()) { + fDrawBufferView->SetHighColor(fMasterView->Color( + B_COLOR_ROW_DIVIDER)); + fDrawBufferView->StrokeRect(BRect(-1, sourceRect.top, + 10000.0, sourceRect.bottom)); + } + + fDrawBufferView->Sync(); + fDrawBuffer->Unlock(); + SetDrawingMode(B_OP_COPY); + DrawBitmap(fDrawBuffer, sourceRect, destRect); + +#else + + SetHighColor(highColor); + SetLowColor(lowColor); + FillRect(destRect, B_SOLID_LOW); + + BField* field = row->GetField(column->fFieldID); + if (field) { + #if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion(destRect); + PushState(); + ConstrainClippingRegion(&clipRegion); + #endif + SetHighColor(fMasterView->Color(row->fNextSelected + ? B_COLOR_SELECTION_TEXT : B_COLOR_TEXT)); + float baseline = floor(destRect.top + fh.ascent + + (destRect.Height() + 1 - (fh.ascent + fh.descent)) / 2); + MovePenTo(destRect.left + 8, baseline); + column->DrawField(field, destRect, this); + #if CONSTRAIN_CLIPPING_REGION + PopState(); + #endif + } + + if (fFocusRow == row && !fEditMode && fMasterView->IsFocus() + && Window()->IsActive()) { + SetHighColor(fMasterView->Color(B_COLOR_ROW_DIVIDER)); + StrokeRect(BRect(0, destRect.top, 10000.0, destRect.bottom)); + } +#endif + } + } +} + + +void +OutlineView::Draw(BRect invalidBounds) +{ +#if SMART_REDRAW + BRegion invalidRegion; + GetClippingRegion(&invalidRegion); +#endif + + font_height fh; + GetFontHeight(&fh); + + float line = 0.0; + bool tintedLine = true; + int32 numColumns = fColumns->CountItems(); + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + BRow* row = iterator.CurrentRow(); + if (line > invalidBounds.bottom) + break; + + tintedLine = !tintedLine; + float rowHeight = row->Height(); + + if (line > invalidBounds.top - rowHeight) { + bool isFirstColumn = true; + float fieldLeftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + + // setup background color + rgb_color lowColor; + if (row->fNextSelected != 0) { + if (Window()->IsActive()) { + if (fEditMode) + lowColor = fMasterView->Color(B_COLOR_EDIT_BACKGROUND); + else + lowColor = fMasterView->Color(B_COLOR_SELECTION); + } + else + lowColor = fMasterView->Color(B_COLOR_NON_FOCUS_SELECTION); + } else + lowColor = fMasterView->Color(B_COLOR_BACKGROUND); + if (tintedLine) + lowColor = tint_color(lowColor, kTintedLineTint); + + for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { + BColumn* column = (BColumn*) fColumns->ItemAt(columnIndex); + if (!column->IsVisible()) + continue; + + if (!isFirstColumn && fieldLeftEdge > invalidBounds.right) + break; + + if (fieldLeftEdge + column->Width() >= invalidBounds.left) { + BRect fullRect(fieldLeftEdge, line, + fieldLeftEdge + column->Width(), line + rowHeight); + + bool clippedFirstColumn = false; + // This happens when a column is indented past the + // beginning of the next column. + + SetHighColor(lowColor); + + BRect destRect(fullRect); + if (isFirstColumn) { + fullRect.left -= fMasterView->LatchWidth(); + destRect.left += iterator.CurrentLevel() + * kOutlineLevelIndent; + if (destRect.left >= destRect.right) { + // clipped + FillRect(BRect(0, line, fieldLeftEdge + + column->Width(), line + rowHeight)); + clippedFirstColumn = true; + } + + FillRect(BRect(0, line, MAX(kLeftMargin, + fMasterView->LatchWidth()), line + row->Height())); + } + + +#if SMART_REDRAW + if (!clippedFirstColumn + && invalidRegion.Intersects(fullRect)) { +#else + if (!clippedFirstColumn) { +#endif + FillRect(fullRect); // Using color set above + + // Draw the latch widget if it has one. + if (isFirstColumn) { + if (row == fTargetRow + && fCurrentState == LATCH_CLICKED) { + // Note that this only occurs if the user is + // holding down a latch while items are added + // in the background. + BPoint pos; + uint32 buttons; + GetMouse(&pos, &buttons); + if (fLatchRect.Contains(pos)) { + fMasterView->DrawLatch(this, fLatchRect, + B_PRESSED_LATCH, fTargetRow); + } else { + fMasterView->DrawLatch(this, fLatchRect, + row->fIsExpanded ? B_OPEN_LATCH + : B_CLOSED_LATCH, fTargetRow); + } + } else { + LatchType pos = B_NO_LATCH; + if (row->HasLatch()) + pos = row->fIsExpanded ? B_OPEN_LATCH + : B_CLOSED_LATCH; + + fMasterView->DrawLatch(this, + BRect(destRect.left + - fMasterView->LatchWidth(), + destRect.top, destRect.left, + destRect.bottom), pos, row); + } + } + + SetHighColor(fMasterView->HighColor()); + // The master view just holds the high color for us. + SetLowColor(lowColor); + + BField* field = row->GetField(column->fFieldID); + if (field) { +#if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion(destRect); + PushState(); + ConstrainClippingRegion(&clipRegion); +#endif + SetHighColor(fMasterView->Color( + row->fNextSelected ? B_COLOR_SELECTION_TEXT + : B_COLOR_TEXT)); + float baseline = floor(destRect.top + fh.ascent + + (destRect.Height() + 1 + - (fh.ascent+fh.descent)) / 2); + MovePenTo(destRect.left + 8, baseline); + column->DrawField(field, destRect, this); +#if CONSTRAIN_CLIPPING_REGION + PopState(); +#endif + } + } + } + + isFirstColumn = false; + fieldLeftEdge += column->Width() + 1; + } + + if (fieldLeftEdge <= invalidBounds.right) { + SetHighColor(lowColor); + FillRect(BRect(fieldLeftEdge, line, invalidBounds.right, + line + rowHeight)); + } + } + + // indicate the keyboard focus row + if (fFocusRow == row && !fEditMode && fMasterView->IsFocus() + && Window()->IsActive()) { + SetHighColor(fMasterView->Color(B_COLOR_ROW_DIVIDER)); + StrokeRect(BRect(0, line, 10000.0, line + rowHeight)); + } + + line += rowHeight + 1; + } + + if (line <= invalidBounds.bottom) { + // fill background below last item + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + FillRect(BRect(invalidBounds.left, line, invalidBounds.right, + invalidBounds.bottom)); + } + + // Draw the drop target line + if (fDropHighlightY != -1) { + InvertRect(BRect(0, fDropHighlightY - kDropHighlightLineHeight / 2, + 1000000, fDropHighlightY + kDropHighlightLineHeight / 2)); + } +} + + +BRow* +OutlineView::FindRow(float ypos, int32* _rowIndent, float* _top) +{ + if (_rowIndent && _top) { + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + + BRow* row = iterator.CurrentRow(); + if (line > ypos) + break; + + float rowHeight = row->Height(); + if (ypos <= line + rowHeight) { + *_top = line; + *_rowIndent = iterator.CurrentLevel(); + return row; + } + + line += rowHeight + 1; + } + } + return NULL; +} + +void OutlineView::SetMouseTrackingEnabled(bool enabled) +{ + fTrackMouse = enabled; + if (!enabled && fDropHighlightY != -1) { + // Erase the old target line + InvertRect(BRect(0, fDropHighlightY - kDropHighlightLineHeight / 2, + 1000000, fDropHighlightY + kDropHighlightLineHeight / 2)); + fDropHighlightY = -1; + } +} + + +// +// Note that this interaction is not totally safe. If items are added to +// the list in the background, the widget rect will be incorrect, possibly +// resulting in drawing glitches. The code that adds items needs to be a little smarter +// about invalidating state. +// +void +OutlineView::MouseDown(BPoint position) +{ + if (!fEditMode) + fMasterView->MakeFocus(true); + + // Check to see if the user is clicking on a widget to open a section + // of the list. + bool reset_click_count = false; + int32 indent; + float rowTop; + BRow* row = FindRow(position.y, &indent, &rowTop); + if (row != NULL) { + + // Update fCurrentField + bool handle_field = false; + BField* new_field = 0; + BRow* new_row = 0; + BColumn* new_column = 0; + BRect new_rect; + + if (position.y >= 0) { + if (position.x >= 0) { + float x = 0; + for (int32 c = 0; c < fMasterView->CountColumns(); c++) { + new_column = fMasterView->ColumnAt(c); + if (!new_column->IsVisible()) + continue; + if ((MAX(kLeftMargin, fMasterView->LatchWidth()) + x) + + new_column->Width() >= position.x) { + if (new_column->WantsEvents()) { + new_field = row->GetField(c); + new_row = row; + FindRect(new_row,&new_rect); + new_rect.left = MAX(kLeftMargin, + fMasterView->LatchWidth()) + x; + new_rect.right = new_rect.left + + new_column->Width() - 1; + handle_field = true; + } + break; + } + x += new_column->Width(); + } + } + } + + // Handle mouse down + if (handle_field) { + fMouseDown = true; + fFieldRect = new_rect; + fCurrentColumn = new_column; + fCurrentRow = new_row; + fCurrentField = new_field; + fCurrentCode = B_INSIDE_VIEW; + fCurrentColumn->MouseDown(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1); + } + + if (!fEditMode) { + + fTargetRow = row; + fTargetRowTop = rowTop; + FindVisibleRect(fFocusRow, &fFocusRowRect); + + float leftWidgetBoundry = indent * kOutlineLevelIndent + + MAX(kLeftMargin, fMasterView->LatchWidth()) + - fMasterView->LatchWidth(); + fLatchRect.Set(leftWidgetBoundry, rowTop, leftWidgetBoundry + + fMasterView->LatchWidth(), rowTop + row->Height()); + if (fLatchRect.Contains(position) && row->HasLatch()) { + fCurrentState = LATCH_CLICKED; + if (fTargetRow->fNextSelected != 0) + SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + else + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + + FillRect(fLatchRect); + if (fLatchRect.Contains(position)) { + fMasterView->DrawLatch(this, fLatchRect, B_PRESSED_LATCH, + row); + } else { + fMasterView->DrawLatch(this, fLatchRect, + fTargetRow->fIsExpanded ? B_OPEN_LATCH + : B_CLOSED_LATCH, row); + } + } else { + Invalidate(fFocusRowRect); + fFocusRow = fTargetRow; + FindVisibleRect(fFocusRow, &fFocusRowRect); + + ASSERT(fTargetRow != 0); + + if ((modifiers() & B_CONTROL_KEY) == 0) + DeselectAll(); + + if ((modifiers() & B_SHIFT_KEY) != 0 && fFirstSelectedItem != 0 + && fSelectionMode == B_MULTIPLE_SELECTION_LIST) { + SelectRange(fFirstSelectedItem, fTargetRow); + } + else { + if (fTargetRow->fNextSelected != 0) { + // Unselect row + fTargetRow->fNextSelected->fPrevSelected + = fTargetRow->fPrevSelected; + fTargetRow->fPrevSelected->fNextSelected + = fTargetRow->fNextSelected; + fTargetRow->fPrevSelected = 0; + fTargetRow->fNextSelected = 0; + fFirstSelectedItem = NULL; + } else { + // Select row + if (fSelectionMode == B_SINGLE_SELECTION_LIST) + DeselectAll(); + + fTargetRow->fNextSelected + = fSelectionListDummyHead.fNextSelected; + fTargetRow->fPrevSelected + = &fSelectionListDummyHead; + fTargetRow->fNextSelected->fPrevSelected = fTargetRow; + fTargetRow->fPrevSelected->fNextSelected = fTargetRow; + fFirstSelectedItem = fTargetRow; + } + + Invalidate(BRect(fVisibleRect.left, fTargetRowTop, + fVisibleRect.right, + fTargetRowTop + fTargetRow->Height())); + } + + fCurrentState = ROW_CLICKED; + if (fLastSelectedItem != fTargetRow) + reset_click_count = true; + fLastSelectedItem = fTargetRow; + fMasterView->SelectionChanged(); + + } + } + + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | + B_NO_POINTER_HISTORY); + + } else if (fFocusRow != 0) { + // User clicked in open space, unhighlight focus row. + FindVisibleRect(fFocusRow, &fFocusRowRect); + fFocusRow = 0; + Invalidate(fFocusRowRect); + } + + // We stash the click counts here because the 'clicks' field + // is not in the CurrentMessage() when MouseUp is called... ;( + if (reset_click_count) + fClickCount = 1; + else + Window()->CurrentMessage()->FindInt32("clicks", &fClickCount); + fClickPoint = position; + +} + + +void +OutlineView::MouseMoved(BPoint position, uint32 /*transit*/, + const BMessage* /*dragMessage*/) +{ + if (!fMouseDown) { + // Update fCurrentField + bool handle_field = false; + BField* new_field = 0; + BRow* new_row = 0; + BColumn* new_column = 0; + BRect new_rect(0,0,0,0); + if (position.y >=0 ) { + float top; + int32 indent; + BRow* row = FindRow(position.y, &indent, &top); + if (row && position.x >=0 ) { + float x=0; + for (int32 c=0;cCountColumns();c++) { + new_column = fMasterView->ColumnAt(c); + if (!new_column->IsVisible()) + continue; + if ((MAX(kLeftMargin, + fMasterView->LatchWidth()) + x) + new_column->Width() + > position.x) { + + if(new_column->WantsEvents()) { + new_field = row->GetField(c); + new_row = row; + FindRect(new_row,&new_rect); + new_rect.left = MAX(kLeftMargin, + fMasterView->LatchWidth()) + x; + new_rect.right = new_rect.left + + new_column->Width() - 1; + handle_field = true; + } + break; + } + x += new_column->Width(); + } + } + } + + // Handle mouse moved + if (handle_field) { + if (new_field != fCurrentField) { + if (fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, + fCurrentCode = B_EXITED_VIEW); + } + fCurrentColumn = new_column; + fCurrentRow = new_row; + fCurrentField = new_field; + fFieldRect = new_rect; + if (fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, + fCurrentCode = B_ENTERED_VIEW); + } + } else { + if (fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, + fCurrentCode = B_INSIDE_VIEW); + } + } + } else { + if (fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, + fCurrentCode = B_EXITED_VIEW); + fCurrentField = 0; + fCurrentColumn = 0; + fCurrentRow = 0; + } + } + } else { + if (fCurrentField) { + if (fFieldRect.Contains(position)) { + if (fCurrentCode == B_OUTSIDE_VIEW + || fCurrentCode == B_EXITED_VIEW) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, + fCurrentCode = B_ENTERED_VIEW); + } else { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, + fCurrentCode = B_INSIDE_VIEW); + } + } else { + if (fCurrentCode == B_INSIDE_VIEW + || fCurrentCode == B_ENTERED_VIEW) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, + fCurrentCode = B_EXITED_VIEW); + } else { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, + fCurrentCode = B_OUTSIDE_VIEW); + } + } + } + } + + if (!fEditMode) { + + switch (fCurrentState) { + case LATCH_CLICKED: + if (fTargetRow->fNextSelected != 0) + SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + else + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + + FillRect(fLatchRect); + if (fLatchRect.Contains(position)) { + fMasterView->DrawLatch(this, fLatchRect, B_PRESSED_LATCH, + fTargetRow); + } else { + fMasterView->DrawLatch(this, fLatchRect, + fTargetRow->fIsExpanded ? B_OPEN_LATCH : B_CLOSED_LATCH, + fTargetRow); + } + break; + + case ROW_CLICKED: + if (abs((int)(position.x - fClickPoint.x)) > kRowDragSensitivity + || abs((int)(position.y - fClickPoint.y)) + > kRowDragSensitivity) { + fCurrentState = DRAGGING_ROWS; + fMasterView->InitiateDrag(fClickPoint, + fTargetRow->fNextSelected != 0); + } + break; + + case DRAGGING_ROWS: +#if 0 + // falls through... +#else + if (fTrackMouse /*&& message*/) { + if (fVisibleRect.Contains(position)) { + float top; + int32 indent; + BRow* target = FindRow(position.y, &indent, &top); + if (target) + SetFocusRow(target, true); + } + } + break; +#endif + + default: { + + if (fTrackMouse /*&& message*/) { + // Draw a highlight line... + if (fVisibleRect.Contains(position)) { + float top; + int32 indent; + BRow* target = FindRow(position.y, &indent, &top); + if (target == fRollOverRow) + break; + if (fRollOverRow) { + BRect rect; + FindRect(fRollOverRow, &rect); + Invalidate(rect); + } + fRollOverRow = target; +#if 0 + SetFocusRow(fRollOverRow,false); +#else + PushState(); + SetDrawingMode(B_OP_BLEND); + SetHighColor(255, 255, 255, 255); + BRect rect; + FindRect(fRollOverRow, &rect); + rect.bottom -= 1.0; + FillRect(rect); + PopState(); +#endif + } else { + if (fRollOverRow) { + BRect rect; + FindRect(fRollOverRow, &rect); + Invalidate(rect); + fRollOverRow = NULL; + } + } + } + } + } + } +} + + +void +OutlineView::MouseUp(BPoint position) +{ + if (fCurrentField) { + fCurrentColumn->MouseUp(fMasterView, fCurrentRow, fCurrentField); + fMouseDown = false; + } + + if (fEditMode) + return; + + switch (fCurrentState) { + case LATCH_CLICKED: + if (fLatchRect.Contains(position)) { + fMasterView->ExpandOrCollapse(fTargetRow, + !fTargetRow->fIsExpanded); + } + + Invalidate(fLatchRect); + fCurrentState = INACTIVE; + break; + + case ROW_CLICKED: + if (fClickCount > 1 + && abs((int)fClickPoint.x - (int)position.x) + < kDoubleClickMoveSensitivity + && abs((int)fClickPoint.y - (int)position.y) + < kDoubleClickMoveSensitivity) { + fMasterView->ItemInvoked(); + } + fCurrentState = INACTIVE; + break; + + case DRAGGING_ROWS: + fCurrentState = INACTIVE; + // Falls through + + default: + if (fDropHighlightY != -1) { + InvertRect(BRect(0, + fDropHighlightY - kDropHighlightLineHeight / 2, + 1000000, fDropHighlightY + kDropHighlightLineHeight / 2)); + // Erase the old target line + fDropHighlightY = -1; + } + } +} + + +void +OutlineView::MessageReceived(BMessage* message) +{ + if (message->WasDropped()) { + fMasterView->MessageDropped(message, + ConvertFromScreen(message->DropPoint())); + } else { + BView::MessageReceived(message); + } +} + + +void +OutlineView::ChangeFocusRow(bool up, bool updateSelection, + bool addToCurrentSelection) +{ + int32 indent; + float top; + float newRowPos = 0; + float verticalScroll = 0; + + if (fFocusRow) { + // A row currently has the focus, get information about it + newRowPos = fFocusRowRect.top + (up ? -4 : fFocusRow->Height() + 4); + if (newRowPos < fVisibleRect.top + 20) + verticalScroll = newRowPos - 20; + else if (newRowPos > fVisibleRect.bottom - 20) + verticalScroll = newRowPos - fVisibleRect.Height() + 20; + } else + newRowPos = fVisibleRect.top + 2; + // no row is currently focused, set this to the top of the window + // so we will select the first visible item in the list. + + BRow* newRow = FindRow(newRowPos, &indent, &top); + if (newRow) { + if (fFocusRow) { + fFocusRowRect.right = 10000; + Invalidate(fFocusRowRect); + } + fFocusRow = newRow; + fFocusRowRect.top = top; + fFocusRowRect.left = 0; + fFocusRowRect.right = 10000; + fFocusRowRect.bottom = fFocusRowRect.top + fFocusRow->Height(); + Invalidate(fFocusRowRect); + + if (updateSelection) { + if (!addToCurrentSelection + || fSelectionMode == B_SINGLE_SELECTION_LIST) { + DeselectAll(); + } + + if (fFocusRow->fNextSelected == 0) { + fFocusRow->fNextSelected + = fSelectionListDummyHead.fNextSelected; + fFocusRow->fPrevSelected = &fSelectionListDummyHead; + fFocusRow->fNextSelected->fPrevSelected = fFocusRow; + fFocusRow->fPrevSelected->fNextSelected = fFocusRow; + } + + fLastSelectedItem = fFocusRow; + } + } else + Invalidate(fFocusRowRect); + + if (verticalScroll != 0) { + BScrollBar* vScrollBar = ScrollBar(B_VERTICAL); + float min, max; + vScrollBar->GetRange(&min, &max); + if (verticalScroll < min) + verticalScroll = min; + else if (verticalScroll > max) + verticalScroll = max; + + vScrollBar->SetValue(verticalScroll); + } + + if (newRow && updateSelection) + fMasterView->SelectionChanged(); +} + + +void +OutlineView::MoveFocusToVisibleRect() +{ + fFocusRow = 0; + ChangeFocusRow(true, true, false); +} + + +BRow* +OutlineView::CurrentSelection(BRow* lastSelected) const +{ + BRow* row; + if (lastSelected == 0) + row = fSelectionListDummyHead.fNextSelected; + else + row = lastSelected->fNextSelected; + + + if (row == &fSelectionListDummyHead) + row = 0; + + return row; +} + + +void +OutlineView::ToggleFocusRowSelection(bool selectRange) +{ + if (fFocusRow == 0) + return; + + if (selectRange && fSelectionMode == B_MULTIPLE_SELECTION_LIST) + SelectRange(fLastSelectedItem, fFocusRow); + else { + if (fFocusRow->fNextSelected != 0) { + // Unselect row + fFocusRow->fNextSelected->fPrevSelected = fFocusRow->fPrevSelected; + fFocusRow->fPrevSelected->fNextSelected = fFocusRow->fNextSelected; + fFocusRow->fPrevSelected = 0; + fFocusRow->fNextSelected = 0; + } else { + // Select row + if (fSelectionMode == B_SINGLE_SELECTION_LIST) + DeselectAll(); + + fFocusRow->fNextSelected = fSelectionListDummyHead.fNextSelected; + fFocusRow->fPrevSelected = &fSelectionListDummyHead; + fFocusRow->fNextSelected->fPrevSelected = fFocusRow; + fFocusRow->fPrevSelected->fNextSelected = fFocusRow; + } + } + + fLastSelectedItem = fFocusRow; + fMasterView->SelectionChanged(); + Invalidate(fFocusRowRect); +} + + +void +OutlineView::ToggleFocusRowOpen() +{ + if (fFocusRow) + fMasterView->ExpandOrCollapse(fFocusRow, !fFocusRow->fIsExpanded); +} + + +void +OutlineView::ExpandOrCollapse(BRow* parentRow, bool expand) +{ + // TODO: Could use CopyBits here to speed things up. + + if (parentRow == NULL) + return; + + if (parentRow->fIsExpanded == expand) + return; + + parentRow->fIsExpanded = expand; + + BRect parentRect; + if (FindRect(parentRow, &parentRect)) { + // Determine my new height + float subTreeHeight = 0.0; + if (parentRow->fIsExpanded) + for (RecursiveOutlineIterator iterator(parentRow->fChildList); + iterator.CurrentRow(); + iterator.GoToNext() + ) + { + subTreeHeight += iterator.CurrentRow()->Height()+1; + } + else + for (RecursiveOutlineIterator iterator(parentRow->fChildList); + iterator.CurrentRow(); + iterator.GoToNext() + ) + { + subTreeHeight -= iterator.CurrentRow()->Height()+1; + } + fItemsHeight += subTreeHeight; + + // Adjust focus row if necessary. + if (FindRect(fFocusRow, &fFocusRowRect) == false) { + // focus row is in a subtree that has collapsed, + // move it up to the parent. + fFocusRow = parentRow; + FindRect(fFocusRow, &fFocusRowRect); + } + + Invalidate(BRect(0, parentRect.top, fVisibleRect.right, + fVisibleRect.bottom)); + FixScrollBar(false); + } +} + +void +OutlineView::RemoveRow(BRow* row) +{ + if (row == NULL) + return; + + BRow* parentRow; + bool parentIsVisible; + float subTreeHeight = row->Height(); + if (FindParent(row, &parentRow, &parentIsVisible)) { + // adjust height + if (parentIsVisible && (parentRow == 0 || parentRow->fIsExpanded)) { + if (row->fIsExpanded) { + for (RecursiveOutlineIterator iterator(row->fChildList); + iterator.CurrentRow(); iterator.GoToNext()) + subTreeHeight += iterator.CurrentRow()->Height(); + } + } + } + if (parentRow) { + if (parentRow->fIsExpanded) + fItemsHeight -= subTreeHeight + 1; + } else { + fItemsHeight -= subTreeHeight + 1; + } + FixScrollBar(false); + if (parentRow) + parentRow->fChildList->RemoveItem(row); + else + fRows.RemoveItem(row); + + if (parentRow != 0 && parentRow->fChildList->CountItems() == 0) { + delete parentRow->fChildList; + parentRow->fChildList = 0; + if (parentIsVisible) + Invalidate(); // xxx crude way of redrawing latch + } + + if (parentIsVisible && (parentRow == 0 || parentRow->fIsExpanded)) + Invalidate(); // xxx make me smarter. + + + // Adjust focus row if necessary. + if (fFocusRow && FindRect(fFocusRow, &fFocusRowRect) == false) { + // focus row is in a subtree that is gone, move it up to the parent. + fFocusRow = parentRow; + if (fFocusRow) + FindRect(fFocusRow, &fFocusRowRect); + } + + // Remove this from the selection if necessary + if (row->fNextSelected != 0) { + row->fNextSelected->fPrevSelected = row->fPrevSelected; + row->fPrevSelected->fNextSelected = row->fNextSelected; + row->fPrevSelected = 0; + row->fNextSelected = 0; + fMasterView->SelectionChanged(); + } + + fCurrentColumn = 0; + fCurrentRow = 0; + fCurrentField = 0; +} + + +BRowContainer* +OutlineView::RowList() +{ + return &fRows; +} + + +void +OutlineView::UpdateRow(BRow* row) +{ + if (row) { + // Determine if this row has changed its sort order + BRow* parentRow = NULL; + bool parentIsVisible = false; + FindParent(row, &parentRow, &parentIsVisible); + + BRowContainer* list = (parentRow == NULL) ? &fRows : parentRow->fChildList; + + if(list) { + int32 rowIndex = list->IndexOf(row); + ASSERT(rowIndex >= 0); + ASSERT(list->ItemAt(rowIndex) == row); + + bool rowMoved = false; + if (rowIndex > 0 && CompareRows(list->ItemAt(rowIndex - 1), row) > 0) + rowMoved = true; + + if (rowIndex < list->CountItems() - 1 && CompareRows(list->ItemAt(rowIndex + 1), + row) < 0) + rowMoved = true; + + if (rowMoved) { + // Sort location of this row has changed. + // Remove and re-add in the right spot + SortList(list, parentIsVisible && (parentRow == NULL || parentRow->fIsExpanded)); + } else if (parentIsVisible && (parentRow == NULL || parentRow->fIsExpanded)) { + BRect invalidRect; + if (FindVisibleRect(row, &invalidRect)) + Invalidate(invalidRect); + } + } + } +} + + +void +OutlineView::AddRow(BRow* row, int32 Index, BRow* parentRow) +{ + if (!row) + return; + + row->fParent = parentRow; + + if (fMasterView->SortingEnabled()) { + // Ignore index here. + if (parentRow) { + if (parentRow->fChildList == NULL) + parentRow->fChildList = new BRowContainer; + + AddSorted(parentRow->fChildList, row); + } else + AddSorted(&fRows, row); + } else { + // Note, a -1 index implies add to end if sorting is not enabled + if (parentRow) { + if (parentRow->fChildList == 0) + parentRow->fChildList = new BRowContainer; + + if (Index < 0 || Index > parentRow->fChildList->CountItems()) + parentRow->fChildList->AddItem(row); + else + parentRow->fChildList->AddItem(row, Index); + } else { + if (Index < 0 || Index >= fRows.CountItems()) + fRows.AddItem(row); + else + fRows.AddItem(row, Index); + } + } + + if (parentRow == 0 || parentRow->fIsExpanded) + fItemsHeight += row->Height() + 1; + + FixScrollBar(false); + + BRect newRowRect; + bool newRowIsInOpenBranch = FindRect(row, &newRowRect); + + if (fFocusRow && fFocusRowRect.top > newRowRect.bottom) { + // The focus row has moved. + Invalidate(fFocusRowRect); + FindRect(fFocusRow, &fFocusRowRect); + Invalidate(fFocusRowRect); + } + + if (newRowIsInOpenBranch) { + if (fCurrentState == INACTIVE) { + if (newRowRect.bottom < fVisibleRect.top) { + // The new row is totally above the current viewport, move + // everything down and redraw the first line. + BRect source(fVisibleRect); + BRect dest(fVisibleRect); + source.bottom -= row->Height() + 1; + dest.top += row->Height() + 1; + CopyBits(source, dest); + Invalidate(BRect(fVisibleRect.left, fVisibleRect.top, fVisibleRect.right, + fVisibleRect.top + newRowRect.Height())); + } else if (newRowRect.top < fVisibleRect.bottom) { + // New item is somewhere in the current region. Scroll everything + // beneath it down and invalidate just the new row rect. + BRect source(fVisibleRect.left, newRowRect.top, fVisibleRect.right, + fVisibleRect.bottom - newRowRect.Height()); + BRect dest(source); + dest.OffsetBy(0, newRowRect.Height() + 1); + CopyBits(source, dest); + Invalidate(newRowRect); + } // otherwise, this is below the currently visible region + } else { + // Adding the item may have caused the item that the user is currently + // selected to move. This would cause annoying drawing and interaction + // bugs, as the position of that item is cached. If this happens, resize + // the scroll bar, then scroll back so the selected item is in view. + BRect targetRect; + if (FindRect(fTargetRow, &targetRect)) { + float delta = targetRect.top - fTargetRowTop; + if (delta != 0) { + // This causes a jump because ScrollBy will copy a chunk of the view. + // Since the actual contents of the view have been offset, we don't + // want this, we just want to change the virtual origin of the window. + // Constrain the clipping region so everything is clipped out so no + // copy occurs. + // + // xxx this currently doesn't work if the scroll bars aren't enabled. + // everything will still move anyway. A minor annoyance. + BRegion emptyRegion; + ConstrainClippingRegion(&emptyRegion); + PushState(); + ScrollBy(0, delta); + PopState(); + ConstrainClippingRegion(NULL); + + fTargetRowTop += delta; + fClickPoint.y += delta; + fLatchRect.OffsetBy(0, delta); + } + } + } + } + + // If the parent was previously childless, it will need to have a latch + // drawn. + BRect parentRect; + if (parentRow && parentRow->fChildList->CountItems() == 1 + && FindVisibleRect(parentRow, &parentRect)) + Invalidate(parentRect); +} + + +void +OutlineView::FixScrollBar(bool scrollToFit) +{ + BScrollBar* vScrollBar = ScrollBar(B_VERTICAL); + if (vScrollBar) { + if (fItemsHeight > fVisibleRect.Height()) { + float maxScrollBarValue = fItemsHeight - fVisibleRect.Height(); + vScrollBar->SetProportion(fVisibleRect.Height() / fItemsHeight); + + // If the user is scrolled down too far when makes the range smaller, the list + // will jump suddenly, which is undesirable. In this case, don't fix the scroll + // bar here. In ScrollTo, it checks to see if this has occured, and will + // fix the scroll bars sneakily if the user has scrolled up far enough. + if (scrollToFit || vScrollBar->Value() <= maxScrollBarValue) { + vScrollBar->SetRange(0.0, maxScrollBarValue); + vScrollBar->SetSteps(20.0, fVisibleRect.Height()); + } + } else if (vScrollBar->Value() == 0.0) + vScrollBar->SetRange(0.0, 0.0); // disable scroll bar. + } +} + + +void +OutlineView::AddSorted(BRowContainer* list, BRow* row) +{ + if (list && row) { + // Find general vicinity with binary search. + int32 lower = 0; + int32 upper = list->CountItems()-1; + while( lower < upper ) { + int32 middle = lower + (upper-lower+1)/2; + int32 cmp = CompareRows(row, list->ItemAt(middle)); + if( cmp < 0 ) upper = middle-1; + else if( cmp > 0 ) lower = middle+1; + else lower = upper = middle; + } + + // At this point, 'upper' and 'lower' at the last found item. + // Arbitrarily use 'upper' and determine the final insertion + // point -- either before or after this item. + if( upper < 0 ) upper = 0; + else if( upper < list->CountItems() ) { + if( CompareRows(row, list->ItemAt(upper)) > 0 ) upper++; + } + + if (upper >= list->CountItems()) + list->AddItem(row); // Adding to end. + else + list->AddItem(row, upper); // Insert + } +} + + +int32 +OutlineView::CompareRows(BRow* row1, BRow* row2) +{ + int32 itemCount (fSortColumns->CountItems()); + if (row1 && row2) { + for (int32 index = 0; index < itemCount; index++) { + BColumn* column = (BColumn*) fSortColumns->ItemAt(index); + int comp = 0; + BField* field1 = (BField*) row1->GetField(column->fFieldID); + BField* field2 = (BField*) row2->GetField(column->fFieldID); + if (field1 && field2) + comp = column->CompareFields(field1, field2); + + if (!column->fSortAscending) + comp = -comp; + + if (comp != 0) + return comp; + } + } + return 0; +} + + +void +OutlineView::FrameResized(float width, float height) +{ + fVisibleRect.right = fVisibleRect.left + width; + fVisibleRect.bottom = fVisibleRect.top + height; + FixScrollBar(true); + _inherited::FrameResized(width, height); +} + + +void +OutlineView::ScrollTo(BPoint position) +{ + fVisibleRect.OffsetTo(position.x, position.y); + + // In FixScrollBar, we might not have been able to change the size of + // the scroll bar because the user was scrolled down too far. Take + // this opportunity to sneak it in if we can. + BScrollBar* vScrollBar = ScrollBar(B_VERTICAL); + float maxScrollBarValue = fItemsHeight - fVisibleRect.Height(); + float min, max; + vScrollBar->GetRange(&min, &max); + if (max != maxScrollBarValue && position.y > maxScrollBarValue) + FixScrollBar(true); + + _inherited::ScrollTo(position); +} + + +const BRect& +OutlineView::VisibleRect() const +{ + return fVisibleRect; +} + + +bool +OutlineView::FindVisibleRect(BRow* row, BRect* _rect) +{ + if (row && _rect) { + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + if (line > fVisibleRect.bottom) + break; + + if (iterator.CurrentRow() == row) { + _rect->Set(fVisibleRect.left, line, fVisibleRect.right, + line + row->Height()); + return true; + } + + line += iterator.CurrentRow()->Height() + 1; + } + } + return false; +} + + +bool +OutlineView::FindRect(const BRow* row, BRect* _rect) +{ + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + if (iterator.CurrentRow() == row) { + _rect->Set(fVisibleRect.left, line, fVisibleRect.right, + line + row->Height()); + return true; + } + + line += iterator.CurrentRow()->Height() + 1; + } + + return false; +} + + +void +OutlineView::ScrollTo(const BRow* row) +{ + BRect rect; + if (FindRect(row, &rect)) { + BRect bounds = Bounds(); + if (rect.top < bounds.top) + ScrollTo(BPoint(bounds.left, rect.top)); + else if (rect.bottom > bounds.bottom) + ScrollBy(0, rect.bottom - bounds.bottom); + } +} + + +void +OutlineView::DeselectAll() +{ + // Invalidate all selected rows + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + if (line > fVisibleRect.bottom) + break; + + BRow* row = iterator.CurrentRow(); + if (line + row->Height() > fVisibleRect.top) { + if (row->fNextSelected != 0) + Invalidate(BRect(fVisibleRect.left, line, fVisibleRect.right, + line + row->Height())); + } + + line += row->Height() + 1; + } + + // Set items not selected + while (fSelectionListDummyHead.fNextSelected != &fSelectionListDummyHead) { + BRow* row = fSelectionListDummyHead.fNextSelected; + row->fNextSelected->fPrevSelected = row->fPrevSelected; + row->fPrevSelected->fNextSelected = row->fNextSelected; + row->fNextSelected = 0; + row->fPrevSelected = 0; + } +} + + +BRow* +OutlineView::FocusRow() const +{ + return fFocusRow; +} + + +void +OutlineView::SetFocusRow(BRow* row, bool Select) +{ + if (row) { + if (Select) + AddToSelection(row); + + if (fFocusRow == row) + return; + + Invalidate(fFocusRowRect); // invalidate previous + + fTargetRow = fFocusRow = row; + + FindVisibleRect(fFocusRow, &fFocusRowRect); + Invalidate(fFocusRowRect); // invalidate current + + fFocusRowRect.right = 10000; + fMasterView->SelectionChanged(); + } +} + + +bool +OutlineView::SortList(BRowContainer* list, bool isVisible) +{ + if (list) { + // Shellsort + BRow** items = (BRow**) list->AsBList()->Items(); + int32 numItems = list->CountItems(); + int h; + for (h = 1; h < numItems / 9; h = 3 * h + 1) + ; + + for (;h > 0; h /= 3) { + for (int step = h; step < numItems; step++) { + BRow* temp = items[step]; + int i; + for (i = step - h; i >= 0; i -= h) { + if (CompareRows(temp, items[i]) < 0) + items[i + h] = items[i]; + else + break; + } + + items[i + h] = temp; + } + } + + if (isVisible) { + Invalidate(); + + InvalidateCachedPositions(); + int lockCount = Window()->CountLocks(); + for (int i = 0; i < lockCount; i++) + Window()->Unlock(); + + while (lockCount--) + if (!Window()->Lock()) + return false; // Window is gone... + } + } + return true; +} + + +int32 +OutlineView::DeepSortThreadEntry(void* _outlineView) +{ + ((OutlineView*) _outlineView)->DeepSort(); + return 0; +} + + +void +OutlineView::DeepSort() +{ + struct stack_entry { + bool isVisible; + BRowContainer* list; + int32 listIndex; + } stack[kMaxDepth]; + int32 stackTop = 0; + + stack[stackTop].list = &fRows; + stack[stackTop].isVisible = true; + stack[stackTop].listIndex = 0; + fNumSorted = 0; + + if (Window()->Lock() == false) + return; + + bool doneSorting = false; + while (!doneSorting && !fSortCancelled) { + + stack_entry* currentEntry = &stack[stackTop]; + + // xxx Can make the invalidate area smaller by finding the rect for the + // parent item and using that as the top of the invalid rect. + + bool haveLock = SortList(currentEntry->list, currentEntry->isVisible); + if (!haveLock) + return ; // window is gone. + + // Fix focus rect. + InvalidateCachedPositions(); + if (fCurrentState != INACTIVE) + fCurrentState = INACTIVE; // sorry... + + // next list. + bool foundNextList = false; + while (!foundNextList && !fSortCancelled) { + for (int32 index = currentEntry->listIndex; index < currentEntry->list->CountItems(); + index++) { + BRow* parentRow = currentEntry->list->ItemAt(index); + BRowContainer* childList = parentRow->fChildList; + if (childList != 0) { + currentEntry->listIndex = index + 1; + stackTop++; + ASSERT(stackTop < kMaxDepth); + stack[stackTop].listIndex = 0; + stack[stackTop].list = childList; + stack[stackTop].isVisible = (currentEntry->isVisible && parentRow->fIsExpanded); + foundNextList = true; + break; + } + } + + if (!foundNextList) { + // back up + if (--stackTop < 0) { + doneSorting = true; + break; + } + + currentEntry = &stack[stackTop]; + } + } + } + + Window()->Unlock(); +} + + +void +OutlineView::StartSorting() +{ + // If this view is not yet attached to a window, don't start a sort thread! + if (Window() == NULL) + return; + + if (fSortThread != B_BAD_THREAD_ID) { + thread_info tinfo; + if (get_thread_info(fSortThread, &tinfo) == B_OK) { + // Unlock window so this won't deadlock (sort thread is probably + // waiting to lock window). + + int lockCount = Window()->CountLocks(); + for (int i = 0; i < lockCount; i++) + Window()->Unlock(); + + fSortCancelled = true; + int32 status; + wait_for_thread(fSortThread, &status); + + while (lockCount--) + if (!Window()->Lock()) + return ; // Window is gone... + } + } + + fSortCancelled = false; + fSortThread = spawn_thread(DeepSortThreadEntry, "sort_thread", B_NORMAL_PRIORITY, this); + resume_thread(fSortThread); +} + + +void +OutlineView::SelectRange(BRow* start, BRow* end) +{ + if (!start || !end) + return; + + if (start == end) // start is always selected when this is called + return; + + RecursiveOutlineIterator iterator(&fRows, false); + while (iterator.CurrentRow() != 0) { + if (iterator.CurrentRow() == end) { + // reverse selection, swap to fix special case + BRow* temp = start; + start = end; + end = temp; + break; + } else if (iterator.CurrentRow() == start) + break; + + iterator.GoToNext(); + } + + while (true) { + BRow* row = iterator.CurrentRow(); + if (row) { + if (row->fNextSelected == 0) { + row->fNextSelected = fSelectionListDummyHead.fNextSelected; + row->fPrevSelected = &fSelectionListDummyHead; + row->fNextSelected->fPrevSelected = row; + row->fPrevSelected->fNextSelected = row; + } + } else + break; + + if (row == end) + break; + + iterator.GoToNext(); + } + + Invalidate(); // xxx make invalidation smaller +} + + +bool +OutlineView::FindParent(BRow* row, BRow** outParent, bool* out_parentIsVisible) +{ + bool result = false; + if (row && outParent) { + *outParent = row->fParent; + + // Walk up the parent chain to determine if this row is visible + bool isVisible = true; + for (BRow* currentRow = row->fParent; currentRow; currentRow = currentRow->fParent) { + if (!currentRow->fIsExpanded) { + isVisible = false; + break; + } + } + + if (out_parentIsVisible) + *out_parentIsVisible = isVisible; + result = (NULL != *outParent); + } + + return result; +} + + +int32 +OutlineView::IndexOf(BRow* row) +{ + if (row) { + if (row->fParent == 0) + return fRows.IndexOf(row); + + ASSERT(row->fParent->fChildList); + return row->fParent->fChildList->IndexOf(row); + } + + return B_ERROR; +} + + +void +OutlineView::InvalidateCachedPositions() +{ + if (fFocusRow) + FindRect(fFocusRow, &fFocusRowRect); +} + + +float +OutlineView::GetColumnPreferredWidth(BColumn* column) +{ + float preferred = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + BRow* row = iterator.CurrentRow(); + BField* field = row->GetField(column->fFieldID); + if (field) { + float width = column->GetPreferredWidth(field, this); + if (preferred < width) + preferred = width; + } + } + // Constrain to preferred width. This makes the method do a little + // more than asked, but it's for convenience. + if (preferred < column->MinWidth()) + preferred = column->MinWidth(); + else if (preferred > column->MaxWidth()) + preferred = column->MaxWidth(); + + return preferred; +} + + +// #pragma mark - + + +RecursiveOutlineIterator::RecursiveOutlineIterator(BRowContainer* list, + bool openBranchesOnly) + : + fStackIndex(0), + fCurrentListIndex(0), + fCurrentListDepth(0), + fOpenBranchesOnly(openBranchesOnly) +{ + if (list == 0 || list->CountItems() == 0) + fCurrentList = 0; + else + fCurrentList = list; +} + + +BRow* +RecursiveOutlineIterator::CurrentRow() const +{ + if (fCurrentList == 0) + return 0; + + return fCurrentList->ItemAt(fCurrentListIndex); +} + + +void +RecursiveOutlineIterator::GoToNext() +{ + if (fCurrentList == 0) + return; + if (fCurrentListIndex < 0 || fCurrentListIndex >= fCurrentList->CountItems()) { + fCurrentList = 0; + return; + } + + BRow* currentRow = fCurrentList->ItemAt(fCurrentListIndex); + if(currentRow) { + if (currentRow->fChildList && (currentRow->fIsExpanded || !fOpenBranchesOnly) + && currentRow->fChildList->CountItems() > 0) { + // Visit child. + // Put current list on the stack if it needs to be revisited. + if (fCurrentListIndex < fCurrentList->CountItems() - 1) { + fStack[fStackIndex].fRowSet = fCurrentList; + fStack[fStackIndex].fIndex = fCurrentListIndex + 1; + fStack[fStackIndex].fDepth = fCurrentListDepth; + fStackIndex++; + } + + fCurrentList = currentRow->fChildList; + fCurrentListIndex = 0; + fCurrentListDepth++; + } else if (fCurrentListIndex < fCurrentList->CountItems() - 1) + fCurrentListIndex++; // next item in current list + else if (--fStackIndex >= 0) { + fCurrentList = fStack[fStackIndex].fRowSet; + fCurrentListIndex = fStack[fStackIndex].fIndex; + fCurrentListDepth = fStack[fStackIndex].fDepth; + } else + fCurrentList = 0; + } +} + + +int32 +RecursiveOutlineIterator::CurrentLevel() const +{ + return fCurrentListDepth; +} + + diff --git a/src/column/ColumnListView.h b/src/column/ColumnListView.h new file mode 100644 index 0000000..6b9a800 --- /dev/null +++ b/src/column/ColumnListView.h @@ -0,0 +1,409 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/******************************************************************************* +/ +/ File: ColumnListView.h +/ +/ Description: Experimental multi-column list view. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLUMN_LIST_VIEW_H +#define _COLUMN_LIST_VIEW_H + +#include +#include +#include +#include +#include + +class BScrollBar; + +namespace BPrivate { + +class OutlineView; +class TitleView; +class BRowContainer; +class RecursiveOutlineIterator; + +} // ns BPrivate + +class BField; +class BRow; +class BColumn; +class BColumnListView; + +enum LatchType { + B_NO_LATCH = 0, + B_OPEN_LATCH = 1, + B_PRESSED_LATCH = 2, + B_CLOSED_LATCH = 3 +}; + +typedef enum { + B_ALLOW_COLUMN_NONE = 0, + B_ALLOW_COLUMN_MOVE = 1, + B_ALLOW_COLUMN_RESIZE = 2, + B_ALLOW_COLUMN_POPUP = 4, + B_ALLOW_COLUMN_REMOVE = 8 +} column_flags; + +enum ColumnListViewColor { + B_COLOR_BACKGROUND = 0, + B_COLOR_TEXT = 1, + B_COLOR_ROW_DIVIDER = 2, + B_COLOR_SELECTION = 3, + B_COLOR_SELECTION_TEXT = 4, + B_COLOR_NON_FOCUS_SELECTION = 5, + B_COLOR_EDIT_BACKGROUND = 6, + B_COLOR_EDIT_TEXT = 7, + B_COLOR_HEADER_BACKGROUND = 8, + B_COLOR_HEADER_TEXT = 9, + B_COLOR_SEPARATOR_LINE = 10, + B_COLOR_SEPARATOR_BORDER = 11, + + B_COLOR_TOTAL = 12 +}; + +enum ColumnListViewFont { + B_FONT_ROW = 0, + B_FONT_HEADER = 1, + + B_FONT_TOTAL = 2 +}; + + +// A single row/column intersection in the list. +class BField { +public: + BField(); + virtual ~BField(); +}; + +// A single line in the list. Each line contains a BField object +// for each column in the list, associated by their "logical field" +// index. Hierarchies are formed by adding other BRow objects as +// a parent of a row, using the AddRow() function in BColumnListView(). +class BRow { +public: + BRow(float height = 16.0); + virtual ~BRow(); + virtual bool HasLatch() const; + + int32 CountFields() const; + BField* GetField(int32 logicalFieldIndex); + const BField* GetField(int32 logicalFieldIndex) const; + void SetField(BField* field, + int32 logicalFieldIndex); + + float Height() const; + bool IsExpanded() const; + +private: + // Blows up into the debugger if the validation fails. + void ValidateFields() const; + void ValidateField(const BField* field, + int32 logicalFieldIndex) const; +private: + BList fFields; + BPrivate:: + BRowContainer* fChildList; + bool fIsExpanded; + float fHeight; + BRow* fNextSelected; + BRow* fPrevSelected; + BRow* fParent; + BColumnListView* fList; + + + friend class BColumnListView; + friend class BPrivate::RecursiveOutlineIterator; + friend class BPrivate::OutlineView; +}; + +// Information about a single column in the list. A column knows +// how to display the BField objects that occur at its location in +// each of the list's rows. See ColumnTypes.h for particular +// subclasses of BField and BColumn that handle common data types. +class BColumn { +public: + BColumn(float width, float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual ~BColumn(); + + float Width() const; + void SetWidth(float width); + float MinWidth() const; + float MaxWidth() const; + + virtual void DrawTitle(BRect rect, BView* targetView); + virtual void DrawField(BField* field, BRect rect, + BView* targetView); + virtual int CompareFields(BField* field1, BField* field2); + + virtual void MouseMoved(BColumnListView* parent, BRow* row, + BField* field, BRect fieldRect, + BPoint point, uint32 buttons, int32 code); + virtual void MouseDown(BColumnListView* parent, BRow* row, + BField* field, BRect fieldRect, + BPoint point, uint32 buttons); + virtual void MouseUp(BColumnListView* parent, BRow* row, + BField* field); + + virtual void GetColumnName(BString* into) const; + virtual float GetPreferredWidth(BField* field, + BView* parent) const; + + bool IsVisible() const; + void SetVisible(bool); + + bool WantsEvents() const; + void SetWantsEvents(bool); + + bool ShowHeading() const; + void SetShowHeading(bool); + + alignment Alignment() const; + void SetAlignment(alignment); + + int32 LogicalFieldNum() const; + + /*! + \param field The BField derivative to validate. + + Implement this function on your BColumn derivatives to validate + BField derivatives that your BColumn will be drawing/manipulating. + + This function will be called when BFields are added to the Column, + use dynamic_cast<> to determine if it is of a kind that your + BColumn know how ot handle. return false if it is not. + + \note The debugger will be called if you return false from here + with information about what type of BField and BColumn and the + logical field index where it occured. + + \note Do not call the inherited version of this, it just returns + true; + */ + virtual bool AcceptsField(const BField* field) const; + +private: + float fWidth; + float fMinWidth; + float fMaxWidth; + bool fVisible; + int32 fFieldID; + BColumnListView* fList; + bool fSortAscending; + bool fWantsEvents; + bool fShowHeading; + alignment fAlignment; + + friend class BPrivate::OutlineView; + friend class BColumnListView; + friend class BPrivate::TitleView; +}; + +// The column list view class. +class BColumnListView : public BView, public BInvoker { +public: + BColumnListView(BRect rect, + const char* name, uint32 resizingMode, + uint32 flags, border_style = B_NO_BORDER, + bool showHorizontalScrollbar = true); + BColumnListView(const char* name, + uint32 flags, border_style = B_NO_BORDER, + bool showHorizontalScrollbar = true); + virtual ~BColumnListView(); + + // Interaction + virtual bool InitiateDrag(BPoint, bool wasSelected); + virtual void MessageDropped(BMessage*, BPoint point); + virtual void ExpandOrCollapse(BRow* row, bool expand); + virtual status_t Invoke(BMessage* message = NULL); + virtual void ItemInvoked(); + virtual void SetInvocationMessage(BMessage* message); + BMessage* InvocationMessage() const; + uint32 InvocationCommand() const; + BRow* FocusRow() const; + void SetFocusRow(int32 index, bool select = false); + void SetFocusRow(BRow* row, bool select = false); + void SetMouseTrackingEnabled(bool); + + // Selection + list_view_type SelectionMode() const; + void Deselect(BRow* row); + void AddToSelection(BRow* row); + void DeselectAll(); + BRow* CurrentSelection(BRow* lastSelected = 0) const; + virtual void SelectionChanged(); + virtual void SetSelectionMessage(BMessage* message); + BMessage* SelectionMessage(); + uint32 SelectionCommand() const; + void SetSelectionMode(list_view_type type); + // list_view_type is defined in ListView.h. + + // Sorting + void SetSortingEnabled(bool); + bool SortingEnabled() const; + void SetSortColumn(BColumn* column, bool add, + bool ascending); + void ClearSortColumns(); + + // The status view is a little area in the lower left hand corner. + void AddStatusView(BView* view); + BView* RemoveStatusView(); + + // Column Manipulation + void AddColumn(BColumn* column, + int32 logicalFieldIndex); + void MoveColumn(BColumn* column, int32 index); + void RemoveColumn(BColumn* column); + int32 CountColumns() const; + BColumn* ColumnAt(int32 index) const; + BColumn* ColumnAt(BPoint point) const; + void SetColumnVisible(BColumn* column, + bool isVisible); + void SetColumnVisible(int32, bool); + bool IsColumnVisible(int32) const; + void SetColumnFlags(column_flags flags); + void ResizeColumnToPreferred(int32 index); + void ResizeAllColumnsToPreferred(); + + // Row manipulation + const BRow* RowAt(int32 index, BRow *parent = 0) const; + BRow* RowAt(int32 index, BRow *parent = 0); + const BRow* RowAt(BPoint) const; + BRow* RowAt(BPoint); + bool GetRowRect(const BRow* row, BRect* _rect) const; + bool FindParent(BRow* row, BRow** _parent, + bool *_isVisible) const; + int32 IndexOf(BRow* row); + int32 CountRows(BRow* parent = 0) const; + void AddRow(BRow* row, BRow* parent = NULL); + void AddRow(BRow* row, int32 index, + BRow* parent = NULL); + + void ScrollTo(const BRow* Row); + void ScrollTo(BPoint point); + + // Does not delete row or children at this time. + // todo: Make delete row and children + void RemoveRow(BRow* row); + + void UpdateRow(BRow* row); + void Clear(); + + // Appearance (DEPRECATED) + void GetFont(BFont* font) const + { BView::GetFont(font); } + virtual void SetFont(const BFont* font, + uint32 mask = B_FONT_ALL); + virtual void SetHighColor(rgb_color); + void SetSelectionColor(rgb_color); + void SetBackgroundColor(rgb_color); + void SetEditColor(rgb_color); + const rgb_color SelectionColor() const; + const rgb_color BackgroundColor() const; + const rgb_color EditColor() const; + + // Appearance (NEW STYLE) + void SetColor(ColumnListViewColor colorIndex, + rgb_color color); + void SetFont(ColumnListViewFont fontIndex, + const BFont* font, + uint32 mask = B_FONT_ALL); + rgb_color Color(ColumnListViewColor colorIndex) const; + void GetFont(ColumnListViewFont fontIndex, + BFont* font) const; + + BPoint SuggestTextPosition(const BRow* row, + const BColumn* column = NULL) const; + + void SetLatchWidth(float width); + float LatchWidth() const; + virtual void DrawLatch(BView* view, BRect frame, + LatchType type, BRow* row); + virtual void MakeFocus(bool isfocus = true); + void SaveState(BMessage* archive); + void LoadState(BMessage* archive); + + BView* ScrollView() const + { return (BView*)fOutlineView; } + void SetEditMode(bool state); + void Refresh(); + + virtual BSize MinSize(); + virtual BSize PreferredSize(); + virtual BSize MaxSize(); + + virtual void InvalidateLayout(bool descendants = false); + +protected: + virtual void MessageReceived(BMessage* message); + virtual void KeyDown(const char* bytes, int32 numBytes); + virtual void AttachedToWindow(); + virtual void WindowActivated(bool active); + virtual void Draw(BRect updateRect); + + virtual void DoLayout(); + +private: + void _Init(bool showHorizontalScrollbar); + void _GetChildViewRects(const BRect& bounds, + bool showHorizontalScrollBar, + BRect& titleRect, BRect& outlineRect, + BRect& vScrollBarRect, + BRect& hScrollBarRect); + + rgb_color fColorList[B_COLOR_TOTAL]; + BPrivate::TitleView* fTitleView; + BPrivate::OutlineView* fOutlineView; + BList fColumns; + BScrollBar* fHorizontalScrollBar; + BScrollBar* fVerticalScrollBar; + BList fSortColumns; + BView* fStatusView; + BMessage* fSelectionMessage; + bool fSortingEnabled; + float fLatchWidth; + border_style fBorderStyle; +}; + +#endif // _COLUMN_LIST_VIEW_H diff --git a/src/column/ColumnTypes.cpp b/src/column/ColumnTypes.cpp new file mode 100644 index 0000000..f5efb23 --- /dev/null +++ b/src/column/ColumnTypes.cpp @@ -0,0 +1,704 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/******************************************************************************* +/ +/ File: ColumnTypes.h +/ +/ Description: Experimental classes that implement particular column/field +/ data types for use in BColumnListView. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#include "ColumnTypes.h" +#include +#include +#include + +#define kTEXT_MARGIN 8 + + +//===================================================================== + +BTitledColumn::BTitledColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BColumn(width, minWidth, maxWidth, align), + fTitle(title) +{ + font_height fh; + + be_plain_font->GetHeight(&fh); + fFontHeight = fh.descent + fh.leading; +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::DrawTitle(BRect rect, BView* parent) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + BString out_string(fTitle); + + parent->TruncateString(&out_string, B_TRUNCATE_END, width + 2); + DrawString(out_string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::GetColumnName(BString* into) const +{ + *into = fTitle; +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::DrawString(const char* string, BView* parent, BRect rect) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + float y; + BFont font; + font_height finfo; + + parent->GetFont(&font); + font.GetHeight(&finfo); + y = rect.top + ((rect.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2) + + (finfo.ascent + finfo.descent) - 2; + + switch (Alignment()) + { + case B_ALIGN_LEFT: + parent->MovePenTo(rect.left + kTEXT_MARGIN, y); + break; + + case B_ALIGN_CENTER: + parent->MovePenTo(rect.left + kTEXT_MARGIN + ((width - font.StringWidth(string)) / 2), y); + break; + + case B_ALIGN_RIGHT: + parent->MovePenTo(rect.right - kTEXT_MARGIN - font.StringWidth(string), y); + break; + } + parent->DrawString(string); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::SetTitle(const char* title) +{ + fTitle.SetTo(title); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::Title(BString* forTitle) const +{ + if (forTitle) + forTitle->SetTo(fTitle.String()); +} + + +//-------------------------------------------------------------------- + +float BTitledColumn::FontHeight() const +{ + return fFontHeight; +} + +// #pragma mark - + +//===================================================================== + +BStringField::BStringField(const char* string) + :fWidth(0), + fString(string), + fClippedString(string) +{ +} + + +//-------------------------------------------------------------------- + +void BStringField::SetString(const char* val) +{ + fString = val; + fClippedString = ""; + fWidth = 0; +} + + +//-------------------------------------------------------------------- + +const char* BStringField::String() const +{ + return fString.String(); +} + + +//-------------------------------------------------------------------- + +void BStringField::SetWidth(float width) +{ + fWidth = width; +} + +//-------------------------------------------------------------------- + +float BStringField::Width() +{ + return fWidth; +} + + +//-------------------------------------------------------------------- + +void BStringField::SetClippedString(const char* val) +{ + fClippedString = val; +} + + +//-------------------------------------------------------------------- + +const char* BStringField::ClippedString() +{ + return fClippedString.String(); +} + + + +// #pragma mark - + +//===================================================================== + +BStringColumn::BStringColumn(const char* title, float width, float minWidth, + float maxWidth, uint32 truncate, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align), + fTruncate(truncate) +{ +} + + +//-------------------------------------------------------------------- + +void BStringColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + BStringField* field = static_cast(_field); + + if (width != field->Width()) + { + BString out_string(field->String()); + + parent->TruncateString(&out_string, fTruncate, width + 2); + field->SetClippedString(out_string.String()); + field->SetWidth(width); + } + DrawString(field->ClippedString(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BStringColumn::CompareFields(BField* field1, BField* field2) +{ + return(ICompare(((BStringField*)field1)->String(), + (((BStringField*)field2)->String()))); +} + + +//-------------------------------------------------------------------- + +bool BStringColumn::AcceptsField(const BField *field) const +{ + return static_cast(dynamic_cast(field)); +} + + +// #pragma mark - + +//===================================================================== + +BDateField::BDateField(time_t *t) + :fTime(*localtime(t)), + fUnixTime(*t), + fSeconds(0), + fClippedString(""), + fWidth(0) +{ + fSeconds = mktime(&fTime); +} + + +//-------------------------------------------------------------------- + +void BDateField::SetWidth(float width) +{ + fWidth = width; +} + + +//-------------------------------------------------------------------- + +float BDateField::Width() +{ + return fWidth; +} + + +//-------------------------------------------------------------------- + +void BDateField::SetClippedString(const char* val) +{ + fClippedString = val; +} + + +//-------------------------------------------------------------------- + +const char* BDateField::ClippedString() +{ + return fClippedString.String(); +} + + +//-------------------------------------------------------------------- + +time_t BDateField::Seconds() +{ + return fSeconds; +} + + +//-------------------------------------------------------------------- + +time_t BDateField::UnixTime() +{ + return fUnixTime; +} + +// #pragma mark - + +//===================================================================== + +BDateColumn::BDateColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align), + fTitle(title) +{ +} + + +//-------------------------------------------------------------------- + +const char *kTIME_FORMATS[] = { + "%A, %B %d %Y, %I:%M:%S %p", // Monday, July 09 1997, 05:08:15 PM + "%a, %b %d %Y, %I:%M:%S %p", // Mon, Jul 09 1997, 05:08:15 PM + "%a, %b %d %Y, %I:%M %p", // Mon, Jul 09 1997, 05:08 PM + "%b %d %Y, %I:%M %p", // Jul 09 1997, 05:08 PM + "%m/%d/%y, %I:%M %p", // 07/09/97, 05:08 PM + "%m/%d/%y", // 07/09/97 + NULL +}; + +void BDateColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + BDateField* field = (BDateField*)_field; + + if (field->Width() != rect.Width()) + { + char dateString[256]; + time_t curtime = field->UnixTime(); + tm time_data; + BFont font; + + parent->GetFont(&font); + localtime_r(&curtime, &time_data); + for (int32 index = 0; ; index++) + { + if (!kTIME_FORMATS[index]) + break; + strftime(dateString, 256, kTIME_FORMATS[index], &time_data); + if (font.StringWidth(dateString) <= width) + break; + } + + if (font.StringWidth(dateString) > width) + { + BString out_string(dateString); + + parent->TruncateString(&out_string, B_TRUNCATE_MIDDLE, width + 2); + strcpy(dateString, out_string.String()); + } + field->SetClippedString(dateString); + field->SetWidth(width); + } + + DrawString(field->ClippedString(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BDateColumn::CompareFields(BField* field1, BField* field2) +{ + return((BDateField*)field1)->Seconds() - ((BDateField*)field2)->Seconds(); +} + +// #pragma mark - + +//===================================================================== + +BSizeField::BSizeField(off_t size) + :fSize(size) +{ +} + + +//-------------------------------------------------------------------- + +void BSizeField::SetSize(off_t size) +{ + fSize = size; +} + + +//-------------------------------------------------------------------- + +off_t BSizeField::Size() +{ + return fSize; +} + +// #pragma mark - + +//===================================================================== + +BSizeColumn::BSizeColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +const int64 kKB_SIZE = 1024; +const int64 kMB_SIZE = 1048576; +const int64 kGB_SIZE = 1073741824; +const int64 kTB_SIZE = kGB_SIZE * kKB_SIZE; + +const char *kSIZE_FORMATS[] = { + "%.2f %s", + "%.1f %s", + "%.f %s", + "%.f%s", + 0 +}; + +void BSizeColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + char str[256]; + float width = rect.Width() - (2 * kTEXT_MARGIN); + BFont font; + BString string; + off_t size = ((BSizeField*)_field)->Size(); + + parent->GetFont(&font); + if (size < kKB_SIZE) + { + sprintf(str, "%Ld bytes", size); + if (font.StringWidth(str) > width) + sprintf(str, "%Ld B", size); + } + else + { + const char* suffix; + float float_value; + if (size >= kTB_SIZE) + { + suffix = "TB"; + float_value = (float)size / kTB_SIZE; + } + else if (size >= kGB_SIZE) + { + suffix = "GB"; + float_value = (float)size / kGB_SIZE; + } + else if (size >= kMB_SIZE) + { + suffix = "MB"; + float_value = (float)size / kMB_SIZE; + } + else + { + suffix = "KB"; + float_value = (float)size / kKB_SIZE; + } + + for (int32 index = 0; ; index++) + { + if (!kSIZE_FORMATS[index]) + break; + + sprintf(str, kSIZE_FORMATS[index], float_value, suffix); + // strip off an insignificant zero so we don't get readings + // such as 1.00 + char *period = 0; + char *tmp (NULL); + for (tmp = str; *tmp; tmp++) + { + if (*tmp == '.') + period = tmp; + } + if (period && period[1] && period[2] == '0') + // move the rest of the string over the insignificant zero + for (tmp = &period[2]; *tmp; tmp++) + *tmp = tmp[1]; + if (font.StringWidth(str) <= width) + break; + } + } + + + string = str; + parent->TruncateString(&string, B_TRUNCATE_MIDDLE, width + 2); + DrawString(string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BSizeColumn::CompareFields(BField* field1, BField* field2) +{ + return ((BSizeField*)field1)->Size() - ((BSizeField*)field2)->Size(); +} + +// #pragma mark - + +//===================================================================== + +BIntegerField::BIntegerField(int32 number) + :fInteger(number) +{ +} + + +//-------------------------------------------------------------------- + +void BIntegerField::SetValue(int32 value) +{ + fInteger = value; +} + + +//-------------------------------------------------------------------- + +int32 BIntegerField::Value() +{ + return fInteger; +} + +// #pragma mark - + +//===================================================================== + +BIntegerColumn::BIntegerColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +void BIntegerColumn::DrawField(BField *field, BRect rect, BView* parent) +{ + char formatted[256]; + float width = rect.Width() - (2 * kTEXT_MARGIN); + BString string; + + sprintf(formatted, "%d", (int)((BIntegerField*)field)->Value()); + + string = formatted; + parent->TruncateString(&string, B_TRUNCATE_MIDDLE, width + 2); + DrawString(string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BIntegerColumn::CompareFields(BField *field1, BField *field2) +{ + return (((BIntegerField*)field1)->Value() - ((BIntegerField*)field2)->Value()); +} + +// #pragma mark - + +//===================================================================== + +GraphColumn::GraphColumn(const char* name, float width, float minWidth, + float maxWidth, alignment align) + :BIntegerColumn(name, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +void GraphColumn::DrawField(BField* field, BRect rect, BView* parent) +{ + int number = ((BIntegerField*)field)->Value(); + + if (number > 100) + number = 100; + else if (number < 0) + number = 0; + + BRect graphRect(rect); + graphRect.InsetBy(5, 3); + parent->StrokeRect(graphRect); + if (number > 0) { + graphRect.InsetBy(1, 1); + float val = graphRect.Width() * (float) number / 100; + graphRect.right = graphRect.left + val; + parent->SetHighColor(0, 0, 190); + parent->FillRect(graphRect); + } + + parent->SetDrawingMode(B_OP_INVERT); + parent->SetHighColor(128, 128, 128); + char numstr[256]; + sprintf(numstr, "%d%%", number); + + float width = be_plain_font->StringWidth(numstr); + parent->MovePenTo(rect.left + rect.Width() / 2 - width / 2, rect.bottom - FontHeight()); + parent->DrawString(numstr); +} + +// #pragma mark - + +//===================================================================== + +BBitmapField::BBitmapField(BBitmap *bitmap) + :fBitmap(bitmap) +{ +} + + +//-------------------------------------------------------------------- + +const BBitmap* BBitmapField::Bitmap() +{ + return fBitmap; +} + +//-------------------------------------------------------------------- + +void BBitmapField::SetBitmap(BBitmap* bitmap) +{ + fBitmap = bitmap; +} + +// #pragma mark - + +//===================================================================== + +BBitmapColumn::BBitmapColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +void BBitmapColumn::DrawField(BField* field, BRect rect, BView* parent) +{ + BBitmapField *bitmapField = static_cast(field); + const BBitmap *bitmap = bitmapField->Bitmap(); + + if (bitmap != NULL) + { + float x = 0.0; + float y; + BRect r = bitmap->Bounds(); + + y = rect.top + ((rect.Height() - r.Height()) / 2); + + switch (Alignment()) + { + case B_ALIGN_LEFT: + x = rect.left + kTEXT_MARGIN; + break; + + case B_ALIGN_CENTER: + x = rect.left + ((rect.Width() - r.Width()) / 2); + break; + + case B_ALIGN_RIGHT: + x = rect.right - kTEXT_MARGIN - r.Width(); + break; + } + parent->SetDrawingMode(B_OP_ALPHA); + parent->DrawBitmap(bitmap, BPoint(x, y)); + parent->SetDrawingMode(B_OP_OVER); + } +} + + +//-------------------------------------------------------------------- + +int BBitmapColumn::CompareFields(BField* /*field1*/, BField* /*field2*/) +{ + // Comparing bitmaps doesn't really make sense... + return 0; +} + + +//-------------------------------------------------------------------- + +bool +BBitmapColumn::AcceptsField(const BField *field) const +{ + return static_cast(dynamic_cast(field)); +} + + diff --git a/src/column/ColumnTypes.h b/src/column/ColumnTypes.h new file mode 100644 index 0000000..9598c10 --- /dev/null +++ b/src/column/ColumnTypes.h @@ -0,0 +1,289 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/******************************************************************************* +/ +/ File: ColumnTypes.h +/ +/ Description: Experimental classes that implement particular column/field +/ data types for use in BColumnListView. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLUMN_TYPES_H +#define _COLUMN_TYPES_H + +#include "ColumnListView.h" +#include +#include +#include + + +//===================================================================== +// Common base-class: a column that draws a standard title at its top. + +class BTitledColumn : public BColumn +{ + public: + BTitledColumn (const char *title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawTitle (BRect rect, + BView* parent); + virtual void GetColumnName (BString* into) const; + + void DrawString (const char*, + BView*, + BRect); + void SetTitle (const char* title); + void Title (BString* forTitle) const; // sets the BString arg to be the title + float FontHeight () const; + + private: + float fFontHeight; + BString fTitle; +}; + + +//===================================================================== +// Field and column classes for strings. + +class BStringField : public BField +{ + public: + BStringField (const char* string); + + void SetString (const char* string); + const char* String () const; + void SetClippedString (const char* string); + const char* ClippedString (); + void SetWidth (float); + float Width (); + + private: + float fWidth; + BString fString; + BString fClippedString; +}; + + +//-------------------------------------------------------------------- + +class BStringColumn : public BTitledColumn +{ + public: + BStringColumn (const char *title, + float width, + float maxWidth, + float minWidth, + uint32 truncate, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); + virtual bool AcceptsField (const BField* field) const; + + + private: + uint32 fTruncate; +}; + + +//===================================================================== +// Field and column classes for dates. + +class BDateField : public BField +{ + public: + BDateField (time_t* t); + void SetWidth (float); + float Width (); + void SetClippedString (const char*); + const char* ClippedString (); + time_t Seconds (); + time_t UnixTime (); + + private: + struct tm fTime; + time_t fUnixTime; + time_t fSeconds; + BString fClippedString; + float fWidth; +}; + + +//-------------------------------------------------------------------- + +class BDateColumn : public BTitledColumn +{ + public: + BDateColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); + private: + BString fTitle; +}; + + +//===================================================================== +// Field and column classes for numeric sizes. + +class BSizeField : public BField +{ + public: + BSizeField (off_t size); + void SetSize (off_t); + off_t Size (); + + private: + off_t fSize; +}; + + +//-------------------------------------------------------------------- + +class BSizeColumn : public BTitledColumn +{ + public: + BSizeColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); +}; + + +//===================================================================== +// Field and column classes for integers. + +class BIntegerField : public BField +{ + public: + BIntegerField (int32 number); + void SetValue (int32); + int32 Value (); + + private: + int32 fInteger; +}; + + +//-------------------------------------------------------------------- + +class BIntegerColumn : public BTitledColumn +{ + public: + BIntegerColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); +}; + + +//===================================================================== +// Field and column classes for bitmaps + +class BBitmapField : public BField +{ + public: + BBitmapField (BBitmap* bitmap); + const BBitmap* Bitmap (); + void SetBitmap (BBitmap* bitmap); + + private: + BBitmap* fBitmap; +}; + + +//-------------------------------------------------------------------- + +class BBitmapColumn : public BTitledColumn +{ + public: + BBitmapColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField*field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, BField* field2); + virtual bool AcceptsField (const BField* field) const; +}; + + +//===================================================================== +// Column to display BIntegerField objects as a graph. + +class GraphColumn : public BIntegerColumn +{ + public: + GraphColumn (const char* name, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField*field, + BRect rect, + BView* parent); +}; + +#endif + diff --git a/src/column/ObjectList.h b/src/column/ObjectList.h new file mode 100644 index 0000000..afb93d8 --- /dev/null +++ b/src/column/ObjectList.h @@ -0,0 +1,800 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/**************************************************************************** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +** ** +** DANGER, WILL ROBINSON! ** +** ** +** The interfaces contained here are part of BeOS's ** +** ** +** >> PRIVATE NOT FOR PUBLIC USE << ** +** ** +** implementation. ** +** ** +** These interfaces WILL CHANGE in future releases. ** +** If you use them, your app WILL BREAK at some future time. ** +** ** +** (And yes, this does mean that binaries built from OpenTracker will not ** +** be compatible with some future releases of the OS. When that happens, ** +** we will provide an updated version of this file to keep compatibility.) ** +** ** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +****************************************************************************/ + +// +// ObjectList is a wrapper around BList that adds type safety, +// optional object ownership, search, insert operations, etc. +// + +#ifndef __OBJECT_LIST__ +#define __OBJECT_LIST__ + +#ifndef _BE_H +#include +#endif + +#include + +template class BObjectList; + +template +struct UnaryPredicate { + + virtual int operator()(const T *) const + // virtual could be avoided here if FindBinaryInsertionIndex, + // etc. were member template functions + { return 0; } + +private: + static int _unary_predicate_glue(const void *item, void *context); + +friend class BObjectList; +}; + +template +int +UnaryPredicate::_unary_predicate_glue(const void *item, void *context) +{ + return ((UnaryPredicate *)context)->operator()((const T *)item); +} + + +class _PointerList_ : public BList { +public: + _PointerList_(const _PointerList_ &list); + _PointerList_(int32 itemsPerBlock = 20, bool owning = false); + ~_PointerList_(); + + typedef void *(* GenericEachFunction)(void *, void *); + typedef int (* GenericCompareFunction)(const void *, const void *); + typedef int (* GenericCompareFunctionWithState)(const void *, const void *, + void *); + typedef int (* UnaryPredicateGlue)(const void *, void *); + + void *EachElement(GenericEachFunction, void *); + void SortItems(GenericCompareFunction); + void SortItems(GenericCompareFunctionWithState, void *state); + void HSortItems(GenericCompareFunction); + void HSortItems(GenericCompareFunctionWithState, void *state); + + void *BinarySearch(const void *, GenericCompareFunction) const; + void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; + + int32 BinarySearchIndex(const void *, GenericCompareFunction) const; + int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; + int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; + + bool Owning() const; + bool ReplaceItem(int32, void *); + +protected: + bool owning; + +}; + +template +class BObjectList : private _PointerList_ { +public: + + // iteration and sorting + typedef T *(* EachFunction)(T *, void *); + typedef const T *(* ConstEachFunction)(const T *, void *); + typedef int (* CompareFunction)(const T *, const T *); + typedef int (* CompareFunctionWithState)(const T *, const T *, void *state); + + BObjectList(int32 itemsPerBlock = 20, bool owning = false); + BObjectList(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + virtual ~BObjectList(); + + BObjectList &operator=(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + // adding and removing + // ToDo: + // change Add calls to return const item + bool AddItem(T *); + bool AddItem(T *, int32); + bool AddList(BObjectList *); + bool AddList(BObjectList *, int32); + + bool RemoveItem(T *, bool deleteIfOwning = true); + // if owning, deletes the removed item + T *RemoveItemAt(int32); + // returns the removed item + + void MakeEmpty(); + + // item access + T *ItemAt(int32) const; + + bool ReplaceItem(int32 index, T *); + // if list is owning, deletes the item at first + T *SwapWithItem(int32 index, T *newItem); + // same as ReplaceItem, except does not delete old item at , + // returns it instead + + T *FirstItem() const; + T *LastItem() const; + + // misc. getters + int32 IndexOf(const T *) const; + bool HasItem(const T *) const; + bool IsEmpty() const; + int32 CountItems() const; + + T *EachElement(EachFunction, void *); + const T *EachElement(ConstEachFunction, void *) const; + + void SortItems(CompareFunction); + void SortItems(CompareFunctionWithState, void *state); + void HSortItems(CompareFunction); + void HSortItems(CompareFunctionWithState, void *state); + + // linear search, returns first item that matches predicate + const T *FindIf(const UnaryPredicate &) const; + T *FindIf(const UnaryPredicate &); + + // list must be sorted with CompareFunction for these to work + const T *BinarySearch(const T &, CompareFunction) const; + const T *BinarySearch(const T &, CompareFunctionWithState, void *state) const; + + // Binary insertion - list must be sorted with CompareFunction for + // these to work + + // simple insert + void BinaryInsert(T *, CompareFunction); + void BinaryInsert(T *, CompareFunctionWithState, void *state); + void BinaryInsert(T *, const UnaryPredicate &); + + // unique insert, returns false if item already in list + bool BinaryInsertUnique(T *, CompareFunction); + bool BinaryInsertUnique(T *, CompareFunctionWithState, void *state); + bool BinaryInsertUnique(T *, const UnaryPredicate &); + + // insert a copy of the item, returns new inserted item + T *BinaryInsertCopy(const T ©This, CompareFunction); + T *BinaryInsertCopy(const T ©This, CompareFunctionWithState, void *state); + + // insert a copy of the item if not in list already + // returns new inserted item or existing item in case of a conflict + T *BinaryInsertCopyUnique(const T ©This, CompareFunction); + T *BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState, void *state); + + + int32 FindBinaryInsertionIndex(const UnaryPredicate &, bool *alreadyInList = 0) const; + // returns either the index into which a new item should be inserted + // or index of an existing item that matches the predicate + + // deprecated API, will go away + BList *AsBList() + { return this; } + const BList *AsBList() const + { return this; } +private: + void SetItem(int32, T *); +}; + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) + break; + + return result; +} + +template +void +EachListItemIgnoreResult(BObjectList *list, Result (Item::*func)()) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *, Param1), Param1 p1) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1); +} + +template +void +EachListItem(BObjectList *list, void (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3), Param1 p1, Param2 p2, Param3 p3) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3); +} + + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3, p4); +} + +// inline code + +inline bool +_PointerList_::Owning() const +{ + return owning; +} + +template +BObjectList::BObjectList(int32 itemsPerBlock, bool isOwning) + : _PointerList_(itemsPerBlock, isOwning) +{ +} + +template +BObjectList::BObjectList(const BObjectList &list) + : _PointerList_(list) +{ + owning = list.owning; + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } +} + +template +BObjectList::~BObjectList() +{ + if (Owning()) + // have to nuke elements first + MakeEmpty(); + +} + +template +BObjectList & +BObjectList::operator=(const BObjectList &list) +{ + owning = list.owning; + BObjectList &result = (BObjectList &)_PointerList_::operator=(list); + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } + return result; +} + +template +bool +BObjectList::AddItem(T *item) +{ + // need to cast to void * to make T work for const pointers + return _PointerList_::AddItem((void *)item); +} + +template +bool +BObjectList::AddItem(T *item, int32 atIndex) +{ + return _PointerList_::AddItem((void *)item, atIndex); +} + +template +bool +BObjectList::AddList(BObjectList *newItems) +{ + return _PointerList_::AddList(newItems); +} + +template +bool +BObjectList::AddList(BObjectList *newItems, int32 atIndex) +{ + return _PointerList_::AddList(newItems, atIndex); +} + + +template +bool +BObjectList::RemoveItem(T *item, bool deleteIfOwning) +{ + bool result = _PointerList_::RemoveItem((void *)item); + + if (result && Owning() && deleteIfOwning) + delete item; + + return result; +} + +template +T * +BObjectList::RemoveItemAt(int32 index) +{ + return (T *)_PointerList_::RemoveItem(index); +} + +template +inline T * +BObjectList::ItemAt(int32 index) const +{ + return (T *)_PointerList_::ItemAt(index); +} + +template +bool +BObjectList::ReplaceItem(int32 index, T *item) +{ + if (owning) + delete ItemAt(index); + return _PointerList_::ReplaceItem(index, (void *)item); +} + +template +T * +BObjectList::SwapWithItem(int32 index, T *newItem) +{ + T *result = ItemAt(index); + _PointerList_::ReplaceItem(index, (void *)newItem); + return result; +} + +template +void +BObjectList::SetItem(int32 index, T *newItem) +{ + _PointerList_::ReplaceItem(index, (void *)newItem); +} + +template +int32 +BObjectList::IndexOf(const T *item) const +{ + return _PointerList_::IndexOf((void *)const_cast(item)); +} + +template +T * +BObjectList::FirstItem() const +{ + return (T *)_PointerList_::FirstItem(); +} + +template +T * +BObjectList::LastItem() const +{ + return (T *)_PointerList_::LastItem(); +} + +template +bool +BObjectList::HasItem(const T *item) const +{ + return _PointerList_::HasItem((void *)item); +} + +template +bool +BObjectList::IsEmpty() const +{ + return _PointerList_::IsEmpty(); +} + +template +int32 +BObjectList::CountItems() const +{ + return _PointerList_::CountItems(); +} + +template +void +BObjectList::MakeEmpty() +{ + if (owning) { + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + delete ItemAt(index); + } + _PointerList_::MakeEmpty(); +} + +template +T * +BObjectList::EachElement(EachFunction func, void *params) +{ + return (T *)_PointerList_::EachElement((GenericEachFunction)func, params); +} + + +template +const T * +BObjectList::EachElement(ConstEachFunction func, void *params) const +{ + return (const T *) + const_cast *>(this)->_PointerList_::EachElement( + (GenericEachFunction)func, params); +} + +template +const T * +BObjectList::FindIf(const UnaryPredicate &predicate) const +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + +template +T * +BObjectList::FindIf(const UnaryPredicate &predicate) +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + + +template +void +BObjectList::SortItems(CompareFunction function) +{ + _PointerList_::SortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::SortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); +} + +template +void +BObjectList::HSortItems(CompareFunction function) +{ + _PointerList_::HSortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::HSortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); +} + +template +const T * +BObjectList::BinarySearch(const T &key, CompareFunction func) const +{ + return (const T *)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)func); +} + +template +const T * +BObjectList::BinarySearch(const T &key, CompareFunctionWithState func, void *state) const +{ + return (const T *)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)func, state); +} + +template +void +BObjectList::BinaryInsert(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + // already in list, add after existing + AddItem(item, index + 1); + else + AddItem(item, -index - 1); +} + +template +void +BObjectList::BinaryInsert(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + // already in list, add after existing + AddItem(item, index + 1); + else + AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + return false; + + AddItem(item, -index - 1); + return true; +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return false; + + AddItem(item, -index - 1); + return true; +} + + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState func, + void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +int32 +BObjectList::FindBinaryInsertionIndex(const UnaryPredicate &pred, bool *alreadyInList) + const +{ + int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, + (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); + + if (alreadyInList) + *alreadyInList = index >= 0; + + if (index < 0) + index = -index - 1; + + return index; +} + +template +void +BObjectList::BinaryInsert(T *item, const UnaryPredicate &pred) +{ + int32 index = FindBinaryInsertionIndex(pred); + AddItem(item, index); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, const UnaryPredicate &pred) +{ + bool alreadyInList; + int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); + if (alreadyInList) + return false; + + AddItem(item, index); + return true; +} + + +#endif diff --git a/src/column/YabColumnType.cpp b/src/column/YabColumnType.cpp new file mode 100644 index 0000000..ba6a520 --- /dev/null +++ b/src/column/YabColumnType.cpp @@ -0,0 +1,413 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +#include "YabColumnType.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef ZETA + #include +#endif + +#define kTEXT_MARGIN 8 +#define kIMG_MARGIN 2 + + +//===================================================================== + +BTitledColumn::BTitledColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BColumn(width, minWidth, maxWidth, align), + fTitle(title) +{ + font_height fh; + + be_plain_font->GetHeight(&fh); + fFontHeight = fh.descent + fh.leading; +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::DrawTitle(BRect rect, BView* parent) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + BString out_string(fTitle); + + parent->TruncateString(&out_string, B_TRUNCATE_END, width + 2); + DrawString(out_string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::GetColumnName(BString* into) const +{ + *into = fTitle; +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::DrawString(const char* string, BView* parent, BRect rect) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + float y; + BFont font; + font_height finfo; + + parent->GetFont(&font); + font.GetHeight(&finfo); + y = rect.top + ((rect.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2) + + (finfo.ascent + finfo.descent) - 2; + + switch (Alignment()) + { + case B_ALIGN_LEFT: + parent->MovePenTo(rect.left + kTEXT_MARGIN, y); + break; + + case B_ALIGN_CENTER: + parent->MovePenTo(rect.left + kTEXT_MARGIN + ((width - font.StringWidth(string)) / 2), y); + break; + + case B_ALIGN_RIGHT: + parent->MovePenTo(rect.right - kTEXT_MARGIN - font.StringWidth(string), y); + break; + } + parent->DrawString(string); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::SetTitle(const char* title) +{ + fTitle.SetTo(title); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::Title(BString* forTitle) const +{ + if (forTitle) + forTitle->SetTo(fTitle.String()); +} + + +//-------------------------------------------------------------------- + +float BTitledColumn::FontHeight() const +{ + return fFontHeight; +} + + +//===================================================================== + +BYabField::BYabField(const char* string) + :fWidth(0), fString(string), fClippedString(string) +{ + int n = fString.FindFirst("__Icon__="); + fBitmap = NULL; + if(n==0) + { + BString myPath; + fString.CopyInto(myPath, 9, fString.Length()-9); + BPath AppDirectory; + + // app directory + BString ApplicationDirectory(""); + app_info appinfo; + + if(be_roster->GetRunningAppInfo(be_app->Team(), &appinfo) == B_OK) + { + BEntry ApplicationEntry( &appinfo.ref); + BEntry ApplicationDirectoryEntry; + + if( ApplicationEntry.GetParent( &ApplicationDirectoryEntry) == B_OK) + { + if( AppDirectory.SetTo( &ApplicationDirectoryEntry) == B_OK) + { + // strcpy(ApplicationDirectory, AppDirectory.Path()); + ApplicationDirectory.SetTo(AppDirectory.Path()); + } + } + } + BFile ImageFile; + BPath ImagePath; + + if(myPath[0] == '/') + ImageFile.SetTo( myPath.String(), B_READ_ONLY); + else + // App directory. + if(ApplicationDirectory != "") + { + if( ImagePath.SetTo(ApplicationDirectory.String(), myPath.String()) == B_OK) + ImageFile.SetTo( ImagePath.Path(), B_READ_ONLY); + } + + if( ImageFile.InitCheck() != B_OK) + ImageFile.SetTo( myPath.String(), B_READ_ONLY); + + if( ImageFile.InitCheck() == B_OK) + { + BTranslatorRoster *Roster = BTranslatorRoster::Default(); + if( Roster) + { + BBitmapStream Stream; + if( Roster->Translate( &ImageFile, NULL, NULL, &Stream, B_TRANSLATOR_BITMAP) == B_OK) + Stream.DetachBitmap( &fBitmap); + delete Roster; + } + } + } +} + + +void BYabField::SetString(const char* val, int height) +{ + fString = val; + fClippedString = ""; + fWidth = 0; + + fBitmap = NULL; + if( ! fString.FindFirst("__Icon__=") ) + { + BString myPath; + fString.CopyInto(myPath, 9, fString.Length()-9); + BPath AppDirectory; + + // app directory + BString ApplicationDirectory(""); + app_info appinfo; + + if(be_roster->GetRunningAppInfo(be_app->Team(), &appinfo) == B_OK) + { + BEntry ApplicationEntry( &appinfo.ref); + BEntry ApplicationDirectoryEntry; + + if( ApplicationEntry.GetParent( &ApplicationDirectoryEntry) == B_OK) + { + if( AppDirectory.SetTo( &ApplicationDirectoryEntry) == B_OK) + { + // strcpy(ApplicationDirectory, AppDirectory.Path()); + ApplicationDirectory.SetTo(AppDirectory.Path()); + } + } + } + BFile ImageFile; + BPath ImagePath; + + if(myPath[0] == '/') + ImageFile.SetTo( myPath.String(), B_READ_ONLY); + else + // App directory. + if(ApplicationDirectory != "") + { + if( ImagePath.SetTo(ApplicationDirectory.String(), myPath.String()) == B_OK) + ImageFile.SetTo( ImagePath.Path(), B_READ_ONLY); + } + + if( ImageFile.InitCheck() != B_OK) + ImageFile.SetTo( myPath.String(), B_READ_ONLY); + + if( ImageFile.InitCheck() == B_OK) + { + BTranslatorRoster *Roster = BTranslatorRoster::Default(); + if( Roster) + { + BBitmapStream Stream; + if( Roster->Translate( &ImageFile, NULL, NULL, &Stream, B_TRANSLATOR_BITMAP) == B_OK) + Stream.DetachBitmap( &fBitmap); + delete Roster; + } + } + } + else if( ! fString.FindFirst("__Mime__=") ) + { + BString myPath; + fString.CopyInto(myPath, 9, fString.Length()-9); + fBitmap = new BBitmap(BRect(0, 0, 15,15), B_CMAP8); + BMimeType mime(myPath.String()); + mime.GetIcon(fBitmap, B_MINI_ICON); + } + else if( ! fString.FindFirst("__Path__=") ) + { + BString myPath; + fString.CopyInto(myPath, 9, fString.Length()-9); +#ifdef ZETA + fBitmap = new BBitmap(BRect(0, 0, 15, 15), B_RGBA32); + BEntry fEntry = BEntry( myPath.String() ); + BBitmap icon = &GetTrackerIcon(fEntry, 16); + *fBitmap = icon; +#else + fBitmap = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32); + BNode *fNode = new BNode(myPath.String()); + BNodeInfo fInfo(fNode); + fInfo.GetTrackerIcon(fBitmap, B_LARGE_ICON); + delete fNode; +#endif + } +} + + +const char* BYabField::String() const +{ + return fString.String(); +} + + +void BYabField::SetWidth(float width) +{ + fWidth = width; +} + +float BYabField::Width() +{ + return fWidth; +} + + +void BYabField::SetClippedString(const char* val) +{ + fClippedString = val; +} + + +const char* BYabField::ClippedString() +{ + return fClippedString.String(); +} + +const BBitmap* BYabField::Bitmap() +{ + return fBitmap; +} + +void BYabField::SetBitmap(BBitmap* bitmap) +{ + fBitmap = bitmap; +} + +bool BYabField::HasBitmap() +{ + if(fBitmap) return true; + return false; +} + + +//===================================================================== + +BYabColumn::BYabColumn(const char* title, float width, float minWidth, + float maxWidth, uint32 truncate, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align), + fTruncate(truncate) +{ +} + + +void BYabColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + if(!((BYabField*)_field)->HasBitmap()) + { + float width = rect.Width() - (2 * kTEXT_MARGIN); + BYabField* field = static_cast(_field); + + if (width != field->Width()) + { + BString out_string(field->String()); + + parent->TruncateString(&out_string, fTruncate, width + 2); + field->SetClippedString(out_string.String()); + field->SetWidth(width); + } + DrawString(field->ClippedString(), parent, rect); + } + else + { + BYabField *bitmapField = static_cast(_field); + const BBitmap *bitmap = bitmapField->Bitmap(); + + if (bitmap != NULL) + { + float x = 0.0; + float y; + BRect r = bitmap->Bounds(); + + y = rect.top + ((rect.Height() - r.Height()) / 2); + + switch (Alignment()) + { + case B_ALIGN_LEFT: + x = rect.left + kIMG_MARGIN; + break; + + case B_ALIGN_CENTER: + x = rect.left + ((rect.Width() - r.Width()) / 2); + break; + + case B_ALIGN_RIGHT: + x = rect.right - kIMG_MARGIN - r.Width(); + break; + } + parent->SetDrawingMode(B_OP_ALPHA); + parent->DrawBitmap(bitmap, BPoint(x, y)); + parent->SetDrawingMode(B_OP_OVER); + } + } +} + + +int BYabColumn::CompareFields(BField* field1, BField* field2) +{ + return(ICompare(((BYabField*)field1)->String(), + (((BYabField*)field2)->String()))); +} + + +bool +BYabColumn::AcceptsField(const BField *field) const +{ + return static_cast(dynamic_cast(field)); +} + diff --git a/src/column/YabColumnType.h b/src/column/YabColumnType.h new file mode 100644 index 0000000..e69e4d2 --- /dev/null +++ b/src/column/YabColumnType.h @@ -0,0 +1,107 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +#ifndef YAB_COLUMN_TYPES_H +#define YAB_COLUMN_TYPES_H + +#include "../global.h" +#include +#include +#include +#include "ColumnListView.h" + +//===================================================================== +// Common base-class: a column that draws a standard title at its top. + +class BTitledColumn : public BColumn +{ + public: + BTitledColumn (const char *title, float width, float minWidth, float maxWidth, alignment align = B_ALIGN_LEFT); + + virtual void DrawTitle(BRect rect, BView* parent); + virtual void GetColumnName(BString* into) const; + void DrawString(const char*, BView*, BRect); + void SetTitle(const char* title); + void Title(BString* forTitle) const; // sets the BString arg to be the title + float FontHeight() const; + private: + float fFontHeight; + BString fTitle; +}; + + +//===================================================================== +// Field and column classes for strings. + +class BYabField : public BField +{ + public: + BYabField (const char* string); + BYabField (BBitmap* bitmap); + + void SetString(const char* string, int height); + const char* String() const; + void SetClippedString(const char* string); + const char*ClippedString(); + void SetWidth(float); + float Width(); + + const BBitmap* Bitmap(); + void SetBitmap(BBitmap* bitmap); + bool HasBitmap(); + + private: + BBitmap* fBitmap; + float fWidth; + BString fString; + BString fClippedString; +}; + + +//-------------------------------------------------------------------- + +class BYabColumn: public BTitledColumn +{ + public: + BYabColumn(const char *title, float width, float maxWidth, float minWidth, uint32 truncate, alignment align = B_ALIGN_LEFT); + + virtual void DrawField(BField* field, BRect rect, BView* parent); + virtual int CompareFields(BField* field1, BField* field2); + virtual bool AcceptsField(const BField* field) const; + + private: + uint32 fTruncate; +}; + +#endif diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..d135413 --- /dev/null +++ b/src/config.h @@ -0,0 +1,216 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define BEOS +// #define LIBBSVG +#define BUILD_TIME __DATE__ +/* Version number of package */ +#define VERSION "1.7.4.3" +/* architecture of build machine */ +#define UNIX_ARCHITECTURE "BePC-Haiku" + +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* defined, if ncurses.h is present */ +#define HAVE_CURSES_HEADER 1 + +/* Define to 1 if you have the `difftime' function. */ +#define HAVE_DIFFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FLOAT_H 1 + +/* Define to 1 if you have the `floor' function. */ +#define HAVE_FLOOR 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `ncurses' library (-lncurses). */ +#define HAVE_LIBNCURSES 0 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MATH_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* defined, if ncurses.h is present */ +#define HAVE_NCURSES_HEADER 0 + +/* Define to 1 if you have the `pow' function. */ +#define HAVE_POW 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the `sqrt' function. */ +#define HAVE_SQRT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* defined, if strings.h is present */ +#define HAVE_STRINGS_HEADER 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* defined, if string.h is present */ +#define HAVE_STRING_HEADER 1 + +/* Define to 1 if you have the `strpbrk' function. */ +#define HAVE_STRPBRK 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the `tmpnam' function. */ +#define HAVE_TMPNAM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfork' function. */ +/* #undef HAVE_VFORK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_VFORK_H */ + +/* Define to 1 if `fork' works. */ +#define HAVE_WORKING_FORK 1 + +/* Define to 1 if `vfork' works. */ +/* #undef HAVE_WORKING_VFORK */ + +/* Name of package */ +#define PACKAGE "yabasic" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + + + +/* Define to 1 if the X Window System is missing or not being used. */ +#define X_DISPLAY_MISSING 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* Define as `fork' if `vfork' does not work. */ +#define vfork fork + +#endif diff --git a/src/fixattributes.sh b/src/fixattributes.sh new file mode 100755 index 0000000..400edbb --- /dev/null +++ b/src/fixattributes.sh @@ -0,0 +1,3 @@ +#!sh +yab RdefApply YAB.rdef yab +addattr -t mime BEOS:TYPE application/x-vnd.be-elfexecutable yab \ No newline at end of file diff --git a/src/function.c b/src/function.c new file mode 100644 index 0000000..2a5c62d --- /dev/null +++ b/src/function.c @@ -0,0 +1,2053 @@ +/* + + YABASIC --- a simple Basic Interpreter + written by Marc-Oliver Ihm 1995-2004 + homepage: www.yabasic.de + + function.c --- code for functions + + This file is part of yabasic and may be copied only + under the terms of either the Artistic License or + the GNU General Public License (GPL), both of which + can be found at www.yabasic.de + +*/ + + +/* ------------- includes ---------------- */ +#include "YabInterface.h" +#ifndef YABASIC_INCLUDED +#include "yabasic.h" /* all prototypes and structures */ +#endif + + +/* ------------- external references ---------------- */ + +extern int mylineno; /* current line number */ +extern int yyparse(); /* call bison parser */ + + +/* ------------- local functions ---------------- */ + +static char *fromto(char *,int,int); /* get portion of string (mid$ et al) */ +static void clear_buff(); /* clear system-input buffers */ +static void store_buff(char *,int); /* store system-input buffer */ +static int do_glob(char *,char *); /* actually do the globbing */ +static double other2dec(char *,int); /* convert hex to decimal */ +static char *dec2other(double,int); /* convert decimal to hex */ +static double peek(char *, YabInterface *); /* peek into internals */ +static char *peek2(char *,struct command *); /* peek into internals */ +static char *peek3(char *,char *); /* peek into internals */ +static int peekfile(int); /* read a byte from stream */ +static char *do_system(char *); /* executes command via command.com */ +static int do_system2(char *); /* execute command as system */ + + +/* ------------- global variables ---------------- */ + +struct command *lastdata=NULL; /* used to associate all data-commands with each others */ +static struct buff_chain *buffroot; /* start of sys-input buffer */ +static struct buff_chain **buffcurr; /* current entry in buff_chain */ +static int buffcount; /* number of filled buffers */ + + +/* ------------- subroutines ---------------- */ + + +void token(struct command *cmd) /* extract token from variable */ +{ + int split; + struct stackentry *s; + struct symbol *sym; + struct array *ar; + int num=0,i; + char *p,*q; + char **pp; + char *del,*line; + int wasdel,isdel; + + + if (cmd->type==cSPLIT2 || cmd->type==cTOKEN2) + del=pop(stSTRING)->pointer; + else + del=" \t"; + split=(cmd->type==cSPLIT || cmd->type==cSPLIT2); + s=pop(stSTRINGARRAYREF); + line=pop(stSTRING)->pointer; + sym=get_sym(s->pointer,syARRAY,amSEARCH); + if (!sym || !sym->pointer) { + sprintf(string,"array '%s()' is not defined",strip(s->pointer)); + error(ERROR,string); + goto token_done; + } + ar=sym->pointer; + if (ar->dimension>1) { + error(ERROR,"only one dimensional arrays allowed"); + goto token_done; + } + + /* count number of tokens */ + isdel=TRUE; + if (split && *line) num=1; + else num=0; + for(p=line;*p;++p) { + wasdel=isdel; + isdel=(strchr(del,*p)!=NULL); + if (split) { + if (isdel) num++; + } else { + if (isdel && isdel!=wasdel) num++; + } + } + if (!split && !isdel) num++; + + /* free previous array content */ + for(i=0;ibounds[0];i++) free(((char **)ar->pointer)[i]); + free(ar->pointer); + ar->pointer=my_malloc((num+1)*sizeof(char *)); + pp=ar->pointer; + pp[0]=my_strdup(""); + + /* extract tokens */ + i=1; + isdel=TRUE; + if (*line) { + for(p=q=line;;p++) { + wasdel=isdel; + isdel=(strchr(del,*p)!=NULL) || !*p; + if ((split && isdel) || (!split && (isdel && isdel!=wasdel))) { + while(strchr(del,*q) && qbounds[0]=num+1; + token_done: + s=push(); + s->type=stNUMBER; + s->value=num; +} + + +void tokenalt(struct command *cmd) /* extract token from variable with alternate semantics */ +{ + char *del; /* delimiter for strings */ + struct stackentry *t; + char *old,*new,*tok; + int split; + + if (cmd->type==cSPLITALT2 || cmd->type==cTOKENALT2) + del=pop(stSTRING)->pointer; + else + del=" \t"; + split=(cmd->type==cSPLITALT || cmd->type==cSPLITALT2); + + t=pop(stSTRING); + old=t->pointer; + t->pointer=NULL; /* prevent push from freeing the memory */ + t=push(); + t->type=stSTRING; + new=old; + tok=NULL; + while(*new) { + if (!tok && (!strchr(del,*new) || split)) tok=new; /* found start of token */ + if (tok && strchr(del,*new)) break; /* found end of token */ + new++; + } + if (*new) { + *new='\0'; /* terminate token */ + new++; + if (!split) { + while(*new) { + if (!strchr(del,*new)) break; /* found start of next token */ + new++; + } + } + } + t->pointer=my_strdup(tok?tok:""); /* copy token */ + /* move rest of string */ + while(*new) { + *old=*new; + old++; + new++; + }; + *old='\0'; +} + + +void glob(void) /* check, if pattern globs string */ +{ + char *str,*pat; + struct stackentry *stack; + int res; + + pat=(char *)pop(stSTRING)->pointer; + str=(char *)pop(stSTRING)->pointer; + + res=do_glob(str,pat); + stack=push(); + stack->value=res; + stack->type=stNUMBER; +} + + +static int do_glob(char *str,char *pat) /* actually do the globbing */ +{ + int res; + + if (infolevel>=DEBUG) { + sprintf(string,"globbing '%s' on '%s'",str,pat); + error(DEBUG,string); + } + if (*pat=='\0' && *str=='\0') return TRUE; + else if (*pat=='\0') return FALSE; + else if (*pat=='?' && *str=='\0') return FALSE; + else if (*pat=='?') { + if (*str=='\0') return FALSE; + pat++; + str++; + } + else if (*pat=='*') { + pat++; + res=FALSE; + while(*str && !(res=do_glob(str,pat))) str++; + if (res) return TRUE; + } + else if (*str=='\0') return FALSE; + else { + while(*pat && *pat!='?' && *pat!='*') { + if (*pat!=*str) return FALSE; + str++; + pat++; + } + } + return do_glob(str,pat); +} + + +void concat() /* concatenates two strings from stack */ +{ + struct stackentry *c; + char *aa,*bb,*cc; + + aa=pop(stSTRING)->pointer; + bb=pop(stSTRING)->pointer; + cc=(char *) my_malloc(sizeof(char)*(strlen(aa)+strlen(bb)+1)); + strcpy(cc,bb); + strcat(cc,aa); + c=push(); + c->type=stSTRING; + c->pointer=cc; +} + + +void create_changestring(int type) /* create command 'changestring' */ +{ + struct command *cmd; + + cmd=add_command(cCHANGESTRING,FALSE); + cmd->args=type; +} + + +void changestring(struct command *current) /* changes a string */ +{ + int type,a2,a3; + char *newpart; + char *oldstring; + int i,len; + struct stackentry *a1; + + type=current->args; + newpart=pop(stSTRING)->pointer; + if (type>fTWOARGS) a3=(int)pop(stNUMBER)->value; + if (type>fONEARGS) a2=(int)pop(stNUMBER)->value; + a1=pop(stSTRING); + oldstring=a1->pointer; + a1->pointer=NULL; /* this prevents push from freeing the memory */ + + if (!oldstring || !*oldstring) return; + switch(type) { + case fMID: + for(i=1;i=a2) { + if (!newpart[i-a2]) break; + oldstring[i-1]=newpart[i-a2]; + } + } + break; + case fMID2: + len=strlen(oldstring); + for(i=1;i<=len;i++) { + if (!oldstring[i-1]) break; + if (i>=a2) { + if (!newpart[i-a2]) break; + oldstring[i-1]=newpart[i-a2]; + } + } + break; + case fLEFT: + for(i=1;i<=a2;i++) { + if (!oldstring[i-1] || !newpart[i-1]) break; + oldstring[i-1]=newpart[i-1]; + } + break; + case fRIGHT: + len=strlen(oldstring); + for(i=1;i<=len;i++) { + if (i>len-a2) { + if (!newpart[i-1-len+a2]) break; + oldstring[i-1]=newpart[i-1-len+a2]; + } + } + break; + } +} + + +void create_function(int type) /* create command 'function' */ +/* type can be sin,cos,mid$ ... */ +{ + struct command *cmd; + + cmd=add_command(cFUNCTION,FALSE); + cmd->args=type; +} + + +void function(struct command *current,YabInterface* yab) /* performs a function */ +{ + struct stackentry *stack,*a1,*a2,*a3,*a4,*a5,*a6; + char *pointer; + double value; + time_t datetime; + int type,result,len,start,i,max, linenum; + char *str,*str2, *str3, *str4, *str5; + + a3=NULL; + a4=NULL; + a5=NULL; + a6=NULL; + type=current->args; + if (type>fFIVEARGS) a6=pop(stSTRING_OR_NUMBER); + if (type>fFOURARGS) a5=pop(stSTRING_OR_NUMBER); + if (type>fTHREEARGS) a4=pop(stSTRING_OR_NUMBER); + if (type>fTWOARGS) a3=pop(stSTRING_OR_NUMBER); + if (type>fONEARGS) a2=pop(stSTRING_OR_NUMBER); + if (type>fZEROARGS) a1=pop(stSTRING_OR_NUMBER); + linenum = current->line; + + switch (type) { + case fSIN: + value=sin(a1->value); + result=stNUMBER; + break; + case fASIN: + value=asin(a1->value); + result=stNUMBER; + break; + case fCOS: + value=cos(a1->value); + result=stNUMBER; + break; + case fACOS: + value=acos(a1->value); + result=stNUMBER; + break; + case fTAN: + value=tan(a1->value); + result=stNUMBER; + break; + case fATAN: + value=atan(a1->value); + result=stNUMBER; + break; + case fEXP: + value=exp(a1->value); + result=stNUMBER; + break; + case fLOG: + value=log(a1->value); + result=stNUMBER; + break; + case fLOG2: + value=log(a1->value)/log(a2->value); + result=stNUMBER; + break; + case fLEN: + value=(double) strlen(a1->pointer); + result=stNUMBER; + break; + case fSTR: + sprintf(string,"%g",a1->value); + pointer=my_strdup(string); + result=stSTRING; + break; + case fSTR2: + case fSTR3: + result=stSTRING; + if (!myformat(string,a1->value,a2->pointer,a3?a3->pointer:NULL)) { + pointer=my_strdup(""); + sprintf(string,"'%s' is not a valid format",(char *)a2->pointer); + error(ERROR,string); + break; + } + pointer=my_strdup(string); + break; + case fSQRT: + value=sqrt(a1->value); + result=stNUMBER; + break; + case fSQR: + value=a1->value*a1->value; + result=stNUMBER; + break; + case fINT: + if (a1->value<0) + value=-floor(-a1->value); + else + value=floor(a1->value); + result=stNUMBER; + break; + case fFRAC: + if (a1->value<0) + value=a1->value+floor(-a1->value); + else + value=a1->value-floor(a1->value); + result=stNUMBER; + break; + case fABS: + value=fabs(a1->value); + result=stNUMBER; + break; + case fSIG: + if (a1->value<0) value=-1.; + else if (a1->value>0) value=1.; + else value=0.; + result=stNUMBER; + break; + case fMOD: + value=a1->value-a2->value*(int)(a1->value/a2->value); + result=stNUMBER; + break; + case fRAN: + value=a1->value*((double)rand()/RAND_MAX); + result=stNUMBER; + break; + case fRAN2: + value=(double)rand()/RAND_MAX; + result=stNUMBER; + break; + case fMIN: + if (a1->value>a2->value) + value=a2->value; + else + value=a1->value; + result=stNUMBER; + break; + case fMAX: + if (a1->value>a2->value) + value=a1->value; + else + value=a2->value; + result=stNUMBER; + break; + case fVAL: + i=sscanf((char *) a1->pointer,"%lf",&value); + if (i!=1) value=0; + result=stNUMBER; + break; + case fATAN2: + value=atan2(a1->value,a2->value); + result=stNUMBER; + break; + case fLEFT: + str=a1->pointer; + len=(int)a2->value; + pointer=fromto(str,0,len-1); + result=stSTRING; + break; + case fRIGHT: + str=a1->pointer; + max=strlen(str); + len=(int)a2->value; + pointer=fromto(str,max-len,max-1); + result=stSTRING; + break; + case fMID: + str=a1->pointer; + start=(int)a2->value; + len=(int)a3->value; + pointer=fromto(str,start-1,start+len-2); + result=stSTRING; + break; + case fMID2: + str=a1->pointer; + start=(int)a2->value; + pointer=fromto(str,start-1,strlen(str)); + result=stSTRING; + break; + case fINKEY: + pointer=inkey(a1->value); + result=stSTRING; + break; + case fAND: + value=(int)a1->value & (int)a2->value; + result=stNUMBER; + break; + case fOR: + value=(int)a1->value | (int)a2->value; + result=stNUMBER; + break; + case fEOR: + value=(int)a1->value ^ (int)a2->value; + result=stNUMBER; + break; +/* + case fMOUSEX: + getmousexybm(a1->pointer,&i,NULL,NULL,NULL); + value=i; + result=stNUMBER; + break; + case fMOUSEY: + getmousexybm(a1->pointer,NULL,&i,NULL,NULL); + value=i; + result=stNUMBER; + break; + case fMOUSEB: + getmousexybm(a1->pointer,NULL,NULL,&i,NULL); + value=i; + result=stNUMBER; + break; + case fMOUSEMOD: + getmousexybm(a1->pointer,NULL,NULL,NULL,&i); + value=i; + result=stNUMBER; + break;*/ + case fCHR: + pointer=my_malloc(2); + i=(int)floor(a1->value); + if (i>255 || i<0) { + sprintf(string,"can't convert %g to character",a1->value); + error(ERROR,string); + return; + } + pointer[1]='\0'; + pointer[0]=(unsigned char)i; + result=stSTRING; + break; + case fASC: + value=((unsigned char *)a1->pointer)[0]; + result=stNUMBER; + break; + case fBIN: + pointer=dec2other(a1->value,2); + result=stSTRING; + break; + case fHEX: + pointer=dec2other(a1->value,16); + result=stSTRING; + break; + case fDEC: + value=other2dec(a1->pointer,16); + result=stNUMBER; + break; + case fDEC2: + value=other2dec(a1->pointer,(int)(a2->value)); + result=stNUMBER; + break; + case fUPPER: + str=a1->pointer; + pointer=my_malloc(strlen(str)+1); + i=-1; + do { + i++; + pointer[i]=toupper((int)str[i]); + } while(pointer[i]); + result=stSTRING; + break; + case fLOWER: + str=a1->pointer; + pointer=my_malloc(strlen(str)+1); + i=-1; + do { + i++; + pointer[i]=tolower((int)str[i]); + } while(pointer[i]); + result=stSTRING; + break; + case fLTRIM: + str=a1->pointer; + while(isspace(*str)) str++; + pointer=my_strdup(str); + result=stSTRING; + break; + case fRTRIM: + str=a1->pointer; + i=strlen(str)-1; + while(isspace(str[i]) && i>=0) i--; + str[i+1]='\0'; + pointer=my_strdup(str); + result=stSTRING; + break; + case fTRIM: + str=a1->pointer; + i=strlen(str)-1; + while(isspace(str[i]) && i>=0) i--; + str[i+1]='\0'; + while(isspace(*str)) str++; + pointer=my_strdup(str); + result=stSTRING; + break; + case fINSTR: + str=a1->pointer; + str2=a2->pointer; + if (*str2) + pointer=strstr(str,str2); + else + pointer=NULL; + if (pointer==NULL) + value=0; + else + value=pointer-str+1; + result=stNUMBER; + break; + case fINSTR2: + str=a1->pointer; + str2=a2->pointer; + start=(int)a3->value; + if (start>strlen(str)) { + value=0; + } else { + if (start<1) start=1; + pointer=strstr(str+start-1,str2); + if (pointer==NULL) + value=0; + else + value=pointer-str+1; + } + result=stNUMBER; + break; + case fRINSTR: + str=a1->pointer; + str2=a2->pointer; + len=strlen(str2); + for(i=strlen(str)-1;i>=0;i--) if (!strncmp(str+i,str2,len)) break; + value=i+1; + result=stNUMBER; + break; + case fRINSTR2: + str=a1->pointer; + str2=a2->pointer; + len=strlen(str2); + start=(int)a3->value; + if (start<1) { + value=0; + } else { + if (start>strlen(str)) start=strlen(str); + for(i=start-1;i;i--) if (!strncmp(str+i,str2,len)) break; + value=i+1; + } + result=stNUMBER; + break; + case fDATE: + pointer=my_malloc(100); + time(&datetime); + strftime(pointer,100,"%w-%m-%d-%Y-%a-%b",localtime(&datetime)); + result=stSTRING; + break; + case fTIME: + pointer=my_malloc(100); + time(&datetime); + strftime(pointer,100,"%H-%M-%S",localtime(&datetime)); + sprintf(pointer+strlen(pointer),"-%d", + (int)(time(NULL)-compilation_start)); + result=stSTRING; + break; + case fSYSTEM: + str=a1->pointer; + pointer=do_system(str); + result=stSTRING; + break; + case fSYSTEM2: + str=a1->pointer; + value=do_system2(str); + result=stNUMBER; + break; + case fPEEK: + str=a1->pointer; + value=peek(str, yab); + result=stNUMBER; + break; + case fPEEK2: + str=a1->pointer; + pointer=peek2(str,current); + result=stSTRING; + break; + case fPEEK3: + str=a1->pointer; + str2=a2->pointer; + pointer=peek3(str,str2); + result=stSTRING; + break; + case fPEEK4: + value=peekfile((int)a1->value); + result=stNUMBER; + break; + case fGETCHAR: + pointer=getchars((int)a1->value,(int)a2->value,(int)a3->value,(int)a4->value); + result=stSTRING; + break; + case fTELL: + i=(int)(a1->value); + if (badstream(i,0)) return; + if (!(stream_modes[i] & (smREAD | smWRITE))) { + sprintf(string,"stream %d not opened",i); + error(ERROR,string); + value=0; + } else { + value=ftell(streams[i]); + } + result=stNUMBER; + break; + case fMESSAGE: + pointer = getmessages(yab,linenum, current->lib->s); + result = stSTRING; + break; + case fMOUSE: + str = a1->pointer; + pointer = getmousemessages(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fTRANSLATE: + str = a1->pointer; + pointer = gettranslation(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fMENUTRANSLATE: + str = a1->pointer; + pointer = getmenutranslation(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fTEXTGET: + str = a1->pointer; + pointer = textget(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fTEXTGET3: + str = a1->pointer; + pointer = textget3(str,a2->value,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fTEXTGET6: + str = a1->pointer; + str2 = a2->pointer; + pointer = textget6(str,str2,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fTEXTCONTROLGET: + str = a1->pointer; + pointer = textcontrolget(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fNUMWINDOWS: + value = numwindows(); + result = stNUMBER; + break; + case fISMOUSEIN: + str = a1->pointer; + value = ismousein(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fMOUSEMOVE: //vasper + pointer = getmousein(yab,linenum, current->lib->s); + result = stSTRING; + break; + case fDRAWIMAGE: + str=a3->pointer; + str2=a4->pointer; + value = createimage(a1->value,a2->value,str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fDRAWIMAGE2: + str=a5->pointer; + str2=a6->pointer; + value = createimage2(a1->value,a2->value,a3->value,a4->value,str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fDRAWSVG: + str=a5->pointer; + str2=a6->pointer; + value = createsvg(a1->value,a2->value,a3->value,a4->value,str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fLOAD: + str=a1->pointer; + str2=a2->pointer; + str3=a3->pointer; + pointer = getloadfilepanel(str,str2,str3,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fSAVE: + str=a1->pointer; + str2=a2->pointer; + str3=a3->pointer; + str4=a4->pointer; + pointer = getsavefilepanel(str,str2,str3,str4,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fKEYBOARD: + str=a1->pointer; + pointer = keyboardmessages(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fCLIPBOARDPASTE: + pointer = clipboardpaste(yab,linenum, current->lib->s); + result = stSTRING; + break; + case fCOLUMNBOXGET: + str=a1->pointer; + pointer = columnboxget(str,a2->value,a3->value,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fLISTBOXGET: + str=a1->pointer; + pointer = listboxget(str,a2->value,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fTREEBOXGET: + str=a1->pointer; + pointer = treeboxget(str,a2->value,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fTEXTGET2: + str=a1->pointer; + str2=a2->pointer; + value = textget2(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fTEXTGET4: + str=a1->pointer; + str2=a2->pointer; + value = textget4(str,str2,a3->value,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fTEXTGET5: + str=a1->pointer; + str2=a2->pointer; + str3=a3->pointer; + value = textget5(str,str2,str3,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fPOPUPMENU: + str=a3->pointer; + str2=a4->pointer; + pointer = popupmenu(a1->value, a2->value, str, str2,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fSCROLLBARGET: + str=a1->pointer; + str2=a2->pointer; + value = scrollbarget(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fSPLITVIEWGET: + str=a1->pointer; + str2=a2->pointer; + value = splitviewget(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fSTACKVIEWGET: + str=a1->pointer; + value = stackviewget(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fTABVIEWGET: + str=a1->pointer; + value = tabviewget(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fSPINCONTROLGET: + str=a1->pointer; + value = spincontrolget(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fLISTBOXCOUNT: + str=a1->pointer; + value = listboxcount(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fTREEBOXCOUNT: + str=a1->pointer; + value = treeboxcount(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fDROPBOXCOUNT: + str=a1->pointer; + value = dropboxcount(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fDROPBOXGET: + str=a1->pointer; + pointer = dropboxget(str,a2->value,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fDRAWGET3: + str=a1->pointer; + pointer = drawget3(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fSLIDERGET: + str=a1->pointer; + value = sliderget(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fCOLORCONTROLGET: + str=a1->pointer; + str2=a2->pointer; + value = colorcontrolget(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fCALENDAR: + str=a1->pointer; + pointer = calendar2(str,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fCOLUMNBOXCOUNT: + str=a1->pointer; + value = columnboxcount(str,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fWINDOWGET: + str=a1->pointer; + str2=a2->pointer; + value = windowgetnum(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fVIEWGET: //vasper + str=a1->pointer; + str2=a2->pointer; + value = viewgetnum(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fDRAWGET1: + str=a1->pointer; + str2=a2->pointer; + str3=a3->pointer; + value = drawget1(str,str2,str3,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fDRAWGET2: + str=a1->pointer; + str2=a2->pointer; + value = drawget2(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fDRAWGET4: + str=a3->pointer; + str2=a4->pointer; + value = drawget4(a1->value, a2->value, str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fLISTBOXGETNUM: + str=a1->pointer; + value = listboxgetnum(str, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fDROPBOXGETNUM: + str=a1->pointer; + value = dropboxgetnum(str, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fTREEBOXGETNUM: + str=a1->pointer; + value = treeboxgetnum(str, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fCOLUMNBOXGETNUM: + str=a1->pointer; + value = columnboxgetnum(str, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fBITMAPLOAD: + str=a1->pointer; + str2=a2->pointer; + value = bitmapload(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fBITMAPGET: + str=a1->pointer; + str2=a2->pointer; + value = bitmapgetnum(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fBITMAPCOLOR: + str = a3->pointer; + str2 = a4->pointer; + value = bitmapcolor(a1->value, a2->value, str, str2, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fBITMAPSAVE: + str=a1->pointer; + str2=a2->pointer; + str3=a3->pointer; + value = bitmapsave(str,str2,str3,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fSOUND: + str=a1->pointer; + value = sound(str, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fTREEBOXGETOPT: + str=a1->pointer; + str2=a2->pointer; + value = treeboxgetopt(str, str2, a3->value, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fTHREADKILL: + str=a1->pointer; + value = threadkill(str, a2->value, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fTHREADGET: + str=a1->pointer; + str2=a2->pointer; + value = threadget(str, str2, yab, linenum, current->lib->s); + result = stNUMBER; + break; + case fALERT: + str=a1->pointer; + str2=a2->pointer; + str3=a3->pointer; + str4=a4->pointer; + str5=a5->pointer; + value = newalert(str,str2,str3,str4,str5,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fPRINTER: + str=a1->pointer; + str2=a2->pointer; + str3=a3->pointer; + value = printer(str,str2,str3,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fISCOMPUTERON: + value = iscomputeron(yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fMESSAGESEND: + str=a1->pointer; + str2=a2->pointer; + value = messagesend(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + case fATTRIBUTEGET1: + str=a1->pointer; + str2=a2->pointer; + pointer = attributeget1(str,str2,yab,linenum, current->lib->s); + result = stSTRING; + break; + case fATTRIBUTEGET2: + str=a1->pointer; + str2=a2->pointer; + value = attributeget2(str,str2,yab,linenum, current->lib->s); + result = stNUMBER; + break; + default: + error(ERROR,"function called but not implemented"); + return; + } + + stack=push(); + /* copy result */ + stack->type=result; + if (result==stSTRING) + stack->pointer=pointer; + else + stack->value=value; +} + + +static int do_system2(char *cmd) /* execute command as system */ +{ +#ifdef UNIX + int ret; + #ifdef BUILD_NCURSES + if (curinized) reset_shell_mode(); + #endif + ret=system(cmd); + #ifdef BUILD_NCURSES + if (curinized) reset_prog_mode(); + #endif + return ret; +#else + STARTUPINFO start; + PROCESS_INFORMATION proc; + DWORD ec; /* exit code */ + SECURITY_ATTRIBUTES prosec; + SECURITY_ATTRIBUTES thrsec; + char *comspec; + + ZeroMemory(&prosec,sizeof(prosec)); + prosec.nLength=sizeof(prosec); + prosec.bInheritHandle=TRUE; + ZeroMemory(&thrsec,sizeof(thrsec)); + thrsec.nLength=sizeof(thrsec); + thrsec.bInheritHandle=TRUE; + ZeroMemory(&start,sizeof(start)); + start.cb=sizeof(STARTUPINFO); + start.dwFlags=STARTF_USESTDHANDLES; + start.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE); + start.hStdError=GetStdHandle(STD_ERROR_HANDLE); + start.hStdInput=GetStdHandle(STD_INPUT_HANDLE); + comspec=getenv("COMSPEC"); + if (!comspec) comspec="command.com"; + sprintf(string,"%s /C %s",comspec,cmd); + if (!CreateProcess(NULL,string,&prosec,&thrsec,TRUE,0, + NULL,NULL,&start,&proc)) { + sprintf(string,"couldn't execute '%s'",cmd); + error(ERROR,string); + return -1; + } + WaitForSingleObject(proc.hProcess,INFINITE); + if (!GetExitCodeProcess(proc.hProcess,&ec)) ec=-1; + CloseHandle(proc.hProcess); + CloseHandle(proc.hThread); + return ec; +#endif +} + + +static void clear_buff() /* clear system-input buffers */ +{ + buffcurr=&buffroot; + buffcount=0; +} + + +static void store_buff(char *buff,int len) /* store system-input buffer */ +{ + *buffcurr=my_malloc(sizeof(struct buff_chain)); + memcpy((*buffcurr)->buff,buff,SYSBUFFLEN+1); + (*buffcurr)->len=len; + buffcurr=&((*buffcurr)->next); + buffcount++; +} + + +char *recall_buff() /* recall store buffer */ +{ + struct buff_chain *curr,*old; + char *result; + int done,len; + + result=(char *)my_malloc(buffcount*(SYSBUFFLEN+1)); + curr=buffroot; + len=0; + for(done=0;donebuff,SYSBUFFLEN); + len+=curr->len; + old=curr; + curr=curr->next; + my_free(old); + } + return result; +} + + +static char *do_system(char *cmd) /* executes command via command.com */ +{ + static char buff[SYSBUFFLEN+1]; /* buffer to store command */ + int len; /* number of bytes read */ +#ifdef UNIX + FILE *p; /* points to pipe */ + int c; /* char read from pipe */ +#else + int ret; + STARTUPINFO start; + PROCESS_INFORMATION proc; + HANDLE piperead,pipewrite; /* both ends of pipes */ + SECURITY_ATTRIBUTES prosec; + SECURITY_ATTRIBUTES thrsec; + char *comspec; +#endif + + clear_buff(); + +#ifdef UNIX + p=popen(cmd,"r"); + if (p==NULL) { + sprintf(string,"couldn't execute '%s'",cmd); + error(ERROR,string); + return my_strdup(""); + } + do { + len=0; + while(len0) store_buff(buff,len); + } while(ret!=ERROR_BROKEN_PIPE && ret!=ERROR_HANDLE_EOF); + CloseHandle(piperead); + CloseHandle(proc.hProcess); + CloseHandle(proc.hThread); +#endif + return recall_buff(); +} + + +void getmousexybm(char *s,int *px,int *py,int *pb,int *pm) /* get mouse coordinates */ +{ + int x=0,y=0,b=0,m=0; + char c; + + if (*s) { + sscanf(s,"MB%d%c+%d:%04d,%04d",&b,&c,&m,&x,&y); + if (px) *px=x; + if (py) *py=y; + if (pb) { + if (c=='d') + *pb=b; + else + *pb=-b; + } + if (pm) *pm=m; + return; + } +/* + if (px) *px=mousex; + if (py) *py=mousey; + if (pb) *pb=mouseb; + if (pm) *pm=mousemod;*/ +} + + +static char *dec2other(double d,int base) /* convert double to hex or binary number */ +{ + int len; + double dec,dec2; + char *other; + int negative=FALSE; + + if (d<0) { + dec2=floor(-d); + negative=TRUE; + } else { + dec2=floor(d); + } + len=negative?2:1; + for(dec=dec2;dec>=base;dec/=base) len++; + other=my_malloc(len+1); + other[len]='\0'; + dec=dec2; + for(len--;len>=0;len--) { + other[len]="0123456789abcdef"[(int)(floor(dec-base*floor(dec/base)+0.5))]; + dec=floor(dec/base); + } + if (negative) other[0]='-'; + return other; +} + + +static double other2dec(char *hex,int base) /* convert hex or binary to double number */ +{ + double dec; + static char *digits="0123456789abcdef"; + char *found; + int i,len; + + if (base!=2 && base !=16) { + sprintf(string,"Cannot convert base-%d numbers",base); + error(ERROR,string); + return 0.; + } + dec=0; + len=strlen(hex); + for(i=0;i=base) { + sprintf(string,"Not a base-%d number: '%s'",base,hex); + error(ERROR,string); + return 0.; + } + dec+=found-digits; + } + return dec; +} + + +int myformat(char *dest,double num,char *format,char *sep) /* format number according to string */ +{ + int i1,i2; /* dummy */ + char c1; /* dummy */ + static char ctrl[6]; + char *found,*form; + int pre,post,dot,len,i,j,digit,colons,dots; + int neg=FALSE; + double ip,fp,round; + static char *digits="0123456789"; + + form=format; + if (*form=='%') { /* c-style format */ + strcpy(ctrl,"+- #0"); /* allowed control chars for c-format */ + form++; + while((found=strchr(ctrl,*form))!=NULL) { + *found='?'; + form++; + } + if (sscanf(form,"%u.%u%c%n",&i1,&i2,&c1,&i)!=3 && + sscanf(form,"%u.%c%n",&i2,&c1,&i)!=2 && + sscanf(form,".%u%c%n",&i2,&c1,&i)!=2 && + sscanf(form,"%u%c%n",&i2,&c1,&i)!=2) return FALSE; + if (!strchr("feEgG",c1) || form[i]) return FALSE; + /* seems okay, let's print */ + sprintf(dest,format,num); + } else { /* basic-style format */ + if (num<0) { + neg=TRUE; + num=-num; + } + colons=0; + dots=0; + pre=0; + post=0; + for(form=format;*form;form++) { + if (*form==',') { + if (dots) return FALSE; + colons++; + } else if (*form=='.') { + dots++; + } else if (*form=='#') { + if (dots) + post++; + else + pre++; + } else { + return FALSE; + } + } + if (dots>1) return FALSE; + len=strlen(format); + dest[len]='\0'; + round=0.5; + for(i=0;i1 || fp<0) fp=0; + dest[pre+colons]=format[pre+colons]; + if ((int)ip) { + for(i=pre+colons-1;i>=0;i--) { + if (neg && !(int)ip) { + neg=0; + dest[i]='-'; + } else { + if (format[i]=='#') { + digit=((int)ip)%10; + ip/=10; + if (((int)ip) || digit>0) + dest[i]=digits[digit]; + else + dest[i]=' '; + } else { + if ((int)ip) + dest[i]=format[i]; + else + dest[i]=' '; + } + } + } + } else { + i=pre+colons-1; + dest[i--]='0'; + } + if ((neg && i<0) || ((int)ip)) { + strcpy(dest,format); + return TRUE; + } + if (neg) dest[i--]='-'; + for(;i>=0;i--) dest[i]=' '; + for(i=pre+colons+1;ito || to<0 || from>len-1) { + /* give back empty string */ + part=my_malloc(1); + part[0]='\0'; + } + else { + if (from<=0) from=0; + if (to>=len) to=len-1; + part=my_malloc(sizeof(char)*(to-from+2)); /* characters and '/0' */ + for(i=from;i<=to;i++) part[i-from]=str[i]; /* copy */ + part[i-from]='\0'; + } + return part; +} + + + +void mywait() /* wait given number of seconds */ +{ + double delay; + +#ifdef UNIX + struct timeval tv; +#else + MSG msg; + int timerid; +#endif + + delay=pop(stNUMBER)->value; + if (delay<0) delay=0.; +#ifdef UNIX + tv.tv_sec=(int)delay; + tv.tv_usec=(delay-(int)delay)*1000000; + select(0,NULL,NULL,NULL,&tv); +#else /* WINDOWS */ + timerid=SetTimer(NULL,0,(int)(delay*1000),(TIMERPROC) NULL); + GetMessage((LPMSG)&msg,NULL,WM_TIMER,WM_TIMER); + KillTimer(NULL,timerid); +#endif +} + + +void mybell() /* ring ascii bell */ +{ +#ifdef UNIX +#ifdef BEOS + yi_beep(); +#else + printf("\007"); + fflush(stdout); +#endif +#else /* WINDOWS */ + Beep(1000,100); +#endif +} + + + +void create_poke(char flag) /* create Command 'cPOKE' */ +{ + struct command *cmd; + + if (flag=='S' || flag=='D') + cmd=add_command(cPOKEFILE,FALSE); + else + cmd=add_command(cPOKE,FALSE); + cmd->tag=flag; +} + + +void poke(struct command *cmd) /* poke into internals */ +{ + char *dest,*s,c; + char *sarg=NULL; + double darg; + + if (cmd->tag=='s') + sarg=pop(stSTRING)->pointer; + else + darg=pop(stNUMBER)->value; + + dest=pop(stSTRING)->pointer; + for(s=dest;*s;s++) *s=tolower((int)*s); + /* + if (!strcmp(dest,"fontheight") && !sarg) { + fontheight=(int)darg; +#ifdef UNIX + calc_psscale(); +#endif + } + else if (!strcmp(dest,"font") && sarg) { + font=my_strdup(sarg); + } */ + if (!strcmp(dest,"dump") && sarg && !strcmp(sarg,"symbols")) { + dump_sym(); + } + else if (!strcmp(dest,"dump") && sarg && + (!strcmp(sarg,"sub") || !strcmp(sarg,"subs") || !strcmp(sarg,"subroutine") || !strcmp(sarg,"subroutines"))) { + dump_sub(0); + } + /* + else if (!strcmp(dest,"winwidth") && !sarg) { + winwidth=(int)darg; + if (winwidth<1) { + error(ERROR,"winwidth less than 1 pixel"); + return; + } +#ifdef UNIX + calc_psscale(); +#endif + } + else if (!strcmp(dest,"winheight") && !sarg) { + winheight=(int)darg; + if (winheight<1) { + error(ERROR,"winheight less than 1 pixel"); + return; + } +#ifdef UNIX + calc_psscale(); +#endif + } + else if (!strcmp(dest,"textalign") && sarg) { + if (!check_alignement(sarg)) return; + strncpy(text_align,sarg,2); + } + else if (!strcmp(dest,"windoworigin") && sarg) { + moveorigin(sarg); + }*/ + else if (!strcmp(dest,"infolevel") && sarg) { + c=tolower((int)*sarg); + switch(c) { + case 'd': infolevel=DEBUG;break; + case 'n': infolevel=NOTE;break; + case 'w': infolevel=WARNING;break; + case 'e': infolevel=ERROR;break; + case 'f': infolevel=FATAL;break; + default: + error(ERROR,"invalid infolevel"); + return; + } + if (infolevel>=DEBUG) { + sprintf(string,"switching infolevel to '%c'",c); + error(DEBUG,string); + } + } + else if (!strcmp(dest,"stdout") && sarg) { + fputs(sarg,stdout); + } + else if (!strcmp(dest,"read_controls") && !sarg) { + read_controls= darg ? 1:0; + } + else if (dest[0]=='#') { + error(ERROR,"don't use quotes when poking into file"); + } + else { + error(ERROR,"invalid poke"); + } + return; +} + + +void pokefile(struct command *cmd) /* poke into file */ +{ + char *sarg=NULL; + double darg; + int stream; + + if (cmd->tag=='S') + sarg=pop(stSTRING)->pointer; + else + darg=pop(stNUMBER)->value; + stream=(int)(pop(stNUMBER)->value); + + if (badstream(stream,0)) return; + + if (!(stream_modes[stream] & smWRITE)) { + sprintf(string,"Stream %d not open for writing",stream); + error(ERROR,string); + return; + } + if (sarg) { + fputs(sarg,streams[stream]); + } else { + if (darg<0 || darg>255) { + error(ERROR,"stream poke out of byte range (0..255)"); + return; + } + fputc((int)darg,streams[stream]); + } +} + + +static double peek(char *dest, YabInterface *yab) /* peek into internals */ +{ + char *s; + + for(s=dest;*s;s++) *s=tolower((int)*s); + /*if (!strcmp(dest,"winwidth")) return winwidth; + else if (!strcmp(dest,"winheight")) return winheight; + else if (!strcmp(dest,"fontheight")) return fontheight; + else*/ + if (!strcmp(dest,"screenheight")) return LINES; + else if (!strcmp(dest,"screenwidth")) return COLS; + else if (!strcmp(dest, "deskbarposition")) return yi_DeskbarPosition(yab); //deskbarposition; + else if (!strcmp(dest, "deskbarexpanded")) return yi_DeskbarExpanded(yab); //deskbarexpanded; + else if (!strcmp(dest, "deskbarwidth")) return yi_DeskbarWidth(yab); //deskbarwidth; + else if (!strcmp(dest, "deskbarheight")) return yi_DeskbarHeight(yab); //deskbarheight; + else if (!strcmp(dest, "deskbar-x")) return yi_DeskbarX(yab); //deskbar-x; + else if (!strcmp(dest, "deskbar-y")) return yi_DeskbarY(yab); //deskbar-y; + else if (!strcmp(dest, "desktopwidth")) return yi_DesktopWidth(yab); //desktopwidth; + else if (!strcmp(dest, "desktopheight")) return yi_DesktopHeight(yab); //desktopheight; + else if (!strcmp(dest, "scrollbarwidth")) return yi_ScrollbarWidth(yab); // scrollbarwidth + else if (!strcmp(dest, "menuheight")) return yi_MenuHeight(yab); // menuheight + else if (!strcmp(dest, "tabheight")) return yi_TabHeight(yab); // tabheight + else if (!strcmp(dest,"argument") || !strcmp(dest,"arguments") ) return yabargc; // number of arguments + else if (!strcmp(dest,"version")) return strtod(VERSION,NULL); + else if (!strcmp(dest,"error")) return errorcode; + else if (!strcmp(dest,"read_controls")) return read_controls; + else if (!strcmp(dest,"isbound")) return is_bound; + else if (dest[0]=='#') { + error(ERROR,"don't use quotes when peeking into a file"); + return 0; + } + + sprintf(stderr, "PEEK is set to %s\n", dest); + error(ERROR,"invalid peek"); + return 0; +} + + +static int peekfile(int stream) /* read a byte from stream */ +{ + if (stream && badstream(stream,0)) return 0; + if (stream && !(stream_modes[stream] & smREAD)) { + sprintf(string,"stream %d not open for reading",stream); + error(ERROR,string); + return 0; + } + return fgetc(stream?streams[stream]:stdin); +} + + +static char *peek2(char *dest,struct command *curr) /* peek into internals */ +{ + char *s; + + for(s=dest;*s;s++) *s=tolower((int)*s); + if (!strcmp(dest,"infolevel")) { + if (infolevel==DEBUG) return my_strdup("debug"); + else if (infolevel==NOTE) return my_strdup("note"); + else if (infolevel==WARNING) return my_strdup("warning"); + else if (infolevel==ERROR) return my_strdup("error"); + else if (infolevel==FATAL) return my_strdup("fatal"); + else return my_strdup("unkown"); + } + /* + else if (!strcmp(dest,"textalign")) return my_strdup(text_align); + else if (!strcmp(dest,"windoworigin")) return my_strdup(winorigin);*/ + else if (!strcmp(dest,"error")) return my_strdup(errorstring); + else if (!strcmp(dest,"library")) return my_strdup(curr->lib->s); + else if (!strcmp(dest,"os")) { +#ifdef HAIKU + return my_strdup("Haiku"); +#else + return my_strdup("BeOS"); +#endif + } + else if (!strcmp(dest,"directory")) return my_strdup(appdirectory); + else if (!strcmp(dest,"refsreceived")) return my_strdup(refsRec); + /* else if (!strcmp(dest,"font")) return my_strdup(font); */ + else if (!strcmp(dest,"argument") || !strcmp(dest,"arguments")) { + if (yabargc>0) { + s=yabargv[0]; + yabargc--; + yabargv++; + } + else { + s=""; + } + return my_strdup(s); + } + else { + error(ERROR,"invalid peek"); + } + return my_strdup(""); +} + + +static char *peek3(char *dest,char *cont) /* peek into internals */ +{ + char *s; + + for(s=dest;*s;s++) *s=tolower((int)*s); + if (!strcmp(dest,"env") || !strcmp(dest,"environment")) { + return my_strdup(getenv(cont)); + } else { + error(ERROR,"invalid peek"); + } + return my_strdup(""); +} + + +void create_exception(int flag) /* create command 'exception' */ +{ + struct command *cmd; + + cmd=add_command(cEXCEPTION,FALSE); + cmd->args=flag; +} + + +void exception(struct command *cmd) /* change handling of exceptions */ +{ + if (cmd->args) { + signal(SIGINT,signal_handler); /* enable keyboard interrupt */ +#ifdef SIGHUP + signal(SIGHUP,signal_handler); +#endif +#ifdef SIGQUIT + signal(SIGQUIT,signal_handler); +#endif +#ifdef SIGABRT + signal(SIGABRT,signal_handler); +#endif +#ifdef SIGTERM + signal(SIGTERM,signal_handler); +#endif + } + else { + signal(SIGINT,SIG_IGN); /* ignore keyboard interrupt */ +#ifdef SIGHUP + signal(SIGHUP,SIG_IGN); +#endif +#ifdef SIGQUIT + signal(SIGQUIT,SIG_IGN); +#endif +#ifdef SIGABRT + signal(SIGABRT,SIG_IGN); +#endif +#ifdef SIGTERM + signal(SIGTERM,SIG_IGN); +#endif + } + return; +} + + +void create_restore(char *label) /* create command 'restore' */ +{ + struct command *c; + + c=add_command(cRESTORE,FALSE); + c->pointer=my_strdup(label); +} + + +void restore(struct command *cmd) /* reset data pointer to given label */ +{ + struct command *label; + struct command **datapointer; + + datapointer=&(cmd->lib->datapointer); + if (cmd->type==cRESTORE) { /* first time; got to search the label */ + if (*((char *)cmd->pointer)=='\0') { + /* no label, restore to first command */ + label=cmd->lib->firstdata; + } else { + label=search_label(cmd->pointer,smLABEL|smGLOBAL); + if (!label) { + /* did not find label */ + sprintf(string,"can't find label '%s'",(char *)cmd->pointer); + error(ERROR,string); + return; + } + } + *datapointer=label; + if (lastdata) { + while((*datapointer)->type!=cDATA && (*datapointer)!=cmdhead) { + *datapointer=(*datapointer)->next; + } + } + cmd->pointer=*datapointer; + cmd->type=cQRESTORE; + } else { + *datapointer=cmd->pointer; + } + return; +} + + +void create_dbldata(double value) /* create command dbldata */ +{ + struct command *c; + + c=add_command(cDATA,FALSE); + c->pointer=my_malloc(sizeof(double)); + if (lastdata) lastdata->nextassoc=c; + lastdata=c; + *((double *)c->pointer)=value; + c->tag='d'; /* double value */ +} + + +void create_strdata(char *value) /* create command strdata */ +{ + struct command *c; + + c=add_command(cDATA,FALSE); + if (lastdata) lastdata->nextassoc=c; + lastdata=c; + c->pointer=my_strdup(value); + c->tag='s'; /* string value */ +} + + +void create_readdata(char type) /* create command readdata */ +{ + struct command *cmd; + + cmd=add_command(cREADDATA,FALSE); + cmd->tag=type; +} + + +void readdata(struct command *cmd) /* read data items */ +{ + struct stackentry *read; + char type; + struct command **datapointer; + + datapointer=&(cmd->lib->datapointer); + type=cmd->tag; + while(*datapointer && ((*datapointer)->type!=cDATA || cmd->lib!=(*datapointer)->lib)) { + *datapointer=(*datapointer)->nextassoc; + } + if (!*datapointer) { + error(ERROR,"run out of data items"); + return; + } + if (type!=(*datapointer)->tag) { + error(ERROR,"type of READ and DATA don't match"); + return; + } + read=push(); + if (type=='d') { /* read a double value */ + read->type=stNUMBER; + read->value= *((double *)(*datapointer)->pointer);} + else { + read->type=stSTRING; + read->pointer=my_strdup((*datapointer)->pointer); + } + *datapointer=(*datapointer)->nextassoc; /* next item */ +} + + +void create_dblrelop(char c) /* create command dblrelop */ +{ + int type; + + switch(c) { + case '=': type=cEQ;break; + case '!': type=cNE;break; + case '<': type=cLT;break; + case '{': type=cLE;break; + case '>': type=cGT;break; + case '}': type=cGE;break; + } + add_command(type,FALSE); +} + + +void dblrelop(struct command *type) /* compare topmost double-values */ +{ + double a,b,c; + struct stackentry *result; + + b=pop(stNUMBER)->value; + a=pop(stNUMBER)->value; + switch(current->type) { + case cEQ:c=(a==b);break; + case cNE:c=(a!=b);break; + case cLE:c=(a<=b);break; + case cLT:c=(a=b);break; + case cGT:c=(a>b);break; + } + result=push(); + result->value=c; + result->type=stNUMBER; +} + + +void create_strrelop(char c) /* create command strrelop */ +{ + int type; + + switch(c) { + case '=': type=cSTREQ;break; + case '!': type=cSTRNE;break; + case '<': type=cSTRLT;break; + case '{': type=cSTRLE;break; + case '>': type=cSTRGT;break; + case '}': type=cSTRGE;break; + } + add_command(type,FALSE); +} + + +void strrelop(struct command *type) /* compare topmost string-values */ +{ + char *a,*b; + double c; + struct stackentry *result; + + b=pop(stSTRING)->pointer; + a=pop(stSTRING)->pointer; + switch(current->type) { + case cSTREQ:c=(strcmp(a,b)==0);break; + case cSTRNE:c=(strcmp(a,b)!=0);break; + case cSTRLT:c=(strcmp(a,b)<0);break; + case cSTRLE:c=(strcmp(a,b)<=0);break; + case cSTRGT:c=(strcmp(a,b)>0);break; + case cSTRGE:c=(strcmp(a,b)>=0);break; + } + result=push(); + result->value=c; + result->type=stNUMBER; +} + +void switch_compare(void) /* compare topmost values for switch statement */ +{ + struct stackentry *result,*first,*second; + double r=0.; + + first=pop(stANY); + second=stackhead->prev; + if ((second->type==stSWITCH_STRING || second->type==stSTRING) && first->type==stSTRING) { + if (second->type==stSWITCH_STRING) + r=1.; + else + r=(strcmp(first->pointer,second->pointer)==0)?1.:0.; + } else if ((second->type==stSWITCH_NUMBER || second->type==stNUMBER) && first->type==stNUMBER) { + if (second->type==stSWITCH_NUMBER) + r=1.; + else + r=(first->value==second->value); + } else { + error(ERROR,"Cannot mix strings and numbers in a single switch statement"); + } + result=push(); + result->type=stNUMBER; + result->value=r; +} + + +void logical_shortcut(struct command *type) /* shortcut and/or if possible */ +{ + struct stackentry *result; + double is; + + is=stackhead->prev->value; + if ((type->type==cORSHORT && is!=0) || (type->type==cANDSHORT && is==0)) { + result=push(); + error(DEBUG,"logical shortcut taken"); + result->type=stNUMBER; + result->value=is; + } else { + current=current->next; + } +} + + +void create_boole(char c) /* create command boole */ +{ + int type; + + switch(c) { + case '|': type=cOR;break; + case '&': type=cAND;break; + case '!': type=cNOT;break; + } + add_command(type,FALSE); +} + + +void boole(struct command *type) /* perform and/or/not */ +{ + int a,b,c; + struct stackentry *result; + + a=(int)pop(stNUMBER)->value; + if (current->type==cNOT) + c=!a; + else { + b=(int)pop(stNUMBER)->value; + if (current->type==cAND) + c=a&&b; + else + c=a||b; + } + result=push(); + result->value=c; + result->type=stNUMBER; +} + diff --git a/src/global.h b/src/global.h new file mode 100644 index 0000000..746450b --- /dev/null +++ b/src/global.h @@ -0,0 +1,3 @@ +//define BUILD_NCURSES +#define BUILD_YABTEXT +#define BUILD_GAMESOUND \ No newline at end of file diff --git a/src/graphic.c b/src/graphic.c new file mode 100644 index 0000000..82f508a --- /dev/null +++ b/src/graphic.c @@ -0,0 +1,2560 @@ +/* + + YABASIC --- a simple Basic Interpreter + written by Marc-Oliver Ihm 1995-2004 + homepage: www.yabasic.de + + graphic.c --- code for windowed graphics, printing and plotting + + This file is part of yabasic and may be copied only + under the terms of either the Artistic License or + the GNU General Public License (GPL), both of which + can be found at www.yabasic.de + +*/ + + +/* ------------- includes ---------------- */ + +//include "YabInterface.h" + +#include "global.h" + +#ifndef YABASIC_INCLUDED +#include "yabasic.h" /* all prototypes and structures */ +#endif +#ifdef UNIX +#ifdef BUILD_NCURSES +#include +#endif +#include +#include +#include +#ifndef KEY_MAX +#define KEY_MAX 0777 +#endif +#endif + + +/* ------------- global variables ---------------- */ + +char translationbuffer[8192]; + +/* mouse and keyboard */ +int mousex=0,mousey=0,mouseb=0,mousemod=0; /* last know mouse coordinates */ +char *ykey[kLASTKEY+1]; /* keys returned by inkey */ + +int winopened = 0; + +/* ------------- functions ---------------- */ + +void create_openwin(int fnt) /* create Command 'openwin' */ +{ + struct command *cmd; + + cmd=add_command(cOPENWIN,FALSE); + cmd->args=fnt; +} + + +void openwin(struct command *cmd, YabInterface* yab) /* open a Window */ +{ + double x1,y1,x2,y2; + char *id, *title; + 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_OpenWindow(x1,y1,x2,y2, id, title, yab); + + winopened++; +} + +void closewin(struct command *cmd, YabInterface* yab) /* close the window */ +{ + char *id; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + if (yi_CloseWindow(id, yab) == 1) + winopened--; +} + +int numwindows() +{ + return winopened; +} + +void createbutton(struct command *cmd, YabInterface* yab) /* set a button */ +{ + 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); +} + +void createmenu(struct command *cmd, YabInterface* yab) /* add a menu */ +{ + char *menuhead, *menuitem, *shortcut, *window; + window = pop(stSTRING)->pointer; + shortcut = pop(stSTRING)->pointer; + menuitem = pop(stSTRING)->pointer; + menuhead = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CreateMenu(menuhead, menuitem, shortcut, window, yab); +} + +void createcheckbox(struct command *cmd, YabInterface* yab) /* add a checkbox */ +{ + char *label, *window, *id; + double x,y,isActivated; + + window = pop(stSTRING)->pointer; + isActivated = pop(stNUMBER)->value; + label = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CreateCheckBox(x,y,id, label,isActivated,window, yab); +} + +void createradiobutton(struct command *cmd, YabInterface* yab) /* add a radio button*/ +{ + char *label, *groupid, *window; + double x,y,isActivated; + + + window = pop(stSTRING)->pointer; + isActivated = pop(stNUMBER)->value; + label = pop(stSTRING)->pointer; + groupid = pop(stSTRING)->pointer; + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CreateRadioButton(x,y,groupid,label,isActivated,window, yab); +} + +void createtextcontrol(struct command *cmd, YabInterface* yab) /* add a textcontrol */ +{ + char *text, *label, *window, *id; + double x1,y1,x2,y2; + + window = pop(stSTRING)->pointer; + text = pop(stSTRING)->pointer; + label = 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_CreateTextControl(x1,y1,x2,y2,id, label, text, window, yab); +} + +void createlistbox(struct command *cmd, YabInterface* yab) /* list box */ +{ + char *title, *window; + double x1,y1,x2,y2,scrollbar; + + window = pop(stSTRING)->pointer; + scrollbar = pop(stNUMBER)->value; + title = 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_CreateListBox(x1,y1,x2,y2, title, scrollbar, window, yab); +} + +void createdropbox(struct command *cmd, YabInterface* yab) /* drop box */ +{ + char *title, *label, *window; + double x1,y1,x2,y2; + + window = pop(stSTRING)->pointer; + label = pop(stSTRING)->pointer; + title = 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_CreateDropBox(x1,y1,x2,y2, title, label, window, yab); +} + +void createitem(struct command *cmd, YabInterface* yab) /* item add */ +{ + char *item, *view; + + item = pop(stSTRING)->pointer; + view = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CreateItem(view,item,yab); +} + +void removeitem(struct command *cmd, YabInterface* yab) /* item add */ +{ + char *title, *item; + + item = pop(stSTRING)->pointer; + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_RemoveItem(title,item,yab); +} + +void clearitems(struct command *cmd, YabInterface* yab) /* clear item list*/ +{ + char *title; + + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ClearItems(title,yab); +} + +int createimage(double x, double y, const char* imagefile, const char* window, YabInterface* yab, int line, const char* libname) /* set an image */ +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_CreateImage(x,y, imagefile, window, yab); +} + +int createimage2(double x1, double y1, double x2, double y2, const char* imagefile, const char* window, YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_CreateImage2(x1,y1,x2,y2, imagefile, window, yab); +} + +int createsvg(double x1, double y1, double x2, double y2, const char* imagefile, const char* window, YabInterface* yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_CreateSVG(x1,y1,x2,y2, imagefile, window, yab); +} + +void mouseset(struct command *cmd, YabInterface* yab) +{ + char *opt; + opt = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_MouseSet(opt, yab); +} + +void drawtext(struct command *cmd, YabInterface* yab) /* draw text */ +{ + double x,y; + char *text, *window; + + window = pop(stSTRING)->pointer; + text = pop(stSTRING)->pointer; + y=pop(stNUMBER)->value; + x=pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawText(x,y,text, window, yab); +} + +void drawrect(struct command *cmd, YabInterface* yab) /* draw rect */ +{ + double x1,y1,x2,y2; + char *window; + + window = 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_DrawRect(x1,y1,x2,y2,window, yab); +} + +void drawdot(struct command *cmd, YabInterface* yab) /* draw dot */ +{ + double x1,y1; + char *window; + + window = pop(stSTRING)->pointer; + y1=pop(stNUMBER)->value; + x1=pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawDot(x1,y1,window, yab); +} + +void drawline(struct command *cmd, YabInterface* yab) /* draw line */ +{ + double x1,y1,x2,y2; + char *window; + + window = 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_DrawLine(x1,y1,x2,y2,window, yab); +} + +void drawcircle(struct command *cmd, YabInterface* yab) /* draw circle */ +{ + double x1,y1,r; + char *window; + + window = pop(stSTRING)->pointer; + r=pop(stNUMBER)->value; + y1=pop(stNUMBER)->value; + x1=pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawCircle(x1,y1,r,window, yab); +} + +void drawellipse(struct command *cmd, YabInterface* yab) /* draw ellipse */ +{ + double x1,y1,r1,r2; + char *window; + + window = pop(stSTRING)->pointer; + r2=pop(stNUMBER)->value; + r1=pop(stNUMBER)->value; + y1=pop(stNUMBER)->value; + x1=pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawEllipse(x1,y1,r1,r2,window, yab); +} + +void drawcurve(struct command *cmd, YabInterface* yab) /* draw a curve */ +{ + double x1,y1,x2,y2,x3,y3,x4,y4; + char *window; + + window = pop(stSTRING)->pointer; + y4=pop(stNUMBER)->value; + x4=pop(stNUMBER)->value; + y3=pop(stNUMBER)->value; + x3=pop(stNUMBER)->value; + 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_DrawCurve(x1,y1,x2,y2,x3,y3,x4,y4,window, yab); +} + +void drawclear(struct command *cmd, YabInterface* yab) /* clear canvas */ +{ + char *window; + + + window = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawClear(window, yab); +} + +void drawset1(struct command *cmd, YabInterface *yab) +{ + char *option, *window; + + window = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawSet1(option,window,yab); +} + +void drawset2(struct command *cmd, YabInterface *yab) +{ + char *pattern; + int mode; + + pattern = pop(stSTRING)->pointer; + mode = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawSet2(mode,pattern,yab); +} + +void drawset3(struct command *cmd, YabInterface *yab) +{ + char *option; + int transparency; + + transparency = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawSet3(option, transparency,yab); +} + +void createtext(struct command *cmd, YabInterface* yab) /* text */ +{ + double x,y; + char *text, *window, *id; + + + window = pop(stSTRING)->pointer; + text = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + y=pop(stNUMBER)->value; + x=pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CreateText(x,y,id,text, window, yab); +} + +void text2(struct command *cmd, YabInterface* yab) /* text */ +{ + double x1,y1,x2,y2; + char *text, *window, *id; + + + window = pop(stSTRING)->pointer; + text = 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_Text2(x1,y1,x2,y2,id,text, window, yab); +} + +void textalign(struct command *cmd, YabInterface* yab) /* align text */ +{ + char *option, *id; + + + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextAlign(id, option, yab); +} + +void createalert(struct command *cmd, YabInterface* yab) /* open an alert window (one button only)*/ +{ + char *text, *button1, *type; + + type = pop(stSTRING)->pointer; + button1 = pop(stSTRING)->pointer; + text = pop(stSTRING)->pointer; + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CreateAlert(text,button1,type, yab); +} + +void setlayout(struct command *cmd, YabInterface *yab) +{ + char *text, *window; + + + window = pop(stSTRING)->pointer; + text = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetLayout(text, window, yab); +} + +void winset1(struct command *cmd, YabInterface *yab) +{ + char *option, *value, *window; + + + value = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + window = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_WindowSet1(option,value,window,yab); +} + +void winset2(struct command *cmd, YabInterface *yab) +{ + char *option, *window; + int r, g, b; + + window = pop(stSTRING)->pointer; + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_WindowSet2(option,r,g,b,window,yab); +} + +void winset3(struct command *cmd, YabInterface *yab) +{ + char *option, *window; + double x,y; + + + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + window = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_WindowSet3(option,x,y,window,yab); +} + +void winset4(struct command *cmd, YabInterface *yab) +{ + char *option, *window; + + + option = pop(stSTRING)->pointer; + window = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_WindowSet4(option,window,yab); +} + +void winclear(struct command *cmd, YabInterface *yab) +{ + char *window; + + + window = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_WindowClear(window,yab); +} + +char* gettranslation(const char* text, YabInterface* yab, int line, const char* libname) /* get translation string */ +{ + yi_SetCurrentLineNumber(line, libname, yab); + yi_Translate((char*)text, translationbuffer); + return my_strdup((char*) translationbuffer); +} + +char* getmenutranslation(const char* text, YabInterface* yab, int line, const char* libname) /* get menu translation string */ +{ + yi_SetCurrentLineNumber(line, libname, yab); + yi_MenuTranslate((char*)text, translationbuffer); + return my_strdup((char*) translationbuffer); +} + +void localize() +{ + yi_SetLocalize(); +} + +void localizestop() +{ + yi_StopLocalize(); +} + +void localize2(struct command *cmd, YabInterface *yab) +{ + char *path; + + path = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetLocalize2(path, yab); +} + +char* getloadfilepanel(const char* mode, const char* title, const char* dir, YabInterface *yab, int line, const char* libname) /* load panel */ +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_LoadFilePanel(mode, title, dir,yab)); +} + +char* getsavefilepanel(const char* mode, const char* title, const char* dir, const char* filename, YabInterface *yab, int line, const char* libname) /* save panel */ +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_SaveFilePanel(mode, title, dir, filename, yab)); +} + +void textedit(struct command *cmd, YabInterface *yab) +{ + char *window, *title; + double x1,y1,x2,y2; + int scrollbar; + + + window = pop(stSTRING)->pointer; + scrollbar = pop(stNUMBER)->value; + title = 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_TextEdit(x1,y1,x2,y2,title,scrollbar,window,yab); +} + +void textadd(struct command *cmd, YabInterface *yab) +{ + char *title, *text; + + + text = pop(stSTRING)->pointer; + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextAdd(title,text,yab); +} + +void textset(struct command *cmd, YabInterface *yab) +{ + char *title, *option; + + + option = pop(stSTRING)->pointer; + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextSet(title,option,yab); +} + +void textset2(struct command *cmd, YabInterface *yab) +{ + char *title, *option; + int value; + + + value = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextSet2(title,option,value,yab); +} + +void textset3(struct command *cmd, YabInterface *yab) +{ + char *title, *option, *option2; + + + option2 = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextSet3(title,option,option2,yab); +} + +void textcolor1(struct command *cmd, YabInterface *yab) +{ + char *title, *option, *command; + + + command = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextColor1(title,option,command,yab); +} + +void textcolor2(struct command *cmd, YabInterface *yab) +{ + char *title, *option; + int r,g,b; + + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextColor2(title,option,r,g,b,yab); +} + +void textclear(struct command *cmd, YabInterface *yab) +{ + char *title; + + + title = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextClear(title,yab); +} + +char* textget(const char* title, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_TextGet(title,yab)); +} + +int textget2(const char* title, const char* option, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_TextGet2(title,option,yab); +} + +char* textget3(const char* title, int linenum, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return (char*)yi_TextGet3(title,linenum,yab); +} + +double textget4(const char* title, const char* option, int linenum, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_TextGet4(title,option,linenum,yab); +} + +int textget5(const char* title, const char* option, const char* option2, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_TextGet5(title,option,option2,yab); +} + +char* textget6(const char* title, const char* option, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return (char*)yi_TextGet6(title,option,yab); +} + +void view(struct command *cmd, YabInterface *yab) +{ + char *id, *view; + double x1, y1, x2, y2; + + + view = 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_View(x1,y1,x2,y2, id, view, yab); +} + +void boxview(struct command *cmd, YabInterface *yab) +{ + char *id, *view, *text; + double x1, y1, x2, y2; + int linetype; + + + view = pop(stSTRING)->pointer; + linetype = pop(stNUMBER)->value; + text = 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_BoxView(x1,y1,x2,y2, id, text, linetype, view, yab); +} + +void boxviewset(struct command *cmd, YabInterface *yab) +{ + char *id, *value, *option; + + + + value= pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_BoxViewSet(id, option, value, yab); +} + + + +void tab(struct command *cmd, YabInterface *yab) +{ + char *id, *names, *view; + double x1, y1, x2, y2; + + + view = pop(stSTRING)->pointer; + names = 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_Tab(x1,y1,x2,y2, id, names, view, yab); +} + +void tabset(struct command *cmd, YabInterface *yab) +{ + char *tabname; + int num; + + + num = pop(stNUMBER)->value; + tabname = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TabSet(tabname, num, yab); +} + +void tabadd(struct command *cmd, YabInterface *yab) +{ + char *id, *tabname; + + + tabname = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TabAdd(id, tabname, yab); +} + +void tabdel(struct command *cmd, YabInterface *yab) +{ + char *id; + int num; + + + num = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TabDel(id, num, yab); +} + +void slider1(struct command *cmd, YabInterface *yab) +{ + char *view, *id, *title; + double x1,y1,x2,y2,min,max; + + + view = pop(stSTRING)->pointer; + max = pop(stNUMBER)->value; + min = pop(stNUMBER)->value; + 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_Slider1(x1,y1,x2,y2,id,title,min,max,view,yab); +} + + +void slider2(struct command *cmd, YabInterface *yab) +{ + char *view, *id, *title, *option; + double x1,y1,x2,y2,min,max; + + + view = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + max = pop(stNUMBER)->value; + min = pop(stNUMBER)->value; + 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_Slider2(x1,y1,x2,y2,id,title,min,max,option,view,yab); +} + +void slider3(struct command *cmd, YabInterface *yab) +{ + char *id, *label1, *label2; + + + label2 = pop(stSTRING)->pointer; + label1 = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetSlider1(id,label1,label2,yab); +} + + +void slider4(struct command *cmd, YabInterface *yab) +{ + char *id, *bottomtop; + int count; + + + count = pop(stNUMBER)->value; + bottomtop = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetSlider2(id,bottomtop,count,yab); +} + +void slider5(struct command *cmd, YabInterface *yab) +{ + char *id, *part; + int r,g,b; + + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + part = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetSlider3(id,part,r,g,b,yab); +} + +void slider6(struct command *cmd, YabInterface *yab) +{ + char *id; + int value; + + + value = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetSlider4(id,value,yab); +} + +void option1(struct command *cmd, YabInterface *yab) +{ + char *id, *option, *value; + + + value = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetOption1(id,option,value,yab); +} + +void option2(struct command *cmd, YabInterface *yab) +{ + char *id, *part; + int r,g,b; + + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + part = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetOption2(id,part,r,g,b,yab); +} + +void option3(struct command *cmd, YabInterface *yab) +{ + char *id, *option; + double x,y; + + + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetOption3(id,option,x,y,yab); +} + +void option4(struct command *cmd, YabInterface *yab) +{ + char *id, *option; + + + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetOption4(id,option,yab); +} + +void option5(struct command *cmd, YabInterface *yab) +{ + char *id, *option; + int value; + + + value = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SetOption5(id,option,value,yab); +} + +void dropzone(struct command *cmd, YabInterface *yab) +{ + char *view; + + + view = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DropZone(view,yab); +} + +void colorcontrol1(struct command *cmd, YabInterface *yab) +{ + char *view, *id; + double x,y; + + + view = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ColorControl1(x,y,id,view,yab); +} + +void colorcontrol2(struct command *cmd, YabInterface *yab) +{ + char *id; + double r,g,b; + + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ColorControl2(id,r,g,b,yab); +} + +void textcontrol2(struct command *cmd, YabInterface *yab) +{ + char *id, *text; + + + text = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextControl2(id,text,yab); +} + +void textcontrol3(struct command *cmd, YabInterface *yab) +{ + char *id; + int mode; + mode = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextControl3(id,mode,yab); +} + +void textcontrol5(struct command *cmd, YabInterface *yab) +{ + char *id; + + + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextControl5(id,yab); +} + + +void textcontrol4(struct command *cmd, YabInterface *yab) +{ + char *id, *option, *value; + + + value = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextControl4(id,option,value,yab); +} + + + + +void treebox1(struct command *cmd, YabInterface *yab) +{ + char *id, *view; + double x1,y1,x2,y2; + int scrollbarType; + + + view = pop(stSTRING)->pointer; + scrollbarType = pop(stNUMBER)->value; + 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_TreeBox1(x1,y1,x2,y2,id,scrollbarType,view,yab); +} + +void treebox2(struct command *cmd, YabInterface *yab) +{ + char *id, *item; + + + item = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox2(id,item,yab); +} + +void treebox3(struct command *cmd, YabInterface *yab) +{ + char *id, *head, *item; + int isExpanded; + + + isExpanded = pop(stNUMBER)->value; + item = pop(stSTRING)->pointer; + head = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox3(id,head,item,isExpanded,yab); +} + +void treebox4(struct command *cmd, YabInterface *yab) +{ + char *id; + + + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox4(id,yab); +} + +void treebox5(struct command *cmd, YabInterface *yab) +{ + char *id,*item; + + + item = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox5(id,item,yab); +} + +void treebox7(struct command *cmd, YabInterface *yab) +{ + char *id; + int pos; + + + pos = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox7(id,pos,yab); +} + +void treebox8(struct command *cmd, YabInterface *yab) +{ + char *id; + int pos; + + + pos = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox8(id,pos,yab); +} + +void treebox9(struct command *cmd, YabInterface *yab) +{ + char *id, *head, *item; + + + item = pop(stSTRING)->pointer; + head = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox9(id,head,item,yab); +} + +void treebox10(struct command *cmd, YabInterface *yab) +{ + char *id, *head; + + + head = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox10(id,head,yab); +} + +void treebox11(struct command *cmd, YabInterface *yab) +{ + char *id, *head; + + + head = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox11(id,head,yab); +} + +void treebox12(struct command *cmd, YabInterface *yab) +{ + char *id, *item; + int pos; + + + pos = pop(stNUMBER)->value; + item = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeBox12(id,item,pos,yab); +} + +void buttonimage(struct command *cmd, YabInterface *yab) +{ + char *id, *enabledon, *enabledoff, *disabled, *view; + double x,y; + + + view = pop(stSTRING)->pointer; + disabled = pop(stSTRING)->pointer; + enabledoff = pop(stSTRING)->pointer; + enabledon = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ButtonImage(x,y,id,enabledon, enabledoff, disabled, view,yab); +} + +void checkboximage(struct command *cmd, YabInterface *yab) +{ + char *id, *enabledon, *enabledoff, *disabledon, *disabledoff, *view; + double x,y; + int isActivated; + + + view = pop(stSTRING)->pointer; + isActivated = pop(stNUMBER)->value; + disabledoff = pop(stSTRING)->pointer; + disabledon = pop(stSTRING)->pointer; + enabledoff = pop(stSTRING)->pointer; + enabledon = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CheckboxImage(x,y,id,enabledon, enabledoff, disabledon, disabledoff, isActivated, view,yab); +} + +void checkboxset(struct command *cmd, YabInterface *yab) +{ + char *id; + int isActivated; + + + isActivated = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_CheckboxSet(id,isActivated,yab); +} + +void radioset(struct command *cmd, YabInterface *yab) +{ + char *id; + int isActivated; + + + isActivated = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_RadioSet(id,isActivated,yab); +} + +char* textcontrolget(const char* textcontrol, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_TextControlGet(textcontrol,yab)); +} + +void tooltip(struct command *cmd, YabInterface *yab) +{ + char *view,*text; + + + text = pop(stSTRING)->pointer; + view = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ToolTip(view,text,yab); +} + +void tooltipcolor(struct command *cmd, YabInterface *yab) +{ + char *color; + int r,g,b; + + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + color = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ToolTipColor(color,r,g,b,yab); +} + +void listsort(struct command *cmd, YabInterface *yab) +{ + char *id; + + + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ListSort(id,yab); +} + +void treesort(struct command *cmd, YabInterface *yab) +{ + char *id; + + + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TreeSort(id,yab); +} + +void filebox(struct command *cmd, YabInterface *yab) +{ + char *id,*view, *option; + int scrollbar; + double x1,y1,x2,y2; + + + view = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + scrollbar = pop(stNUMBER)->value; + 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_FileBox(x1,y1,x2,y2,id,scrollbar,option,view,yab); +} + +void fileboxadd2(struct command *cmd, YabInterface *yab) +{ + char *columnbox, *name, *option; + double width, maxWidth, minWidth; + int pos; + + + option = pop(stSTRING)->pointer; + width = pop(stNUMBER)->value; + minWidth = pop(stNUMBER)->value; + maxWidth = pop(stNUMBER)->value; + pos = pop(stNUMBER)->value; + name = pop(stSTRING)->pointer; + columnbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_FileBoxAdd2(columnbox, name, pos, maxWidth, minWidth, width, option, yab); +} + +void fileboxclear(struct command *cmd, YabInterface *yab) +{ + char *id; + + + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_FileBoxClear(id,yab); +} + +void columnboxadd(struct command *cmd, YabInterface *yab) +{ + char *id, *item ; + int position, height, column; + + + item = pop(stSTRING)->pointer; + height = pop(stNUMBER)->value; + position = pop(stNUMBER)->value; + column = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ColumnBoxAdd(id,column,position,height,item,yab); +} + +void columnboxremove(struct command *cmd, YabInterface *yab) +{ + char *columnbox; + int pos; + + + pos = pop(stNUMBER)->value; + columnbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ColumnBoxRemove(columnbox,pos,yab); +} + +void columnboxselect(struct command *cmd, YabInterface *yab) +{ + char *columnbox; + int pos; + + + pos = pop(stNUMBER)->value; + columnbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ColumnBoxSelect(columnbox,pos,yab); +} + +void columnboxcolor(struct command *cmd, YabInterface *yab) +{ + char *columnbox, *option; + int r,g,b; + + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + columnbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ColumnBoxColor(columnbox,option,r,g,b,yab); +} + +void dropboxselect(struct command *cmd, YabInterface *yab) +{ + char *dropbox; + int num; + + + num = pop(stNUMBER)->value; + dropbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DropBoxSelect(dropbox,num,yab); +} + +void menu2(struct command *cmd, YabInterface *yab) +{ + char *menuhead, *view; + int radio; + + + view = pop(stSTRING)->pointer; + radio = pop(stNUMBER)->value; + menuhead = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Menu2(menuhead,radio,view,yab); +} + +void submenu1(struct command *cmd, YabInterface *yab) +{ + char *menuhead, *menuitem, *submenuitem, *modifier, *view; + + + view = pop(stSTRING)->pointer; + modifier = pop(stSTRING)->pointer; + submenuitem = pop(stSTRING)->pointer; + menuitem = pop(stSTRING)->pointer; + menuhead = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SubMenu1(menuhead,menuitem,submenuitem,modifier,view,yab); +} + +void submenu2(struct command *cmd, YabInterface *yab) +{ + char *menuhead, *menuitem, *view; + int radio; + + + view = pop(stSTRING)->pointer; + radio = pop(stNUMBER)->value; + menuitem = pop(stSTRING)->pointer; + menuhead = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SubMenu2(menuhead,menuitem,radio,view,yab); +} + +void submenu3(struct command *cmd, YabInterface *yab) +{ + char *menuhead, *menuitem, *submenuitem, *option, *view; + + + view = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + submenuitem = pop(stSTRING)->pointer; + menuitem = pop(stSTRING)->pointer; + menuhead = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SubMenu3(menuhead,menuitem,submenuitem,option,view,yab); +} + +void menu3(struct command *cmd, YabInterface *yab) +{ + char *menuhead, *menuitem, *option, *view; + + + view = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + menuitem = pop(stSTRING)->pointer; + menuhead = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Menu3(menuhead,menuitem,option,view,yab); +} + +int sliderget(const char *slider, YabInterface *yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_SliderGet(slider, yab); +} + +int colorcontrolget(const char* colorcontrol, const char* option, YabInterface *yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ColorControlGet(colorcontrol, option, yab); +} + +void spincontrol1(struct command *cmd, YabInterface *yab) +{ + char *id, *view, *label; + int min, max, step; + double x,y; + + + view = pop(stSTRING)->pointer; + step = pop(stNUMBER)->value; + max = pop(stNUMBER)->value; + min = pop(stNUMBER)->value; + label = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SpinControl1(x,y,id,label,min,max,step,view,yab); +} + +void spincontrol2(struct command *cmd, YabInterface *yab) +{ + char *spincontrol; + int value; + + + value = pop(stNUMBER)->value; + spincontrol = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SpinControl2(spincontrol,value,yab); +} + +int spincontrolget(const char* view, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_SpinControlGet(view,yab); +} + +char* popupmenu(double x, double y, const char* menuitems, const char* view, YabInterface *yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_PopUpMenu(x,y,menuitems,view,yab)); +} + +void dropboxremove(struct command *cmd, YabInterface *yab) +{ + char *dropbox; + int value; + + + value = pop(stNUMBER)->value; + dropbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DropBoxRemove(dropbox,value,yab); +} + +void dropboxclear(struct command *cmd, YabInterface *yab) +{ + char *dropbox; + + + dropbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DropBoxClear(dropbox,yab); +} + +int dropboxcount(const char* id, YabInterface *yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_DropBoxCount(id,yab); +} + +char* dropboxget(const char* id, int position, YabInterface *yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_DropBoxGet(id,position,yab)); +} + +void splitview1(struct command *cmd, YabInterface *yab) +{ + char *id, *view; + double x1,y1,x2,y2; + int isVertical, NormalStyle; + + + view = pop(stSTRING)->pointer; + NormalStyle = pop(stNUMBER)->value; + isVertical = pop(stNUMBER)->value; + 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_SplitView1(x1,y1,x2,y2, id, isVertical, NormalStyle, view, yab); +} + +void splitview2(struct command *cmd, YabInterface *yab) +{ + char *id, *option; + double value; + + + value = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SplitView2(id, option, value, yab); +} + +void splitview3(struct command *cmd, YabInterface *yab) +{ + char *id, *option; + double left, right; + + + right = pop(stNUMBER)->value; + left = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SplitView3(id, option, left, right, yab); +} + +double splitviewget(const char* id, const char* option, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_SplitViewGet(id, option, yab); +} + +void stackview1(struct command *cmd, YabInterface *yab) +{ + char *id, *view; + double x1,y1,x2,y2; + int number; + + + view = pop(stSTRING)->pointer; + number = pop(stNUMBER)->value; + 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_StackView1(x1,y1,x2,y2, id, number, view, yab); +} + +void stackview2(struct command *cmd, YabInterface *yab) +{ + char *id; + int num; + + + num = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_StackView2(id, num, yab); +} + +int stackviewget(const char* id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_StackViewGet(id, yab); +} + +int tabviewget(const char* id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_TabViewGet(id, yab); +} + +void calendar1(struct command *cmd, YabInterface *yab) +{ + char *format, *id, *date, *view; + double x,y; + + + view = pop(stSTRING)->pointer; + date = pop(stSTRING)->pointer; + format = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Calendar1(x,y, id, format, date, view, yab); +} + +char* calendar2(const char* id, YabInterface *yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_Calendar2(id, yab)); +} + +void calendar3(struct command *cmd, YabInterface *yab) +{ + char *id, *date; + + + date = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Calendar3(id, date, yab); +} + +void scrollbar(struct command *cmd, YabInterface *yab) +{ + char *view, *id; + int format; + + view = pop(stSTRING)->pointer; + format = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Scrollbar(id, format, view, yab); +} + +void scrollbarset1(struct command *cmd, YabInterface *yab) +{ + char *scrollbar, *option; + double position; + + + position = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + scrollbar = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ScrollbarSet1(scrollbar, option, position, yab); +} + +void scrollbarset2(struct command *cmd, YabInterface *yab) +{ + char *scrollbar, *option; + double a,b; + + + b = pop(stNUMBER)->value; + a = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + scrollbar = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ScrollbarSet2(scrollbar, option, a, b, yab); +} + +void scrollbarset3(struct command *cmd, YabInterface *yab) +{ + char *scrollbar, *option; + double a,b; + + + option = pop(stSTRING)->pointer; + scrollbar = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ScrollbarSet3(scrollbar, option, yab); +} + +void texturl1(struct command *cmd, YabInterface *yab) +{ + char *id, *text, *url, *view; + double x,y; + + + view = pop(stSTRING)->pointer; + url = pop(stSTRING)->pointer; + text = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextURL1(x,y, id, text, url, view, yab); +} + +void texturl2(struct command *cmd, YabInterface *yab) +{ + char *id, *color; + int r,g,b; + + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + color = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_TextURL2(id, color,r,g,b,yab); +} + +double scrollbarget(const char* scrollbar, const char* option, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ScrollbarGet(scrollbar, option, yab); +} + +void clipboardcopy(struct command *cmd, YabInterface *yab) +{ + char *text; + text = pop(stSTRING)->pointer; + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ClipboardCopy(text,yab); +} + +int printer(const char* docname, const char *view, const char* config, YabInterface *yab,int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_Printer(docname, view,config,yab); +} + +void printerconfig(struct command *cmd, YabInterface *yab) +{ + char *config, *docname; + + config = pop(stSTRING)->pointer; + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_PrinterConfig(config,yab); +} + +void listboxadd1(struct command *cmd, YabInterface *yab) +{ + char *listbox, *item; + + + item = pop(stSTRING)->pointer; + listbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ListboxAdd1(listbox, item, yab); +} + +void listboxadd2(struct command *cmd, YabInterface *yab) +{ + char *listbox, *item; + int position; + + + item = pop(stSTRING)->pointer; + position = pop(stNUMBER)->value; + listbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ListboxAdd2(listbox, position, item, yab); +} + +void listboxselect(struct command *cmd, YabInterface *yab) +{ + char *listbox; + int position; + + + position = pop(stNUMBER)->value; + listbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ListboxSelect(listbox, position, yab); +} + +void listboxremove(struct command *cmd, YabInterface *yab) +{ + char *listbox; + int position; + + + position = pop(stNUMBER)->value; + listbox = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ListboxRemove(listbox, position, yab); +} + +char* clipboardpaste(YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_ClipboardPaste(yab)); +} + +char* keyboardmessages(const char* view, YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_KeyboardMessages(view,yab)); +} + +char* columnboxget(const char* columnbox, int column, int position, YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_ColumnBoxGet(columnbox,column,position,yab)); +} + +int columnboxcount(const char* columnbox, YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ColumnBoxCount(columnbox, yab); +} + +int windowgetnum(const char* view, const char *option, YabInterface* yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_WindowGet(view,option,yab); +} + +int viewgetnum(const char* view, const char *option, YabInterface* yab, int line, const char* libname) //vasper +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ViewGet(view,option,yab); +} + +double drawget1(const char* option, const char* txt, const char* view, YabInterface* yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_DrawGet1(option, txt, view, yab); +} + +double drawget2(const char* option, const char* view, YabInterface* yab, int line, const char* libname) +{ + + yi_SetCurrentLineNumber(line, libname, yab); + return yi_DrawGet2(option, view, yab); +} + +char* drawget3(const char* option, YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_DrawGet3(option, yab)); +} + +int drawget4(double x, double y, const char* rgb, const char* view, YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_DrawGet4(x,y,rgb, view, yab); +} + +int newalert(const char* text, const char* button1, const char* button2, const char* button3, const char* option, YabInterface* yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_NewAlert(text,button1,button2,button3,option,yab); +} + +char* listboxget(const char* listbox, int position, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_ListboxGet(listbox,position,yab)); +} + +int listboxcount(const char* listbox, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ListboxCount(listbox, yab); +} + +char* treeboxget(const char* treebox, int position, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_TreeboxGet(treebox,position,yab)); +} + +int treeboxcount(const char* treebox, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_TreeboxCount(treebox, yab); +} + +int ismousein(const char* view, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_IsMouseIn(view,yab); +} + +char* getmousein(YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_GetMouseIn(yab)); +} + +char* getmousemessages(const char* view, YabInterface* yab, int line, const char* libname) /* get a mouse message string */ +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_GetMouseMessages(view, yab)); +} + +char* getmessages(YabInterface* yab, int line, const char* libname) /* get message string */ +{ + // char tmp[1024]; + //strcpy(tmp, yi_CheckMessages(yab)); + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_CheckMessages(yab)); +} + +int messagesend(const char* app, const char *msg, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_MessageSend(app, msg, yab); +} + +int threadkill(const char* option, int id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ThreadKill(option, id, yab); +} + +int threadget(const char* option, const char* appname, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ThreadGet(option, appname, yab); +} + +void bitmap(struct command *cmd, YabInterface *yab) +{ + char *id; + double w,h; + + id = pop(stSTRING)->pointer; + h = pop(stNUMBER)->value; + w = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Bitmap(w, h, id, yab); +} + +void bitmapdraw(struct command *cmd, YabInterface *yab) +{ + char *id, *mask, *view; + double x,y; + + view = pop(stSTRING)->pointer; + mask = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + y = pop(stNUMBER)->value; + x = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_BitmapDraw(x,y, id, mask, view, yab); +} + +void bitmapdraw2(struct command *cmd, YabInterface *yab) +{ + char *id, *mask, *view; + double x1,y1,x2,y2; + + view = pop(stSTRING)->pointer; + mask = 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_BitmapDraw2(x1,y1,x2,y2, id, mask, view, yab); +} + +void bitmapget(struct command *cmd, YabInterface *yab) +{ + char *id, *bitmap; + double x1,y1,x2,y2; + + bitmap = 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_BitmapGet(x1,y1, x2,y2, id, bitmap, yab); +} + +void bitmapget2(struct command *cmd, YabInterface *yab) +{ + char *id, *path; + double w; + + path = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + w = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_BitmapGet2(w, id, path, yab); +} + +void bitmapgeticon(struct command *cmd, YabInterface *yab) +{ + char *id, *option, *path; + + path = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_BitmapGetIcon(id, option, path, yab); +} + +void bitmapdrag(struct command *cmd, YabInterface *yab) +{ + char *id; + + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_BitmapDrag(id, yab); +} + +void screenshot(struct command *cmd, YabInterface *yab) +{ + char *bitmap; + double x1,y1,x2,y2; + + bitmap = 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_Screenshot(x1,y1,x2,y2, bitmap, yab); +} + +void statusbar(struct command *cmd, YabInterface *yab) +{ + char *view, *label2, *label1, *id; + double x1, y1, x2, y2; + + view = pop(stSTRING)->pointer; + label2 = pop(stSTRING)->pointer; + label1 = 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_StatusBar(x1,y1,x2,y2, id, label1, label2, view, yab); +} + +void statusbarset(struct command *cmd, YabInterface *yab) +{ + double state; + char *label2, *label1, *id; + + state = pop(stNUMBER)->value; + label2 = pop(stSTRING)->pointer; + label1 = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_StatusBarSet(id, label1, label2, state, yab); +} + +void statusbarset2(struct command *cmd, YabInterface *yab) +{ + double x1, y1, x2, y2; + char *id, *view; + + view = 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_StatusBarSet2(x1,y1,x2,y2, id, view, yab); +} + +void statusbarset3(struct command *cmd, YabInterface *yab) +{ + int r,g,b; + char *id; + + b = pop(stNUMBER)->value; + g = pop(stNUMBER)->value; + r = pop(stNUMBER)->value; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_StatusBarSet3(id, r, g, b, yab); +} + +void bitmapremove(struct command *cmd, YabInterface *yab) +{ + char *id; + + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_BitmapRemove(id, yab); +} + +int bitmapsave(const char* id, const char* filename, const char* type, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_BitmapSave(id, filename, type, yab); +} + +int bitmapload(const char* filename, const char* id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_BitmapLoad(filename, id, yab); +} + +int bitmapgetnum(const char* id, const char* option, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_BitmapGetNum(id, option, yab); +} + +int bitmapcolor(double x, double y, const char* id, const char* option, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_BitmapColor(x,y,id,option,yab); +} + +void canvas(struct command *cmd, YabInterface *yab) +{ + char *id, *view; + double x1,y1,x2,y2; + + + view = 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_Canvas(x1,y1,x2,y2,id,view, yab); +} + +int listboxgetnum(const char* id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ListboxGetNum(id, yab); +} + +int dropboxgetnum(const char* id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_DropboxGetNum(id, yab); +} + +int columnboxgetnum(const char* id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_ColumnboxGetNum(id, yab); +} + +int treeboxgetnum(const char* id, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_TreeboxGetNum(id, yab); +} + +int treeboxgetopt(const char* id, const char* option, int pos, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_TreeboxGetOpt(id, option, pos, yab); +} + +void treebox13(struct command *cmd, YabInterface *yab) +{ + char *id, *option; + int pos; + + pos = pop(stNUMBER)->value; + option = pop(stSTRING)->pointer; + id = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Treebox13(id,option,pos, yab); +} + +void drawset4(struct command *cmd, YabInterface *yab) +{ + char *option, *color, *view; + + view = pop(stSTRING)->pointer; + color = pop(stSTRING)->pointer; + option = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_DrawSet4(option, color, view, yab); +} + +void launch(struct command *cmd, YabInterface *yab) +{ + char *strg; + strg = pop(stSTRING)->pointer; + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Launch(strg, yab); +} + +int sound(const char* filename, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_Sound(filename, yab); +} + +void soundstop(struct command *cmd, YabInterface *yab) +{ + int id; + + id = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SoundStop(id, yab); +} + +void soundwait(struct command *cmd, YabInterface *yab) +{ + int id; + + id = pop(stNUMBER)->value; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_SoundWait(id, yab); +} + +int iscomputeron(YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_IsComputerOn(yab); +} + +void attribute1(struct command *cmd, YabInterface *yab) +{ + char *type, *name, *value, *filename; + + filename = pop(stSTRING)->pointer; + value = pop(stSTRING)->pointer; + name = pop(stSTRING)->pointer; + type = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_Attribute1(type, name, value, filename, yab); +} + +void attributeclear(struct command *cmd, YabInterface *yab) +{ + char *name, *filename; + + filename = pop(stSTRING)->pointer; + name = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_AttributeClear(name, filename, yab); +} + + +char* attributeget1(const char* name, const char* filename, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return my_strdup((char*)yi_AttributeGet1(name, filename, yab)); +} + +double attributeget2(const char* name, const char* filename, YabInterface *yab, int line, const char* libname) +{ + yi_SetCurrentLineNumber(line, libname, yab); + return yi_AttributeGet2(name, filename, yab); +} + +void shortcut(struct command *cmd, YabInterface *yab) +{ + char *view, *key, *msg; + + msg = pop(stSTRING)->pointer; + key = pop(stSTRING)->pointer; + view = pop(stSTRING)->pointer; + + yi_SetCurrentLineNumber(cmd->line, (const char*)cmd->lib->s, yab); + yi_ShortCut(view, key, msg, yab); +} + +void gettermkey(char *keybuff) /* read a key from terminal */ +{ +#ifdef BUILD_NCURSES + char *skey=NULL; + int key; /* returned key */ + + do key=getch(); while(key==ERR); + switch(key) { + case KEY_UP: skey=ykey[kUP];break; + case KEY_DOWN: skey=ykey[kDOWN];break; + case KEY_LEFT: skey=ykey[kLEFT];break; + case KEY_RIGHT: skey=ykey[kRIGHT];break; + case KEY_DC: skey=ykey[kDEL];break; + case KEY_IC: skey=ykey[kINS];break; + case KEY_IL: skey=ykey[kINS];break; + case KEY_CLEAR: skey=ykey[kCLEAR];break; + case KEY_HOME: skey=ykey[kHOME];break; +#ifdef KEY_END + case KEY_END: skey=ykey[kEND];break; +#endif + case KEY_F0: skey=ykey[kF0];break; + case KEY_F(1): skey=ykey[kF1];break; + case KEY_F(2): skey=ykey[kF2];break; + case KEY_F(3): skey=ykey[kF3];break; + case KEY_F(4): skey=ykey[kF4];break; + case KEY_F(5): skey=ykey[kF5];break; + case KEY_F(6): skey=ykey[kF6];break; + case KEY_F(7): skey=ykey[kF7];break; + case KEY_F(8): skey=ykey[kF8];break; + case KEY_F(9): skey=ykey[kF9];break; + case KEY_F(10): skey=ykey[kF10];break; + case KEY_F(11): skey=ykey[kF11];break; + case KEY_F(12): skey=ykey[kF12];break; + case KEY_F(13): skey=ykey[kF13];break; + case KEY_F(14): skey=ykey[kF14];break; + case KEY_F(15): skey=ykey[kF15];break; + case KEY_F(16): skey=ykey[kF16];break; + case KEY_F(17): skey=ykey[kF17];break; + case KEY_F(18): skey=ykey[kF18];break; + case KEY_F(19): skey=ykey[kF19];break; + case KEY_F(20): skey=ykey[kF20];break; + case KEY_F(21): skey=ykey[kF21];break; + case KEY_F(22): skey=ykey[kF22];break; + case KEY_F(23): skey=ykey[kF23];break; + case KEY_F(24): skey=ykey[kF24];break; + case KEY_BACKSPACE: skey=ykey[kBACKSPACE];break; + case KEY_NPAGE: skey=ykey[kSCRNDOWN];break; + case KEY_PPAGE: skey=ykey[kSCRNUP];break; + case KEY_ENTER: skey=ykey[kENTER];break; + default: + if (isprint(key)) { + keybuff[0]=key; + keybuff[1]='\0'; + } else if (key<0 || key>=KEY_MAX) { + keybuff[0]='\0'; + } else { + switch(key) { + case 0x1b:skey=ykey[kESC];break; + case 0x7f:skey=ykey[kDEL];break; + case 0xa:skey=ykey[kENTER];break; + case 0x9:skey=ykey[kTAB];break; + default: + sprintf(keybuff,"key%x",key); + } + } + break; + } + if (skey) strcpy(keybuff,skey); + snooze(20000); +#endif +} + diff --git a/src/io.c b/src/io.c new file mode 100644 index 0000000..b925021 --- /dev/null +++ b/src/io.c @@ -0,0 +1,1586 @@ +/* + + YABASIC --- a simple Basic Interpreter + written by Marc-Oliver Ihm 1995-2004 + homepage: www.yabasic.de + + io.c --- code for screen and file i/o + + This file is part of yabasic and may be copied only + under the terms of either the Artistic License or + the GNU General Public License (GPL), both of which + can be found at www.yabasic.de + +*/ + + +/* ------------- defines ---------------- */ + +#ifdef WINDOWS +#define WM_WANTKEY (WM_APP+7) +#endif + +/* ------------- includes ---------------- */ + +#ifndef YABASIC_INCLUDED +#include "yabasic.h" /* all prototypes and structures */ +#endif + + +/* ------------- local defines ----------------- */ + +#define YC_BLACK 0 +#define YC_WHITE 1 +#define YC_RED 2 +#define YC_BLUE 3 +#define YC_GREEN 4 +#define YC_YELLOW 5 +#define YC_CYAN 6 +#define YC_MAGENTA 7 + +#ifndef COLOR_BLACK +#define COLOR_BLACK 0 +#define COLOR_RED 1 +#define COLOR_GREEN 2 +#define COLOR_YELLOW 3 +#define COLOR_BLUE 4 +#define COLOR_MAGENTA 5 +#define COLOR_CYAN 6 +#define COLOR_WHITE 7 +#endif +#ifndef A_COLOR +#define A_COLOR 0xff00 +#endif + +/* ------------- external references ---------------- */ + +extern int mylineno; /* current line number */ +extern int yyparse(); /* call bison parser */ + + +/* ------------- local functions ---------------- */ + +static int onechar(void); /* read one char from currentinstream */ +static void backchar(int); /* put char back into stream */ +static void readline(void); /* read one line from current stream */ +static void curinit(void); /* initialize curses */ +static void initcol(void); /* initialize curses colors */ +void myswitch(int); /* switch to specified stream */ +int checkstream(void); /* test if currst is still valid */ +#ifdef WINDOWS +static DWORD keythread(LPWORD); /* wait for key input from console */ +static int is_valid_key(INPUT_RECORD *); /* check if input rec is valid key */ +#endif +int name2yc(char *); /* convert a color name to an integer */ +int yc2oc(int,int); /* convert a yabasic color to operating system color */ +char *yc2short(int); /* convert yabasic colours to short colour name */ +#ifdef UNIX +int oc2yc(int); /* convert an operating system color to yabasic color */ +#endif + +/* ------------- global variables ---------------- */ + +static int prompted; /* TRUE, if prompt is fresh */ +int read_controls; /* TRUE, if input should read control characters */ +FILE *streams[FOPEN_MAX]; /* file streams */ +int stream_modes[FOPEN_MAX]; /* modes for streams */ +int lprstream=-1; /* stream associated with lineprinter */ +static int currstr=STDIO_STREAM; /* currently switched stream */ +static FILE *cinstr; /* current stream for input */ +static FILE *coutstr; /* current stream for output */ +static char linebuffer[INBUFFLEN]; /* buffer for one line of input */ +int curinized=FALSE; /* true, if curses has been initialized */ +static char *currchar; /* current char to read */ +static short stdfc; /* standard foreground color of window */ +static short stdbc; /* standard background color of window */ +#ifdef UNIX +int winpid=-1; /* pid of process waiting for window keys */ +int termpid=-1; /* pid of process waiting for terminal keys */ +FILE *lineprinter=NULL; /* handle for line printer */ +#ifndef BUILD_NCURSES +int COLS = 80; +int LINES = 25; +#endif +#else +HANDLE wantkey=INVALID_HANDLE_VALUE; /* mutex to signal key desire */ +HANDLE gotkey=INVALID_HANDLE_VALUE; /* mutex to signal key reception */ +HANDLE wthandle=INVALID_HANDLE_VALUE; /* handle of win thread */ +HANDLE kthandle=INVALID_HANDLE_VALUE; /* handle of inkey thread */ +DWORD ktid; /* id of inkey thread */ +int LINES=0; /* number of lines on screen */ +int COLS=0; /* number of columns on screen */ +HANDLE ConsoleInput; /* handle for console input */ +HANDLE ConsoleOutput; /* handle for console output */ +HANDLE lineprinter=INVALID_HANDLE_VALUE; /* handle for line printer */ +#endif + + +/* ------------- functions ---------------- */ + +void create_print(char type) /* create command 'print' */ +{ + struct command *cmd; + + cmd=add_command(cPRINT,NULL); + cmd->pointer=my_malloc(sizeof(int)); + /* store type of print */ + cmd->tag=type; +} + + +void print(struct command *cmd) /* print on screen */ +{ + int type; + struct stackentry *p,*q,*r; + static int last='n'; + char *s; + int x,y; + long int n; + double d; +#ifdef WINDOWS + CONSOLE_SCREEN_BUFFER_INFO csbi; + SMALL_RECT screen; + COORD to; + CHAR_INFO ci; +#endif + + r=NULL; + type=cmd->tag; + if (!checkstream()) return; + switch(type) { + case 'n': /* print newline */ + if (curinized && coutstr==stdout) { +#ifdef WINDOWS + GetConsoleScreenBufferInfo(ConsoleOutput,&csbi); + x=csbi.dwCursorPosition.X; + y=csbi.dwCursorPosition.Y; + if (y>=LINES-1) { + screen.Left=0; + screen.Right=COLS; + screen.Top=1; + screen.Bottom=LINES; + to.X=0; + to.Y=0; + ci.Char.AsciiChar=' '; + ci.Attributes=FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED; + ScrollConsoleScreenBuffer(ConsoleOutput,&screen,NULL,to,&ci); + to.X=0; + to.Y=y; + } else { + to.X=0; + to.Y=y+1; + } + SetConsoleCursorPosition(ConsoleOutput,to); + break; +#else +#ifdef BUILD_NCURSES + getyx(stdscr,y,x); + if (y>=LINES-1) { + scrl(1); + y=y-1; + } + move(y+1,0); + refresh(); +#endif + break; +#endif + } else { + string[0]='\n'; + if (abs(currstr)==lprstream) { + string[1]='\r'; + string[2]='\0'; + } else { + string[1]='\0'; + } + } + onestring(string); + break; + case 't': /* print tab */ + string[0]='\t'; + string[1]='\0'; + onestring(string); + break; + case 'd': /* print double value */ + p=pop(stNUMBER); + d=p->value; + n=(int)d; + if (n==d && dLONG_MIN) + sprintf(string,"%s%ld",(last=='d')?" ":"",n); + else + sprintf(string,"%s%g",(last=='d')?" ":"",d); + onestring(string); + break; + case 'U': + r=pop(stSTRING); + case 'u': /* print using */ + p=pop(stSTRING); + q=pop(stNUMBER); + type='d'; + s=string; + if (last=='d') { + *s=' '; + s++; + } + if (!myformat(s,q->value,p->pointer,r?r->pointer:NULL)) { + sprintf(string,"'%s' is not a valid format",(char *)p->pointer); + error(ERROR,string); + break; + } + onestring(string); + break; + case 's': + p=pop(stSTRING); + onestring((char *)p->pointer); + break; + } + last=type; +} + + +void mymove() /* move to specific position on screen */ +{ +#ifdef BUILD_NCURSES + int x,y; +#ifdef WINDOWS + COORD coord; +#endif + + y=(int)pop(stNUMBER)->value; + if (y<0) y=0; + if (y>LINES-1) y=LINES-1; + x=(int)pop(stNUMBER)->value; + if (x<0) x=0; + if (x>COLS-1) x=COLS-1; + if (!curinized) { + error(ERROR,"need to call 'clear screen' first"); + return; + } +#ifdef UNIX + move(y,x); + refresh(); +#else + coord.X=x; + coord.Y=y; + SetConsoleCursorPosition(ConsoleOutput,coord); +#endif +#endif +} + + +void clearscreen() /* clear entire screen */ +{ +#ifdef WINDOWS + DWORD written; /* number of chars actually written */ + COORD coord; /* coordinates to start writing */ +#endif + + if (!curinized) curinit(); +#ifdef UNIX +#ifdef BUILD_NCURSES + clear(); + refresh(); +#else + error(ERROR,"ncurses support was not compiled!"); +#endif +#else + coord.X=0; + coord.Y=0; + FillConsoleOutputCharacter(ConsoleOutput,' ',LINES*COLS,coord,&written); + FillConsoleOutputAttribute(ConsoleOutput, + FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE, + LINES*COLS, + coord,&written); + SetConsoleCursorPosition(ConsoleOutput,coord); +#endif +} + + +static void curinit(void) /* initialize curses */ +{ +#ifdef WINDOWS + CONSOLE_SCREEN_BUFFER_INFO coninfo; /* receives console size */ +#endif + +#ifdef UNIX +#ifdef BUILD_NCURSES + initscr(); + initcol(); + setscrreg(0,LINES); + scrollok(stdscr,TRUE); + leaveok(stdscr,TRUE); + keypad(stdscr,TRUE); + intrflush(stdscr,FALSE); + curs_set(0); + def_prog_mode(); +#endif +#else + GetConsoleScreenBufferInfo(ConsoleOutput,&coninfo); + COLS=coninfo.dwSize.X; + LINES=coninfo.dwSize.Y; +#endif + curinized=TRUE; +} + + +char *inkey(double maxtime) /* get char from keyboard */ +{ + char *skey; +#ifdef WINDOWS + int ms; /* number of milliseconds to wait*/ + DWORD oflags; /* saves normal state of console input buffer */ + DWORD flags; /* new input mode for console input buffer */ + static char conkeybuff[100],winkeybuff[100]; +#else + fd_set readfds; + struct timeval tv; + int maxfd; + int winfd[2],termfd[2]; + char retkey[100]; + int status,ret; +#endif + + + if (maxtime>=0.0 && maxtime<0.01) maxtime=0.01; + if (!curinized) { + error(ERROR,"need to call 'clear screen' first"); + return my_strdup(""); + } +#ifdef UNIX +#ifdef BUILD_NCURSES + retkey[0]='\0'; + winfd[0]=winfd[1]=termfd[0]=termfd[1]=-1; + winpid=termpid=-1; + if (pipe(winfd) || pipe(termfd)) { + error(ERROR,"Couldn't open pipes"); + goto sane_state; + } + + winpid=fork(); + if (winpid==0) { + /* this is the child */ + signal(SIGINT,SIG_DFL); + signal(SIGFPE,SIG_DFL); + signal(SIGSEGV,SIG_DFL); + retkey[0]='\0'; +#ifndef BEOS + if (winopened) getwinkey(retkey); +#endif + if (*retkey) write(winfd[1],retkey,strlen(retkey)); + wait(&status); + exit(0); + } else if (winpid==-1) { + error(ERROR,"couldn't fork child"); + goto sane_state; + } + + termpid=fork(); + if (termpid==0) { + /* this is the child */ + signal(SIGINT,SIG_DFL); + signal(SIGFPE,SIG_DFL); + signal(SIGSEGV,SIG_DFL); + retkey[0]='\0'; + noecho(); + cbreak(); + timeout(-1); + gettermkey(retkey); + if (*retkey) write(termfd[1],retkey,strlen(retkey)); + wait(&status); + exit(0); + } else if (termpid==-1) { + error(ERROR,"Couldn't fork child"); + goto sane_state; + } + + FD_ZERO(&readfds); + FD_SET(termfd[0],&readfds); + FD_SET(winfd[0],&readfds); + fflush(stdout); + maxfd=(termfd[0]>winfd[0])?termfd[0]:winfd[0]; + if (maxtime>=0) { + tv.tv_sec=(int)maxtime; + tv.tv_usec=(maxtime-(int)maxtime)*1000000.; + ret=select(maxfd+1,&readfds,NULL,NULL,&tv); + } else { + ret=select(maxfd+1,&readfds,NULL,NULL,NULL); + } + if (ret==-1) { + error(ERROR,"select failed"); + goto sane_state; + } + + if (FD_ISSET(termfd[0],&readfds)) { + ret=read(termfd[0],retkey,100); + } else if (FD_ISSET(winfd[0],&readfds)) { + ret=read(winfd[0],retkey,100); + // if (!strncmp("MB",retkey,2)) getmousexybm(retkey,&mousex,&mousey,&mouseb,&mousemod); + } + else ret=0; + retkey[ret]='\0'; + sane_state: + skey=retkey; + if (winfd[0]>0) close(winfd[0]); + if (winfd[1]>0) close(winfd[1]); + if (termfd[0]>0) close(termfd[0]); + if (termfd[1]>0) close(termfd[1]); + if (termpid>0) { + kill(termpid,SIGTERM); + waitpid(termpid,&status,0); + termpid=-1; + } + if (winpid>0) { + kill(winpid,SIGTERM); + waitpid(winpid,&status,0); + winpid=-1; + } + reset_prog_mode(); /* prepare for input afterwards */ +#endif +#elif WINDOWS + /* create event to signal key */ + if (gotkey==INVALID_HANDLE_VALUE) gotkey=CreateEvent(NULL,FALSE,FALSE,NULL); + if (wantkey==INVALID_HANDLE_VALUE) wantkey=CreateEvent(NULL,TRUE,FALSE,NULL); + + conkeybuff[0]=winkeybuff[0]='\0'; + + GetConsoleMode(ConsoleInput,&oflags); + flags=oflags&~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT); + SetConsoleMode(ConsoleInput,flags); + + /* create thread to observe console */ + if (kthandle==INVALID_HANDLE_VALUE) { + kthandle=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)keythread, + (LPVOID)conkeybuff,0,(LPDWORD)&ktid); + } + /* signal, that we want a key */ + if (winopened) { + SendMessage(window,WM_WANTKEY,0,(LPARAM)winkeybuff); + } + SetEvent(wantkey); + ms=(int)(1000*maxtime); + if (ms<0) + WaitForSingleObject(gotkey,INFINITE); + else + WaitForSingleObject(gotkey,ms); + + ResetEvent(wantkey); + SetConsoleMode(ConsoleInput,oflags); + if (*winkeybuff) + skey=winkeybuff; + else + skey=conkeybuff; +#endif + return my_strdup(skey); +} + + +#ifdef WINDOWS +static DWORD keythread(LPWORD lparam) /* wait for key input from console */ +{ + INPUT_RECORD inrec; /* for reading key-event */ + int key,skey; + int num; + char *keybuff; + HANDLE evn[2]; + + keybuff=(char *)lparam; + keybuff[0]='\0'; + evn[0]=wantkey; + evn[1]=ConsoleInput; + do { + do { + do { + WaitForMultipleObjects(2,evn,TRUE,INFINITE); + ReadConsoleInput(ConsoleInput,&inrec,1,&num); + } while(!is_valid_key(&inrec)); + if (isprint(inrec.Event.KeyEvent.uChar.AsciiChar)) { + keybuff[0]=inrec.Event.KeyEvent.uChar.AsciiChar; + keybuff[1]='\0'; + } else { + key=inrec.Event.KeyEvent.wVirtualKeyCode; + skey=-1; + switch(key) { + case 0x1b: skey=kESC;break; + case 0x0d: skey=kENTER;break; + case 0x09: skey=kTAB;break; + case 0x21: skey=kSCRNUP;break; + case 0x22: skey=kSCRNDOWN;break; + case 0x70: skey=kF1;break; + case 0x71: skey=kF2;break; + case 0x72: skey=kF3;break; + case 0x73: skey=kF4;break; + case 0x74: skey=kF5;break; + case 0x75: skey=kF6;break; + case 0x76: skey=kF7;break; + case 0x77: skey=kF8;break; + case 0x78: skey=kF9;break; + case 0x79: skey=kF10;break; + case 0x7a: skey=kF11;break; + case 0x7b: skey=kF12;break; + case 0x24: skey=kHOME;break; + case 0x23: skey=kEND;break; + case 0x2d: skey=kINS;break; + case 0x2e: skey=kDEL;break; + case 0x08: skey=kBACKSPACE;break; + case 0x27: skey=kRIGHT;break; + case 0x25: skey=kLEFT;break; + case 0x28: skey=kDOWN;break; + case 0x26: skey=kUP;break; + default: + sprintf(keybuff,"key%x",key); + } + if (skey>0) strcpy(keybuff,ykey[skey]); + } + if (!keybuff[0]) printf("Loop !\n"); + } while(!keybuff[0]); + ResetEvent(wantkey); + SetEvent(gotkey); + }while(TRUE); + + return 0; +} + + +static int is_valid_key(INPUT_RECORD *rec) /* check if input rec contains valid key */ +{ + if (rec->EventType!=KEY_EVENT || + !rec->Event.KeyEvent.bKeyDown || + rec->Event.KeyEvent.wVirtualKeyCode==VK_SHIFT || + rec->Event.KeyEvent.wVirtualKeyCode==VK_CONTROL) { + return FALSE; + } + return TRUE; +} +#endif + + +char *replace(char *string) /* replace \n,\a, etc. */ +{ + char *from,*to; + char *p; + int val; + static char *hexdigits="0123456789abcdef"; + + from=to=string; + while(*from) { + if (*from=='\\') { + from++; + switch(*from) { + case 'n': *to='\n';break; + case 't': *to='\t';break; + case 'v': *to='\v';break; + case 'b': *to='\b';break; + case 'r': *to='\r';break; + case 'f': *to='\f';break; + case 'a': *to='\a';break; + case '\\': *to='\\';break; + case '\?': *to='\?';break; + case '\'': *to='\'';break; + case '\"': *to='\"';break; + case 'x': + val=0; + if ((p=strchr(hexdigits,tolower(*(from+1)))) && p-hexdigits<16) { + from++; + val=p-hexdigits; + if ((p=strchr(hexdigits,tolower(*(from+1)))) && p-hexdigits<16) { + from++; + val*=16; + val+=p-hexdigits; + } + } + *to=(char)val; + break; + default: + *to='\\'; + to++; + *to=*from; + } + } + else + *to=*from; + from++; + to++; + } + *to='\0'; + return string; +} + + +void create_myopen(int num) /* create command 'myopen' */ +{ + struct command *cmd; + + cmd=add_command(cOPEN,NULL); + cmd->tag=num; +} + + +void myopen(struct command *cmd) /* open specified file for given name */ +{ +#ifdef WINDOWS + char PrinterName[200]; /* Name of default Printer */ + char *n; /* points into PrinterName */ + DOC_INFO_1 di; +#endif + FILE *handle=NULL; + int stream,i; + char *name=NULL; + char *mode=NULL; + char **pmode; + static char *valid_modes[]={"r","w","a","rb","wb","ab",""}; + static int smodes[]={smREAD,smWRITE,smWRITE,smREAD,smWRITE,smWRITE}; + int smode; + struct stackentry *p; + int has_mode,has_stream,printer=0; + + /* decode cmd->tag */ + has_stream=cmd->tag&OPEN_HAS_STREAM; + has_mode=cmd->tag&OPEN_HAS_MODE; + /* printer=cmd->tag&OPEN_PRINTER;*/ + + if (has_mode) + mode=my_strdup(pop(stSTRING)->pointer); + else + mode=printer ? my_strdup("w") : my_strdup("r"); + if (printer) + name=my_strdup("/usr/bin/lpr"); + else + name=my_strdup(pop(stSTRING)->pointer); + + if (has_stream) { + stream=(int)pop(stNUMBER)->value; + } else { + stream=0; + for(i=1;ivalue=0.; + p->type=stNUMBER; + +/* + if (printer && print_to_file) { + sprintf(errorstring,"cannot open printer: already printing grafics"); + errorcode=6; + goto open_done; + }*/ + + if (badstream(stream,1)) { + sprintf(errorstring,"invalid stream number %d",stream); + errorcode=9; + goto open_done; + } + if (stream_modes[stream]!=smCLOSED) { + sprintf(errorstring,"stream already in use"); + errorcode=2; + goto open_done; + } + + smode=0; + for(pmode=valid_modes;**pmode;pmode++) { + if (!strcmp(*pmode,mode)) break; + smode++; + } + if (!**pmode) { + sprintf(errorstring,"\'%s\' is not a valid filemode",mode); + errorcode=3; + goto open_done; + } + + if (printer) { +#ifdef UNIX + lineprinter=popen(name,"w"); + if (!lineprinter) { + sprintf(errorstring,"could not open line printer"); + errorcode=7; + goto open_done; + } +#else + /* query win.ini for default printer */ + GetProfileString("windows","device",",,,",PrinterName,200); + + /* truncate printer name */ + n=PrinterName; + while(*n && *n!=',') n++; + *n='\0'; + + OpenPrinter(PrinterName,&lineprinter,NULL); + di.pDocName="yabasic text"; + di.pOutputFile=(LPTSTR)NULL; + di.pDatatype="RAW"; + if (!StartDocPrinter(lineprinter,1,(LPBYTE)&di)) { + sprintf(errorstring,"could not open line printer"); + errorcode=7; + goto open_done; + } + StartPagePrinter(lineprinter); +#endif + lprstream=stream; + } else { + handle=fopen(name,mode); + if (handle==NULL) { + sprintf(errorstring,"could not open '%s': %s",name,my_strerror(errno)); + errorcode=4; + goto open_done; + } + streams[stream]=handle; + } + stream_modes[stream]=smodes[smode]; + errorcode=0; + p->value=stream; + open_done: + if (name) my_free(name); + if (mode) my_free(mode); +} + + +void checkopen(void) /* check, if open has been sucessfull */ +{ + double result; + + result=pop(stNUMBER)->value; + if (result<=0) { + error(ERROR,errorstring); + } +} + + +void myclose(void) /* close the specified stream */ +{ + int s; +#ifdef WINDOWS + DWORD written; +#endif + + s=(int)pop(stNUMBER)->value; + if (abs(s)==STDIO_STREAM || badstream(s,0)) return; + if (stream_modes[s]==smCLOSED) { + sprintf(string,"stream %d already closed",s); + error(WARNING,string); + return; + } + if (s==lprstream) { +#ifdef UNIX + pclose(lineprinter); +#else + WritePrinter(lineprinter,"\f",2,&written); + EndPagePrinter(lineprinter); + EndDocPrinter(lineprinter); + ClosePrinter(lineprinter); + lineprinter=INVALID_HANDLE_VALUE; +#endif + lprstream=-1; + } else { + fclose(streams[s]); + } + streams[s]=NULL; + stream_modes[s]=smCLOSED; +} + + +void myseek(struct command *cmd) /* reposition file pointer */ +{ + int s,p,m,i; + struct stackentry *pp; + char *mode; + + if (cmd->type==cSEEK2) + mode=(char *)my_strdup(pop(stSTRING)->pointer); + else + mode=my_strdup("begin"); + p=(int)pop(stNUMBER)->value; + s=(int)pop(stNUMBER)->value; + pp=push(); + pp->value=0.; + pp->type=stNUMBER; + for(i=0;mode[i];i++) mode[i]=tolower(mode[i]); + if (!strcmp(mode,"begin")) { + m=SEEK_SET; + } else if (!strcmp(mode,"end")) { + m=SEEK_END; + } else if (!strcmp(mode,"here")) { + m=SEEK_CUR; + } else { + sprintf(errorstring,"seek mode '%s' is none of begin,end,here",mode); + errorcode=12; + my_free(mode); + return; + } + my_free(mode); + if (abs(s)==STDIO_STREAM || badstream(s,0)) return; + if (!(stream_modes[s] & (smREAD | smWRITE))) { + sprintf(errorstring,"stream %d not open",s); + errorcode=11; + return; + } + if (fseek(streams[s],(long)p,m)) { + sprintf(errorstring,"could not position stream %d to byte %d",s,p); + errorcode=10; + return; + } + pp->value=1.0; +} + + +void create_pps(int type,int input) /* create command pushswitch or popswitch */ +{ + struct command *cmd; + + cmd=add_command(type,NULL); + cmd->args=input; +} + + +void push_switch(struct command *cmd) /* push current stream on stack and switch to new one */ +{ + static int oldstream=STDIO_STREAM; + struct stackentry *s; + int stream; + + stream=(int)pop(stNUMBER)->value; + if (badstream(stream,0)) return; + if (!cmd->args) stream=-stream; + + s=push(); + s->type=stNUMBER; + s->value=oldstream; + if (infolevel>=DEBUG) { + sprintf(string,"pushing %d on stack, switching to %d",oldstream,stream); + error(DEBUG,string); + } + oldstream=stream; + myswitch(stream); +} + + +void pop_switch(void) /* pop current stream from stack and switch to it */ +{ + int stream; + + stream=(int)pop(stNUMBER)->value; + if (infolevel>=DEBUG) { + sprintf(string,"popping %d from stack, switching to it",stream); + error(DEBUG,string); + } + myswitch(stream); +} + + +void myswitch(int stream) /* switch to specified stream */ +{ + int stdio,input; + + stdio=(abs(stream)==STDIO_STREAM); + input=(stream>0); + currstr=stream; + if (stream<0) stream=-stream; + if (badstream(stream,0)) return; + + if (stdio) { + cinstr=stdin; + coutstr=stdout; + } else { + cinstr=coutstr=NULL; + if (input) + cinstr=streams[stream]; + else + coutstr=streams[stream]; + } +} + + +int checkstream(void) /* test if currst is still valid */ +{ + int stdio,input; + + stdio=(abs(currstr)==STDIO_STREAM); + input=(currstr>0); + + if (!stdio) { + if (input && !(stream_modes[abs(currstr)] & smREAD)) { + sprintf(string,"stream %d not open for reading",abs(currstr)); + error(ERROR,string); + return FALSE; + } + if (!input && !(stream_modes[abs(currstr)] & (smWRITE | smPRINT))) { + sprintf(string,"stream %d not open for writing or printing",abs(currstr)); + error(ERROR,string); + return FALSE; + } + } + return TRUE; +} + + +void testeof(struct command *cmd) /* close the specified stream */ +{ + int s,c; + struct stackentry *result; + + s=(int)pop(stNUMBER)->value; + if (s!=STDIO_STREAM && badstream(s,0)) return; + result=push(); + result->type=stNUMBER; + if (s && !(stream_modes[s] & smREAD)) { + result->value=1.; + return; + } + if (!s) { + result->value=0.; + return; + } + c=getc(streams[s]); + if (c==EOF) { + result->value=1.; + return; + } + + result->value=0.; + ungetc(c,streams[s]); + return; +} + + +int badstream(int stream,int errcode) /* test for valid stream id */ +{ + if (stream!=STDIO_STREAM && (stream>FOPEN_MAX-4 || stream<=0)) { + sprintf(errcode?errorstring:string,"invalid stream: %d (can handle only streams from 1 to %d)",stream,FOPEN_MAX-4); + if (errcode) + errorcode=errcode; + else + error(ERROR,string); + return TRUE; + } + return FALSE; +} + + +void create_myread(char type,int tileol) /* create command 'read' */ +{ + struct command *cmd; + + cmd=add_command(cREAD,NULL); + cmd->args=tileol; /* true, if read should go til eol */ + cmd->tag=type; /* can be 'd' or 's' */ +} + + +void myread(struct command *cmd) /* read string or double */ +{ + double d; + static char buffer[INBUFFLEN]; /* buffer with current input */ + int numread; /* number of bytes read */ + int tileol; /* true, if read should go til end of line */ + struct stackentry *s; + int currch; /* current character */ + + numread=0; /* no chars read'til now */ + buffer[0]='\0'; + tileol=cmd->args; + + /* skip leading whitespace */ + if (!tileol) { + do { + currch=onechar(); + } while(currch==' ' || currch=='\t'); + /* put back last char */ + if (currch!=EOF && currch!='\0') backchar(currch); + if (currch=='\0' || currch==EOF) goto done; + } + + /* read chars */ + do { + currch=onechar(); + buffer[numread]=currch; + numread++; + } while(((tileol && currch!='\0') || + (!tileol && currch!=' ' && + currch!='\t' && currch!='\0')) && + currch!=EOF && numreadtag=='s') { /* read string */ + s=push(); + s->type=stSTRING; + s->pointer=my_strdup(buffer);} + else { /* read double */ + s=push(); + s->type=stNUMBER; + s->value=0.0; + if (buffer[0] && (sscanf(buffer,"%lf",&d)==1)) s->value=d; + } +} + + +static void readline(void) /* read one line from current stream */ +{ +#ifdef UNIX + char *nl; /* position of newline */ + int x,y; +#else + int read; +#endif + + if (!checkstream()) return; + linebuffer[0]='\0'; +#ifdef UNIX + if (curinized && cinstr==stdin) { + ; + #ifdef BUILD_NCURSES + getyx(stdscr,y,x); +#ifdef HAVE_GETNSTR + getnstr(linebuffer,INBUFFLEN); +#else + getstr(linebuffer); +#endif + if ((nl=strchr(linebuffer,'\0'))) { + *nl='\n'; + *(nl+1)='\0'; + } + if (y>=LINES-1) scrl(1); + refresh(); + #endif + } +#else + if (curinized && cinstr==stdin) { + ; + #ifdef BUILD_NCURSES + FlushConsoleInputBuffer(ConsoleInput); + ReadConsole(ConsoleInput,linebuffer,INBUFFLEN,&read,NULL); + if (read>=2) { + linebuffer[read-2]='\n'; + linebuffer[read-1]='\0'; + } + #endif + } +#endif + else { + fgets(linebuffer,INBUFFLEN,cinstr); + } + currchar=linebuffer; + prompted=FALSE; +} + + +static int onechar() /* read one char from cinstr */ +{ + int ch; + + if (!checkstream()) return '\0'; + if (cinstr==stdin) { + if (!currchar || !*currchar) { + readline(); + } + do { + ch=*currchar; + currchar++; + } while(! (!iscntrl(ch) || strchr(" \t\n",ch) || read_controls || ch=='\0')); + } else { + do { + ch=fgetc(cinstr); + } while(! (!iscntrl(ch) || strchr(" \t\n",ch) || read_controls || ch=='\0' || ch==EOF)); + } + + if (ch=='\n' || ch==EOF) + return '\0'; + else + return ch; +} + + +static void backchar(int ch) /* put char back into stream */ +{ + if (!checkstream()) return; + if (cinstr==stdin) { + if (currchar>linebuffer) currchar--; + } + else { + ungetc(ch,cinstr); + } +} + + +void chkprompt() /* print an intermediate prompt if necessary */ +{ + if (cinstr==stdin && (!currchar || !*currchar) && !prompted) onestring("?"); +} + + +void create_onestring(char *str) /* create command 'onestring' */ +{ + struct command *cmd; + + cmd=add_command(cONESTRING,NULL); + cmd->pointer=my_strdup(str); +} + + +void onestring(char *s) /* write string to file */ +{ +#ifdef WINDOWS + DWORD len,written; +#endif + + if (!checkstream()) return; + if (curinized && abs(currstr)==STDIO_STREAM) { + ; + #ifdef BUILD_NCURSES +#ifdef UNIX + addstr(s); + refresh(); +#else + len=strlen(s); + WriteConsole(ConsoleOutput,s,len,&written,NULL); +#endif +#endif + } else if (abs(currstr)==lprstream) { +#ifdef UNIX + fprintf(lineprinter,"%s",s); + fflush(lineprinter); +#else + len=strlen(s); + WritePrinter(lineprinter,s,len,&written); +#endif + } else { + fprintf(coutstr,"%s",s); + fflush(coutstr); + } + prompted=TRUE; +} + + +void create_colour(int flag) /* create command 'colour' */ +{ + struct command *c; + + c=add_command(cCOLOUR,NULL); + c->args=flag; +} + + +void colour(struct command *cmd) /* switch on colour */ +{ + char *fore=NULL,*back=NULL,*p; + int fc,bc; + + if (cmd->args && !curinized) { + error(ERROR,"need to call 'clear screen' first"); + return; + } + if (cmd->args==0) { + if (!curinized) return; +#ifdef UNIX + ; + #ifdef BUILD_NCURSES + if (has_colors()) + attrset(A_NORMAL|COLOR_PAIR(stdfc*8+stdbc)); + else + attrset(A_NORMAL); + return; + #endif +#else + SetConsoleTextAttribute(ConsoleOutput,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); + return; +#endif + } else if (cmd->args==1) { +#ifdef UNIX + ; + #ifdef BUILD_NCURSES + if (has_colors()) + attrset(A_NORMAL|COLOR_PAIR(stdbc*8+stdfc)); + else { + attrset(A_REVERSE); + return; + } + #endif +#else + SetConsoleTextAttribute(ConsoleOutput,BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE); + return; +#endif + } else { /* decode colours */ +#ifdef UNIX + ; + #ifdef BUILD_NCURSES + if (!has_colors()) { + pop(stSTRING); + if (cmd->args==3) pop(stSTRING); + attrset(A_REVERSE); + return; + } + #endif +#endif + if (cmd->args==2) { + back=NULL; + fore=pop(stSTRING)->pointer; + for(p=fore;*p;p++) *p=tolower(*p); + } else { + back=pop(stSTRING)->pointer; + for(p=back;*p;p++) *p=tolower(*p); + fore=pop(stSTRING)->pointer; + for(p=fore;*p;p++) *p=tolower(*p); + } + fc=name2yc(fore); + if (fc<0) { + sprintf(string,"unknown foreground colour: '%s'",fore); + error(ERROR,string); + } + bc=stdbc; + if (back) { + bc=name2yc(back); + if (fc<0) { + sprintf(string,"unknown background colour: '%s'",back); + error(ERROR,string); + } + } +#ifdef UNIX + #ifdef BUILD_NCURSES + attrset(COLOR_PAIR(fc*8+bc)); + #endif +#else + SetConsoleTextAttribute(ConsoleOutput,(WORD)(yc2oc(fc,TRUE)|yc2oc(bc,FALSE))); +#endif + } +} + + +static void initcol(void) /* initialize curses colors */ +{ + static int first=TRUE; +#ifdef UNIX + int i,j,col; + short f,b; +#else + CONSOLE_SCREEN_BUFFER_INFO csbi; +#endif + + if (!first) return; + first=FALSE; +#ifdef UNIX + #ifdef BUILD_NCURSES + if (!has_colors()) return; + start_color(); + + for(i=0;i<8;i++) { + for(j=0;j<8;j++) { + if (!i && !j) continue; + init_pair(i*8+j,yc2oc(i,TRUE),yc2oc(j,FALSE)); + } + } + init_color(COLOR_YELLOW,1000,1000,0); + + col=inch()&A_COLOR; + pair_content(col,&f,&b); + stdfc=oc2yc(f); + stdbc=oc2yc(b); + bkgdset(COLOR_PAIR(stdfc*8+stdbc)); +#endif +#else + GetConsoleScreenBufferInfo(ConsoleOutput,&csbi); + stdfc=csbi.wAttributes & (FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED); + stdbc=csbi.wAttributes & (BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED); +#endif +} + + +int name2yc(char *name) /* convert a color name to an integer */ +{ + char *c; + + for(c=name;*c;c++) *c=tolower(*c); + if (!strcmp(name,"black") || !strcmp(name,"bla")) return YC_BLACK; + if (!strcmp(name,"white") || !strcmp(name,"whi")) return YC_WHITE; + if (!strcmp(name,"red") || !strcmp(name,"red")) return YC_RED; + if (!strcmp(name,"blue") || !strcmp(name,"blu")) return YC_BLUE; + if (!strcmp(name,"green") || !strcmp(name,"gre")) return YC_GREEN; + if (!strcmp(name,"yellow") || !strcmp(name,"yel")) return YC_YELLOW; + if (!strcmp(name,"cyan") || !strcmp(name,"cya")) return YC_CYAN; + if (!strcmp(name,"magenta") || !strcmp(name,"mag")) return YC_MAGENTA; + return -1; +} + + +int yc2oc(int yc,int fore) /* convert a yabasic color to operating system color */ +{ +#ifdef UNIX + fore=0; /* stop gcc from complaining */ + if (yc==YC_BLACK) return COLOR_BLACK; + if (yc==YC_WHITE) return COLOR_WHITE; + if (yc==YC_RED) return COLOR_RED; + if (yc==YC_BLUE) return COLOR_BLUE; + if (yc==YC_GREEN) return COLOR_GREEN; + if (yc==YC_YELLOW) return COLOR_YELLOW; + if (yc==YC_CYAN) return COLOR_CYAN; + if (yc==YC_MAGENTA) return COLOR_MAGENTA; +#else + if (fore) { + if (yc==YC_BLACK) return 0; + if (yc==YC_WHITE) return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + if (yc==YC_RED) return FOREGROUND_RED; + if (yc==YC_BLUE) return FOREGROUND_BLUE; + if (yc==YC_GREEN) return FOREGROUND_GREEN; + if (yc==YC_YELLOW) return FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; + if (yc==YC_CYAN) return FOREGROUND_GREEN | FOREGROUND_BLUE; + if (yc==YC_MAGENTA) return FOREGROUND_BLUE | FOREGROUND_RED; + } else { + if (yc==YC_BLACK) return 0; + if (yc==YC_WHITE) return BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; + if (yc==YC_RED) return BACKGROUND_RED; + if (yc==YC_BLUE) return BACKGROUND_BLUE; + if (yc==YC_GREEN) return BACKGROUND_GREEN; + if (yc==YC_YELLOW) return BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; + if (yc==YC_CYAN) return BACKGROUND_GREEN | BACKGROUND_BLUE; + if (yc==YC_MAGENTA) return BACKGROUND_BLUE | BACKGROUND_RED; + } +#endif + return -1; +} + + +int oc2yc(int oc) /* convert an operating system color to yabasic color */ +{ +#ifdef UNIX + if (oc==COLOR_BLACK) return YC_BLACK; + if (oc==COLOR_WHITE) return YC_WHITE; + if (oc==COLOR_RED) return YC_RED; + if (oc==COLOR_BLUE) return YC_BLUE; + if (oc==COLOR_GREEN) return YC_GREEN; + if (oc==COLOR_YELLOW) return YC_YELLOW; + if (oc==COLOR_CYAN) return YC_CYAN; + if (oc==COLOR_MAGENTA) return YC_MAGENTA; +#else + if (oc==0) return YC_BLACK; + if (oc==(FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN) || + oc==(BACKGROUND_RED|BACKGROUND_BLUE|BACKGROUND_GREEN)) return YC_WHITE; + if (oc==(FOREGROUND_RED) || + oc==(BACKGROUND_RED)) return YC_RED; + if (oc==(FOREGROUND_BLUE) || + oc==(BACKGROUND_BLUE)) return YC_BLUE; + if (oc==(FOREGROUND_GREEN) || + oc==(BACKGROUND_GREEN)) return YC_GREEN; + if (oc==(FOREGROUND_RED|FOREGROUND_GREEN) || + oc==(BACKGROUND_RED|BACKGROUND_GREEN) || + oc==(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY) || + oc==(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_INTENSITY)) return YC_YELLOW; + if (oc==(FOREGROUND_BLUE|FOREGROUND_GREEN) || + oc==(BACKGROUND_BLUE|BACKGROUND_GREEN)) return YC_CYAN; + if (oc==(FOREGROUND_RED|FOREGROUND_BLUE) || + oc==(BACKGROUND_RED|BACKGROUND_BLUE)) return YC_MAGENTA; +#endif + return -1; +} + + +void putchars(void) /* put rect onto screen */ +{ + char *ch,text,fore[4],back[4]; + int n,sx,sy,x,y,f,b; + int tox,toy; + int oldx,oldy; +#ifdef WINDOWS + CONSOLE_SCREEN_BUFFER_INFO csbi; + COORD cp; + char buff[2]; + int written; +#endif + + toy=(int)(pop(stNUMBER)->value); + tox=(int)(pop(stNUMBER)->value); + ch=pop(stSTRING)->pointer; +#ifdef UNIX +#ifdef BUILD_NCURSES + getyx(stdscr,oldy,oldx); +#endif +#else + GetConsoleScreenBufferInfo(ConsoleOutput,&csbi); + oldx=csbi.dwCursorPosition.X; + oldy=csbi.dwCursorPosition.Y; +#endif + if (sscanf(ch,"%d,%d:%n",&sx,&sy,&n)!=2) { + error(ERROR,"illegal screen string"); + return; + } + ch+=n; + for(x=tox;x=COLS) continue; + for(y=toy;y=COLS || y<0 || y>=LINES) { + for(n=0;n<10;n++) if (*ch) ch++; + continue; + } + if (!*ch) { + text=' '; + f=YC_BLACK; + b=YC_BLACK; + } else { + text=*ch; + strncpy(fore,ch+2,3); + fore[3]='\0'; + strncpy(back,ch+6,3); + back[3]='\0'; + for(n=0;n<10;n++) if (*ch) ch++; + f=name2yc(fore); + if (f<0) f=YC_WHITE; + b=name2yc(back); + if (b<0) b=YC_WHITE; + } +#ifdef UNIX + #ifdef BUILD_NCURSES + if (has_colors()) attrset(COLOR_PAIR(f*8+b)); + mvaddch(y,x,text); + #endif +#else + cp.X=x; + cp.Y=y; + SetConsoleCursorPosition(ConsoleOutput,cp); + SetConsoleTextAttribute(ConsoleOutput,(WORD)(yc2oc(f,TRUE)|yc2oc(b,FALSE))); + buff[0]=text; + buff[1]='\0'; + WriteConsole(ConsoleOutput,buff,1,&written,NULL); +#endif + } + } +#ifdef UNIX + #ifdef BUILD_NCURSES + if (has_colors()) + attrset(A_NORMAL|COLOR_PAIR(stdfc*8+stdbc)); + else + attrset(A_NORMAL); + move(y,x); + refresh(); + #endif +#else + cp.X=oldx; + cp.Y=oldy; + SetConsoleCursorPosition(ConsoleOutput,cp); + SetConsoleTextAttribute(ConsoleOutput,(WORD)(stdfc|stdbc)); +#endif + + return; +} + + +char *getchars(int xf,int yf,int xt,int yt) /* get rect from screen */ +{ + int x,y; +#ifdef UNIX + int c,ct,cc; +#endif + int cf,cb; + int oldx,oldy; + char *res; + char cols[20]; +#ifdef WINDOWS + CONSOLE_SCREEN_BUFFER_INFO csbi; + COORD cp; + char charbuff[2]; + WORD attrbuff[2]; + int read; +#endif + + if (xf>xt) {x=xf;xf=xt;xt=x;} + if (yf>yt) {y=yf;yf=yt;yt=y;} + + res=my_malloc(12+(xt-xf+1)*(yt-yf+1)*12); + sprintf(res,"%d,%d:",xt-xf+1,yt-yf+1); +#ifdef UNIX +#ifdef BUILD_NCURSES + getyx(stdscr,oldy,oldx); +#endif +#else + GetConsoleScreenBufferInfo(ConsoleOutput,&csbi); + oldx=csbi.dwCursorPosition.X; + oldy=csbi.dwCursorPosition.Y; +#endif + + for(x=xf;x<=xt;x++) { + for(y=yf;y<=yt;y++) { + if (y<0 || y>=LINES || x<0 || x>=COLS) { + strcat(res," blbl"); + } else { +#ifdef UNIX +#ifdef BUILD_NCURSES + c=mvinch(y,x); + ct=c&A_CHARTEXT; + if (!isprint(ct)) ct=' '; + cc=PAIR_NUMBER(c&A_COLOR); + cb=cc&7; + cf=(cc-cb)/8; + if (has_colors()) { + sprintf(cols,"%c:%s:%s,",ct,yc2short(cf),yc2short(cb)); + } else + { + + sprintf(cols,"%c:???:???,",ct); + } +#endif +#else + cp.X=x; + cp.Y=y; + ReadConsoleOutputCharacter(ConsoleOutput,charbuff,1,cp,&read); + charbuff[1]='\0'; + ReadConsoleOutputAttribute(ConsoleOutput,attrbuff,1,cp,&read); + cf=oc2yc(attrbuff[0]&(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE)); + cb=oc2yc(attrbuff[0]&(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE)); + sprintf(cols,"%c:%s:%s,",charbuff[0],yc2short(cf),yc2short(cb)); +#endif + strcat(res,cols); + } + } + } +#ifdef UNIX +#ifdef BUILD_NCURSES + move(oldy,oldx); +#endif +#endif + res[strlen(res)-1]='\0'; + return res; +} + + +char *yc2short(int col) /* convert yabasic colours to short colour name */ +{ + static char r1[4],r2[4]; + static char *pr=r1; + + if (pr==r1) + pr=r2; + else + pr=r1; + + strcpy(pr,"***"); + if (col==YC_BLACK) strcpy(pr,"Bla"); + if (col==YC_WHITE) strcpy(pr,"Whi"); + if (col==YC_RED) strcpy(pr,"Red"); + if (col==YC_BLUE) strcpy(pr,"Blu"); + if (col==YC_GREEN) strcpy(pr,"Gre"); + if (col==YC_YELLOW) strcpy(pr,"Yel"); + if (col==YC_CYAN) strcpy(pr,"Cya"); + if (col==YC_MAGENTA) strcpy(pr,"Mag"); + + return pr; +} + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..7c96b37 --- /dev/null +++ b/src/main.c @@ -0,0 +1,2250 @@ +/* + +YABASIC --- a simple Basic Interpreter +written by Marc-Oliver Ihm 1995-2004 +homepage: www.yabasic.de + +main.c --- main() and auxilliary functions + +This file is part of yabasic and may be copied only +under the terms of either the Artistic License or +the GNU General Public License (GPL), both of which +can be found at www.yabasic.de + +*/ + + +/* ------------- includes ---------------- */ + +// include "YabInterface.h" + +#ifndef YABASIC_INCLUDED +#include "yabasic.h" /* all prototypes and structures */ +#endif + + +/* ------------- defines ---------------- */ + +#define DONE {current=current->next;break;} /* reduces type-work */ +#define COPYRIGHT "original yabasic Copyright 1995-2006 by Marc-Oliver Ihm\n +\tyab improvements Copyright 2006-2014 by Jan Bungeroth\n +\tyab improvements Copyright 2013-2015 by Jim Saxton\n" +#define BANNER \ +"\n yab is yabasic for Haiku. This is version " VERSION ",\n built on "\ +ARCHITECTURE " on " BUILD_TIME "\n\n " COPYRIGHT "\n\n" +#define BANNER_VERSION \ +"yab " VERSION ", built on " ARCHITECTURE "\n" COPYRIGHT +#define YABFORHELP "(type 'yab -help' for help)" +#define YABMAGIC "__YaBaSiC_MaGiC_CoOkIe__" + +/* ------------- external references ---------------- */ + +extern int mylineno; /* current line number */ +extern int yyparse(); /* call bison parser */ + + +/* ------------- local functions ---------------- */ + +static void std_diag(char *,int,char *); /* produce standard diagnostic */ +static void parse_arguments(int,char *argv[]); /* parse cmd line arguments */ +static void initialize(void); /* give correct values to pointers etc ... */ +static void run_it(YabInterface* yab); /* execute the compiled code */ +static void end_it(void); /* perform shutdown operations */ +#ifdef WINDOWS +static void chop_command(char *,int *,char ***); /* chops WIN95-commandline */ +#endif +void create_docu_array(void); /* create array with documentation */ +int equal(char *,char *,int); /* helper for processing options */ +void do_help(char *); /* process help option */ +static int mybind(char *); /* bind a program to the interpreter and save it */ +char *find_interpreter(char *); /* find interpreter with full path */ + +/* ------------- global variables ---------------- */ + +struct command *cmdroot; /* first command */ +struct command *cmdhead; /* next command */ +struct command *lastcmd; /* last command */ +struct command *current; /* currently executed command */ +int infolevel; /* controls issuing of error messages */ +int errorlevel; /* highest level of error message seen til now */ +static int debug_count; /* number of debug messages */ +static int note_count; /* number of notes */ +static int warning_count; /* number of warning messages */ +static int error_count; /* number of error messages */ +int interactive; /* true, if commands come from stdin */ +int is_bound; /* true, if this executable is bound */ +char* appdirectory; +static char *to_bind=NULL; /* name bound program to be written */ +FILE *bound_program=NULL; /* points to embedded yabasic program (if any) */ +char *string; /* for trash-strings */ +char *errorstring; /* for error-strings */ +int errorcode; /* error-codes */ +int enterkeyflag = 0; /* press enter to end program */ +static int commandcount; /* total number of commands */ +int program_state; /* state of program */ +char *progname=NULL; /* name of yabasic-program */ +int print_docu=FALSE; /* TRUE, if only docu should be printed */ +int hold_docu=FALSE; /* TRUE, if docu should be printed in portions */ +#ifdef WINDOWS +DWORD InitialConsole; /* initial state of console window */ +#endif +char *explanation[cLAST_COMMAND-cFIRST_COMMAND+1]; /* explanations of commands */ +char *explicit=NULL; /* yabasic commands given on the command line */ +char **yabargv; /* arguments for yabasic */ +int yabargc; /* number of arguments in yabargv */ +static int endreason=erNONE; /* reason for termination */ +static int exitcode=0; +static int signal_arrived=0; +/* timing */ +time_t compilation_start,compilation_end,execution_end; +char library_path[200]; /* full path to search libraries */ +char library_default[200]; /* default full path to search libraries */ +static struct command *docuhead=NULL; /* first docu in main */ +static int docucount=0; /* number of docu-lines in array */ +int check_compat=0; /* true, if compatibility should be checked */ +static char *interpreter_path=NULL; /* name of interpreter executing; i.e. ARGV[0] */ +static char *main_file_name=NULL; /* name of program to be executed */ + +YabInterface *yab; + +/* ------------- main program ---------------- */ + +int mmain(int argc,char **argv, YabInterface* y) +{ +#ifdef WINDOWS + CONSOLE_SCREEN_BUFFER_INFO csbi; + char *lp; + int fromlibpath; +#endif + int len; + + yab = y; + appdirectory = yi_GetApplicationDirectory(yab); + + // appdirectory=(char *)my_malloc(sizeof(argv[0])); + // strcpy(appdirectory, argv[0]); + + string=(char *)my_malloc(sizeof(char)*INBUFFLEN); + errorstring=(char *)my_malloc(sizeof(char)*INBUFFLEN); + *errorstring='\0'; + errorcode=0; + + program_state=HATCHED; + infolevel=WARNING; /* set the initial Infolevel */ + +#ifdef WINDOWS + /* get handle for current thread */ + DuplicateHandle(GetCurrentProcess(),GetCurrentThread(), + GetCurrentProcess(),&mainthread,THREAD_ALL_ACCESS,FALSE,0); + + /* get handle of instance */ + this_instance=GetModuleHandle(NULL); + + /* define my window class */ + myclass.style=0; + myclass.lpfnWndProc=(LPVOID)mywindowproc; + myclass.cbClsExtra=0; /* no extra bytes */ + myclass.cbWndExtra=0; + myclass.hInstance=this_instance; + myclass.hIcon=LoadIcon(this_instance,"yabasicIcon"); + myclass.hCursor=LoadCursor(NULL,IDC_ARROW); /* standard cursor */ + myclass.hbrBackground=(HBRUSH)COLOR_WINDOW; /* default-background */ + myclass.lpszMenuName=NULL; + myclass.lpszClassName=my_class; + + RegisterClass(&myclass); + + /* get console handles */ + ConsoleInput=GetStdHandle(STD_INPUT_HANDLE); + ConsoleOutput=GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleMode(ConsoleInput,&InitialConsole); + + /* find out, if launched from commandline */ + GetConsoleScreenBufferInfo(ConsoleOutput,&csbi); + Commandline=!((csbi.dwCursorPosition.X==0) && (csbi.dwCursorPosition.Y==0)); + if ((csbi.dwSize.X<=0) || (csbi.dwSize.Y <= 0)) Commandline=TRUE; + +#endif + /* get library path */ + library_path[0]='\0'; + library_default[0]='\0'; +#ifdef UNIX + strcpy(library_default,LIBRARY_PATH); +#else + fromlibpath=TRUE; + if (lp=getreg("librarypath")) { + strcpy(library_default,lp); + fromlibpath=TRUE; + } else if (lp=getreg("path")) { + strcpy(library_default,lp); + fromlibpath=FALSE; + } else { + library_default[0]='\0'; + fromlibpath=FALSE; + } +#endif + + /* find out, if this executable is bound to a yabasic program */ + interpreter_path=find_interpreter(argv[0]); + is_bound=isbound(); + + /* parse arguments */ + parse_arguments(argc,argv); + + /* brush up library path */ + if (!library_path[0]) strcpy(library_path,library_default); + len=strlen(library_path); +#ifdef UNIX + if (library_path[len-1]=='/' || library_path[len-1]=='\\') library_path[len-1]='\0'; +#else + if (library_path[0]) { + if (library_path[len-1]!='/' && library_path[len-1]!='\\') strcat(library_path,"\\"); + if (!fromlibpath) strcat(library_path,"lib\\"); + } +#endif + + time(&compilation_start); + error(DEBUG,"this is yab " VERSION); + initialize(); + program_state=INITIALIZED; + + error(NOTE,"calling parser/compiler"); + + if (interactive) { + printf("%s",BANNER); + printf("Enter your program and type RETURN twice when done.\n\n"); + printf("Your program will execute immediately and CANNOT BE SAVED;\n"); + printf("create your program with an EXTERNAL EDITOR, if you want to keep it.\n"); +#ifdef UNIX +#ifndef BEOS + printf("Type 'man yabasic' or see the file yabasic.htm for more information.\n\n"); +#else + printf("See the documentation for more information.\n\n"); +#endif +#else + printf("See the documentation within the start-menu for more information.\n\n"); +#endif + } + program_state=COMPILING; + if (yyparse() && errorlevel>ERROR) error(ERROR,"Couldn't parse program"); + + if (errorlevel>ERROR) create_docu_array(); + + add_command(cEND,NULL); + sprintf(string,"read %d line(s) and generated %d command(s)",mylineno,commandcount); + error(NOTE,string); + + time(&compilation_end); + + if (to_bind) { + struct libfile_name *lib; + if (mybind(to_bind)) { + sprintf(string,"Successfully bound '%s' and '%s' into '%s'",interpreter_path,main_file_name,to_bind); + error(INFO,string); + end_it(); + } else { + sprintf(string,"could not bind '%s' and '%s' into '%s'",interpreter_path,main_file_name,to_bind); + error(ERROR,string); + end_it(); + } + } + + if (errorlevel>ERROR && !check_compat) { + program_state=RUNNING; + run_it(yab); + } else { + program_state=FINISHED; + if (check_compat) + printf("Check for possible compatibility problems done\nProgram will not be executed, %d possible problem(s) reported\n",warning_count); + else + error(ERROR,"Program not executed"); + } + + program_state=FINISHED; + sprintf(string,"%d debug(s), %d note(s), %d warning(s), %d error(s)", + debug_count,note_count,warning_count,error_count); + error(NOTE,string); + time(&execution_end); + sprintf(string,"compilation time %g second(s), execution %g", + (double)(compilation_end-compilation_start),(double)(execution_end-compilation_end)); + error(NOTE,string); + end_it(); + return !(errorlevel>ERROR); +} + + + +/* ------------- subroutines ---------------- */ + + +static void std_diag(char *head,int type,char *name) /* produce standard diagnostic */ +{ + int n,i; + char *s; + struct stackentry *sp; + + if (infolevel>=DEBUG) { + s=string; + if (type>cLAST_COMMAND || typeprev!=stackroot) { + sprintf(s,"t["); + s+=2; + sp=stackhead; + for(i=0;TRUE;i++) { + sp=sp->prev; + if (sp==stackroot) break; + if (i>=5) continue; + if (i>0) { + sprintf(s,","); + s++; + } + switch(sp->type) { + case stGOTO: + sprintf(s,"goto%n",&n); + break; + case stSTRINGARRAYREF: + case stNUMBERARRAYREF: + if (sp->pointer) + sprintf(s,"%s()%n",(char *)sp->pointer,&n); + else + sprintf(s,"ARRAY()%n",&n); + break; + case stSTRING: + sprintf(s,"'%s'%n",(char *)sp->pointer,&n); + break; + case stNUMBER: + sprintf(s,"%g%n",sp->value,&n); + break; + case stLABEL: + sprintf(s,"label%n",&n); + break; + case stRETADD: + sprintf(s,"retadd%n",&n); + break; + case stRETADDCALL: + sprintf(s,"retaddcall%n",&n); + break; + case stSWITCH_MARK: + sprintf(s,"switch_mark%n",&n); + break; + case stFREE: + sprintf(s,"free%n",&n); + break; + case stROOT: + sprintf(s,"root%n",&n); + break; + case stSWITCH_STRING: + sprintf(s,"switch_string%n",&n); + break; + case stSWITCH_NUMBER: + sprintf(s,"switch_number%n",&n); + break; + default: + sprintf(s,"unknown%n",&n); + break; + } + s+=n; + } + if (i>5) { + sprintf(s,";+%d%n",i-5,&n); + s+=n; + } + strcat(s,"]b"); + } + error(DEBUG,string); + } +} + + +struct command *add_command(int type,char *name) + /* get room for new command, and make a link from old one */ +{ + struct command *new; + + if (infolevel>=DEBUG) std_diag("creating",type,name); + cmdhead->type=type; /* store command */ + cmdhead->line=mylineno; + cmdhead->lib=currlib; + cmdhead->cnt=commandcount; + if (!name || !*name) + cmdhead->name=NULL; + else + cmdhead->name=my_strdup(name); + commandcount++; + cmdhead->pointer=NULL; /* no data yet */ + cmdhead->jump=NULL; + cmdhead->nextassoc=NULL; + cmdhead->switch_id=get_switch_id(); + if (!currlib->datapointer && cmdhead->type==cDATA) currlib->firstdata=currlib->datapointer=cmdhead; + + /* link into chain of commands referencing a symbol */ + if (name) { + if (lastref) lastref->nextref=cmdhead; + lastref=cmdhead; + } + + /* create new command */ + new=(struct command *)my_malloc(sizeof(struct command)); + /* and initialize */ + new->next=NULL; + new->prev=cmdhead; + new->pointer=NULL; + new->symbol=NULL; + new->nextref=NULL; + new->nextassoc=NULL; + new->name=NULL; + + cmdhead->next=new; + lastcmd=cmdhead; + cmdhead=cmdhead->next; + return lastcmd; +} + + +static void parse_arguments(int cargc,char *cargv[]) + /* parse arguments from the command line */ +{ + char **argv; + int argc,larg; +#ifdef UNIX + char *parg; + int i; +#endif + int ar; + FILE *inputfile=NULL; + char *option; + char *info; + int options_done=FALSE; + + if (cargc>1) larg=strlen(cargv[1]); + else larg=0; +#ifdef UNIX + if (cargc>0) { + /* get room for arguments */ + argv=(char **)my_malloc((larg+cargc+1)*sizeof(char *)); + /* copy zero argument */ + argv[0]=cargv[0]; + argc=0; + /* chop first argument into pieces */ + if (cargc>=2) { + parg=strtok(my_strdup(cargv[1])," \t"); + for(argc=1;parg;argc++) { + argv[argc]=parg; + parg=strtok(NULL," \t"); + } + } + /* copy other arguments */ + for(i=2;i=argc) { + error(ERROR,"no infolevel specified " YABFORHELP); + end_it(); + } + info=argv[ar]; + if (!strncmp(info,"debug",strlen(info))) infolevel=DEBUG; + else if (!strncmp(info,"note",strlen(info))) infolevel=NOTE; + else if (!strncmp(info,"warning",strlen(info))) infolevel=WARNING; + else if (!strncmp(info,"error",strlen(info))) infolevel=ERROR; + else if (!strncmp(info,"fatal",strlen(info))) infolevel=FATAL; + else if (!strncmp(info,"bison",strlen(info))) {yydebug=1;infolevel=DEBUG;} + else { + sprintf(string,"there's no infolevel '%s' " YABFORHELP,argv[ar]); + error(ERROR,string); + end_it(); + } + } + /*else if (equal("-fg",option,3) || equal("-foreground",option,4)) { + ar++; + if (ar>=argc) { + error(ERROR,"no foreground colour specified " YABFORHELP); + end_it(); + } + foreground=my_strdup(argv[ar]); + } + else if (equal("-bg",option,2) || equal("-background",option,2)) { + ar++; + if (ar>=argc) { + error(ERROR,"no background colour specified (-h for help)"); + end_it(); + } + background=my_strdup(argv[ar]); + } + else if (equal("-geometry",option,2)) { + ar++; + if (ar>=argc) { + error(ERROR,"no geometry string specified (-h for help)"); + end_it(); + } + geometry=my_strdup(argv[ar]); + }*/ + else if (equal("-bind",option,3)) { + ar++; + if (ar>=argc) { + error(ERROR,"name of bound program to be written is missing"); + end_it(); + } + to_bind=my_strdup(argv[ar]); + } + else if (equal("-execute",option,2)) { + ar++; + if (ar>=argc) { + error(ERROR,"no commands specified (-h for help)"); + end_it(); + } + explicit=my_strdup(argv[ar]); + } + else if (equal("-librarypath",option,4)) { + ar++; + if (ar>=argc) { + error(ERROR,"no library path specified (-h for help)"); + end_it(); + } + strcpy(library_path,argv[ar]); + }/* + else if (equal("-display",option,3)) { + ar++; + if (ar>=argc) { + error(ERROR,"no display name specified (-h for help)"); + end_it(); + } + displayname=my_strdup(argv[ar]); + } + else if (equal("-font",option,4)) { + ar++; + if (ar>=argc) { + error(ERROR,"no font specified (-h for help)"); + end_it(); + } + font=my_strdup(argv[ar]); + }*/ else if (!print_docu && + (!strcmp("-doc",option) || !strncmp("-doc_",option,5) || + !strcmp("-docu",option) || !strncmp("-docu_",option,6))) { + print_docu=TRUE; + if (!strncmp("-doc_",option,5)) { + ar--; + hold_docu=TRUE; + main_file_name=my_strdup(option+5); + } else if (!strncmp("-docu_",option,6)) { + ar--; + hold_docu=TRUE; + main_file_name=my_strdup(option+6); + } else { + if (ar>=argc-1) { + error(ERROR,"no filename specified (-h for help)"); + end_it(); + } + hold_docu=FALSE; + main_file_name=my_strdup(argv[ar+1]); + } + } else if (!print_docu && *option=='-') { + sprintf(string,"unknown or ambigous option '%s' " YABFORHELP,option); + error(ERROR,string); + end_it(); + } else if (!is_bound && !inputfile && !explicit) { /* not an option */ + if (!main_file_name) main_file_name=my_strdup(argv[ar]); + inputfile=fopen(main_file_name,"r"); + if (inputfile==NULL) { + sprintf(string,"could not open '%s': %s",main_file_name,my_strerror(errno)); + error(ERROR,string); + endreason=erERROR; + exitcode=1; + end_it(); + } else { + progname=strrchr(main_file_name,'\\'); + if (!progname) progname=strrchr(main_file_name,'/'); + if (progname) + progname++; + else + progname=main_file_name; + if (!progname) progname="yab"; + } + } else { /* option for yabasic program */ + yabargv[yabargc]=my_strdup(argv[ar]); + yabargc++; + } + } else { + yabargv[yabargc]=my_strdup(argv[ar]); + yabargc++; + } + } + + interactive=FALSE; + +#ifdef WINDOWS + if (is_bound || !progname) { + SetConsoleTitle(""); + } else { + SetConsoleTitle(progname); + } +#endif + + if (is_bound) { + inputfile=bound_program; + main_file_name=my_strdup(interpreter_path); + } else if (!inputfile && !explicit) { + interactive=TRUE; + inputfile=stdin; + main_file_name="standard input"; + } + if (explicit) main_file_name="command line"; + + yi_SetMainFileName(main_file_name, yab); + + /* open a flex buffer for the initial file */ + open_main(inputfile,explicit,main_file_name); + return; + +} + +void do_help(char *op) /* process help option */ +{ + char *ooop=op; + char *oop=op; + if (op[0]=='-' && op[1]=='-') op++; + oop=op; + op=strchr(++op,'-'); + if (!op) { + if (equal("-version",oop,2)) { + fprintf(stderr,"%s\n",BANNER_VERSION); + } else if (equal("-license",oop,2) || equal("-licence",oop,2)) { + fprintf(stderr,"\n%s\n",YABLICENSE); + } else { + fprintf(stderr,"%s",BANNER); + fprintf(stderr,"For more help try one of these options:\n"); + fprintf(stderr," -help-license : show license and conditions of copying\n"); + fprintf(stderr," -help-usage : invoking yabasic and commandline options\n\n"); +#ifdef UNIX +#ifndef BEOS + fprintf(stderr,"Type 'man yabasic' or see the file yabasic.htm for a description\n"); +#else + fprintf(stderr,"Read the documentation for a description of the language.\n\n"); +#endif +#else + fprintf(stderr,"See the file yabasic.htm (accessible from the start-menu) for a\ndescription"); +#endif +// fprintf(stderr,"of the language, or go to www.yabasic.de for the latest\n"); +// fprintf(stderr,"information and other yabasic resources.\n\n"); + } + } else if (equal("-license",op,2) || equal("-licence",op,2)) { + fprintf(stderr,"\n%s\n",YABLICENSE); + } else if (equal("-usage",op,2)) { + fprintf(stderr,"\nUsage: yab [OPTIONS] [FILENAME [ARGUMENTS]]\n\n"); + fprintf(stderr,"FILENAME : file, which contains the yab program; omit it to type\n"); + fprintf(stderr," in your program on the fly (terminated by a double newline)\n"); + fprintf(stderr,"ARGUMENTS : strings, that are available from within the yab program\n\n"); + fprintf(stderr,"available OPTIONS:\n"); + fprintf(stderr," -help : print help message and other help options\n"); + fprintf(stderr," -version : show version of yab\n"); + fprintf(stderr," -infolevel [dnwefb] : set infolevel to debug,note,warning,error or fatal\n"); + fprintf(stderr," -execute COMMANDS : execute yab COMMANDS right away\n"); + fprintf(stderr," -bind BOUND : bind interpreter with FILENAME into BOUND\n"); +// fprintf(stderr," -geometry x+y : position graphic window at x,y\n"); +#ifdef UNIX +// fprintf(stderr," -fg,-bg COL : specify fore/background color of graphic window\n"); +// fprintf(stderr," -display DISP : display, where window will show up\n"); +// fprintf(stderr," -font FONT : font for graphic window\n"); +#else +// fprintf(stderr," -font FONT : font for graphic, supply style (decorative,dontcare,\n"); +// fprintf(stderr," modern,roman,script or swiss) and size, e.g. swiss10\n"); +#endif + fprintf(stderr," -docu NAME : print embedded docu of program or library\n"); + fprintf(stderr," -check : check for possible compatibility problems\n"); + fprintf(stderr," -- : pass any subsequent words as arguments to yab\n"); + fprintf(stderr," -librarypath PATH : directory to search libraries not found in\n"); + fprintf(stderr," current dir (default %s)\n",library_default); + fprintf(stderr," -enter : waits for the user to press the return key after\n"); + fprintf(stderr," the program finished\n"); + fprintf(stderr,"\n"); + } else { + sprintf(string,"unknown or ambigous option '%s' " YABFORHELP,ooop); + error(ERROR,string); + } +} + + +int equal(char *a,char *b,int min) /* helper for processing options */ +{ + int len; + if (b[0]=='-' && b[1]=='-' && b[2]) b++; + if (min<0) { + min=-min; + len=min; + } else { + len=strlen(b); + } + + return (!strncmp(a,b,len) && len>=min); +} + + +#ifdef WINDOWS +static void chop_command(char *command,int *argc,char ***argv) + /* chop the WIN95-commandline into seperate strings */ +{ + int i,j,count; + int quote; + char c,last; + char *curr; + char **list; + + /* count, how many arguments */ + count=i=0; + last=' '; + quote=FALSE; + while((c=*(command+i))!='\0') { + if (!quote && c!=' ' && last==' ') count++; + if (c=='\"') quote=!quote; + last=c; + i++; + } + + /* fill yabasic into argv[0] */ + *argv=my_malloc((count+1)*sizeof(char *)); + list=*argv; + *argc=count+1; + *list=my_strdup("yabasic"); + + /* fill in other strings */ + i=0; + count=1; + last=' '; + quote=FALSE; + do { + c=*(command+i); + if (!quote && c!=' ' && last==' ') j=i; + if (c=='\"') { + quote=!quote; + if (quote) j++; + } + if (((c==' ' && !quote) || c=='\0') && last!=' ') { + *(list+count)=my_malloc((i-j+1)*sizeof(char)); + strncpy(*(list+count),command+j,i-j); + curr=*(list+count)+i-j; + *curr='\0'; + if (*(curr-1)=='\"') *(curr-1)='\0'; + count++; + } + last=c; + i++; + } while(c!='\0'); +} +#endif + + +static void end_it(void) /* perform shutdown-operations */ +{ + char l[2]; +#ifdef UNIX + int status; +#ifndef BEOS + if (winpid==0 || termpid==0 || backpid==0) + yi_exit(1,yab); + if (backpid>0) { + kill(backpid,SIGTERM); + waitpid(backpid,&status,0); + backpid=-1; + } +#else + if(enterkeyflag) + { + printf("---Press RETURN to continue "); + getchar(); + // fgets(1,2,stdin); + } + if (winpid==0 || termpid==0) yi_exit(1,yab); +#endif + if ((curinized || winopened) && endreason!=erREQUEST) { +#else + if (!Commandline && endreason!=erREQUEST) { +#endif + myswitch(STDIO_STREAM); + onestring("---Program done, press RETURN---\n"); +#ifdef WINDOWS + SetConsoleMode(ConsoleInput,InitialConsole & (~ENABLE_ECHO_INPUT)); + FlushConsoleInputBuffer(ConsoleInput); +#endif + fgets(l,2,stdin); +#ifdef WINDOWS + if (wthandle!=INVALID_HANDLE_VALUE) TerminateThread(wthandle,0); +#endif +#ifdef UNIX + } +#else + } +#endif + +#ifdef UNIX +#ifdef BUILD_NCURSES + if (curinized) endwin(); +#endif +#else + if (printerfont) DeleteObject(printerfont); + if (myfont) DeleteObject(myfont); + if (printer) DeleteDC(printer); +#endif + yi_exit(exitcode,yab); +} + + +static void initialize(void) + /* give correct values to pointers etc ... */ +{ + struct symbol *s; + struct stackentry *base; + int i; + + /* install exception handler */ + /*signal(SIGFPE,signal_handler); + signal(SIGSEGV,signal_handler); + signal(SIGINT,signal_handler); +#ifdef SIGHUP + signal(SIGHUP,signal_handler); +#endif +#ifdef SIGQUIT + signal(SIGQUIT,signal_handler); +#endif +#ifdef SIGABRT + signal(SIGABRT,signal_handler); +#endif */ + + /* initialize error handling: no errors seen 'til now */ + errorlevel=DEBUG; + debug_count=0; + note_count=0; + warning_count=0; + error_count=0; + + /* initialize stack of symbol lists */ + pushsymlist(); + + /* initialize random number generator */ + srand((unsigned)time(NULL)); + + /* initialize numeric stack */ + /* create first : */ + stackroot=(struct stackentry *)my_malloc(sizeof(struct stackentry)); + stackroot->next=NULL; + stackroot->prev=NULL; + stackhead=stackroot; /* stack of double values */ + + /* initialize command stack */ + /* create first: */ + cmdroot=(struct command *)my_malloc(sizeof(struct command)); + cmdroot->next=cmdroot->prev=NULL; + + /* initialize random number generator */ + srand((unsigned int)time(NULL)); + + /* specify default text-alignement and window origin */ + /* + text_align=my_strdup("lb"); + winorigin=my_strdup("lt");*/ + + /* initialize stack */ + base=push(); + base->type=stROOT; /* push nil, so that pop will not crash */ + cmdhead=cmdroot; /* list of commands */; + commandcount=0; + + /* add internal string variables */ + s=get_sym("yabos$",sySTRING,amADD_GLOBAL); + if (s->pointer) my_free(s->pointer); +#ifdef UNIX +#ifndef BEOS + s->pointer=my_strdup("unix"); +#elseifdef HAIKU + s->pointer=my_strdup("Haiku"); +#else + s->pointer=my_strdup("BeOS"); +#endif +#else + s->pointer=my_strdup("windows"); +#endif + + /* set default-scales for grafics */ + /* + fontheight=10; + winheight=100; + winwidth=100; +#ifdef UNIX + calc_psscale(); +#endif*/ + + + /* file stuff */ + for(i=1;i<=9;i++) { + streams[i]=NULL; + stream_modes[i]=smCLOSED; + } + streams[0]=stdin; + stream_modes[0]=smREAD | smWRITE; +#ifdef UNIX + /* printerfile=NULL; /* no ps-file yet */ +#endif + + /* array with explanation */ + for(i=cFIRST_COMMAND;i<=cLAST_COMMAND;i++) explanation[i]="???"; + explanation[cFIRST_COMMAND]="FIRST_COMMAND"; + explanation[cFINDNOP]="FINDNOP"; + explanation[cEXCEPTION]="EXCEPTION"; + explanation[cLABEL]="LABEL"; + explanation[cSUBLINK]="cSUBLINK"; + explanation[cTOKEN]="TOKEN"; + explanation[cTOKEN2]="TOKEN2"; + explanation[cTOKENALT]="TOKENALT"; + explanation[cTOKENALT2]="TOKENALT2"; + explanation[cSPLIT]="SPLIT"; + explanation[cSPLIT2]="SPLIT2"; + explanation[cSPLITALT]="SPLITALT"; + explanation[cSPLITALT2]="SPLITALT2"; + explanation[cGOTO]="GOTO"; + explanation[cQGOTO]="QGOTO"; + explanation[cGOSUB]="GOSUB"; + explanation[cQGOSUB]="QGOSUB"; + explanation[cCALL]="CALL"; + explanation[cQCALL]="QCALL"; + explanation[cRETURN]="RETURN"; + explanation[cRET_FROM_FUN]="RET_FROM_FUN"; + explanation[cRETVAL]="RETVAL"; + explanation[cSWAP]="SWAP"; + explanation[cDECIDE]="DECIDE"; + explanation[cANDSHORT]="ANDSHORT"; + explanation[cORSHORT]="ORSHORT"; + explanation[cSKIPPER]="SKIPPER"; + explanation[cSKIPONCE]="SKIPONCE"; + explanation[cRESETSKIPONCE]="RESETSKIPONCE"; + explanation[cNOP]="NOP"; + explanation[cEND_FUNCTION]="END_FUNCTION"; + explanation[cDIM]="DIM"; + explanation[cFUNCTION]="FUNCTION"; + explanation[cDOARRAY]="DOARRAY"; + explanation[cDBLADD]="DBLADD"; + explanation[cDBLMIN]="DBLMIN"; + explanation[cDBLMUL]="DBLMUL"; + explanation[cDBLDIV]="DBLDIV"; + explanation[cDBLPOW]="DBLPOW"; + explanation[cNEGATE]="NEGATE"; + explanation[cPUSHDBLSYM]="PUSHDBLSYM"; + explanation[cREQUIRE]="REQUIRE"; + explanation[cCLEARREFS]="CLEARREFS"; + explanation[cPUSHSYMLIST]="PUSHSYMLIST"; + explanation[cPOPSYMLIST]="POPSYMLIST"; + explanation[cMAKELOCAL]="MAKELOCAL"; + explanation[cNUMPARAM]="NUMPARAM"; + explanation[cMAKESTATIC]="MAKESTATIC"; + explanation[cARRAYLINK]="ARRAYLINK"; + explanation[cPUSHARRAYREF]="PUSHARRAYREF"; + explanation[cARDIM]="ARRAYDIMENSION"; + explanation[cARSIZE]="ARRAYSIZE"; + explanation[cUSER_FUNCTION]="USER_FUNCTION"; + explanation[cFUNCTION_OR_ARRAY]="FUNCTION_OR_ARRAY"; + explanation[cSTRINGFUNCTION_OR_ARRAY]="STRINGFUNCTION_OR_ARRAY"; + explanation[cPUSHFREE]="PUSHFREE"; + explanation[cPOPDBLSYM]="POPDBLSYM"; + explanation[cPOP]="POP"; + explanation[cPUSHDBL]="PUSHDBL"; + explanation[cPOKE]="POKE"; + explanation[cPOKEFILE]="POKEFILE"; + explanation[cAND]="AND"; + explanation[cOR]="OR"; + explanation[cNOT]="NOT"; + explanation[cLT]="LT"; + explanation[cGT]="GT"; + explanation[cLE]="LE"; + explanation[cGE]="GE"; + explanation[cEQ]="EQ"; + explanation[cNE]="NE"; + explanation[cSTREQ]="STREQ"; + explanation[cSTRNE]="STRNE"; + explanation[cPUSHSTRSYM]="PUSHSTRSYM"; + explanation[cPOPSTRSYM]="POPSTRSYM"; + explanation[cPUSHSTR]="PUSHSTR"; + explanation[cCONCAT]="CONCAT"; + explanation[cPUSHSTRPTR]="PUSHSTRPTR"; + explanation[cCHANGESTRING]="CHANGESTRING"; + explanation[cGLOB]="GLOB"; + explanation[cPRINT]="PRINT"; + explanation[cREAD]="READ"; + explanation[cRESTORE]="RESTORE"; + explanation[cQRESTORE]="QRESTORE"; + explanation[cREADDATA]="READDATA"; + explanation[cONESTRING]="ONESTRING"; + explanation[cDATA]="DATA"; + explanation[cOPEN]="OPEN"; + explanation[cCHECKOPEN]="CHECKOPEN"; + explanation[cCHECKSEEK]="CHECKSEEK"; + explanation[cCOMPILE]="COMPILE"; + explanation[cEXECUTE]="EXECUTE"; + explanation[cEXECUTE2]="EXECUTE$"; + explanation[cCLOSE]="CLOSE"; + explanation[cSEEK]="SEEK"; + explanation[cSEEK2]="SEEK2"; + explanation[cPUSHSTREAM]="cPUSHSTREAM"; + explanation[cPOPSTREAM]="cPOPSTREAM"; + explanation[cWAIT]="WAIT"; + explanation[cBELL]="BELL"; + explanation[cMOVE]="MOVE"; + explanation[cCLEARSCR]="CLEARSCR"; + explanation[cOPENWIN]="OPENWIN"; + explanation[cDOT]="DOT"; + explanation[cPUTCHAR]="PUTCHAR"; + explanation[cLINE]="LINE"; + explanation[cCIRCLE]="CIRCLE"; + explanation[cTEXT]="TEXT"; + explanation[cCLOSEWIN]="CLOSEWIN"; + explanation[cTESTEOF]="TESTEOF"; + explanation[cCOLOUR]="COLOUR"; + explanation[cDUPLICATE]="DUPLICATE"; + explanation[cDOCU]="DOCU"; + explanation[cEND]="END"; + explanation[cEXIT]="EXIT"; + explanation[cBIND]="BIND"; + explanation[cERROR]="ERROR"; + explanation[cSTARTFOR]="STARTFOR"; + explanation[cFORCHECK]="FORCHECK"; + explanation[cFORINCREMENT]="FORINCREMENT"; + explanation[cBREAK_MARK]="BREAK_MARK"; + explanation[cPUSH_SWITCH_MARK]="PUSH_SWITCH_MARK"; + explanation[cCLEAN_SWITCH_MARK]="CLEAN_SWITCH_MARK"; + explanation[cSWITCH_COMPARE]="SWITCH_COMPARE"; + explanation[cNEXT_CASE]="NEXT_CASE"; + explanation[cBREAK]="BREAK"; + explanation[cMINOR_BREAK]="MINOR_BREAK"; + explanation[cCONTINUE]="CONTINUE"; + explanation[cBREAK_HERE]="BREAK_HERE"; + explanation[cCONTINUE_HERE]="CONTINUE_HERE"; + explanation[cBREAK_MARK]="BREAK_MARK"; + explanation[cCONTINUE_CORRECTION]="CONTINUE_CORRECTION"; + explanation[cLAST_COMMAND]="???"; + + ykey[kERR]="error"; + ykey[kUP]="up"; + ykey[kDOWN]="down"; + ykey[kLEFT]="left"; + ykey[kRIGHT]="right"; + ykey[kDEL]="del"; + ykey[kINS]="ins"; + ykey[kCLEAR]="clear"; + ykey[kHOME]="home"; + ykey[kEND]="end"; + ykey[kF0]="f0"; + ykey[kF1]="f1"; + ykey[kF2]="f2"; + ykey[kF3]="f3"; + ykey[kF4]="f4"; + ykey[kF5]="f5"; + ykey[kF6]="f6"; + ykey[kF7]="f7"; + ykey[kF8]="f8"; + ykey[kF9]="f9"; + ykey[kF10]="f10"; + ykey[kF11]="f11"; + ykey[kF12]="f12"; + ykey[kF13]="f13"; + ykey[kF14]="f14"; + ykey[kF15]="f15"; + ykey[kF16]="f16"; + ykey[kF17]="f17"; + ykey[kF18]="f18"; + ykey[kF19]="f19"; + ykey[kF20]="f20"; + ykey[kF21]="f21"; + ykey[kF22]="f22"; + ykey[kF23]="f23"; + ykey[kF24]="f24"; + ykey[kBACKSPACE]="backspace"; + ykey[kSCRNDOWN]="scrndown"; + ykey[kSCRNUP]="scrnup"; + ykey[kENTER]="enter"; + ykey[kESC]="esc"; + ykey[kTAB]="tab"; + ykey[kLASTKEY]=""; +} + +void signal_handler(int sig) /* handle signals */ +{ + signal(sig,SIG_DFL); + if (program_state==FINISHED) { + yi_exit(1,yab); + } + signal_arrived=sig; + +#ifdef WINDOWS + if (signal_arrived) { + SuspendThread(mainthread); + if (wthandle!=INVALID_HANDLE_VALUE) SuspendThread(wthandle); + if (kthandle!=INVALID_HANDLE_VALUE) TerminateThread(kthandle,0); + } +#endif + + switch(sig) { + case SIGFPE: + error(FATAL,"floating point exception, cannot proceed."); + case SIGSEGV: + error(FATAL,"segmentation fault, cannot proceed."); + case SIGINT: +#ifdef UNIX +#ifndef BEOS + if (winpid==0 || termpid==0 || backpid==0) yi_exit(1,yab); +#endif +#endif + error(FATAL,"keyboard interrupt, cannot proceed."); +#ifdef SIGHUP + case SIGHUP: + error(FATAL,"received signal HANGUP, cannot proceed."); +#endif +#ifdef SIGQUIT + case SIGQUIT: + error(FATAL,"received signal QUIT, cannot proceed."); +#endif +#ifdef SIGABRT + case SIGABRT: + error(FATAL,"received signal ABORT, cannot proceed."); +#endif + default: + break; + } +} + + +static void run_it(YabInterface* yab) + /* execute the compiled code */ +{ + int l=0; + + current=cmdroot; /* start with first comand */ + if (print_docu) { /* don't execute program, just print docu */ + while(current!=cmdhead) { + if (current->type==cDOCU) { + if (infolevel>=DEBUG) std_diag("executing",current->type,current->name); + printf("%s\n",(char *)current->pointer); + l++; + if (hold_docu && !(l%24)) { + printf("---Press RETURN to continue "); + fgets(string,20,stdin); + } + } else { + if (infolevel>=DEBUG) std_diag("skipping",current->type,current->name); + } + current=current->next; + } + if (!l) printf("---No embbeded documentation\n"); + if (hold_docu) { + printf("---End of embbedded documentation, press RETURN "); + fgets(string,20,stdin); + } + } else { + while(current!=cmdhead && endreason==erNONE) { + if (infolevel>=DEBUG) std_diag("executing",current->type,current->name); + switch(current->type) { + case cGOTO:case cQGOTO:case cGOSUB:case cQGOSUB:case cCALL:case cQCALL: + jump(current); DONE; + case cEXCEPTION: + exception(current); DONE; + case cSKIPPER: + skipper(); break; + case cSKIPONCE: + skiponce(current); DONE; + case cRESETSKIPONCE: + resetskiponce(current); DONE; + case cNEXT_CASE: + next_case(); DONE; + case cBREAK:case cMINOR_BREAK: + mybreak(current); DONE; + case cSWITCH_COMPARE: + switch_compare(); DONE; + case cPUSH_SWITCH_MARK: + push_switch_mark(); DONE; + case cCLEAN_SWITCH_MARK: + clean_switch_mark(current); DONE; + case cCONTINUE: + mycontinue(current); DONE; + case cFINDNOP: + findnop(); DONE; + case cFUNCTION_OR_ARRAY: case cSTRINGFUNCTION_OR_ARRAY: + function_or_array(current); + break; /* NOT 'DONE' ! */ + case cLABEL:case cDATA:case cNOP:case cUSER_FUNCTION: + case cSUBLINK:case cEND_FUNCTION: case cDOCU: case cBREAK_HERE: + case cCONTINUE_HERE:case cBREAK_MARK:case cCONTINUE_CORRECTION: + DONE; + case cERROR: + do_error(current); DONE; + case cCOMPILE: + compile(); DONE; + case cEXECUTE: case cEXECUTE2: + execute(current); DONE; + case cRETURN:case cRET_FROM_FUN: + myreturn(current); DONE; + case cRETVAL: + retval(current); DONE; + case cPUSHDBLSYM: + pushdblsym(current); DONE; + case cPUSHDBL: + pushdbl(current); DONE; + case cPOPDBLSYM: + popdblsym(current); DONE; + case cPOP: + pop(stANY); DONE; + case cPOPSTRSYM: + popstrsym(current); DONE; + case cPUSHSTRSYM: + pushstrsym(current); DONE; + case cPUSHSTR: + pushstr(current); DONE; + case cCLEARREFS: + clearrefs(current); DONE; + case cPUSHSYMLIST: + pushsymlist(); DONE; + case cPOPSYMLIST: + popsymlist(); DONE; + case cREQUIRE: + require(current); DONE; + case cMAKELOCAL: + makelocal(current); DONE; + case cNUMPARAM: + numparam(current); DONE; + case cMAKESTATIC: + makestatic(current); DONE; + case cARRAYLINK: + arraylink(current); DONE; + case cPUSHARRAYREF: + pusharrayref(current); DONE; + case cTOKEN: case cTOKEN2: case cSPLIT: case cSPLIT2: + token(current); DONE; + case cTOKENALT: case cTOKENALT2: case cSPLITALT: case cSPLITALT2: + tokenalt(current); DONE; + case cARDIM: case cARSIZE: + query_array(current); DONE; + case cPUSHFREE: + push()->type=stFREE; DONE; + case cCONCAT: + concat(); DONE; + case cPRINT: + print(current); DONE; + case cMOVE: + mymove(); DONE; + case cCOLOUR: + colour(current); DONE; + case cCLEARSCR: + clearscreen(); DONE; + case cONESTRING: + onestring(current->pointer); DONE; + case cTESTEOF: + testeof(current); DONE; + case cOPEN: + myopen(current); DONE; + case cCHECKOPEN:case cCHECKSEEK: + checkopen(); DONE; + case cCLOSE: + myclose(); DONE; + case cSEEK:case cSEEK2: + myseek(current); DONE; + case cPUSHSTREAM: + push_switch(current); DONE; + case cPOPSTREAM: + pop_switch(); DONE; + case cCHKPROMPT: + chkprompt(); DONE; + case cREAD: + myread(current); DONE; + case cRESTORE:case cQRESTORE: + restore(current); DONE; + case cREADDATA: + readdata(current); DONE; + case cDBLADD:case cDBLMIN:case cDBLMUL:case cDBLDIV:case cDBLPOW: + dblbin(current); DONE; + case cNEGATE: + negate(); DONE; + case cEQ:case cNE:case cGT:case cGE:case cLT:case cLE: + dblrelop(current); DONE; + case cSTREQ:case cSTRNE:case cSTRLT:case cSTRLE:case cSTRGT:case cSTRGE: + strrelop(current); DONE; + case cAND:case cOR:case cNOT: + boole(current); DONE; + case cFUNCTION: + function(current, yab); DONE; + case cGLOB: + glob(); DONE; + case cDOARRAY: + doarray(current); DONE; + case cCHANGESTRING: + changestring(current); DONE; + case cPUSHSTRPTR: + pushstrptr(current); DONE; + case cDIM: + dim(current); DONE; + case cDECIDE: + decide(); DONE; + case cANDSHORT:case cORSHORT: + logical_shortcut(current); DONE; + case cOPENWIN: + openwin(current, yab); DONE; + case cBUTTON: + createbutton(current, yab); DONE; + case cALERT: + createalert(current, yab); DONE; + case cWINSET1: + winset1(current, yab); DONE; + case cWINSET2: + winset2(current, yab); DONE; + case cWINSET3: + winset3(current, yab); DONE; + case cWINSET4: + winset4(current, yab); DONE; + case cWINCLEAR: + winclear(current, yab); DONE; + case cLAYOUT: + setlayout(current,yab); DONE; + case cTEXTEDIT: + textedit(current,yab); DONE; + case cTEXTADD: + textadd(current,yab); DONE; + case cTEXTSET: + textset(current,yab); DONE; + case cTEXTSET2: + textset2(current,yab); DONE; + case cTEXTSET3: + textset3(current,yab); DONE; + case cTEXTCOLOR1: + textcolor1(current,yab); DONE; + case cTEXTCOLOR2: + textcolor2(current,yab); DONE; + case cTEXTCLEAR: + textclear(current,yab); DONE; + case cDRAWSET1: + drawset1(current,yab); DONE; + case cDRAWSET2: + drawset2(current,yab); DONE; + case cDRAWSET3: + drawset3(current,yab); DONE; + case cTEXT: + createtext(current, yab); DONE; + case cTEXT2: + text2(current, yab); DONE; + case cTEXTALIGN: + textalign(current, yab); DONE; + case cTEXTURL1: + texturl1(current, yab); DONE; + case cTEXTURL2: + texturl2(current, yab); DONE; + case cLOCALIZE: + localize(); DONE; + case cLOCALIZESTOP: + localizestop(); DONE; + case cLOCALIZE2: + localize2(current, yab); DONE; + case cMENU: + createmenu(current, yab); DONE; + case cCHECKBOX: + createcheckbox(current, yab); DONE; + case cRADIOBUTTON: + createradiobutton(current, yab); DONE; + case cTEXTCONTROL: + createtextcontrol(current, yab); DONE; + case cLAUNCH: + launch(current, yab); DONE; + case cLISTBOX: + createlistbox(current, yab); DONE; + case cDROPBOX: + createdropbox(current, yab); DONE; + case cITEMADD: + createitem(current, yab); DONE; + case cITEMDEL: + removeitem(current, yab); DONE; + case cITEMCLEAR: + clearitems(current, yab); DONE; + case cDRAWRECT: + drawrect(current, yab); DONE; + case cDRAWTEXT: + drawtext(current, yab); DONE; + case cDRAWCLEAR: + drawclear(current, yab); DONE; + case cDOT: + drawdot(current,yab); DONE; + case cPUTCHAR: + putchars(); DONE; + case cLINE: + drawline(current,yab); DONE; + case cCIRCLE: + drawcircle(current,yab); DONE; + case cCURVE: + drawcurve(current,yab); DONE; + case cELLIPSE: + drawellipse(current,yab); DONE; +/* case cTEXT: + text(current); DONE;*/ + case cCLOSEWIN: + closewin(current,yab); DONE; + case cVIEW: + view(current, yab); DONE; + case cBOXVIEW: + boxview(current, yab); DONE; + case cBOXVIEWSET: + boxviewset(current, yab); DONE; + case cTAB: + tab(current, yab); DONE; + case cTABSET: + tabset(current, yab); DONE; + case cTABADD: + tabadd(current, yab); DONE; + case cTABDEL: + tabdel(current, yab); DONE; + case cSLIDER1: + slider1(current, yab); DONE; + case cSLIDER2: + slider2(current, yab); DONE; + case cSLIDER3: + slider3(current, yab); DONE; + case cSLIDER4: + slider4(current, yab); DONE; + case cSLIDER5: + slider5(current, yab); DONE; + case cSLIDER6: + slider6(current, yab); DONE; + case cOPTION1: + option1(current, yab); DONE; + case cOPTION2: + option2(current, yab); DONE; + case cOPTION3: + option3(current, yab); DONE; + case cOPTION4: + option4(current, yab); DONE; + case cOPTION5: + option5(current, yab); DONE; + case cDROPZONE: + dropzone(current, yab); DONE; + case cCOLORCONTROL1: + colorcontrol1(current, yab); DONE; + case cCOLORCONTROL2: + colorcontrol2(current, yab); DONE; + case cTEXTCONTROL2: + textcontrol2(current, yab); DONE; + case cTEXTCONTROL3: + textcontrol3(current, yab); DONE; + case cTEXTCONTROL4: + textcontrol4(current, yab); DONE; + case cTEXTCONTROL5: + textcontrol5(current, yab); DONE; + case cTREEBOX1: + treebox1(current, yab); DONE; + case cTREEBOX2: + treebox2(current, yab); DONE; + case cTREEBOX3: + treebox3(current, yab); DONE; + case cTREEBOX4: + treebox4(current, yab); DONE; + case cTREEBOX5: + treebox5(current, yab); DONE; + case cTREEBOX7: + treebox7(current, yab); DONE; + case cTREEBOX8: + treebox8(current, yab); DONE; + case cTREEBOX9: + treebox9(current, yab); DONE; + case cTREEBOX10: + treebox10(current, yab); DONE; + case cTREEBOX11: + treebox11(current, yab); DONE; + case cTREEBOX12: + treebox12(current, yab); DONE; + case cBUTTONIMAGE: + buttonimage(current, yab); DONE; + case cCHECKBOXIMAGE: + checkboximage(current, yab); DONE; + case cCHECKBOXSET: + checkboxset(current, yab); DONE; + case cRADIOSET: + radioset(current, yab); DONE; + case cTOOLTIP: + tooltip(current, yab); DONE; + case cTOOLTIPCOLOR: + tooltipcolor(current, yab); DONE; + case cFILEBOX: + filebox(current, yab); DONE; + case cFILEBOXADD2: + fileboxadd2(current, yab); DONE; + case cFILEBOXCLEAR: + fileboxclear(current, yab); DONE; + case cCOLUMNBOXADD: + columnboxadd(current, yab); DONE; + case cCOLUMNBOXREMOVE: + columnboxremove(current, yab); DONE; + case cCOLUMNBOXSELECT: + columnboxselect(current, yab); DONE; + case cCOLUMNBOXCOLOR: + columnboxcolor(current, yab); DONE; + case cDROPBOXSELECT: + dropboxselect(current, yab); DONE; + case cDROPBOXREMOVE: + dropboxremove(current, yab); DONE; + case cDROPBOXCLEAR: + dropboxclear(current, yab); DONE; + case cPRINTERCONFIG: + printerconfig(current, yab); DONE; + case cMENU2: + menu2(current, yab); DONE; + case cMENU3: + menu3(current, yab); DONE; + case cSUBMENU1: + submenu1(current, yab); DONE; + case cSUBMENU2: + submenu2(current, yab); DONE; + case cSUBMENU3: + submenu3(current, yab); DONE; + case cCLIPBOARDCOPY: + clipboardcopy(current, yab); DONE; + case cLISTSORT: + listsort(current, yab); DONE; + case cTREESORT: + treesort(current, yab); DONE; + case cCALENDAR: + calendar1(current, yab); DONE; + case cCALENDARSET: + calendar3(current, yab); DONE; + case cSCROLLBAR: + scrollbar(current, yab); DONE; + case cSCROLLBARSET1: + scrollbarset1(current, yab); DONE; + case cSCROLLBARSET2: + scrollbarset2(current, yab); DONE; + case cSCROLLBARSET3: + scrollbarset3(current, yab); DONE; + case cLISTBOXADD1: + listboxadd1(current, yab); DONE; + case cLISTBOXADD2: + listboxadd2(current, yab); DONE; + case cLISTBOXSELECT: + listboxselect(current, yab); DONE; + case cLISTBOXDEL2: + listboxremove(current, yab); DONE; + case cSOUNDSTOP: + soundstop(current, yab); DONE; + case cSOUNDWAIT: + soundwait(current, yab); DONE; + case cSHORTCUT: + shortcut(current, yab); DONE; + case cTREEBOX13: + treebox13(current, yab); DONE; + case cDRAWSET4: + drawset4(current, yab); DONE; + case cSPLITVIEW1: + splitview1(current, yab); DONE; + case cSPLITVIEW2: + splitview2(current, yab); DONE; + case cSPLITVIEW3: + splitview3(current, yab); DONE; + case cSTACKVIEW1: + stackview1(current, yab); DONE; + case cSTACKVIEW2: + stackview2(current, yab); DONE; + case cSPINCONTROL1: + spincontrol1(current, yab); DONE; + case cSPINCONTROL2: + spincontrol2(current, yab); DONE; + case cBITMAP: + bitmap(current, yab); DONE; + case cBITMAPDRAW: + bitmapdraw(current, yab); DONE; + case cBITMAPDRAW2: + bitmapdraw2(current, yab); DONE; + case cBITMAPGET: + bitmapget(current, yab); DONE; + case cBITMAPGET2: + bitmapget2(current, yab); DONE; + case cBITMAPGETICON: + bitmapgeticon(current, yab); DONE; + case cBITMAPDRAG: + bitmapdrag(current, yab); DONE; + case cSCREENSHOT: + screenshot(current, yab); DONE; + case cBITMAPREMOVE: + bitmapremove(current, yab); DONE; + case cSTATUSBAR: + statusbar(current, yab); DONE; + case cSTATUSBARSET: + statusbarset(current, yab); DONE; + case cSTATUSBARSET2: + statusbarset2(current, yab); DONE; + case cSTATUSBARSET3: + statusbarset3(current, yab); DONE; + case cCANVAS: + canvas(current, yab); DONE; + case cMOUSESET: + mouseset(current, yab); DONE; + case cATTRIBUTE1: + attribute1(current, yab); DONE; + case cATTRIBUTECLEAR: + attributeclear(current, yab); DONE; + case cWAIT: + mywait(); DONE; + case cRESTORE2: { + struct command *c; + char *s; + c = add_command(cRESTORE, FALSE); + s = pop(stSTRING)->pointer; + if(!strcmp(s, "")) + c->pointer=my_strdup(s); + else + c->pointer=my_strdup(dotify(s, TRUE)); + restore(c); + } DONE; + case cBELL: + mybell(); DONE; + case cPOKE: + poke(current); DONE; + case cPOKEFILE: + pokefile(current); DONE; + case cSWAP: + swap(); DONE; + case cDUPLICATE: + duplicate(); DONE; + case cFORCHECK: + forcheck(); DONE; + case cFORINCREMENT: + forincrement(); DONE; + case cSTARTFOR: + startfor(); DONE; + case cBIND: + mybind(pop(stSTRING)->pointer); DONE; + case cEND: + endreason=erEOF; break; + case cEXIT: + exitcode=(int)pop(stNUMBER)->value;endreason=erREQUEST; break; + default: + sprintf(string,"Command %s (%d, right before '%s') not implemented", + explanation[current->type],current->type,explanation[current->type+1]); + error(ERROR,string); + } + } + } + program_state=FINISHED; + switch(errorlevel) { + case NOTE:case DEBUG: + error(NOTE,"Program ended normally."); break; + case WARNING: + error(WARNING,"Program ended with a warning"); break; + case ERROR: + error(ERROR,"Program stopped due to an error"); break; + case FATAL: /* should not come here ... */ + error(FATAL,"Program terminated due to FATAL error"); + break; + } +} + + +void error(int severity, char *messageline) + /* reports an basic error to the user and possibly exits */ +{ + if (program_state==COMPILING) + error_with_line(severity,messageline,mylineno); + else if (program_state==RUNNING && current->line>0) + error_with_line(severity,messageline,current->line); + else + error_with_line(severity,messageline,-1); +} + + +void error_with_line(int severity, char *message,int line) + /* reports an basic error to the user and possibly exits */ +{ + char *callstack; + char *stext; + char *f=NULL; + int l; + static int lastline; + static int first=TRUE; + + if (severity<=infolevel) { +#ifdef UNIX +#ifdef BUILD_NCURSES + if (curinized) reset_shell_mode(); +#endif +#endif + + switch(severity) { + case(INFO): + stext="---Info"; + break; + case(DUMP): + stext="---Dump"; + break; + case(DEBUG): + stext="---Debug"; + debug_count++; + break; + case(NOTE): + stext="---Note"; + note_count++; + break; + case(WARNING): + stext="---Warning"; + warning_count++; + break; + case(ERROR): + stext="---Error"; + error_count++; + break; + case(FATAL): + stext="---Fatal"; + break; + } + fprintf(stderr,"%s",stext); + if (line>=0) { + if (program_state==COMPILING) { + f=currlib->l; + l=mylineno; + } else if (program_state==RUNNING && current->line>0) { + f=current->lib->l; + l=current->line; + } + if (f) { + if (first || lastline!=l) { + fprintf(stderr," in %s, line %d",f,l); + } + lastline=l; + first=FALSE; + } + } + fprintf(stderr,": %s\n",message); + if (program_state==RUNNING && severity<=ERROR && severity!=DUMP) dump_sub(1); + } + if (severitynext) { + if (!strcmp(curr->l,l)) { + if (is_bound) + return curr; + else + return NULL; + } + } + + new=my_malloc(sizeof(struct libfile_name)); + new->next=NULL; + new->lineno=1; + if (last) last->next=new; + last=new; + + new->l=my_strdup(l); + new->llen=strlen(new->l); + + if (s) { + new->s=my_strdup(s); + } else { + /* no short name supplied get piece from l */ + end=strlen(l); + for(start=end;start>0;start--) { + if (l[start-1]=='\\' || l[start-1]=='/') break; + if (l[start]=='.') end=start; + } + end--; + new->s=my_malloc(end-start+2); + strncpy(new->s,new->l+start,end-start+1); + new->s[end-start+1]='\0'; + } + new->slen=strlen(new->s); + new->datapointer=new->firstdata=NULL; + + return new; +} + + +char *dotify(char *name,int addfun) /* add library name, if not already present */ +{ + static char buff[200]; + if (!strchr(name,'.')) { + strcpy(buff,currlib->s); + strcat(buff,"."); + strcat(buff,name); + } else { + strcpy(buff,name); + } + if (addfun && !strchr(name,'@')) { + strcat(buff,"@"); + strcat(buff,current_function); + } + return buff; +} + + +char *strip(char *name) /* strip down to minimal name */ +{ + static char buff[300]; + char *at,*dot; + + if (infolevel>=DEBUG) return name; + dot=strchr(name,'.'); + if (dot) + strcpy(buff,dot+1); + else + strcpy(buff,name); + at=strchr(buff,'@'); + if (at) *at='\0'; + + return buff; +} + + +void do_error(struct command *cmd) /* issue user defined error */ +{ + struct stackentry *s; + struct command *r; + + s=stackhead; + while(s!=stackroot) { + if (s->type==stRETADDCALL) { + r=s->pointer; + cmd->line=r->line; + cmd->lib=r->lib; + break; + } + s=s->prev; + } + error(ERROR,pop(stSTRING)->pointer); +} + + +void compile() /* create s subroutine at runtime */ +{ + open_string(pop(stSTRING)->pointer); + yyparse(); + add_command(cEND,NULL); +} + + +void create_execute(int string) /* create command 'cEXECUTESUB' */ +{ + struct command *cmd; + + cmd=add_command(string?cEXECUTE2:cEXECUTE,NULL); + cmd->pointer=my_strdup(dotify("",FALSE)); +} + + +void execute(struct command *cmd) /* execute a subroutine */ +{ + struct stackentry *st,*ret; + char *fullname,*shortname; + struct command *newcurr; + + st=stackhead; + do {st=st->prev;} while(st->type!=stFREE); + st=st->next; + if (st->type!=stSTRING) { + error(ERROR,"need a string as a function name"); + return; + } + shortname=st->pointer; + if ((shortname[strlen(shortname)-1]=='$')!=(cmd->type==cEXECUTE2)) { + if (cmd->type==cEXECUTE2) + sprintf(string,"expecting the name of a string function (not '%s')",shortname); + else + sprintf(string,"expecting the name of a numeric function (not '%s')",shortname); + error(ERROR,string); + return; + } + fullname=my_malloc(strlen(cmd->pointer)+strlen(shortname)+2); + strcpy(fullname,cmd->pointer); + strcat(fullname,shortname); + free(st->pointer); + st->type=stFREE; + newcurr=search_label(fullname,smSUB); + if (!newcurr) { + sprintf(string,"subroutine '%s' not defined",fullname); + error(ERROR,string); + return; + } + ret=push(); + ret->pointer=current; + ret->type=stRETADDCALL; + reshufflestack(ret); + current=newcurr; + free(fullname); +} + + +void create_docu(char *doc) /* create command 'docu' */ +{ + struct command *cmd; + static struct command *previous=NULL; + + if (inlib) return; + cmd=add_command(cDOCU,NULL); + cmd->pointer=doc; + if (previous) + previous->nextassoc=cmd; + else + docuhead=cmd; + previous=cmd; + docucount++; +} + + +void create_docu_array(void) /* create array with documentation */ +{ + struct array *ar; + struct command *doc; + int i; + + /* create and prepare docu-array */ + ar=create_array('s',1); + ar->bounds[0]=docucount+1; + ar->pointer=my_malloc((docucount+1)*sizeof(char *)); + ((char **)ar->pointer)[0]=my_strdup(""); + doc=docuhead; + i=1; + while(doc) { + ((char **)ar->pointer)[i]=doc->pointer; + doc=doc->nextassoc; + i++; + } + get_sym("main.docu$",syARRAY,amADD_GLOBAL)->pointer=ar; +} + + +int isbound(void) /* check if this interpreter is bound to a program */ +{ +/* + if (!interpreter_path || !interpreter_path[0]) { + error(FATAL,"interpreter_path is not set !"); + return 0; + } + if (!(interpreter=fopen(interpreter_path,"r"))) { + sprintf(string,"Couldn't open '%s' to check, if it is bound: %s",interpreter_path,my_strerror(errno)); + error(WARNING,string); + return 0; + } + + if(sizeof(myProg)>1) + return 1; + else + return 0; + */ + FILE *interpreter; + int i; + int c; + int proglen=0; + int bound=1; + + if (!interpreter_path || !interpreter_path[0]) { + error(FATAL,"interpreter_path is not set !"); + return 0; + } + if (!(interpreter=fopen(interpreter_path,"r"))) { + sprintf(string,"Couldn't open '%s' to check, if it is bound: %s",interpreter_path,my_strerror(errno)); + error(WARNING,string); + return 0; + } + + if (fseek(interpreter,0-strlen(YABMAGIC)-1,SEEK_END)) { + sprintf(string,"Couldn't seek within '%s': %s",interpreter_path,my_strerror(errno)); + error(WARNING,string); + return 0; + } + for(i=0;i=NOTE) { + error(NOTE,"Dumping the embedded program, that will be executed:"); + fprintf(stderr," "); + for(i=0;i=DEBUG) { + sprintf(string,"binding %s and %s into %s",interpreter_path,main_file_name,bound); + error(NOTE,string); + } + + while((c=fgetc(fyab))!=EOF) { + fputc(c,fbound); + } + for (i=1;il,"rb"))) { + sprintf(string,"could not open '%s' for reading: %s",libfile_chain[i]->l,my_strerror(errno)); + error(ERROR,string); + fclose(flib); + return 0; + } + sprintf(string,"\nimport %s\n",libfile_chain[i]->s); + for (pc=string;*pc;pc++) { + fputc(*pc,fbound); + proglen++; + } + while((c=fgetc(flib))!=EOF) { + fputc(c,fbound); + proglen++; + } + } + + for (pc="\nimport main\n";*pc;pc++) { + fputc(*pc,fbound); + proglen++; + } + for (pc="\nimport __END_OF_IMPORT\n";*pc;pc++) { + fputc(*pc,fbound); + proglen++; + } + while((c=fgetc(fprog))!=EOF) { + fputc(c,fbound); + proglen++; + } + fprintf(fbound,"\nend\n"); + fprintf(fbound,"rem %08d\n",proglen); + fprintf(fbound,"rem %s\n",YABMAGIC); + fclose(fyab); + fclose(fprog); + fclose(fbound); + + return 1; +} + +char *find_interpreter(char *name) /* find interpreter with full path */ +{ + FILE *f; + char *path=NULL; + +#ifdef WINDOWS + path=my_malloc(1000); + GetModuleFileName(NULL,path,1000); + if (f=fopen(path,"r")) { + fclose(f); + return path; + } else { + my_free(path); + return my_strdup(name); + } + +#else + if (f=fopen(name,"r")) { + fclose(f); + path=my_strdup(name); + return path; + } else { + char *from,*to,*try; + from=to=path=getenv("PATH"); + try=my_malloc(strlen(path)+strlen(name)+2); + to=strchr(to+1,':'); + while(to) { + strncpy(try,from,to-from); + try[to-from]=0; + if (try[to-from-1]!='/') strcat(try,"/"); + strcat(try,name); + if (f=fopen(try,"r")) { + fclose(f); + return try; + } + from=to+1; + to=strchr(to+1,':'); + } + return name; + } +#endif +} + + +char *my_strerror(int err) { /* return description of error */ +#ifdef WINDOWS + return strerror(err); +#else +#ifdef HAVE_STRERROR + return strerror(err); +#else + char buff[100]; + sprintf(buff,"errno=%d",err); + return buff; +#endif +#endif +} diff --git a/src/resattr b/src/resattr new file mode 100755 index 0000000..36f7fc9 Binary files /dev/null and b/src/resattr differ diff --git a/src/symbol.c b/src/symbol.c new file mode 100644 index 0000000..e582a07 --- /dev/null +++ b/src/symbol.c @@ -0,0 +1,1775 @@ +/* + + YABASIC --- a simple Basic Interpreter + written by Marc-Oliver Ihm 1995-2004 + homepage: www.yabasic.de + + symbol.c --- code for control structures, symbol and stack management + + This file is part of yabasic and may be copied only + under the terms of either the Artistic License or + the GNU General Public License (GPL), both of which + can be found at www.yabasic.de + +*/ + +/* ------------- includes ---------------- */ + +#ifndef YABASIC_INCLUDED +#include "yabasic.h" /* all prototypes and structures */ +#endif + + +/* ------------- external references ---------------- */ + +extern int mylineno; /* current line number */ +extern int yyparse(); /* call bison parser */ + + +/* ------------- local defines ---------------- */ +struct switch_id { + int id; + int depth; + struct switch_id *next; + struct switch_id *prev; +}; + + +/* ------------- local functions ---------------- */ + +static struct symbol *create_symbol(int,char *); /* create a new symbol */ +static void link_label(struct command *); /* link label into list of labels */ +static int count_args(int); /* count number of arguments on stack */ +static void stackdesc(int,char *); /* give back string describing stackentry */ +static void freesym(struct symbol *); /* free contents of symbol */ +static int ind_to_off(int *,int *); /* convert array of indices to single offset */ +static void off_to_ind(int,int *,int *); /* convert a single offset to an array of indices */ + + +/* ------------- global variables ---------------- */ + +static struct symstack *symroot=NULL; /* first element in symbol list */ +static struct symstack *symhead=NULL; /* last element ind symbol list */ +struct stackentry *stackroot; /* lowest element in stack */ +struct stackentry *stackhead; /* topmost element in stack */ +static struct command *labelroot=NULL; /* first label among commands */ +static struct command *labelhead=NULL; /* last label seen so far */ +extern char *current_function; /* name of currently defined function */ +struct command *lastref; /* last command in UDS referencing a symbol */ +struct command *firstref; /* first command in UDS referencing a symbol */ +int labelcount=0; /* count self-generated labels */ +int in_switch=0; /* true, if in switch (at compile-time) */ +struct switch_id *switch_id_stackhead=NULL; /* topmost (and valid) element of switch_id stack */ +struct switch_id *switch_id_stackroot=NULL; /* bottommost element of switch_id stack */ + + +/* ------------- subroutines ---------------- */ + + +void pushsymlist(void) /* push a new list of symbols on symbol stack */ +{ + struct symstack *new; + + new=my_malloc(sizeof(struct symstack)); + if (symhead) + symhead->next_in_stack=new; + else + symroot=new; /* first time called */ + new->prev_in_stack=symhead; + new->next_in_stack=NULL; + new->next_in_list=NULL; + symhead=new; +} + + +void popsymlist(void) /* pop list of symbols and free symbol contents */ +{ + struct symstack *prevstack; + struct symbol *currsym,*nextsym; + int count=0; + + currsym=symhead->next_in_list; + while(currsym) { /* loop through symbol list */ + freesym(currsym); + count++; + nextsym=currsym->next_in_list; + my_free(currsym); + currsym=nextsym; + } + if (infolevel>=DEBUG) { + sprintf(string,"removed symbol list with %d symbols",count); + error(DEBUG,string); + } + prevstack=symhead->prev_in_stack; + my_free(symhead); + prevstack->next_in_stack=NULL; + symhead=prevstack; +} + + +static void freesym(struct symbol *s) /* free contents of symbol */ +{ + int i; + int total; + + struct array *ar; + if (s->link) { /* it's a link, don't remove memory */ + sprintf(string,"removing linked symbol '%s'",s->name); + error(DEBUG,string); + my_free(s->name); + return; + } + if (s->type==sySTRING) { + if (infolevel>=DEBUG) { + sprintf(string,"removing string symbol '%s'",s->name); + error(DEBUG,string); + } + my_free(s->pointer); + } else if (s->type==syARRAY) { + if (infolevel>=DEBUG) { + sprintf(string,"removing array symbol '%s()'",s->name); + error(DEBUG,string); + } + ar=s->pointer; + if (ar->dimension>0) { + /* count total amount of memory */ + total=1; + for(i=0;idimension;i++) total*=(ar->bounds)[i]; + if (ar->type=='s') { /* string array */ + for(i=0;ipointer+i)); + } + my_free(ar->pointer); + } + my_free(ar); + } else if (s->type==syNUMBER) { + if (infolevel>=DEBUG) { + sprintf(string,"removing numeric symbol '%s'",s->name); + error(DEBUG,string); + } + } + my_free(s->name); + return; +} + + +void clearrefs(struct command *cmd) /* clear references for commands within function */ +{ + struct command *curr; + int n=0; + + curr=cmd->nextref; + while(curr) { + n++; + curr->symbol=NULL; + curr=curr->nextref; + } + sprintf(string,"removed references from %d symbols",n); + error(DEBUG,string); +} + + +struct symbol *get_sym(char *name,int type,int add) +/* get the value of a symbol, or create it with given type */ +{ + struct symstack *currstack; + struct symbol **currsym; + struct symbol *prelink; + struct symbol *new; + int stackcount=0; + int symbolcount=0; + int linked=FALSE; + + if (!name) return NULL; + /* go through all lists */ + currstack=symhead; /* start with symhead */ + if (add==amSEARCH_PRE && symhead->prev_in_stack) currstack=symhead->prev_in_stack; + while(TRUE) { + stackcount++; + currsym=&(currstack->next_in_list); + while(*currsym) { + prelink=*currsym; + symbolcount++; + if ((*currsym)->type==type && !strcmp(name,(*currsym)->name)) { /* do the types and names match ? */ + if ((*currsym)->link) { + currsym=&((*currsym)->link); + linked=TRUE; + } + if (infolevel>=DEBUG) { + if (linked) + sprintf(string,"found symbol '%s%s', linked to %s after searching %d symbol(s) in %d stack(s)", + name,(type==syARRAY)?"()":"",(*currsym)->name,symbolcount,stackcount); + else + sprintf(string,"found symbol '%s%s' after searching %d symbol(s) in %d stack(s)", + name,(type==syARRAY)?"()":"",symbolcount,stackcount); + error(DEBUG,string); + } + return *currsym; /* give back address */ + } + currsym=&((*currsym)->next_in_list); /* try next entry */ + } + /* not found in first list */ + if (add==amSEARCH_VERY_LOCAL) return NULL; + if (add==amADD_LOCAL) { + new=create_symbol(type,name); + (*currsym)=new; + if (infolevel>=DEBUG) { + sprintf(string,"created local symbol %s%s",name,(type==syARRAY)?"()":""); + error(DEBUG,string); + } + return new; + } + if (currstack!=symroot) + currstack=symroot; + else + break; + } + if (add==amADD_GLOBAL) { + new=create_symbol(type,name); + (*currsym)=new; + if (infolevel>=DEBUG) { + sprintf(string,"created global symbol %s%s",name,(type==syARRAY)?"()":""); + error(DEBUG,string); + } + return new; + } + return NULL; +} + + +void link_symbols(struct symbol *from,struct symbol *to) { /* link one symbol to the other */ + from->link=to; + if (infolevel>=DEBUG) { + sprintf(string,"linking symbol '%s' to '%s'",from->name,to->name); + error(DEBUG,string); + } +} + + +void create_retval(int is,int should) /* create command 'cRETVAL' */ +{ + struct command *cmd; + + cmd=add_command(cRETVAL,NULL); + cmd->args=is; + cmd->tag=should; +} + + +void retval(struct command *cmd) /* check return value of function */ +{ + int is,should; + struct stackentry *s; + + is=cmd->args; + should=cmd->tag; + if (is==should) { + /* okay, function returns expected type */ + } else if (is==ftNONE) { /* no element on stack, create one */ + s=push(); + if (should==ftNUMBER) { + s->type=stNUMBER; + s->value=0.0; + } else { + s->type=stSTRING; + s->pointer=my_strdup(""); + } + } else { + sprintf(string,"subroutine returns %s but should return %s", + (is==ftSTRING)?"a string":"a number",(should==ftSTRING)?"a string":"a number"); + error(ERROR,string); + } + if (infolevel>=DEBUG) { + s=stackhead->prev; + if (s->type==stNUMBER) + sprintf(string,"subroutine returns number %g",s->value); + else if (s->type==stSTRING) + sprintf(string,"subroutine returns string '%s'",(char *)s->pointer); + else + sprintf(string,"subroutine returns something strange (%d)",s->type); + error(DEBUG,string); + } + swap(); +} + + +void create_endfunction(void) /* create command cEND_FUNCTION */ +{ + struct command *cmd; + + cmd=add_command(cEND_FUNCTION,NULL); + link_label(cmd); +} + + +void dump_sym(void) /* dump the stack of lists of symbols */ +{ + struct symstack *currstack; + struct symbol **currsym; + + /* go through all lists */ + error(DUMP,"head of symbol stack"); + currstack=symhead; + while(currstack) { /* search 'til last element of stack */ + currsym=&(currstack->next_in_list); + string[0]='\0'; + while(*currsym) { + switch((*currsym)->type) { + case sySTRING: strcat(string," STRING:"); break; + case syNUMBER: strcat(string," NUMBER:"); break; + case syFREE: strcat(string," FREE:"); break; + case syARRAY: strcat(string," ARRAY:"); break; + default:sprintf(string," UNKNOWN:"); break; + } + strcat(string,(*currsym)->name); + + currsym=&((*currsym)->next_in_list); /* try next entry */ + } + error(DUMP,string); + currstack=currstack->prev_in_stack; + } + error(DUMP,"root of symbol stack"); + return; +} + + +void dump_sub(int short_dump) /* dump the stack of subroutine calls */ +{ + struct stackentry *st=stackhead; + struct command *cmd; + int first=TRUE; + do { + if (st->type==stRETADDCALL) { + cmd=st->pointer; + if (cmd->type==cCALL || cmd->type==cQCALL) { + char *dot; + dot=strchr(cmd->pointer,'.'); + if (first && !short_dump) error(DUMP,"Executing in:"); + sprintf(string,"sub %s() called in %s,%d",dot ? (dot+1):cmd->pointer,cmd->lib->l,cmd->line); + error(DUMP,string); + first=FALSE; + } + } + st=st->prev; + } while(st && st!=stackroot); + if (first && !short_dump) { + if (!short_dump) error(DUMP,"Executing in:"); + } + if (!short_dump) error(DUMP,"main program"); + + return; +} + + +static struct symbol *create_symbol(int type,char *name) /* create a new symbol */ +{ + struct symbol *new; + + new=my_malloc(sizeof(struct symbol)); + new->type=type; + new->next_in_list=NULL; + new->name=my_strdup(name); + new->pointer=NULL; + new->args=NULL; + new->value=0.0; + new->link=NULL; + + return new; +} + + +void function_or_array(struct command *cmd) /* decide whether to perform function or array */ +{ + struct command *fu; + + fu=search_label(cmd->name,smSUB|smLINK); + if (fu) { + cmd->type=cCALL; + cmd->pointer=cmd->name; + cmd->name=NULL; + error(DEBUG,"converting FUNCTION_OR_ARRAY to FUNCTION"); + } else { + if (cmd->type==cFUNCTION_OR_ARRAY) + cmd->tag=CALLARRAY; + else + cmd->tag=CALLSTRINGARRAY; + cmd->type=cDOARRAY; + cmd->args=-1; + error(DEBUG,"converting FUNCTION_OR_ARRAY to ARRAY"); + } +} + + +void swap() /* swap topmost elements on stack */ +{ + struct stackentry *a,*b; + + if ((a=stackhead->prev)==NULL || (b=a->prev)==NULL) { + error(ERROR,"Nothing to swap on stack !"); + return; + } + a->prev=b->prev;b->next=a->next; /* just swap the pointers */ + a->next=b;b->prev=a; + stackhead->prev=b; + (a->prev)->next=a; +} + + +struct stackentry *push() +/* push element on stack and enlarge stack it */ +{ + struct stackentry *new; + + if (!stackhead->next) { /* no next element */ + /* create new element */ + new=(struct stackentry *)my_malloc(sizeof(struct stackentry)); + /* and initialize it */ + new->next=NULL; + new->value=0.0; + new->type=stFREE; + new->prev=stackhead; + new->pointer=NULL; + stackhead->next=new; + } else if (stackhead->pointer!=NULL && (stackhead->type==stSTRING || stackhead->type==stSTRINGARRAYREF || stackhead->type==stNUMBERARRAYREF || stackhead->type==stLABEL)) { + /* any content is set free */ + my_free(stackhead->pointer); + stackhead->pointer=NULL; + } + stackhead=stackhead->next; /* advance head */ + return stackhead->prev; +} + + +struct stackentry *pop(int etype) +/* pops element to memory and looks for pop-error */ +{ + static char expected[50]; + static char found[50]; + int ftype; + struct stackentry *s; + + /* test if there is something on the stack */ + if (stackhead==stackroot) { + error(FATAL,"Popped too much."); + return stackhead; + } + stackhead=stackhead->prev; /* move down in stack */ + ftype=stackhead->type; + if (etype==ftype || etype==stANY || + (etype==stSTRING_OR_NUMBER && (ftype==stNUMBER || ftype==stSTRING)) || + (etype==stSTRING_OR_NUMBER_ARRAYREF && (ftype==stSTRINGARRAYREF || ftype==stNUMBERARRAYREF))) + return stackhead; /* this is your value; use it quickly ! */ + + /* expected and found don't match */ + stackdesc(etype,expected); + stackdesc(ftype,found); + sprintf(string,"expected %s but found %s",expected,found); + if (etype==stNUMBER || etype==stSTRING || etype==stSTRING_OR_NUMBER) { + s=push(); + if (etype==stNUMBER) { + s->type=stNUMBER; + s->value=0.0; + } else { + s->type=stSTRING; + s->pointer=my_strdup(""); + } + error(ERROR,string); + return s; + } else { + error(FATAL,string); + } + return stackhead; +} + + +static void stackdesc(int type,char *desc) /* give back string describing stackentry */ +{ + switch(type) { + case stGOTO: strcpy(desc,"a goto");break; + case stSTRING: strcpy(desc,"a string");break; + case stSTRINGARRAYREF: strcpy(desc,"a reference to a string array");break; + case stNUMBER: strcpy(desc,"a number");break; + case stNUMBERARRAYREF: strcpy(desc,"a reference to a numeric array");break; + case stLABEL: strcpy(desc,"a label");break; + case stRETADD: strcpy(desc,"a return address for gosub");break; + case stRETADDCALL: strcpy(desc,"a return address for a subroutine");break; + case stFREE: strcpy(desc,"nothing");break; + case stROOT: strcpy(desc,"the root of the stack");break; + case stANY: strcpy(desc,"anything");break; + case stSTRING_OR_NUMBER: strcpy(desc,"a string or a number");break; + case stSTRING_OR_NUMBER_ARRAYREF: strcpy(desc,"reference to a string or an array");break; + case stSWITCH_STRING: strcpy(desc,"number for switch");break; + case stSWITCH_NUMBER: strcpy(desc,"string for switch");break; + default: sprintf(desc,"type %d",type);break; + } +} + + +void pushname(char *name) /* bison: push a name on stack */ +{ + struct stackentry *s; + + s=push(); + s->pointer=my_strdup(name); + s->type=stSTRING; +} + + +void pushlabel() /* bison: generate goto and push label on stack */ +{ + char *st; + struct stackentry *en; + + st=(char *) my_malloc(sizeof(char)*20); + sprintf(st,"***%d",labelcount); + labelcount++; + create_goto(st); + en=push(); + en->type=stLABEL; + en->pointer=st; +} + + +void poplabel() /* bison: pops a label and generates the matching command */ +{ + create_label(pop(stLABEL)->pointer,cLABEL); /* and create it */ +} + + +void pushgoto() /* bison: generate label and push goto on stack */ +{ + char *st; + struct stackentry *en; + + st=(char *) my_malloc(sizeof(char)*20); + sprintf(st,"***%d",labelcount); + labelcount++; + create_label(st,cLABEL); + en=push(); + en->type=stGOTO; + en->pointer=st; +} + + +void popgoto() /* bison: pops a goto and generates the matching command */ +{ + create_goto(pop(stGOTO)->pointer); /* and create it */ +} + + +void storelabel() /* bison: push label on stack */ +{ + char *st; + struct stackentry *en; + + st=(char *)my_malloc(sizeof(char)*20); + sprintf(st,"***%d",labelcount); + labelcount++; + en=push(); + en->type=stLABEL; + en->pointer=st; +} + + +void matchgoto() /* bison: generate goto matching label on stack */ +{ + create_goto(stackhead->prev->pointer); +} + + +void create_pushdbl(double value) /* create command 'cPUSHDBL' */ +{ + struct command *cmd; + + cmd=add_command(cPUSHDBL,NULL); + cmd->pointer=my_malloc(sizeof(double)); + *(double *)(cmd->pointer)=value; +} + + +void pushdbl(struct command *cmd) +{ + /* push double onto stack */ + struct stackentry *p; + + p=push(); + p->value= *(double *)cmd->pointer; + p->type=stNUMBER; +} + + +void pushdblsym(struct command *cmd) +{ + /* push double symbol onto stack */ + struct stackentry *p; + + p=push(); + if (!cmd->name) error(WARNING,"invalid pushdblsym"); + + if (!cmd->symbol) cmd->symbol=&(get_sym(cmd->name,syNUMBER,amADD_GLOBAL)->value); + p->value=*(double *)cmd->symbol; + p->type=stNUMBER; +} + + +void popdblsym(struct command *cmd) /* pop double from stack */ +{ + double d; + + d=pop(stNUMBER)->value; + if (!cmd->symbol) cmd->symbol=&(get_sym(cmd->name,syNUMBER,amADD_GLOBAL)->value); + *(double *)(cmd->symbol)=d; +} + + +void create_makelocal(char *name,int type) /* create command 'cMAKELOCAL' */ +{ + struct command *cmd; + + cmd=add_command(cMAKELOCAL,name); + cmd->args=type; +} + + +void makelocal(struct command *cmd) /* makes symbol local */ +{ + if (get_sym(cmd->name,cmd->args,amSEARCH_VERY_LOCAL)) { + sprintf(string,"local variable '%s' already defined within this subroutine",strip(cmd->name)); + error(ERROR,string); + return; + } + get_sym(cmd->name,cmd->args,amADD_LOCAL); +} + + +void create_numparam(void) /* create command 'cNUMPARAM' */ +{ + struct command *cmd; + + /* dotifying numparams at compiletime (as opposed to runtime) is essential, + because the function name is not known at runtime */ + cmd=add_command(cNUMPARAM,dotify("numparams",FALSE)); +} + + +void numparam(struct command *cmd) /* count number of function parameters */ +{ + struct symbol *sym; + + sym=get_sym(cmd->name,syNUMBER,amADD_LOCAL); + sym->value=abs(count_args(FALSE)); +} + + +void create_makestatic(char *name,int type) /* create command 'cMAKESTATIC' */ +{ + struct command *cmd; + + cmd=add_command(cMAKESTATIC,name); + cmd->args=type; +} + + +void makestatic(struct command *cmd) /* makes symbol static */ +{ + struct symbol *l,*g; + char *at=NULL; + + + /* mask function name */ + if ((at=strchr(cmd->name,'@'))!=NULL) *at='\0'; + + if (get_sym(cmd->name,cmd->args,amSEARCH_VERY_LOCAL)) { + sprintf(string,"static variable '%s' already defined within this subroutine",strip(cmd->name)); + error(ERROR,string); + return; + } + + /* create global variable with unique name */ + if (at) *at='@'; + g=get_sym(cmd->name,cmd->args,amADD_GLOBAL); + if (at) *at='\0'; + + /* create local variable */ + l=get_sym(cmd->name,cmd->args,amADD_LOCAL); + if (at) *at='@'; + /* link those two together */ + link_symbols(l,g); +} + + +void create_arraylink(char *name,int type) /* create command 'cARRAYLINK' */ +{ + struct command *cmd; + + cmd=add_command(cARRAYLINK,name); + cmd->pointer=current_function; + cmd->args=type; +} + + +void arraylink(struct command *cmd) /* link a local symbol to a global array */ +{ + struct symbol *l,*g; + struct array *ar; + + if (get_sym(cmd->name,cmd->args,amSEARCH_VERY_LOCAL)) { + sprintf(string,"'%s()' already defined within this subroutine",strip(cmd->name)); + error(ERROR,string); + return; + } + /* get globally defined array */ + g=get_sym(pop(cmd->args)->pointer,syARRAY,amSEARCH_PRE); + /* create local array */ + l=get_sym(cmd->name,syARRAY,amADD_LOCAL); + if (!l) return; + if (!g || !g->pointer) { /* no global array supplied, create one */ + error(DEBUG,"creating dummy array"); + ar=create_array((cmd->args==stNUMBERARRAYREF)?'d':'s',0); + l->pointer=ar; + if (infolevel>=DEBUG) { + sprintf(string,"creating 0-dimensional dummy array '%s()'",cmd->name); + error(DEBUG,string); + } + } else { + /* link those two together */ + link_symbols(l,g); + } +} + + +void create_pusharrayref(char *name,int type) /* create command 'cPUSHARRAYREF' */ +{ + struct command *cmd; + + cmd=add_command(cPUSHARRAYREF,name); + cmd->args=type; +} + + +void pusharrayref(struct command *cmd) /* push an array reference onto stack */ +{ + struct stackentry *s; + s=push(); + s->type=cmd->args; + s->pointer=my_strdup(cmd->name); +} + + +void create_require(int type) /* create command 'cREQUIRE' */ +{ + struct command *cmd; + + cmd=add_command(cREQUIRE,NULL); + cmd->args=type; +} + + +void require(struct command *cmd) /* check, that item on stack has right type */ +{ + char *expected,*supplied; + struct stackentry *s; + + if (stackhead->prev->type==cmd->args) return; /* okay, they match */ + + if (stackhead->prev->type==stFREE) { /* no argument supplied, create it */ + s=push(); + if (cmd->args==stSTRING) { + s->type=stSTRING; + s->pointer=my_strdup(""); + return; + } else if (cmd->args==stNUMBER) { + s->type=stNUMBER; + s->value=0.0; + return; + } else { + /* create array */ + s->type=cmd->args; + s->pointer=NULL; + return; + } + } + + s=stackhead->prev; + if (s->type==stSTRING) + supplied="string"; + else if (s->type==stNUMBER) + supplied="number"; + else if (s->type==stSTRINGARRAYREF) + supplied="string array"; + else if (s->type==stNUMBERARRAYREF) + supplied="numeric array"; + else if (s->type==stFREE) + supplied="nothing"; + else + supplied="something strange"; + + if (cmd->args==stSTRING) + expected="string"; + else if (cmd->args==stNUMBER) + expected="number"; + else if (cmd->args==stSTRINGARRAYREF) + expected="string array"; + else if (cmd->args==stNUMBERARRAYREF) + expected="numeric array"; + else if (cmd->args==stFREE) + expected="nothing"; + else + expected="something strange"; + + sprintf(string,"invalid subroutine call: %s expected, %s supplied",expected,supplied); + error(ERROR,string); +} + + +void create_dblbin(char c) /* create command for binary double operation */ +{ + switch(c) { + case '+':add_command(cDBLADD,NULL);break; + case '-':add_command(cDBLMIN,NULL);break; + case '*':add_command(cDBLMUL,NULL);break; + case '/':add_command(cDBLDIV,NULL);break; + case '^':add_command(cDBLPOW,NULL);break; + } + /* no specific information needed */ +} + + +void dblbin(struct command *cmd) /* compute with two numbers from stack */ +{ + struct stackentry *d; + double a,b,c; + + b=pop(stNUMBER)->value; + a=pop(stNUMBER)->value; + d=push(); + switch(cmd->type) { + case(cDBLADD):c=a+b; break; + case(cDBLMIN):c=a-b; break; + case(cDBLMUL):c=a*b; break; + case(cDBLDIV): + if (fabs(b)value=c; + d->type=stNUMBER; +} + + +void negate() /* negates top of stack */ +{ + stackhead->prev->value=-stackhead->prev->value; +} + + +void pushstrptr(struct command *cmd) /* push string-pointer onto stack */ +{ + struct stackentry *p; + + p=push(); + if (!cmd->symbol) cmd->symbol=&(get_sym(cmd->name,sySTRING,amADD_GLOBAL)->pointer); + p->pointer=*(char **)cmd->symbol; + if (!p->pointer) p->pointer=my_strdup(""); + p->type=stSTRING; +} + + +void pushstrsym(struct command *cmd) /* push string-symbol onto stack */ +{ + struct stackentry *p; + + p=push(); + if (!cmd->symbol) cmd->symbol=&(get_sym(cmd->name,sySTRING,amADD_GLOBAL)->pointer); + p->pointer=my_strdup(*(char **)cmd->symbol); + p->type=stSTRING; +} + + +void popstrsym(struct command *cmd) /* pop string from stack */ +{ + if (!cmd->name) return; + if (!cmd->symbol) cmd->symbol= &(get_sym(cmd->name,sySTRING,amADD_GLOBAL)->pointer); + if (*(char **)cmd->symbol!=NULL) my_free(*(char **)cmd->symbol); + *(char **)cmd->symbol=my_strdup(pop(stSTRING)->pointer); +} + + +void create_pushstr(char *s) /* creates command pushstr */ +{ + struct command *cmd; + + cmd=add_command(cPUSHSTR,NULL); + cmd->pointer=my_strdup(s); /* store string */ +} + + +void pushstr(struct command *cmd) +{ + /* push string onto stack */ + struct stackentry *p; + + p=push(); + p->pointer=my_strdup((char *)cmd->pointer); + p->type=stSTRING; +} + + +void duplicate(void) /* duplicate topmost element of stack */ +{ + struct stackentry *s; + double actual; + + actual=stackhead->prev->value; + s=push(); + s->type=stNUMBER; + s->value=actual; +} + + +void create_goto(char *label) /* creates command goto */ +{ + struct command *cmd; + + cmd=add_command(cGOTO,NULL); + /* specific info */ + cmd->pointer=my_strdup(label); +} + + +void create_gosub(char *label) /* creates command gosub */ +{ + struct command *cmd; + + cmd=add_command(cGOSUB,NULL); + /* specific info */ + cmd->pointer=my_strdup(label); +} + + +void create_call(char *label) /* creates command function call */ +{ + struct command *cmd; + + cmd=add_command(cCALL,NULL); + /* specific info */ + cmd->pointer=my_strdup(label); +} + + +static void link_label(struct command *cmd) /* link label into list of labels */ +{ + if (!labelroot) + labelroot=cmd; + else + labelhead->nextassoc=cmd; + labelhead=cmd; +} + + +struct command *search_label(char *name,int type) /* search label */ +{ + struct command *curr; + char *at=NULL; + + curr=labelroot; + if (type&smGLOBAL) { + at=strchr(name,'@'); + if (at) *at='\0'; + } + while(curr) { + if ((type&smSUB) && curr->type==cUSER_FUNCTION && !strcmp(curr->pointer,name)) { + if (at) *at='@'; + return curr; + } + if ((type&smLINK) && curr->type==cSUBLINK && !strcmp(curr->pointer,name)) { + if (at) *at='@'; + return curr->next; + } + if ((type&smLABEL) && curr->type==cLABEL && !strcmp(curr->pointer,name)) { + if (at) *at='@'; + return curr; + } + curr=curr->nextassoc; + } + return NULL; +} + + +void jump(struct command *cmd) +/* jump to specific Label; used as goto, gosub or function call */ +{ + struct command *label; + struct stackentry *ret; + int type; + char *dot; + + type=cmd->type; + if (type==cGOSUB || type==cQGOSUB || type==cCALL || type==cQCALL) { + /* leave return address for return */ + ret=push(); + ret->pointer=current; + if (type==cGOSUB || type==cQGOSUB) { + ret->type=stRETADD; + } else { + ret->type=stRETADDCALL; + reshufflestack(ret); + } + } + + if (type==cQGOSUB || type==cQGOTO || type==cQCALL) { + current=(struct command *)cmd->jump; /* use remembered address */ + return; + } + label=search_label(cmd->pointer,smSUB|smLINK|smLABEL); + if (!label && type==cCALL && (dot=strchr(cmd->pointer,'.'))) { + strcpy(string,"main"); + strcat(string,dot); + label=search_label(string,smLINK); + } + if (label) { + /* found right label */ + current=label; /* jump to new location */ + /* use the address instead of the name next time */ + cmd->jump=label; + switch(cmd->type) { + case cGOTO: cmd->type=cQGOTO; break; + case cGOSUB: cmd->type=cQGOSUB; break; + case cCALL: cmd->type=cQCALL; break; + } + } else { + /* label not found */ + sprintf(string,"can't find %s '%s'",(type==cCALL)?"subroutine":"label",strip((char *)cmd->pointer)); + if (strchr(cmd->pointer,'@')) strcat(string," (not in this sub)"); + error(ERROR,string); + } + + /* check, if goto enters or leaves a switch_statement */ + if (cmd->type==cQGOTO) { + if (label->switch_id && !cmd->switch_id) + error(ERROR,"cannot jump into switch-statement"); + else if (!label->switch_id && cmd->switch_id) + error(ERROR,"cannot jump out of switch-statement"); + else if (label->switch_id!=cmd->switch_id) + error(ERROR,"cannot jump between switch statements"); + } +} + + +void reshufflestack(struct stackentry *ret) /* reorganize stack for function call */ +{ + struct stackentry *a,*b,*c; + struct stackentry *top,*bot; + struct stackentry *ttop,*bbot; + int args; + + + /* this is a function call; revert stack and shuffle return address to bottom */ + /* push address below parameters */ + args=0; + top=a=ret->prev; + while(a->type!=stFREE) { + a=a->prev; + args++; + } + bot=a->next; + b=a->prev; + /* remove ret */ + ret->prev->next=ret->next; + ret->next->prev=ret->prev; + /* squeeze ret between a and b */ + ret->next=a; + a->prev=ret; + b->next=ret; + ret->prev=b; + /* revert stack between top and bot */ + if (args>1) { + a=bot; + b=a->next; + bbot=bot->prev; + ttop=top->next; + for(;args>1;args--) { + a->prev=b; + c=b->next; + b->next=a; + a=b; + b=c; + } + bot->next=ttop; + bot->next->prev=bot; + top->prev=bbot; + top->prev->next=top; + } +} + + +void myreturn(struct command *cmd) /* return from gosub of function call */ +{ + struct stackentry *address; + + address=pop(stANY); + if (cmd->type==cRET_FROM_FUN) { + if (address->type!=stRETADDCALL) { + error(ERROR,"RETURN from a subroutine without CALL"); + return; + } + } else { + if (address->type!=stRETADD) { + error(ERROR,"RETURN without GOSUB"); + return; + } + } + current=(struct command *)address->pointer; + return; +} + + +void create_label(char *label,int type) /* creates command label */ +{ + struct command *cmd; + + /* check, if label is duplicate */ + if (search_label(label,smSUB|smLINK|smLABEL)) { + sprintf(string,"duplicate %s '%s'",(type==cLABEL)?"label":"subroutine",strip(label)); + error(ERROR,string); + return; + } + + cmd=add_command(type,NULL); + /* store label */ + cmd->pointer=my_strdup(label); + link_label(cmd); +} + + +void create_sublink(char *label) /* create link to subroutine */ +{ + char global[200]; + char *dot; + struct command *cmd; + + if (!inlib) return; + dot=strchr(label,'.'); + strcpy(global,"main"); + strcat(global,dot); + + /* check, if label is duplicate */ + if (search_label(global,smSUB|smLINK|smLABEL)) { + sprintf(string,"duplicate subroutine '%s'",strip(global)); + error(ERROR,string); + return; + } + + cmd=add_command(cSUBLINK,NULL); + /* store label */ + cmd->pointer=my_strdup(global); + link_label(cmd); +} + + +void decide() /* skips next command, if not 0 on stack */ +{ + if (pop(stNUMBER)->value!=0) current=current->next; /* skip one command */ +} + + +void create_dim(char *name,char type) /* create command 'dim' */ +/* type can be 's'=string or 'd'=double Array */ +{ + struct command *cmd; + + cmd=add_command(cDIM,name); + cmd->tag=type; /* type: string or double */ + cmd->args=-1; +} + + +void dim(struct command *cmd) /* get room for array */ +{ + struct array *nar,*oar; + char *nul; + int ntotal,ototal,esize,i,j; + int ind[10],nbounds[10],larger; + struct symbol *s; + int local; + + local=((cmd->tag==tolower(cmd->tag))?TRUE:FALSE); + if (cmd->args<0) cmd->args=count_args(FALSE); + if (cmd->args<0) { + error(ERROR,"only numerical indices allowed for arrays"); + return; + } + s=get_sym(cmd->name,syARRAY,local?amADD_LOCAL:amADD_GLOBAL); + if (search_label(cmd->name,smSUB|smLINK)) { + sprintf(string,"array '%s()' conflicts with user subroutine",strip(cmd->name)); + error(ERROR,string); + return; + } + + /* check for dimensions */ + if (cmd->args>10) { + error(ERROR,"more than 10 indices"); + return; + } + oar=s->pointer; + if (oar) { + /* check, if old and new array are compatible */ + if (cmd->args!=oar->dimension) { + sprintf(string,"cannot change dimension of '%s()' from %d to %d", + strip(cmd->name),oar->dimension,cmd->args); + error(ERROR,string); + } + } + /* check, if redim is actually needed */ + for(i=0;i<10;i++) nbounds[i]=0; + larger=FALSE; + for(i=0;iargs;i++) { + nbounds[i]=1+(int)pop(stNUMBER)->value; + if (nbounds[i]<=1) { + sprintf(string,"array index %d is less or equal zero",cmd->args-i); + error(ERROR,string); + return; + } + if (oar) { + if (nbounds[i]>oar->bounds[i]) + larger=TRUE; + else + nbounds[i]=oar->bounds[i]; + } + } + pop(stFREE); /* remove left over stFREE */ + if (oar && !larger) return; /* new array won't be larger than old one */ + + /* create array */ + nar=create_array(tolower(cmd->tag),cmd->args); + + /* count needed memory */ + ntotal=1; + for(i=0;idimension;i++) { + (nar->bounds)[i]=nbounds[i]; + ntotal*=nbounds[i]; + } + esize=(nar->type=='s')?sizeof(char *):sizeof(double); /* size of one array element */ + nar->pointer=my_malloc(ntotal*esize); + + if (oar) { /* array already exists, get its size */ + ototal=1; + for(i=0;idimension;i++) ototal*=(oar->bounds)[i]; + } + + /* initialize Array */ + for(i=0;itype=='s') { + nul=my_malloc(sizeof(char)); + *nul='\0'; + ((char **)nar->pointer)[i]=nul; + } else { + ((double *)nar->pointer)[i]=0.0; + } + } + + if (oar) { /* copy contents of old array onto new */ + for(i=0;ibounds,ind); + j=ind_to_off(ind,nar->bounds); + if (nar->type=='s') { + my_free(((char **)nar->pointer)[j]); + ((char **)nar->pointer)[j]= ((char **)oar->pointer)[i]; + } else { + ((double *)nar->pointer)[j]= ((double *)oar->pointer)[i]; + } + } + my_free(oar->pointer); + my_free(oar); + } + + s->pointer=nar; + cmd->symbol=nar; +} + + +static int ind_to_off(int *ind,int *bound) /* convert array of indices to single offset */ +{ + int i; + int cur,off; + + off=0; + cur=1; + for(i=0;i<10 && bound[i];i++) { + off+=ind[i]*cur; + cur*=bound[i]; + } + return off; +} + + +static void off_to_ind(int off,int *bound,int *ind) /* convert a single offset to an array of indices */ +{ + int i; + int cur; + + cur=1; + for(i=0;i<10;i++) { + if (bound[i]) cur*=bound[i]; + ind[i]=0; + } + for(i=9;i>=0;i--) { + if (bound[i]) { + cur/=bound[i]; + ind[i]=off/cur; + off-=ind[i]*cur; + } else { + ind[i]=0; + } + } +} + + +void query_array(struct command *cmd) /* query array */ +{ + int index; + struct stackentry *s; + struct array *ar; + struct symbol *sym; + + if (cmd->type==cARSIZE) index=(int)pop(stNUMBER)->value; + + s=pop(stSTRING_OR_NUMBER_ARRAYREF); + + if (!cmd->symbol) { + sym=get_sym(s->pointer,syARRAY,amSEARCH); + if (!sym || !sym->pointer) { + sprintf(string,"array '%s()' is not defined",strip(s->pointer)); + error(ERROR,string); + return; + } + cmd->symbol=sym; + } + + ar=((struct symbol *)cmd->symbol)->pointer; + + if (cmd->type==cARSIZE && (index<1 || index>ar->dimension)) { + sprintf(string,"only indices between 1 and %d allowed",ar->dimension); + error(ERROR,string); + return; + } + s=push(); + s->type=stNUMBER; + if (cmd->type==cARSIZE) + s->value=ar->bounds[ar->dimension-index]-1; + else + s->value=ar->dimension; + + return; +} + + +void create_doarray(char *symbol,int command) /* creates array-commands */ +{ + struct command *cmd; + + cmd=add_command(cDOARRAY,symbol); + cmd->tag=command; /* operation to perform */ + cmd->args=-1; +} + + +void doarray(struct command *cmd) /* call an array */ +{ + struct array *ar; + struct stackentry *stack; + struct symbol *sym; + void *p; + char **str; + double *dbl; + int i,j,bnd,index,cur,rval; + + + if (!cmd->symbol) { + sym=get_sym(cmd->name,syARRAY,amSEARCH); + if (!sym || !sym->pointer) { + sprintf(string,"'%s()' is neither array nor subroutine",strip(cmd->name)); + error(ERROR,string); + return; + } + cmd->symbol=sym; + } + rval=(current->tag==CALLARRAY || current->tag==CALLSTRINGARRAY || current->tag==GETSTRINGPOINTER); + if (cmd->args<0) cmd->args=count_args(!rval); + if (cmd->args<0) { + error(ERROR,"only numerical indices allowed for arrays"); + return; + } + cmd->args=abs(cmd->args); + if (!cmd->args) { /* no indizes supplied, create a reference to an array */ + pop(stFREE); /* remove left over stFREE */ + stack=push(); + if (cmd->tag==CALLARRAY) + stack->type=stNUMBERARRAYREF; + else + stack->type=stSTRINGARRAYREF; + stack->pointer=my_strdup(cmd->name); + return; + } + + ar=((struct symbol *)cmd->symbol)->pointer; + + if (!ar->dimension) { + sprintf(string,"array parameter '%s()' has not been supplied",strip(cmd->name)); + error(ERROR,string); + return; + } + if (cmd->args!=ar->dimension) { + sprintf(string,"%d indices supplied, %d expected for '%s()'",cmd->args,ar->dimension,strip(cmd->name)); + error(ERROR,string); + return; + } + + if (!rval) stack=pop(stSTRING_OR_NUMBER); + index=0; + cur=1; + for(i=0;idimension;i++) { + bnd=(ar->bounds[i]); + j=(int)pop(stNUMBER)->value; + if (j<0 || j>=bnd) { + sprintf(string,"index %d (=%d) out of range",ar->dimension-i,j); + error(ERROR,string); + return; + } + index+=j*cur; + cur*=bnd; + } + + pop(stFREE); /* remove left over stFREE */ + if (rval) stack=push(); + + p=ar->pointer; + switch(current->tag) { + case CALLARRAY: + dbl=(double *)p+index; + stack->value= *dbl; + stack->type=stNUMBER; + break; + case ASSIGNARRAY: + dbl=(double *)p+index; + *dbl=stack->value; + break; + case CALLSTRINGARRAY: + str=((char **)p+index); + stack->pointer=my_strdup(*str); + stack->type=stSTRING; + break; + case ASSIGNSTRINGARRAY: + str=((char **)p+index); + if (*str!=NULL)my_free(*str); + *str=my_strdup(stack->pointer); + break; + case GETSTRINGPOINTER: + str=((char **)p+index); + stack->pointer=*str; + stack->type=stSTRING; + break; + } +} + + +struct array *create_array(int type,int dimension) /* create an array */ +{ + int i; + struct array *ar; + + ar=my_malloc(sizeof(struct array)); + ar->type=type; + ar->dimension=dimension; + ar->pointer=NULL; + for(i=0;i<10;i++) ar->bounds[i]=0; + + return ar; +} + + +static int count_args(int skipfirst) /* count number of numeric arguments on stack */ +{ + int i=0; + int sign=1; + struct stackentry *curr; + + curr=stackhead->prev; + if (skipfirst) curr=curr->prev; + while(curr) { + if (curr->type==stFREE) return i*sign; + if (curr->type!=stNUMBER) sign=-1; + curr=curr->prev; + i++; + } + return -1; +} + + +void skipper() +/* used for on_goto/gosub, skip specified number of commands */ +{ + int i,len; + struct command *ahead; /* command to follow */ + + len=(int)pop(stNUMBER)->value; + i=1; + current=current->next; /* advance to first goto/gosub */ + for(i=1;inext->next; /* skip interleaving findnop statement */ + if (ahead->type==cNOP) + break; + else + current=ahead; + } +} + + +void skiponce(struct command *cmd) /* skip next command exectly once */ +{ + if (cmd->tag) current=current->next; + cmd->tag=0; +} + + +void resetskiponce(struct command *cmd) /* find and reset next skip */ +{ + struct command *c; + + c=cmd; + while(c->type!=cSKIPONCE) c=c->next; + c->tag=1; +} + +void create_break_mark(int minor,int major) /* create marks for break */ +{ + struct command *cmd; + + in_loop+=major; + cmd=add_command(cBREAK_MARK,NULL); + cmd->tag=(major+2)*16+minor+2; +} + + +void next_case(void) /* go to next case in switch statement */ +{ + if (stackhead->prev->type==stSTRING || stackhead->prev->type==stSWITCH_STRING) + stackhead->prev->type=stSWITCH_STRING; + else + stackhead->prev->type=stSWITCH_NUMBER; +} + + +void push_switch_id(void) /* generate a new switch id */ +{ + static int max_switch_id=0; + static int switch_stack_depth=1; + + struct switch_id *new_id; + if (switch_id_stackhead==NULL || switch_id_stackhead->next==NULL) { + if (switch_id_stackroot && switch_id_stackhead==NULL) { + new_id=switch_id_stackroot; + } else { + new_id=my_malloc(sizeof(struct switch_id)); + new_id->next=NULL; + new_id->depth=switch_stack_depth++; + } + } else { + new_id=switch_id_stackhead->next; + } + max_switch_id++; + new_id->id=max_switch_id; + if (switch_id_stackhead==NULL) { + switch_id_stackhead=new_id; + switch_id_stackhead->prev=NULL; + } else { + switch_id_stackhead->next=new_id; + new_id->prev=switch_id_stackhead; + switch_id_stackhead=new_id; + } +} + + +void pop_switch_id(void) /* get previous switch id */ +{ + if (switch_id_stackhead) switch_id_stackhead=switch_id_stackhead->prev; +} + + +int get_switch_id(void) /* get current switch id */ +{ + return switch_id_stackhead ? switch_id_stackhead->id : 0; +} + + +int get_switch_depth(void) /* get current depth of switch id stack */ +{ + return switch_id_stackhead ? switch_id_stackhead->depth : 0; +} + + +void push_switch_mark(void) /* push a switch mark */ +{ + push()->type=stSWITCH_MARK; +} + + +void create_clean_switch_mark(int keep,int ret) /* add command clean_switch_mark */ +{ + struct command *cmd; + + cmd=add_command(cCLEAN_SWITCH_MARK,NULL); + cmd->args=keep; + cmd->tag=ret; +} + + +void clean_switch_mark(struct command *cmd) /* pop everything up to (and including) first switch_mark from stack */ +{ + struct stackentry *t,*tt,*b,*bb,*s; + int keep,k,ret; + + k=keep=cmd->args; + ret=cmd->tag; + s=stackhead->prev; + while(k && s!=stackroot) { + k--; + s=s->prev; + } + t=s; + tt=s->next; + while(((ret && s->type!=stRETADDCALL) || (!ret && s->type!=stSWITCH_MARK)) && s!=stackroot) { + s=s->prev; + } + if (ret) { + bb=s; + b=s->next; + } else { + b=s; + bb=s->prev; + } + + /* cut part between (and including) b and t out of stack */ + bb->next=tt; + tt->prev=bb; + /* insert cut-out part between stackhead and stackhead->prev */ + stackhead->prev->next=b; + b->prev=stackhead->prev; + t->next=stackhead; + stackhead->prev=t; + if (keep) + stackhead=tt->next; + else + stackhead=bb->next; +} + + +void mybreak(struct command *cmd) /* find break_here statement */ +{ + struct command *curr; + int major,minor; + int major_nesting=0; + int minor_nesting=0; + + if (cmd->type==cBREAK) + major_nesting=1; + else + minor_nesting=0; + curr=cmd; + while(curr->type!=cBREAK_HERE || major_nesting || minor_nesting) { + if (curr->type==cBREAK_MARK) { + minor=(curr->tag&15)-2; + major=((curr->tag&240)/16)-2; + if (!major_nesting) minor_nesting+=minor; + major_nesting+=major; + if (infolevel>=DEBUG) { + sprintf(string,"searching break-mark: diff(%d,%d), total(%d,%d)",minor,major,minor_nesting,major_nesting); + error(DEBUG,string); + } + } + curr=curr->next; + if (!curr) error(FATAL,"break has left program"); + } + cmd->type=cQGOTO; + if (infolevel>=DEBUG) error(DEBUG,"converting cBREAK to cQGOTO"); + cmd->jump=current=curr; +} + + +void mycontinue(struct command *cmd) /* find continue_here statement */ +{ + struct command *curr; + int major; + int major_nesting=-1; + + curr=cmd; + while(curr->type!=cCONTINUE_HERE || major_nesting) { + if (curr->type==cBREAK_MARK) { + major=((curr->tag&240)>>4)-2; + major_nesting+=major; + } + if (curr->type==cCONTINUE_CORRECTION) major_nesting--; + curr=curr->prev; + if (!curr) error(FATAL,"continue has left program"); + } + cmd->type=cQGOTO; + if (infolevel>=DEBUG) error(DEBUG,"converting cCONTINUE to cQGOTO"); + cmd->jump=current=curr; +} + + +void findnop() +/* used for on_gosub, find trailing nop command */ +{ + while(current->type!=cNOP) { + current=current->next; /* next label */ + } +} + + +void forcheck(void) /* check, if for-loop is done */ +{ + double start,bound,step,val; + + val=pop(stNUMBER)->value; + step=pop(stNUMBER)->value; + bound=pop(stNUMBER)->value; + start=stackhead->prev->value; + if ((val<=bound && val>=start && step>=0) || (val<=start && val>=bound && step<=0)) + stackhead->prev->value=1.; + else + stackhead->prev->value=0.; +} + + +void forincrement(void) /* increment value on stack */ +{ +/* expecting on stack: BOUND,STEP,VAL,stackhead + where for VAL=START to BOUND step STEP */ + stackhead->prev->value+=stackhead->prev->prev->value; +} + + +void startfor(void) /* compute initial value of for-variable */ +{ + struct stackentry *p; + + p=push(); + p->value=stackhead->prev->prev->prev->prev->value-stackhead->prev->prev->value; + p->type=stNUMBER; + + return; +} + + diff --git a/src/yab-IDE.yab b/src/yab-IDE.yab new file mode 100755 index 0000000..e423046 --- /dev/null +++ b/src/yab-IDE.yab @@ -0,0 +1,3918 @@ +#!yab + +doc Author: Jan Bungeroth +doc Thanks to: Genki, Lelldorin, lorglas, Stargater, DasJott +doc (c) 2006-2015 in terms of the Artistic License + +doc +doc The yab-IDE provides you with an integrated development suite for yab +doc Enjoy. +path() +versionnumber$="2.2.4" + +settingsRCSOff = true +globalConfigDir$ = trim$(system$("finddir B_USER_SETTINGS_DIRECTORY"))+"/yab-ide/" + +if(LoadSettings() = 1) then + + MAXFILES = 20 + DEBUG = true + + + settingsYabDir$ = path$ //"/boot/apps/yab-1.7/" + globalProjectDir$ = trim$(system$("finddir B_USER_DIRECTORY"))+"/yab_work/Programs/" + yabDir$ = yabpath$() + ideDir$ = path$ //settingsYabDir$ + "yab-IDE/" + + buildDir$ = trim$(system$("finddir B_USER_DIRECTORY"))+"/yab_work/BuildFactory/" + globalHelpDir$ = settingsYabDir$ + "Documentation/" + + settingsLangUse = true + settingsLangPath$ = "x-vnd.yab-IDE" + + settingsAutoIndent = true + settingsAutoCompletion = true + settingsACNumChar = 2 + settingsX = 50 + settingsY = 50 + settingsWidth = peek("desktopwidth")-100 + if(settingsWidth<600) settingsWidth = 600 + settingsHeight = peek("desktopheight")-100 + settingsFullScreen = false + settingsFullEditor = false + settingsVSplitDivider = 180 + settingsV2SplitDivider = 41 + settingsHSplitDivider = settingsHeight-240 + settingsCalcPatternX = 200 + settingsCalcPatternY = 150 + settingsColorSelectX = 100 + settingsColorSelectY = 100 + settingsColorSelectR = 255 + settingsColorSelectG = 255 + settingsColorSelectB = 255 + settingsAskForSaving = true + settingsFindCS = false + settingsOldSearch$ = "" + settingsFindAlert = true + settingsReformatAlert = true + settingsReformatUndoAlert = true + settingsTabSpaces = 4 + settingsFontFamily$ = "DejaVu Sans Mono" + settingsFontStyle$ = "Book" + settingsFontSize = 12 + globalRealFontSize = 15 + settingsYabParam$ = "" + settingsProgParam$ = "" + + dim globalAllNames$(MAXFILES) + dim globalTextFinder(MAXFILES) + + for i=1 to MAXFILES + globalAllNames$(i) = "" + globalTextFinder(i) = 0 + next i + +endif + + +restartSettingsLangUse = settingsLangUse +textcolor_r = 0 +textcolor_g = 0 +textcolor_b = 0 + +// globalNoRCS = system("test -e /boot/beos/bin/ci") or system("test -e /boot/beos/bin/co") or system("test -e /boot/beos/bin/rlog") or settingsRCSOff +globalNoRCS = settingsRCSOff +globalCurrentText = 0 +globalHSplitDivider = settingsHSplitDivider +globalReformatUndo = false +globalSelectErrorLines = true +globalNewNumber = 0 +globalNumOpenFiles = 0 +globalWasChanged = false +globalRealOS$ = upper$(system$("uname -o")) +globalRealOS$ = left$(globalRealOS$, 4) + +oldSpinner = 1 + +if(settingsLangUse) then + localize settingsLangPath$ +endif + + +OpenMainWindow() +ActivateMenus(false) +UpdateStatusbar() + +LoadOpenFiles() + +if(settingsFullScreen) then + menu set "View", "Full screen", "mark", "MainView" + window set "MainView", "moveto", 0,0 + window set "MainView", "resizeto", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MinimumTo", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MaximumTo", peek("desktopwidth")-1, peek("desktopheight")-1 +endif +if(settingsFullEditor) then + oldSplitX = splitview get "VSplit", "Divider" +// oldSplitY = splitview get "HSplit", "Divider" + tmp = window get "MainView", "Height" + splitview set "HSplit", "Divider", tmp-51 + splitview set "VSplit", "Divider", 0 + menu set "View", "Maximize editor", "mark", "MainView" +endif + +dim msg$(1) +dim pattern(8,8) + +inloop = true +while(inloop) + sleep 0.01 + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + switch(msg$(i)) + case "ToolbarNew" + case MyTranslate$("MainView:File:New...") + foundEmpty = 0 + for j=1 to MAXFILES + if(globalAllNames$(j) = "") then + foundEmpty = j + break + endif + next j + if(not foundEmpty) then + alert MyTranslate$("Sorry, you can not open more than ")+str$(MAXFILES)+MyTranslate$(" files at once!\n\nPlease close one or more other files first."), "Ok", "Warning" + else + NewDocument(foundEmpty) + if(globalNumOpenFiles = 1) then + ActivateMenus(true) + splitview set "V2Split", "Divider", settingsV2SplitDivider + endif + endif + break + case "ToolbarOpen" + case MyTranslate$("MainView:File:Open...") + foundEmpty = 0 + for j=1 to MAXFILES + if(globalAllNames$(j) = "") then + foundEmpty = j + break + endif + next j + if(not foundEmpty) then + alert MyTranslate$("Sorry, you can not open more than ")+str$(MAXFILES)+MyTranslate$(" files at once!\n\nPlease close one or more other files first."), "Ok", "Warning" + else + tmp$ = filepanel "Load-File", "Open", globalProjectDir$ + if(tmp$<>"") then + foundProject = false + for j = 1 to MAXFILES + if(globalAllNames$(j) = tmp$) then + alert "File is already open.", "Ok", "info" + ActivateText(j) + foundProject = true + break + endif + next j + if(foundProject) break + + handle = open(tmp$, "r") + if(handle) then + WaitWindow(tmp$) + text$ = "" + while(not eof(handle)) + t$ = GetLine$(handle)+"\n" + if(len(t$)*8>4000) textedit set "Text"+str$(foundEmpty), "textwidth", len(t$)*8+8 + text$ = text$ + t$ + wend + close(handle) + globalCurrentText = foundEmpty + textedit add "Text"+str$(globalCurrentText), text$ + textedit set "Text"+str$(globalCurrentText), "changed", false + textedit set "Text"+str$(globalCurrentText), "gotoline", ReadLineFromAttr(tmp$) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + globalAllNames$(globalCurrentText) = tmp$ + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/gespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(tmp$) // "Filename", t, GetFileName$(tmp$) + columnbox select "FileBox", t+1 + globalTextFinder(globalCurrentText) = t+1 + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + globalNumOpenFiles = globalNumOpenFiles + 1 + if(globalNumOpenFiles = 1) then + ActivateMenus(true) + splitview set "V2Split", "Divider", settingsV2SplitDivider + endif + globalProjectDir$ = GetDirectory$(tmp$) + window close "WaitWindow" + else + alert MyTranslate$("Error while loading file:\n\n")+tmp$, "Ok", "Stop" + endif + endif + endif + break + case "ToolbarClose" + case MyTranslate$("MainView:File:Close") + if(textedit get "Text"+str$(globalCurrentText), "hasChanged") then + tmpSave = alert MyTranslate$("File \"")+GetFileName$(globalAllNames$(globalCurrentText))+MyTranslate$("\" not saved!\n\nSave the file now?"), "Cancel", "Close", "Save", "warning" + if(tmpSave = 1) break + if(tmpSave = 3) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + endif + + textedit clear "Text"+str$(globalCurrentText) + globalAllNames$(globalCurrentText) = "" + + columnbox remove "FileBox", globalTextFinder(globalCurrentText) + closeFinished = 0 + newCurrent = 0 + for tmpClose = 1 to MAXFILES + if(globalTextFinder(tmpClose)>globalTextFinder(globalCurrentText)) then + if(globalTextFinder(tmpClose) = globalTextFinder(globalCurrentText) + 1) then + closeFinished = globalTextFinder(tmpClose) - 1 + newCurrent = tmpClose + endif + globalTextFinder(tmpClose) = globalTextFinder(tmpClose) - 1 + endif + next tmpClose + + if(closeFinished=0) then + closeFinished = globalTextFinder(globalCurrentText) - 1 + if(closeFinished = 0) then + newCurrent = 0 + else + for j = 1 to MAXFILES + if(globalTextFinder(j) = globalTextFinder(globalCurrentText)-1) then + newCurrent = j + break + endif + next j + endif + endif + + globalTextFinder(globalCurrentText) = 0 + globalCurrentText = newCurrent + + if(closeFinished=0) then + stackview set "Stack", MAXFILES+2 + stackview set "Lines", MAXFILES+2 + settingsV2SplitDivider = splitview get "V2Split", "Divider" + splitview set "V2Split", "Divider", 0 + ActivateMenus(false) + else + ActivateText(globalCurrentText) + endif + globalNumOpenFiles = globalNumOpenFiles - 1 + break + case "ToolbarSave" + case MyTranslate$("MainView:File:Save") + tmpNull = SaveCurrentFile() + break + case MyTranslate$("MainView:File:Save as...") + tmpSaveAs$ = filepanel "Save-File", "Save", GetDirectory$(globalAllNames$(globalCurrentText)), GetFileName$(globalAllNames$(globalCurrentText)) + print tmpSaveAs$ + if(tmpSaveAs$<>"") then + handle = open(tmpSaveAs$, "w") + if(handle) then + print #handle textedit get$ "Text"+str$(globalCurrentText); + close(handle) + tmpCurrentLine = textedit get "Text"+str$(globalCurrentText), "currentline" + attribute set "Int", "linenumber", "tmpCurrentLine", tmpSaveAs$ + textedit set "Text"+str$(globalCurrentText), "changed", false + globalAllNames$(globalCurrentText) = tmpSaveAs$ + columnbox clear "FileBox" + for j=1 to MAXFILES + for k=1 to MAXFILES + if(globalTextFinder(j)=k) then + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/gespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(globalAllNames$(j)) + break + endif + next k + next j + columnbox select "FileBox", globalTextFinder(globalCurrentText) + else + alert "File could not be saved!", "Ok", "warning" + endif + endif + break + case MyTranslate$("MainView:File:Save as template...") + SaveAsTemplate() + break + case MyTranslate$("MainView:File:Export as HTML...") + ExportAsHTML() + break + case MyTranslate$("MainView:File:Page setup...") + printer setup globalConfigDir$+"printersetup" + break + case MyTranslate$("MainView:File:Print...") + if(globalCurrentText>0) then + err = printer globalAllNames$(globalCurrentText), globalConfigDir$+"printersetup", "Text"+str$(globalCurrentText) + if(err = 4) then + printer setup "/tmp/printersetup" + err = printer globalAllNames$(globalCurrentText), "/tmp/printersetup", "Text"+str$(globalCurrentText) + system("rm -f /tmp/printersetup >/dev/null") + endif + if(err>1 and err<5) then + alert "Error while printing!", "Ok", "warning" + endif + endif + break + case "_QuitRequested" + // TODO make backups and save open files + inloop = false + if(not settingsFullScreen) then + settingsX = window get "MainView", "Position-X" + settingsY = window get "MainView", "Position-Y" + settingsWidth = window get "MainView", "Width" + settingsHeight = window get "MainView", "Height" + endif + if(not settingsFullEditor) then + settingsVSplitDivider = splitview get "VSplit", "Divider" + settingsV2SplitDivider = splitview get "V2Split", "Divider" + settingsHSplitDivider = splitview get "HSplit", "Divider" + endif + break + case "MainView:_QuitRequested" + case MyTranslate$("MainView:File:Quit") + tmpSelect = 1 + if(globalCurrentText>0) then + for j=1 to MAXFILES + if(textedit get "Text"+str$(j), "hasChanged") then + tmpSelect = alert "Some files are not saved!\n\nDo you really want to quit?", "Quit", "Cancel", "", "warning" + break + endif + next j + endif + if(tmpSelect = 1) then + inloop = false + if(not settingsFullScreen) then + settingsX = window get "MainView", "Position-X" + settingsY = window get "MainView", "Position-Y" + settingsWidth = window get "MainView", "Width" + settingsHeight = window get "MainView", "Height" + endif + if(not settingsFullEditor) then + settingsVSplitDivider = splitview get "VSplit", "Divider" + settingsV2SplitDivider = splitview get "V2Split", "Divider" + settingsHSplitDivider = splitview get "HSplit", "Divider" + endif + endif + break + case "ToolbarCut" + case MyTranslate$("MainView:Edit:Cut") + textedit set "Text"+str$(globalCurrentText), "Cut" + break + case "ToolbarCopy" + case MyTranslate$("MainView:Edit:Copy") + if(globalIsHelp) then + textedit set "Text"+str$(MAXFILES+1), "Copy" + else + textedit set "Text"+str$(globalCurrentText), "Copy" + endif + break + case "ToolbarPaste" + case MyTranslate$("MainView:Edit:Paste") + textedit set "Text"+str$(globalCurrentText), "Paste" + break + case "ToolbarUndo" + case MyTranslate$("MainView:Edit:Undo") + textedit set "Text"+str$(globalCurrentText), "Undo" + break + case MyTranslate$("MainView:Edit:Select all") + if(globalIsHelp) then + textedit set "Text"+str$(MAXFILES+1), "Select-All" + else + textedit set "Text"+str$(globalCurrentText), "Select-All" + endif + break + case MyTranslate$("MainView:Edit:Clear") + textedit set "Text"+str$(globalCurrentText), "Clear" + break + case MyTranslate$("MainView:Edit:Find") + option set "ToolbarText", "focus", true + break + case MyTranslate$("MainView:Edit:Find again") + if(settingsOldSearch$<>"") then + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + case MyTranslate$("MainView:Edit:Find and replace") + if(settingsFullEditor) then + splitview set "VSplit", "Divider", oldSplitX + splitview set "HSplit", "Divider", oldSplitY + menu set "View", "Maximize editor", "plain", "MainView" + settingsFullEditor = false + endif + tabview set "HTab", 3 + option set "FindTCFind", "Focus", true + break + case "ToolbarRun" + case MyTranslate$("MainView:Program:Run") + isNotSaved = textedit get "Text"+str$(globalCurrentText), "hasChanged" + askForSaving = 3 + if(settingsAskForSaving and isNotSaved) then + askForSaving = alert "Program is not saved.\n\nSave it now?", "Cancel", "Save Always", "Save Now", "info" + endif + + if(askForSaving>1) then + if(askForSaving = 2) settingsAskForSaving = true + if(isNotSaved) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + RunProgram(globalAllNames$(globalCurrentText)) + endif + break + case "ToolbarRunTerm" + case MyTranslate$("MainView:Program:Run in Terminal") + isNotSaved = textedit get "Text"+str$(globalCurrentText), "hasChanged" + askForSaving = 3 + if(settingsAskForSaving and isNotSaved) then + askForSaving = alert "Program is not saved.\n\nSave it now?", "Cancel", "Save Always", "Save Now", "info" + endif + + if(askForSaving>1) then + if(askForSaving = 2) settingsAskForSaving = true + if(isNotSaved) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + RunInTerminal(globalAllNames$(globalCurrentText)) + endif + break + case MyTranslate$("MainView:Program:Set run parameters...") + SetRunParameters() + break + case "ToolbarBuild" + case MyTranslate$("MainView:Program:Build Factory...") + isNotSaved = textedit get "Text"+str$(globalCurrentText), "hasChanged" + askForSaving = 3 + if(settingsAskForSaving and isNotSaved) then + askForSaving = alert "Program is not saved.\n\nSave it now?", "Cancel", "Save Always", "Save Now", "info" + endif + + if(askForSaving>1) then + if(askForSaving = 2) settingsAskForSaving = true + if(isNotSaved) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + Building() + endif + break + case MyTranslate$("MainView:Program:Open project folder...") + system("open " + globalProjectDir$) + break + case "ToolbarPattern" + case MyTranslate$("MainView:Tools:Pattern editor...") + OpenCalcPattern(settingsCalcPatternX,settingsCalcPatternY) + break + case MyTranslate$("MainView:Tools:Color selection...") + OpenColorSelection(settingsColorSelectX,settingsColorSelectY, settingsColorSelectR, settingsColorSelectG, settingsColorSelectB) + break + case MyTranslate$("MainView:Tools:ASCII table...") + AsciiWindow() + break + case MyTranslate$("MainView:View:Next file") + findNext = false + tmpCounter = globalCurrentText + while(not findNext) + tmpCounter = tmpCounter + 1 + if(tmpCounter>MAXFILES) tmpCounter = 1 + if(tmpCounter = globalCurrentText) then + findNext = true + else + if(globalAllNames$(tmpCounter)<>"") then + globalCurrentText = tmpCounter + ActivateText(globalCurrentText) + findNext = true + endif + endif + wend + break + case MyTranslate$("MainView:View:Previous file") + findNext = false + tmpCounter = globalCurrentText + while(not findNext) + tmpCounter = tmpCounter - 1 + if(tmpCounter=0) tmpCounter = MAXFILES + if(tmpCounter = globalCurrentText) then + findNext = true + else + if(globalAllNames$(tmpCounter)<>"") then + globalCurrentText = tmpCounter + ActivateText(globalCurrentText) + findNext = true + endif + endif + wend + break + case MyTranslate$("MainView:View:Full screen") + if settingsFullScreen then + menu set "View", "Full screen", "plain", "MainView" + currentDivider = peek("desktopheight")-1 - splitview get "HSplit", "Divider" + window set "MainView", "moveto", settingsX,settingsY + window set "MainView", "MinimumTo", 600,300 + window set "MainView", "MaximumTo", 2000, 2000 + window set "MainView", "resizeto", settingsWidth, settingsHeight + splitview set "HSplit", "Divider", settingsHeight-currentDivider + settingsFullScreen = false + else + settingsX = window get "MainView", "Position-X" + settingsY = window get "MainView", "Position-Y" + settingsWidth = window get "MainView", "Width" + settingsHeight = window get "MainView", "Height" + currentDivider = settingsHeight - splitview get "HSplit", "Divider" + menu set "View", "Full screen", "mark", "MainView" + window set "MainView", "moveto", 0,0 + window set "MainView", "resizeto", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MinimumTo", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MaximumTo", peek("desktopwidth")-1, peek("desktopheight")-1 + splitview set "HSplit", "Divider", peek("desktopheight")-1-currentDivider + settingsFullScreen = true + endif + break + case MyTranslate$("MainView:View:Maximize editor") + if(settingsFullEditor) then + splitview set "VSplit", "Divider", oldSplitX + splitview set "HSplit", "Divider", oldSplitY + menu set "View", "Maximize editor", "plain", "MainView" + settingsFullEditor = false + else + oldSplitX = splitview get "VSplit", "Divider" + oldSplitY = splitview get "HSplit", "Divider" + tmp = window get "MainView", "Height" + splitview set "HSplit", "Divider", tmp-51 + splitview set "VSplit", "Divider", 0 + menu set "View", "Maximize editor", "mark", "MainView" + settingsFullEditor = true + endif + break + case MyTranslate$("MainView:View:Auto indent") + if(settingsAutoIndent) then + menu set "View", "Auto indent", "plain", "MainView" + else + menu set "View", "Auto indent", "mark", "MainView" + endif + settingsAutoIndent = not settingsAutoIndent + for tmpAllFiles = 1 to MAXFILES + textedit set "Text"+str$(tmpAllFiles), "autoindent", settingsAutoIndent + next tmpAllFiles + break + case MyTranslate$("MainView:View:Auto completion") + if(settingsAutoCompletion) then + menu set "View", "Auto completion", "plain", "MainView" + else + menu set "View", "Auto completion", "mark", "MainView" + endif + settingsAutoCompletion = not settingsAutoCompletion + for tmpAllFiles = 1 to MAXFILES + textedit set "Text"+str$(tmpAllFiles), "has-autocompletion", settingsAutoCompletion + next tmpAllFiles + break + case MyTranslate$("MainView:View:Reformat sourcecode") + reformatUndo$ = textedit get$ "Text"+str$(globalCurrentText) + globalReformatUndo = true + menu set "View", "Undo reformat", "enable", "MainView" + textedit clear "Text"+str$(globalCurrentText) + //tmp$ = ReformatSource$(reformatUndo$) + textedit add "Text"+str$(globalCurrentText),ReformatSource$(reformatUndo$) + if(ReformatError(false,0)<>0 and settingsReformatAlert) then + tmp = alert "Reformating did not close all open loops and conditions.\nReformating currently does not support loops and conditions opened and closed by a colon (:).\nE.g. while(loop):wend\n\nYou can undo the reformating before doing any further changes.", "Do not show this warning again", "Ok" , "", "warning" + if(tmp = 1) settingsReformatAlert = false + endif + break + case MyTranslate$("MainView:View:Undo reformat") + tmp = alert "Changes made since reformating will be lost!", "Cancel", "Do not show this warning again", "Undo reformating", "warning" + if(tmp > 1) then + if(tmp=2) settingsReformatUndoAlert = false + globalReformatUndo = false + textedit clear "Text"+str$(globalCurrentText) + textedit add "Text"+str$(globalCurrentText), reformatUndo$ + menu set "View", "Undo reformat", "disable", "MainView" + endif + break + case MyTranslate$("MainView:View:Refresh colors") + textedit color "Text"+str$(globalCurrentText), "textcolor", textcolor_r, textcolor_g, textcolor_b + break + case "ToolbarOptions" + case MyTranslate$("MainView:View:Options...") + OptionWindow() + break + case "ToolbarHelp" + case MyTranslate$("MainView:Help:Short command help...") + system("open "+globalHelpDir$+"yab-Commands &") + break + case MyTranslate$("MainView:Help:Yabasic manual...") + system("open "+globalHelpDir$+"yabasic.html &") + break + case MyTranslate$("MainView:Help:Online resources:German BeUsergroup...") + system("open http://www.beusergroup.de &") + break + case MyTranslate$("MainView:Help:Online resources:BeSly database...") + system("open http://www.besly.de &") + break + case MyTranslate$("MainView:Help:Online resources:Yabasic homepage...") + system("open http://www.yabasic.de &") + break + case MyTranslate$("MainView:Help:Online resources:Haikuware yab forum...") + system("open http://haikuware.com/forum/yab &") + break + case MyTranslate$("MainView:Help:About...") + AboutWindow() + break + + // the find and replace tabview + case "FindCS:ON" + case "FindCS:OFF" + settingsFindCS = not settingsFindCS + break + case "FindFind" + settingsOldSearch$ = textcontrol get$ "FindTCFind" + if(settingsOldSearch$<>"") then + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + case "FindReplace" + settingsOldSearch$ = textcontrol get$ "FindTCFind" + if(settingsOldSearch$<>"") then + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + if(searchLineNum <> -1) then + changestring() + + endif + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + case "FindReplAll" + if(settingsFindAlert) then + tmpAlert = alert "The operation \"Replace All\" can not be reverted!\n\nDo you want to continue?", "Cancel", "Do not show this warning again", "Ok", "warning" + if(tmpAlert = 1) break + if(tmpAlert = 2) settingsFindAlert = false + endif + settingsOldSearch$ = textcontrol get$ "FindTCFind" + if(settingsOldSearch$<>"") then + searchLineNum = 0 + while(searchLineNum<>-1) + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + if(searchLineNum <> -1) then + changestring() + endif + wend + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + + // the immediate tabview + case "ImmediateExecute" + tmp$ = textcontrol get$ "ImmediateInput" + ImmediateExec(tmp$) + break + + end switch + + // the output listbox, handle error messages + if((left$(msg$(i),22) = "YabOutputList:_Select:") or (left$(msg$(i),22) = "YabOutputList:_Invoke:")) then + tmp$ = listbox get$ "YabOutputList", val(right$(msg$(i),len(msg$(i))-22)) + if(left$(tmp$,8) = "---Error") then + num = instr(tmp$, "line ") + if(num) then + num = num + 5 + number$ = "" + repeat + number$ = number$ + mid$(tmp$,num,1) + num = num + 1 + until (mid$(tmp$,num,1) = ":") + num = val(number$) + + errorFileName$ = globalAllNames$(globalCurrentText) + errorFileFound = false + rightBound = instr(tmp$, ".yab") + if(rightBound) then + errorFileName$ = mid$(tmp$, 13, rightBound-13+4) + endif + if(errorFileName$<>globalAllNames$(globalCurrentText)) then + // check whether library is loaded already... + for tmpCheckName = 1 to MAXFILES + if((left$(errorFileName$,1) = "/" and errorFileName$ = globalAllNames$(tmpCheckName)) or (left$(errorFileName$,1) <> "/" and right$(globalAllNames$(tmpCheckName),len(errorFileName$)) = errorFileName$)) then + ActivateText(tmpCheckName) + errorFileFound = true + break + endif + next tmpCheckName + // otherwise load it now + else + errorFileFound = true + endif + + if(errorFileFound) then + textedit set "Text"+str$(globalCurrentText),"gotoline", num+7 + textedit set "Text"+str$(globalCurrentText),"gotoline", num + textedit set "Text"+str$(globalCurrentText),"select", num + if(globalSelectErrorLines) option set "Text"+str$(globalCurrentText),"focus", true + endif + endif + endif + endif + + + // the search field in the toolbar + if(left$(msg$(i),12) = "ToolbarText:" or msg$(i) = "ToolbarFind") then + if(msg$(i) = "ToolbarFind") then + settingsOldSearch$ = textcontrol get$ "ToolbarText" + else + settingsOldSearch$ = right$(msg$(i), len(msg$(i))-12) + endif + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + if(DEBUG) print searchLineNum + option set "Text"+str$(globalCurrentText), "Focus", true + endif + + // the find and replace tabview + // if(left$(msg$(i),11) = "FindTCFind:" and ) then + // option set "FindTCReplace", "focus", true + // endif + // if(left$(msg$(i),14) = "FindTCReplace:") then + // option set "FindFind", "focus", true + // endif + + + // the immediate tabview + if(left$(msg$(i),15) = "ImmediateInput:") then + ImmediateExec(right$(msg$(i), len(msg$(i))-15)) + endif + + // the project columnbox + if(left$(msg$(i),15) = "FileBox:_Select") then + tmp$ = right$(msg$(i),len(msg$(i))-16) + for tmpFiles = 1 to MAXFILES // arraysize(globalTextFinder(),1) + if(DEBUG) print val(tmp$), globalTextFinder(tmpFiles) + if(globalTextFinder(tmpFiles)=val(tmp$)) then + ActivateText(tmpFiles) + break + endif + next tmpFiles + endif + + // something dropped on the textedit + if(left$(msg$(i),18) = "V2Split2:_Dropped:" and globalCurrentText<>0) then + tmp$ = right$(msg$(i),len(msg$(i))-18) + handle = open(tmp$, "r") + if(handle) then + WaitWindow(tmp$) + text$ = "" + while(not eof(handle)) + text$ = text$ + GetLine$(handle)+"\n" + wend + close(handle) + tmp = textedit get "Text"+str$(globalCurrentText), "currentline" + textedit add "Text"+str$(globalCurrentText), left$(text$,len(text$)-1) + textedit set "Text"+str$(globalCurrentText), "changed", true + textedit set "Text"+str$(globalCurrentText), "gotoline", tmp + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + window close "WaitWindow" + else + alert MyTranslate$("Error while loading file:\n\n")+tmp$, "Ok", "warning" + endif + endif + + // something dropped on the project columnbox + if(left$(msg$(i),17) = "VSplit1:_Dropped:") then + foundEmpty = 0 + for j=1 to MAXFILES + if(globalAllNames$(j) = "") then + foundEmpty = j + break + endif + next j + if(not foundEmpty) then + alert MyTranslate$("Sorry, you can not open more than ")+str$(MAXFILES)+MyTranslate$(" files at once!\n\nPlease close one or more other files first."), "Ok", "Warning" + else + tmp$ = right$(msg$(i),len(msg$(i))-17) + foundProject = false + for j = 1 to MAXFILES + if(globalAllNames$(j) = tmp$) then + alert "File is already open.", "Ok", "info" + ActivateText(j) + foundProject = true + break + endif + next j + if(not foundProject) then + handle = open(tmp$, "r") + if(handle) then + WaitWindow(tmp$) + text$ = "" + while(not eof(handle)) + text$ = text$ + GetLine$(handle)+"\n" + wend + close(handle) + globalCurrentText = foundEmpty + textedit add "Text"+str$(globalCurrentText), left$(text$,len(text$)-1) + textedit set "Text"+str$(globalCurrentText), "changed", false + textedit set "Text"+str$(globalCurrentText), "gotoline", ReadLineFromAttr(tmp$) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + globalAllNames$(globalCurrentText) = tmp$ + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + window close "WaitWindow" + else + alert MyTranslate$("Error while loading file:\n\n")+tmp$, "Ok", "Stop" + endif + endif + endif + endif + + // help selected + if(left$(msg$(i),9) = "HelpTree:") then + tmp$ = right$(msg$(i), len(msg$(i))-17) + tmp$ = treebox get$ "HelpTree", val(tmp$) + t$ = SyntaxGetInfoText$(ideDir$+"data/Help_En.dat", ideDir$+"data/Help_En_Index.dat", tmp$) + if(t$<>"") then + textedit clear "Text"+str$(MAXFILES+1) + textedit add "Text"+str$(MAXFILES+1), t$ + endif + endif + + // search help + if(left$(msg$(i),9) = "HelpFind:") then + tmp$ = right$(msg$(i), len(msg$(i))-9) + tmp$ = trim$(tmp$) + tmp$ = lower$(tmp$) + t$ = SyntaxGetInfoText$(ideDir$+"data/Help_En.dat", ideDir$+"data/Help_En_Index.dat", tmp$) + if(t$<>"") then + textedit clear "Text"+str$(MAXFILES+1) + textedit add "Text"+str$(MAXFILES+1), t$ + endif + endif + next i + + if(globalCurrentText>0 and not globalWasChanged and textedit get "Text"+str$(globalCurrentText), "hasChanged") then + globalWasChanged = true + columnbox add "FileBox", 1, globalTextFinder(globalCurrentText), 20, "__Icon__="+ideDir$+"img/nichtgespeichert.png" + endif + + UpdateStatusbar() + + if(settingsFullEditor) then + tmp = window get "MainView", "Height" - 74 + if(splitview get "VSplit", "Divider" <> 0 or splitview get "HSplit", "Divider" <> tmp) then + settingsFullEditor = false + menu set "View", "Maximize editor", "plain", "MainView" + endif + endif + + if(globalCurrentText > 0) then + // Update the line numbers + // we are cheeting a bit :), we calculate the numbers for a 1200-pixel high view + scroll = textedit get "Text"+str$(globalCurrentText), "vertical-scrollbar" + v2Split = splitview get "V2Split", "divider" + if(scroll<>oldScroll or v2Split<>oldV2Split) then + scrollLine = int(scroll/globalRealFontSize) + scrollPos = mod(scroll,globalRealFontSize) + UpdateLines(scrollPos, 1200, scrollLine, globalRealFontSize) + oldScroll = scroll + oldV2Split = v2Split + // scrollLine = int((scroll+2)/15)+1 + // scrollPos = mod((globalHSplitDivider-1-peek("scrollbarwidth")+scroll),15)+5 + // scrollPos = mod((1000+scroll),15)+5 + // UpdateLines(scrollPos, globalHSplitDivider-1-peek("scrollbarwidth"), scrollLine, 15) + // UpdateLines(scrollPos, 1200, scrollLine, 15) + // oldScroll = scroll + endif + + // Check the spincontrol + spinner = spincontrol get "ToolbarGotoLine" + if(spinner <> oldSpinner) then + textedit set "Text"+str$(globalCurrentText), "gotoline", spinner + textedit set "Text"+str$(globalCurrentText), "select", 0 + textedit set "Text"+str$(globalCurrentText), "select", spinner + option set "Text"+str$(globalCurrentText), "Focus", true + oldSpinner = spinner + endif + endif + + // switch tabs from help to files and vice versa + if(globalIsHelp and tabview get "Tree" = 1) then + globalIsHelp = false + splitview set "V2Split", "divider", helpOldV2Split + if(globalCurrentText>0) then + ActivateHelpMenus(1) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + else + ActivateHelpMenus(0) + stackview set "Stack", MAXFILES+2 + stackview set "Lines", MAXFILES+2 + endif + endif + if(not globalIsHelp and tabview get "Tree" = 2) then + ActivateHelpMenus(-1) + globalIsHelp = true + stackview set "Stack", MAXFILES+1 + stackview set "Lines", MAXFILES+1 + helpOldV2Split = splitview get "V2Split", "divider" + splitview set "V2Split", "divider", 0 + endif +wend + +window close "MainView" +SaveSettings() + +// Open main window with everything +sub OpenMainWindow() + local vsplitheight, hsplitheight, tabwidth, i, handle + local tmp$ + local err, x, y + + x = peek("desktopwidth") + y = peek("desktopheight") + + // open initialize the main window + window open settingsX-3000,settingsY-3000 to settingsX+settingsWidth-3000,settingsY+settingsHeight-3000, "MainView", "yab-IDE" + + window open x/2-250-3000, y/2-200-3000 to x/2+249-3000,y/2+199-3000, "Splash", "" + window set "Splash", "look", "bordered" + err = draw image 0,0, ideDir$+"img/Splash.png", "Splash" + draw set "HighColor", 56,61,127, "Splash" + draw set "DejaVu Sans Mono,Bold,18", "Splash" + draw text 30, 280, "Version "+versionnumber$, "Splash" + window set "Splash", "moveto", x/2-250,y/2-200 + set_up_BuildFactory() + if(err>0) window close "Splash" + + + + window set "MainView", "look", "document" + window set "MainView", "MinimumTo", 600,300 + + // set all menus + menu "File", "New...", "N", "MainView" + menu "File", "Open...", "O", "MainView" + menu "File", "Close", "W", "MainView" + menu "File", "--", "", "MainView" + menu "File", "Save", "S", "MainView" + menu "File", "Save as...", "", "MainView" + menu "File", "Save as template...", "", "MainView" + menu "File", "Export as HTML...", "", "MainView" + + menu "File", "--", "", "MainView" + menu "File", "Page setup...", "", "MainView" + menu "File", "Print...", "P", "MainView" + menu "File", "--", "", "MainView" + menu "File", "Quit", "Q", "MainView" + + menu "Edit", "Undo", "Z", "MainView" + menu "Edit", "--", "", "MainView" + menu "Edit", "Cut", "X", "MainView" + menu "Edit", "Copy", "C", "MainView" + menu "Edit", "Paste", "V", "MainView" + menu "Edit", "--", "", "MainView" + menu "Edit", "Select all", "A", "MainView" + menu "Edit", "--", "", "MainView" + menu "Edit", "Find", "F", "MainView" + menu "Edit", "Find again", "G", "MainView" + menu "Edit", "Find and replace", "E", "MainView" + + menu "Program", "Run", "R", "MainView" + menu "Program", "Run in Terminal", "T", "MainView" + menu "Program", "--", "", "MainView" + menu "Program", "Set run parameters...", "SR", "MainView" + menu "Program", "--", "", "MainView" + menu "Program", "Build Factory...", "B", "MainView" + menu "Program", "--", "", "MainView" + menu "Program", "Open project folder...", "SO", "MainView" + + if(not globalNoRCS) then + menu "RCS", "Check In", "CI", "MainView" + menu "RCS", "Check Out", "CO", "MainView" + menu "RCS", "--", "", "MainView" + menu "RCS", "Version History...", "CV", "MainView" + endif + + menu "Tools", "Pattern editor...", "CP", "MainView" + menu "Tools", "Color selection...", "CC", "MainView" + menu "Tools", "--", "", "MainView" + menu "Tools", "ASCII table...", "CA", "MainView" + + menu "View", "Next file", ".", "MainView" + menu "View", "Previous file", ",", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Full screen", "CF", "MainView" + menu "View", "Maximize editor", "CE", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Auto indent", "", "MainView" + menu "View", "Auto completion", "", "MainView" + menu "View", "Refresh colors", "", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Reformat sourcecode", "CR", "MainView" + menu "View", "Undo reformat", "", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Options...", "", "MainView" + if settingsFullScreen menu set "View", "Full screen", "mark", "MainView" + if settingsFullEditor menu set "View", "Maximize editor", "mark", "MainView" + if settingsAutoIndent menu set "View", "Auto indent", "mark", "MainView" + if settingsAutoCompletion menu set "View", "Auto completion", "mark", "MainView" + menu set "View", "Undo reformat", "disable", "MainView" + + menu "Help", "Short command help...", "H", "MainView" + menu "Help", "Yabasic manual...", "M", "MainView" + menu "Help", "--", "", "MainView" + menu "Help", "Online resources", "", "MainView" + submenu "Help", "Online resources", "German BeUsergroup...", "", "MainView" + submenu "Help", "Online resources", "BeSly database...", "", "MainView" + submenu "Help", "Online resources", "Yabasic homepage...", "", "MainView" + submenu "Help", "Online resources", "Haikuware yab forum...", "", "MainView" + menu "Help", "--", "", "MainView" + menu "Help", "About...", "", "MainView" + + // set the toolbar + ToolbarCreate(0,peek("menuheight")+1,2000, "Toolbar", ideDir$+"img/", "MainView") + ToolbarAddIcon("ToolbarNew", "New", "newp.png", "newn.png", "newd.png") + ToolbarAddIcon("ToolbarOpen", "Open", "openp.png", "openn.png", "opend.png") + ToolbarAddIcon("ToolbarSave", "Save", "savep.png", "saven.png", "saved.png") + ToolbarAddIcon("ToolbarClose", "Close", "closep.png", "closen.png", "closed.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarCut", "Cut", "cutp.png", "cutn.png", "cutd.png") + ToolbarAddIcon("ToolbarCopy", "Copy", "copyp.png", "copyn.png", "copyd.png") + ToolbarAddIcon("ToolbarPaste", "Paste", "pastep.png", "pasten.png", "pasted.png") + ToolbarAddIcon("ToolbarUndo", "Undo", "undop.png", "undon.png", "undod.png") + // ToolbarAddIcon("ToolbarFind", "Find", "searchp.png", "searchn.png", "searchd.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarRun", "Run", "runp.png", "runn.png", "rund.png") + ToolbarAddIcon("ToolbarRunTerm", "Run in Terminal", "runtermp.png", "runtermn.png", "runtermd.png") + // ToolbarAddIcon("ToolbarDebug", "Debugger", "debugp.png", "debugn.png", "debugd.png") + ToolbarAddIcon("ToolbarBuild", "Build Factory", "bindp.png", "bindn.png", "bindd.png") + // ToolbarAddSeparator() + // ToolbarAddIcon("ToolbarGui", "GUI Designer", "guip.png", "guin.png", "guid.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarPattern", "Pattern editor", "patternp.png", "patternn.png", "patternd.png") + ToolbarAddIcon("ToolbarOptions", "Options", "optionsp.png", "optionsn.png", "optionsd.png") + ToolbarAddIcon("ToolbarHelp", "yab Help", "helpp.png", "helpn.png", "helpd.png") + ToolbarAddSeparator() + + spincontrol 383,2, "ToolbarGotoLine", "Go to Line:", 1, 100000, 1, "Toolbar" + tooltip "ToolbarGotoLine", "Go to Line" + draw set "highcolor", 185,185,185, "Toolbar" + draw line 430,5 to 400,25, "Toolbar" + draw set "highcolor", 239,239,239, "Toolbar" + draw line 431,5 to 401,25, "Toolbar" + + button image 538,7, "ToolbarFind", ideDir$+"img/searchp.png", ideDir$+"img/searchn.png", ideDir$+"img/searchd.png", "Toolbar" + tooltip "ToolbarFind", "Find" + textcontrol 553,5 to 640,25, "ToolbarText", "", settingsOldSearch$, "Toolbar" + draw set "highcolor", 185,185,185, "Toolbar" + draw line 510,5 to 480,25, "Toolbar" + draw set "highcolor", 239,239,239, "Toolbar" + draw line 511,5 to 481,25, "Toolbar" + + // layout "top, left, right", "Toolbar" + draw set "highcolor", 200,200,200, "Toolbar" + draw line 0,29 to 2000,29, "Toolbar" + draw set "highcolor", 184,184,184, "Toolbar" + draw line 0,30 to 2000,30, "Toolbar" + draw set "highcolor", 239,239,239, "Toolbar" + draw line 0,31 to 2000,31, "Toolbar" + + + // vertical splitview + layout "standard", "MainView" + splitview 0,peek("menuheight")+31, settingsWidth,settingsHeight-peek("scrollbarwidth"), "VSplit", true, true, "MainView" + splitview set "VSplit", "Divider", settingsVSplitDivider + splitview set "VSplit", "MinimumSizes", 0,400 + + // horizontal splitview + splitview 0,0, settingsWidth-settingsVSplitDivider,settingsHeight-peek("scrollbarwidth")+1, "HSplit", false, true, "VSplit2" + splitview set "HSplit", "Divider", settingsHSplitDivider + splitview set "HSplit", "MinimumSizes", 100,51 + + splitview 0,0, settingsWidth-settingsVSplitDivider,settingsHSplitDivider-1, "V2Split", true,false, "HSplit1" + splitview set "V2Split", "Divider", 0 + splitview set "V2Split", "MinimumSizes", 0,300 + + + vsplitheight = settingsHeight - peek("menuheight")-peek("scrollbarwidth") + + // tabview and treeboxes in the left vertical splitview + tabview 0,1 to settingsVSplitDivider-1,vsplitheight-32, "Tree", "bottom", "VSplit1" + tabview add "Tree", " Files " + tabview add "Tree", " Help " + columnbox 0,0 to settingsVSplitDivider-10,vsplitheight-42-peek("tabheight"), "FileBox", false, "no-border, resizable", "Tree1" + columnbox column "FileBox", " ", 1, 20, 20, 20, "align-center" + columnbox column "FileBox", "Filename",2, 300, 32, settingsVSplitDivider-32, "align-left" + columnbox color "FileBox", "Selection-Active", 220,220,250 + columnbox color "FileBox", "Row-Divider", 255,255,255 + + treebox 0,0 to settingsVSplitDivider-10, vsplitheight-42-peek("tabheight")-40, "HelpTree", 1, "Tree2" + layout "left,bottom,right", "Tree2" + textcontrol 0,vsplitheight-42-peek("tabheight")-30 to settingsVSplitDivider-14,vsplitheight-42-peek("tabheight")-10, "HelpFind", "Command", "", "Tree2" + layout "standard", "Tree2" + + view dropzone "VSplit1" + view dropzone "V2Split2" + + // a stackview with textedits in the upper right splitview + // implement a dynamic stackview in future! + // stackview 0,0 to settingsWidth-settingsVSplitDivider-11,settingsHSplitDivider-1, "Stack", MAXFILES+2, "HSplit1" + stackview 0,0 to settingsWidth-settingsVSplitDivider-11-4,settingsHSplitDivider-1, "Stack", MAXFILES+2, "V2Split2" + stackview 0,0 to settingsV2SplitDivider,settingsHSplitDivider-1, "Lines", MAXFILES+2, "V2Split1" + for i=1 to MAXFILES + // textedit 37,0 to settingsWidth-settingsVSplitDivider-12,settingsHSplitDivider-1, "Text"+str$(i), 3, "Stack"+str$(i) + textedit 1,1 to settingsWidth-settingsVSplitDivider-12-5,settingsHSplitDivider-2, "Text"+str$(i), 3, "Stack"+str$(i) + textedit set "Text"+str$(i), "wordwrap", false + textedit set "Text"+str$(i), "textwidth", 4000 + textedit set "Text"+str$(i), "tabwidth", settingsTabSpaces*7 + textedit set "Text"+str$(i), "font", settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize) + textedit set "Text"+str$(i), "autoindent", settingsAutoIndent + + // layout "left,top,bottom", "Lines"+str$(i) + // view 0,0 to 36,settingsHSplitDivider-1, "Lines"+str$(i), "LineStack"+str$(i) + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "Lines"+str$(i) + layout "standard", "Stack"+str$(i) + + textedit set "Text"+str$(i), "autocomplete-start", settingsACNumChar + handle = open(ideDir$+"/data/autocompletion") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit set "Text"+str$(i), "autocomplete", tmp$ + wend + close(handle) + endif + + handle = open(ideDir$+"/data/color1") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color1", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color2") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color2", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color3") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color3", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color4") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color4", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color5") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "char-color", tmp$ + wend + close(handle) + endif + next i + + textedit 1,1 to settingsWidth-settingsVSplitDivider-12-5,settingsHSplitDivider-2, "Text"+str$(MAXFILES+1), 1, "Stack"+str$(MAXFILES+1) + textedit set "Text"+str$(MAXFILES+1), "font", settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize) + textedit set "Text"+str$(MAXFILES+1), "editable", false + textedit color "Text"+str$(MAXFILES+1), "color1", "Name:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Synopsis:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Description:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Example:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Design:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Layout:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Message:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Related:" + SyntaxLoadTree(ideDir$+"data/Help_En.dat", "HelpTree") + + // UpdateLines(0, globalHSplitDivider-1-peek("scrollbarwidth"), 1, 15) + UpdateLines(0, 1200, 1, globalRealFontSize) + + layout "h-center, v-center", "Stack"+str$(MAXFILES+2) + // view (settingsWidth-settingsVSplitDivider-12)/2-150,(settingsHSplitDivider-1)/2-190 to (settingsWidth-settingsVSplitDivider-12)/2+150,(settingsHSplitDivider-1)/2+190, "Logo", "Stack"+str$(MAXFILES+2) + view (settingsWidth-settingsVSplitDivider-12-41-4)/2-150,(settingsHSplitDivider-1)/2-190 to (settingsWidth-settingsVSplitDivider-12-41-4)/2+150,(settingsHSplitDivider-1)/2+190, "Logo", "Stack"+str$(MAXFILES+2) + draw set "bgcolor", 255,255,255, "Stack"+str$(MAXFILES+2) + draw set "bgcolor", 255,255,255, "Logo" + err = draw image 0,0 to 350,-1, ideDir$+"img/logo.png", "Logo" + stackview set "Stack", MAXFILES+2 + stackview set "Lines", MAXFILES+2 + layout "standard", "Stack"+str$(MAXFILES+2) + + hsplitheight = settingsHeight-settingsHSplitDivider-peek("scrollbarwidth")-peek("menuheight")-42 + + // the tabview in the lower right splitview + tabview 0,0 to settingsWidth-settingsVSplitDivider-11,hsplitheight, "HTab", "bottom", "HSplit2" + tabview add "HTab", "yab Output" + tabview add "HTab", "Immediate" + tabview add "HTab", "Find and replace" + if(not globalNoRCS) then + tabview add "HTab", "Version Control" + endif + + hsplitheight = hsplitheight-peek("tabheight")-12 + tabwidth = settingsWidth-settingsVSplitDivider-21 + + // the output box + listbox 0,0 to tabwidth,hsplitheight, "YabOutputList", 1, "HTab1" + + // the immediate stuff + layout "left,right,top", "HTab2" + textcontrol 5,5 to tabwidth-110,25, "ImmediateInput", "Command", "", "HTab2" + layout "right,top", "HTab2" + button tabwidth-100,3 to tabwidth-10,23, "ImmediateExecute", "Execute", "HTab2" + layout "standard", "HTab2" + textedit 10,35 to tabwidth-10,hsplitheight-10, "ImmediateOutput", 1, "HTab2" + textedit set "ImmediateOutput", "editable", false + + // search and replace + layout "left,top", "HTab3" + w = draw get "Text-width", MyTranslate$("Find:"), "HTab3" + draw text 55-w,23, "Find:", "HTab3" + w = draw get "Text-width", MyTranslate$("Replace:"), "HTab3" + draw text 55-w,48, "Replace:", "HTab3" + textcontrol 55,10 to 290,30, "FindTCFind", "", "", "HTab3" + textcontrol 55,35 to 290,55, "FindTCReplace", "", "", "HTab3" + checkbox 55,60, "FindCS", "Case Sensitive", settingsFindCS, "HTab3" + MyLine(300,5,300,90,"HTab3") + button 310,10 to 460,30, "FindFind", "Find", "HTab3" + button 310,35 to 460,55, "FindReplace", "Find and replace", "HTab3" + button 310,60 to 460,80, "FindReplAll", "Replace All", "HTab3" + + // the statusbar + layout "left, bottom", "MainView" + view 0,settingsHeight-peek("scrollbarwidth") to 2000,settingsHeight, "Statusbar", "MainView" + draw set "highcolor", 200,200,200, "Statusbar" + draw line 0,0 to 2000,0, "Statusbar" + draw set "highcolor", 184,184,184, "Statusbar" + draw line 0,1 to 2000,1, "Statusbar" + draw set "highcolor", 239,239,239, "Statusbar" + draw line 0,2 to 2000,2, "Statusbar" + + if(window count>1) window close "Splash" + + window set "MainView", "moveto", settingsX, settingsY + + return +end sub + + +// (De-)activate menus +sub ActivateMenus(toActivate) + local tmp$ + + if(toActivate) then + tmp$ = "Enable" + else + tmp$ = "Disable" + endif + + menu set "File", "Close", tmp$, "MainView" + menu set "File", "Save", tmp$, "MainView" + menu set "File", "Save as...", tmp$, "MainView" + menu set "File", "Save as template...", tmp$, "MainView" + menu set "File", "Export as HTML...", tmp$, "MainView" + menu set "File", "Page setup...", tmp$, "MainView" + menu set "File", "Print...", tmp$, "MainView" + + menu set "Edit", "Undo", tmp$, "MainView" + menu set "Edit", "Cut", tmp$, "MainView" + menu set "Edit", "Copy", tmp$, "MainView" + menu set "Edit", "Paste", tmp$, "MainView" + menu set "Edit", "Select all", tmp$, "MainView" + menu set "Edit", "Find", tmp$, "MainView" + menu set "Edit", "Find again", tmp$, "MainView" + menu set "Edit", "Find and replace", tmp$, "MainView" + + menu set "Program", "Run", tmp$, "MainView" + menu set "Program", "Run in Terminal", tmp$, "MainView" + menu set "Program", "Set run parameters...", tmp$, "MainView" + menu set "Program", "Build Factory...", tmp$, "MainView" + menu set "Program", "Open project folder...", tmp$, "MainView" + + if(not globalNoRCS) then + menu set "RCS", "Check In", tmp$, "MainView" + menu set "RCS", "Check Out", tmp$, "MainView" + menu set "RCS", "Version History...", tmp$, "MainView" + endif + + menu set "Tools", "Pattern editor...", tmp$, "MainView" + menu set "Tools", "Color selection...", tmp$, "MainView" + + menu set "View", "Next file", tmp$, "MainView" + menu set "View", "Previous file", tmp$, "MainView" + menu set "View", "Auto indent", tmp$, "MainView" + menu set "View", "Auto completion", tmp$, "MainView" + menu set "View", "Refresh colors", tmp$, "MainView" + menu set "View", "Reformat sourcecode", tmp$, "MainView" + menu set "View", "Undo reformat", "disable", "MainView" + menu set "View", "Options...", tmp$, "MainView" + + option set "ToolbarSave", "Enabled", toActivate + option set "ToolbarClose", "Enabled", toActivate + option set "ToolbarCut", "Enabled", toActivate + option set "ToolbarCopy", "Enabled", toActivate + option set "ToolbarPaste", "Enabled", toActivate + option set "ToolbarUndo", "Enabled", toActivate + option set "ToolbarFind", "Enabled", toActivate + option set "ToolbarText", "Enabled", toActivate + option set "ToolbarRun", "Enabled", toActivate + option set "ToolbarRunTerm", "Enabled", toActivate + option set "ToolbarPattern", "Enabled", toActivate + option set "ToolbarBuild", "Enabled", toActivate + option set "ToolbarOptions", "Enabled", toActivate + option set "ToolbarGotoLine", "Enabled", toActivate + + option set "FindTCFind", "Enabled", toActivate + option set "FindTCReplace", "Enabled", toActivate + option set "FindCS", "Enabled", toActivate + option set "FindFind", "Enabled", toActivate + option set "FindReplace", "Enabled", toActivate + option set "FindReplAll", "Enabled", toActivate + + return +end sub + +// (De-)activate menus when help is selected +sub ActivateHelpMenus(toActivate) + local tmp$ + + if(toActivate = 1) then + tmp$ = "Enable" + else + tmp$ = "Disable" + endif + + if(toActivate = -1) then + menu set "File", "Open...", tmp$, "MainView" + menu set "File", "New...", tmp$, "MainView" + else + menu set "File", "Open...", "Enable", "MainView" + menu set "File", "New...", "Enable", "MainView" + endif + menu set "File", "Close", tmp$, "MainView" + menu set "File", "Save", tmp$, "MainView" + menu set "File", "Save as...", tmp$, "MainView" + menu set "File", "Save as template...", tmp$, "MainView" + menu set "File", "Export as HTML...", tmp$, "MainView" + + menu set "Edit", "Undo", tmp$, "MainView" + menu set "Edit", "Cut", tmp$, "MainView" + menu set "Edit", "Paste", tmp$, "MainView" + menu set "Edit", "Find and replace", tmp$, "MainView" + + menu set "Program", "Run", tmp$, "MainView" + menu set "Program", "Run in Terminal", tmp$, "MainView" + menu set "Program", "Set run parameters...", tmp$, "MainView" + menu set "Program", "Build Factory...", tmp$, "MainView" + menu set "Program", "Open project folder...", tmp$, "MainView" + + if(not globalNoRCS) then + menu set "RCS", "Check In", tmp$, "MainView" + menu set "RCS", "Check Out", tmp$, "MainView" + menu set "RCS", "Version History...", tmp$, "MainView" + endif + + menu set "Tools", "Pattern editor...", tmp$, "MainView" + menu set "Tools", "Color selection...", tmp$, "MainView" + + menu set "View", "Next file", tmp$, "MainView" + menu set "View", "Previous file", tmp$, "MainView" + menu set "View", "Auto indent", tmp$, "MainView" + menu set "View", "Auto completion", tmp$, "MainView" + menu set "View", "Refresh colors", tmp$, "MainView" + menu set "View", "Reformat sourcecode", tmp$, "MainView" + menu set "View", "Undo reformat", "disable", "MainView" + + if(toActivate = -1) then + option set "ToolbarOpen", "Enabled", false + option set "ToolbarNew", "Enabled", false + toActivate = 0 + else + option set "ToolbarOpen", "Enabled", true + option set "ToolbarNew", "Enabled", true + endif + option set "ToolbarSave", "Enabled", toActivate + option set "ToolbarClose", "Enabled", toActivate + option set "ToolbarCut", "Enabled", toActivate + option set "ToolbarPaste", "Enabled", toActivate + option set "ToolbarUndo", "Enabled", toActivate + option set "ToolbarText", "Enabled", toActivate + option set "ToolbarRun", "Enabled", toActivate + option set "ToolbarRunTerm", "Enabled", toActivate + option set "ToolbarPattern", "Enabled", toActivate + option set "ToolbarBuild", "Enabled", toActivate + option set "ToolbarGotoLine", "Enabled", toActivate + + option set "FindTCReplace", "Enabled", toActivate + option set "FindReplace", "Enabled", toActivate + option set "FindReplAll", "Enabled", toActivate + + return +end sub + +// Update the line numbering +sub UpdateLines(starty, height, topline, fontHeight) + local i, pos + local t$ + + if(globalCurrentText > 0) then + pos = splitview get "V2Split", "Divider" - 3 + draw flush "Lines"+str$(globalCurrentText) + for i=fontHeight-4-starty to height step fontHeight + t$ = str$(int(i/fontHeight)+topline+1) + draw text pos-(draw get "text-width", t$, "Lines"+str$(globalCurrentText)),i, t$, "Lines"+str$(globalCurrentText) + next i + endif + return +end sub + +// Open new file +sub NewDocument(foundEmpty) + local inloop + local browse$ + local i, n, err, nTemplates, isButton + local handle, handle2 + local x, y, winSize, w, t + local t$, txt$ + + x = (peek("desktopwidth")-500)/2 + y = (peek("desktopheight")-390)/2-50 + if(y<50) y=50 + + window open x+200-3000,y+150-3000 to x+700-3000,y+440-3000, "NewWindow", "yab-IDE New Program" + window set "NewWindow", "Feel", "Modal-App" + window set "NewWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("New yab Program", "NewWindow", 500) + + text 10,50, "NewText1", "Please select one of the available templates for your program:", "NewWindow" + listbox 10,70 to 166,200, "NewList", 1, "NewWindow" + + handle = open(ideDir$+"Templates/TemplateList", "r") + if(handle>0) then + nTemplates = 0 + while(not eof(handle)) + nTemplates = nTemplates + 1 + dim tmp$(nTemplates) + tmp$(nTemplates) = GetLine$(handle)+"\n" + tmp$(nTemplates) = left$(tmp$(nTemplates), len(tmp$(nTemplates))-1) + if(left$(tmp$(nTemplates),1) = "#") nTemplates = nTemplates - 1 + wend + close handle + else + dim tmp$(1) + tmp$(1) = "Empty" + nTemplates = 1 + endif + for i = 1 to nTemplates step 4 + listbox add "NewList", tmp$(i) + next i + view 190,70 to 490,200, "NewImage", "NewWindow" + + browse$ = globalProjectDir$+"untitled"+str$(GetNewNumber(globalProjectDir$))+".yab" + + textcontrol 10,220 to 400,240, "NewName", "Name:", browse$, "NewWindow" + button 410,220 to 490,240, "NewBrowse", "Browse...", "NewWindow" + + checkbox image 10,270, "NewAdvanced", ideDir$+"img/arrowdown.png", ideDir$+"img/arrowright.png", "", "", false, "NewWindow" + winSize = false + text 20,270, "NewText2", "Advanced Options", "NewWindow" + button 430,260 to 490,280, "NewOk", "Ok", "NewWindow" + option set "NewOk", "enabled", false + isButton = false + + draw set "highcolor", 185,185,185, "NewWindow" + draw line 0,252 to 500,252, "NewWindow" + draw line 0,292 to 500,292, "NewWindow" + draw set "highcolor", 239,239,239, "NewWindow" + draw line 0,253 to 500,253, "NewWindow" + draw line 0,293 to 500,293, "NewWindow" + + // button 260,300 to 280,310, "NewHelp", "?", "NewWindow" + button 350,295 to 490,325, "NewDel", "Remove Template", "NewWindow" + option set "NewDel", "enabled", false + + if(not globalNoRCS) then + checkbox 10, 300, "NewCheckbox", "Use RCS Version Control", settingsUseRCS, "NewWindow" + // option set "NewCheckbox", "enabled", false + // option set "NewHelp", "enabled", false + endif + + textcontrol 10,330 to 490,350, "NewProject", "Project Directory", globalProjectDir$, "NewWindow" + + window set "NewWindow", "moveto", x,y + + inloop = true + dim msg$(1) + while(inloop) + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + if(left$(msg$(i),16) = "NewList:_Invoke:") then + msg$(i) = "NewOk" + endif + switch(msg$(i)) + case "NewOk" + if(j>0) then + browse$ = textcontrol get$ "NewName" + if(arraysize(tmp$(), 1) = 1) then + txt$ = "" + else + handle = open(ideDir$+"Templates/"+tmp$(j), "r") + if(handle) then + while(not eof(handle)) + txt$ = txt$ + GetLine$(handle)+"\n" + wend + close(handle) + // txt$ = left$(txt$, len(txt$)-1) + else + alert MyTranslate$("Could not open template: ")+tmp$(j)+"\n\n"+MyTranslate$("Opening an empty file instead."), "Ok", "warning" + txt$ = "" + endif + endif + globalCurrentText = foundEmpty + textedit add "Text"+str$(globalCurrentText), txt$ + textedit set "Text"+str$(globalCurrentText), "changed", true + textedit set "Text"+str$(globalCurrentText), "gotoline", 1 + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + globalAllNames$(globalCurrentText) = browse$ + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/nichtgespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(browse$) + columnbox select "FileBox", t+1 + + globalTextFinder(globalCurrentText) = t+1 + + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + globalNewNumber = globalNewNumber + 1 + globalNumOpenFiles = globalNumOpenFiles + 1 + inloop = false + endif + break + case "NewAdvanced:ON" + case "NewAdvanced:OFF" + winSize = not winSize + if(winSize) then + window set "NewWindow", "MinimumTo", 500,360 + window set "NewWindow", "MaximumTo", 500,360 + window set "NewWindow", "ResizeTo", 500,360 + else + window set "NewWindow", "MinimumTo", 500,290 + window set "NewWindow", "MaximumTo", 500,290 + window set "NewWindow", "ResizeTo", 500,290 + endif + break + case "NewBrowse" + browse$ = filepanel "Save-File", "New", globalProjectDir$ + if(browse$<>"") textcontrol set "NewName", browse$ + break + case "NewWindow:_QuitRequested" + inloop = false + break + case "_QuitRequested" + //emergency break + exit(1) + break + case "NewDel" + t$ = listbox get$ "NewList", (j-1)/4+1 + t = alert MyTranslate$("Really delete template")+" \""+t$+"\"?", "Yes", "Cancel", "", "warning" + if(t = 1) then + if((j-1)/4+1 < 4) then + alert "This standard template can not be deleted!", "Ok", "warning" + else + handle = open(ideDir$+"Templates/TemplateList", "r") + handle2 = open("/tmp/TemplateList", "w") + if(handle) then + if(handle2) then + while(not eof(handle)) + t$ = GetLine$(handle)+"\n" + if(left$(t$,len(t$)-1)<>tmp$(j)) then + print #handle2 t$; + else + t$ = GetLine$(handle)+"\n" + t$ = GetLine$(handle)+"\n" + t$ = GetLine$(handle)+"\n" + endif + wend + close(handle2) + system("mv /tmp/TemplateList "+ideDir$+"Templates/TemplateList") + system("rm "+ideDir$+tmp$(j+1)) + system("rm "+ideDir$+"Templates/"+tmp$(j)) + listbox remove "NewList", (j-1)/4+1 + listbox select "NewList", (j-5)/4+1 + msg$(i) = "NewList:_Select:"+str$((j-5)/4+1) + alert "Template successfully removed.", "Ok", "info" + else + alert "Error while deleting template!", "Ok", "stop" + endif + close(handle) + else + alert "Error while deleting template!", "Ok", "stop" + endif + endif + endif + + break + end switch + if(left$(msg$(i),16) = "NewList:_Select:") then + draw rect 0,0 to 200,140, "NewImage" + draw flush "NewImage" + j = (val(mid$(msg$(i),17,len(msg$(i))-1))-1)*4+1 + if(arraysize(tmp$(),1)>=j+1) then + err = draw image 50,0 to 250,100, ideDir$+tmp$(j+1), "NewImage" + endif + if(arraysize(tmp$(),1)>=j+2) then + draw text 10,110, tmp$(j+2), "NewImage" + endif + if(arraysize(tmp$(),1)>=j+3) then + draw text 10,125, tmp$(j+3), "NewImage" + endif + if(not isButton) then + isButton = false + option set "NewOk", "enabled", true + option set "NewDel", "enabled", true + endif + endif + next i + wend + + window close "NewWindow" +end sub + +sub GetNewNumber(dir$) + local tmp$ + local num: local i: local ret + local numFound + local t$(1) + + numFound = false + ret = 0 + tmp$ = system$("ls "+dir$+"untitled*.yab") + num = token(tmp$, t$(), "\n") + while(not numFound) + numFound = true + for i=1 to num + tmp$ = left$(t$(i), len(t$(i))-4) + tmp$ = right$(tmp$, len(tmp$)-8-len(dir$)) + if(ret = val(tmp$)) then + ret = ret + 1 + numFound = false + break + endif + next i + if(numFound) then + for i=1 to MAXFILES + tmp$ = dir$+"untitled"+str$(ret)+".yab" + if(globalAllNames$(i) = tmp$) then + ret = ret + 1 + numFound = false + break + endif + next i + endif + wend + return ret +end sub + +sub ImmediateExec(command$) + local result$ + + if(instr(command$, "input")) then + alert "Suspecting user input, therefore starting in a terminal.", "Ok", "info" + result$ = system$("Terminal "+yabDir$+" -enter -execute '"+command$+":exit'") + else + result$ = system$(yabDir$+" -execute '"+command$+":exit' 2>&1") + result$ = left$(result$, len(result$)-1) + + textedit clear "ImmediateOutput" + textedit add "ImmediateOutput", result$ + endif + + return +end sub + +sub GetFileName$(directory$) + local lastSlash + local j + + lastSlash = 0 + for j=1 to len(directory$) + if(mid$(directory$,j,1)="/" and mid$(directory$,j-1,1)<>"/") + lastSlash = j + next j + + return right$(directory$,len(directory$)-lastSlash) +end sub + +sub GetDirectory$(directory$) + local lastSlash + local j + + lastSlash = 0 + for j=1 to len(directory$) + if(mid$(directory$,j,1)="/" and mid$(directory$,j-1,1)<>"/") + lastSlash = j + next j + + return left$(directory$,lastSlash) +end sub + +sub ActivateText(num) + globalCurrentText = num + globalWasChanged = textedit get "Text"+str$(globalCurrentText), "hasChanged" + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + option set "Text"+str$(globalCurrentText), "focus", true + columnbox select "FileBox", globalTextFinder(num) + oldScroll = -1 + return +end sub + +sub ReadLineFromAttr(filename$) + a$=attribute get$ "",filename$ + if instr (a$,"linenumber") then + return attribute get "linenumber", filename$ + else return 0 + endif +end sub + +sub UpdateStatusbar() + static oldText$ + local newText$ + + if(globalCurrentText = 0) then + if(oldText$<>"") then + oldText$ = "" + draw flush "Statusbar" + draw set "highcolor", 200,200,200, "Statusbar" + draw line 0,0 to 2000,0, "Statusbar" + draw set "highcolor", 184,184,184, "Statusbar" + draw line 0,1 to 2000,1, "Statusbar" + draw set "highcolor", 239,239,239, "Statusbar" + draw line 0,2 to 2000,2, "Statusbar" + endif + return + endif + + newText$ = globalAllNames$(globalCurrentText) + if(textedit get "Text"+str$(globalCurrentText), "hasChanged") then + newText$ = newText$ + MyTranslate$(" (not saved) ") + else + newText$ = newText$ + " " + endif + + newText$ = newText$ + MyTranslate$("Line:")+" "+str$(textedit get "Text"+str$(globalCurrentText), "currentline") + newText$ = newText$ + " / "+str$(textedit get "Text"+str$(globalCurrentText), "countlines") + + + if(oldText$<>newText$) then + draw flush "Statusbar" + draw set "highcolor", 200,200,200, "Statusbar" + draw line 0,0 to 2000,0, "Statusbar" + draw set "highcolor", 184,184,184, "Statusbar" + draw line 0,1 to 2000,1, "Statusbar" + draw set "highcolor", 239,239,239, "Statusbar" + draw line 0,2 to 2000,2, "Statusbar" + draw set "highcolor", 0,0,0, "Statusbar" + draw text 5,13, "File: ", "Statusbar" + // draw set "highcolor", 0,200,0, "Statusbar" + draw text (5+draw get "Text-Width", MyTranslate$("File: "), "Statusbar"),13, newText$, "Statusbar" + // draw text (5+draw get "Text-Width", "Status: ", "Statusbar"),11, globalAllNames$(globalCurrentText)+" saved", "Statusbar" + oldText$ = newText$ + endif + + return +end sub + +sub WaitWindow(text$) + local x + local y + local width + local err + + x = peek("desktopwidth")/2 - 125 + y = peek("desktopheight")/2 - 100 + window open x,y to x+249,y+79, "WaitWindow", "" + window set "WaitWindow", "feel", "modal-app" + window set "WaitWindow", "look", "modal" + window set "WaitWindow", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + err = draw image 0,0, ideDir$+"img/Loading.png", "WaitWindow" + + w = draw get "text-width", GetFileName$(text$), "WaitWindow" + text 143-w/2,32, "TWait", GetFileName$(text$), "WaitWindow" + + w = draw get "text-width", MyTranslate$("Please wait..."), "WaitWindow" + text 143-w/2,60, "TRunning2", "Please wait...", "WaitWindow" + + draw set "Bitstream Vera Sans, Bold Oblique, 14", "WaitWindow" + w = draw get "text-width", MyTranslate$("Loading Program"), "WaitWindow" + draw text 143-w/2,20, "Loading Program", "WaitWindow" + + return +end sub + +// Run the program and display its output +sub RunProgram(yabFile$) + local tmp$, unique$ + local num, i, t, teamID, pos + local x, y, err, w + + if(isRunning) return + isRunning = true + + // easy way to make the tmp file sort-of unique + unique$ = date$+time$ + + x = peek("desktopwidth")/2 - 125 + y = peek("desktopheight")/2 - 100 + window open x,y to x+249,y+79, "Running", "" + window set "Running", "feel", "modal-app" + window set "Running", "look", "modal" + window set "Running", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + err = draw image 0,0, ideDir$+"img/Running.png", "Running" + + w = draw get "text-width", GetFileName$(yabFile$), "Running" + text 143-w/2,32, "TRunning", GetFileName$(yabFile$), "Running" + button 150,50 to 240,75, "BRunning", "Break", "Running" + + draw set "Bitstream Vera Sans, Bold Oblique, 14", "Running" + w = draw get "text-width", MyTranslate$("Running Program"), "Running" + draw text 143-w/2,20, "Running Program", "Running" + + // text 5,5, "TRunning", MyTranslate$("Now Running: ")+GetFileName$(yabFile$), "Running" + // button 50,25 to 150,45, "BRunning", "Break", "Running" + listbox clear "YabOutputList" + window set "Running", "deactivate" + + if DEBUG print "cd "+GetDirectory$(yabFile$)+";"+yabDir$+" "+settingsYabParam$+" "+yabFile$+" "+settingsProgParam$+" &>/tmp/yab-log."+unique$+" &" + system("cd "+GetDirectory$(yabFile$)+";"+yabDir$+" "+settingsYabParam$+" "+yabFile$+" "+settingsProgParam$+" &>/tmp/yab-log."+unique$+" &") + sleep 0.1 + while(teamID <> -1) + teamID = thread get "teamid", yabDir$+" "+param$+yabFile$ + + handle = open("/tmp/yab-log."+unique$,"r") + if(handle) then + seek handle,pos + while(not eof(handle)) + tmp$ = GetLine$(handle)+"\n" + listbox add "YabOutputList", left$(tmp$, len(tmp$)-1) + listbox select "YabOutputList", listbox count "YabOutputList" + pos = tell(handle) + wend + close(handle) + endif + + if(instr(message$, "BRunning")) then + t = thread remove "teamid", teamID + if(not t) alert "Error! Program could not be killed.", "Oops", "stop" + break + endif + sleep 0.1 + wend + + window close "Running" + + system("rm -f "+"/tmp/yab-log."+unique$+" >/dev/null") + + isRunning = false + return +end sub + +// Run the program in a terminal +sub RunInTerminal(yabFile$) + local tmp$, param$ + local num, i, t, pos + local x, y, err, w + + if(isRunning) return + isRunning = true + + x = peek("desktopwidth")/2 - 150 + y = peek("desktopheight")/2 - 100 + window open x,y to x+299,y+79, "Running", "" + window set "Running", "feel", "modal-app" + window set "Running", "look", "modal" + window set "Running", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + err = draw image 0,0, ideDir$+"img/Running.png", "Running" + + w = draw get "text-width", GetFileName$(yabFile$), "Running" + text 168-w/2,32, "TRunning", GetFileName$(yabFile$), "Running" + + w = draw get "text-width", MyTranslate$("Close terminal to break program"), "Running" + text 168-w/2,60, "TRunning2", "Close terminal to break program", "Running" + + draw set "Bitstream Vera Sans, Bold Oblique, 14", "Running" + w = draw get "text-width", MyTranslate$("Running Program"), "Running" + draw text 168-w/2,20, "Running Program", "Running" + + window set "Running", "deactivate" + sleep 0.1 + + param$ = settingsYabParam$ + " -enter" + tmp$ = system$("Terminal "+yabDir$+" "+param$+" "+yabFile$+" "+settingsProgParam$+" 2>&1") + window close "Running" + + listbox clear "YabOutputList" + dim result$(1) + num = split(tmp$, result$(), "\n") + for i = 1 to num + listbox add "YabOutputList", result$(i) + next i + + isRunning = false + return +end sub + +sub AboutWindow() + local x + local y + local width + local t + + x = peek("desktopwidth")/2 - 200 + y = peek("desktopheight")/2 - 200 + window open x-3000,y-3000 to x+400-3000, y+300-3000, "AboutWindow", "" + window set "AboutWindow", "look", "bordered" + window set "AboutWindow", "feel", "modal-app" + window set "AboutWindow", "MaximumTo", 400,300 + window set "AboutWindow", "MinimumTo", 400,300 + window set "AboutWindow", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + + draw set "bgcolor", 255,255,255, "AboutWindow" + draw set "lowcolor", 255,255,255, "AboutWindow" + + width = draw get "text-width", "(c) 2006-2015 in terms of the Artistic License", "AboutWindow" + draw text 198-width/2, 260, "(c) 2006-2015 in terms of the Artistic License", "AboutWindow" + width = draw get "text-width", "Coded by Jan, graphics by Genki, thanks to BeSly", "AboutWindow" + draw text 200-width/2, 240, "Coded by Jan, graphics by Genki, thanks to BeSly", "AboutWindow" + + if(peek$("os") = "Haiku") then + draw set "DejaVu Sans, Bold, 18", "AboutWindow" + else + draw set "Swis721 BT, Bold, 18", "AboutWindow" + endif + width = draw get "text-width", "yab-IDE", "AboutWindow" + draw text 200-width/2, 25, "yab-IDE", "AboutWindow" + if(peek$("os") = "Haiku") then + draw set "DejaVu Sans, Bold, 10", "AboutWindow" + else + draw set "Swis721 BT, Bold, 10", "AboutWindow" + endif + width = draw get "text-width", "Version "+versionnumber$, "AboutWindow" + draw text 200-width/2, 40, "Version "+versionnumber$, "AboutWindow" + + t = draw image 100,50 to 300,-1, ideDir$+"img/yablogo.png", "AboutWindow" + + button 100,265 to 300,290, "AboutButton", "Close", "AboutWindow" + option set "AboutButton", "focus", true + + window set "AboutWindow", "moveto", x,y + + while(not instr(message$, "AboutButton")) + wend + + + window close "AboutWindow" + return +end sub + +sub SaveAsTemplate() + local x: local y + local w: local i: local n + local isButton + local handle: local handle2 + local inloop + local msg$(1) + local name$: local description1$: local description2$: local image$ + local t$ + + x = (peek("desktopwidth")-600)/2 + y = (peek("desktopheight")-200)/2-50 + if(y<50) y=50 + + window open x-3000,y-3000 to x+600-3000,y+200-3000, "SaveTempWindow", "yab-IDE Save as Template" + window set "SaveTempWindow", "Feel", "Modal-App" + window set "SaveTempWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Save as Template", "SaveTempWindow", 600) + + text 10,50, "SaveTempText1", "Save your code as a template for other programs:", "SaveTempWindow" + textcontrol 10,70 to 380,90, "SaveTempName", "Template Name", "", "SaveTempWindow" + text 10,98, "SaveTempText2", "Description (not more than 30 characters per line)", "SaveTempWindow" + textcontrol 5,110 to 380,120, "SaveTempDes1", "", "", "SaveTempWindow" + textcontrol 5,130 to 380,150, "SaveTempDes2", "", "", "SaveTempWindow" + + draw set "highcolor", 0,0,0, "SaveTempWindow" + draw set "lowcolor", 255,255,0, "SaveTempWindow" + draw set 0, "240225195135015030060120" + draw rect 390,50 to 590,150, "SaveTempWindow" + draw set 0, "lowsolidfill" + draw set "lowcolor", 216,216,216, "SaveTempWindow" + draw rect 400,60 to 580,140, "SaveTempWindow" + draw set 0, "highsolidfill" + + w = draw get "Text-width", MyTranslate$("Drop image here"), "SaveTempWindow" + draw text 490-w/2,105, "Drop image here", "SaveTempWindow" + view dropzone "SaveTempWindow" + + draw set "highcolor", 185,185,185, "SaveTempWindow" + draw line 0,162 to 600,162, "SaveTempWindow" + draw set "highcolor", 239,239,239, "SaveTempWindow" + draw line 0,163 to 600,163, "SaveTempWindow" + + button 530,170 to 590,190, "SaveTempOk", "Save", "SaveTempWindow" + option set "SaveTempOk", "enabled", false + isButton = false + + option set "SaveTempName", "focus", true + + window set "SaveTempWindow", "moveto", x,y + + inloop = true + while(inloop) + n = split(message$, msg$(), ":|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + // check for emergency exit + if(i > 1) then + if(msg$(i) = "_QuitRequested" and msg$(i-1) <> "SaveTempWindow") then + exit(1) + endif + else + if(msg$(i) = "_QuitRequested") then + exit(1) + endif + endif + switch(msg$(i)) + case "_Dropped" + if(arraysize(msg$(),1)>=i+1) then + w = draw image 390,50 to 590,150, msg$(i+1), "SaveTempWindow" + if(w<>0) then + alert "Could not load image!", "Ok", "warning" + else + image$ = msg$(i+1) + endif + endif + break + case "SaveTempOk" + name$ = left$(textcontrol get$ "SaveTempName", 50) + description1$ = left$(textcontrol get$ "SaveTempDes1", 30) + description2$ = left$(textcontrol get$ "SaveTempDes2", 30) + imageShort$ = GetFileName$(image$) + system("cp "+image$+" "+ideDir$+"Templates/img/"+imageShort$) + handle = open(ideDir$+"Templates/TemplateList", "a") + if(handle) then + print #handle "#" + print #handle name$ + print #handle "Templates/img/"+imageShort$ + print #handle description1$ + print #handle description2$ + close(handle) + handle2 = open(ideDir$+"Templates/"+name$, "w") + if(handle2) then + t$ = textedit get$ "Text"+str$(globalCurrentText) + print #handle t$; + close(handle2) + else + alert "Error while saving template!", "Ok", "warning" + endif + else + alert "Error while saving template!", "Ok", "warning" + endif + inloop = false + break + case "_QuitRequested" + inloop = false + break + end switch + next i + + name$ = textcontrol get$ "SaveTempName" + if(name$<>"" and not isButton) then + option set "SaveTempOk", "enabled", true + isButton = true + endif + if(name$="" and isButton) then + option set "SaveTempOk", "enabled", false + isButton = false + endif + wend + + window close "SaveTempWindow" + return +end sub + +sub SaveCurrentFile() +local savetext$ + handle = open(globalAllNames$(globalCurrentText), "w") + if(handle) then + savetext$=textedit get$ "Text"+str$(globalCurrentText) + if right$(savetext$,1)<>chr$(10) savetext$=savetext$+chr$(10) + print #handle savetext$; + close(handle) + tmpCurrentLine = textedit get "Text"+str$(globalCurrentText), "currentline" + print "ATTR SET "; + print str$(tmpCurrentLine) + attribute set "Int", "linenumber", str$(tmpCurrentLine), globalAllNames$(globalCurrentText) + textedit set "Text"+str$(globalCurrentText), "changed", false + globalWasChanged = false + columnbox add "FileBox", 1, globalTextFinder(globalCurrentText), 20, "__Icon__="+ideDir$+"img/gespeichert.png" + else + alert "File could not be saved!", "Ok", "warning" + return false + endif + return true +end sub + +sub Header(headerText$, window$, size) + local w + local head$ + + head$ = window$+"Header" + layout "none", window$ + view 0,0 to size,40, head$, window$ + draw set "bgcolor", 230,230,255, head$ + draw set "lowcolor", 230,230,255, head$ + if(peek$("os") = "Haiku") then + draw set "DejaVu Sans, Condensed Bold, 18", head$ + else + draw set "Swis721 BT, Bold, 18", head$ + endif + draw set "highcolor", 0,0,0, head$ + w = draw get "Text-width", MyTranslate$(headerText$), head$ + draw text size-w-10,25, headerText$, head$ + draw set "highcolor", 239,239,239, head$ + draw line 0,40 to size,40, head$ + draw set "highcolor", 185,185,185, head$ + draw line 0,39 to size,39, head$ + return +end sub + +// open the build factory window +sub Building() + local x, y, inloop, isEmpty + local binName$, t$, myTab$, result$ + local msg$(1) + local i, n, tmp + + + x = (peek("desktopwidth")-500)/2 + y = (peek("desktopheight")-400)/2-50 + if(y<50) y=50 + + window open x-3000,y-3000 to x+500-3000,y+400-3000, "BuildWindow", "yab-IDE Build Factory" + window set "BuildWindow", "Feel", "Modal-App" + window set "BuildWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Build Factory", "BuildWindow", 500) + + if(right$(globalAllNames$(globalCurrentText),4) = ".yab") then + binName$ = left$(globalAllNames$(globalCurrentText), len(globalAllNames$(globalCurrentText))-4) + else + binName$= globalAllNames$(globalCurrentText)+".bin" + endif + + while (instr(binName$, "/")) + pos=instr(binName$, "/") + binName$=right$(binName$,len(binName$)-pos) + wend + + + isEmpty = false + + textcontrol 10,50 to 380,70, "BuildPath", "Target file name:", binName$, "BuildWindow" + AppSig$="application/x-vnd.yab-app" + textcontrol 10,80 to 380,100, "AppSig", "Application Signature:", AppSig$, "BuildWindow" + //button 390,50 to 490,70, "BuildBrowse", "Browse", "BuildWindow" + + button 390,100 to 490,130, "BuildBuild", "Create Binary", "BuildWindow" + + MyLine(0,140,500,140, "BuildWindow") + textedit 10,155 to 490,390, "BuildOutput", 3, "BuildWindow" + textedit set "BuildOutput", "editable", false + textedit set "BuildOutput", "wordwrap", false + textedit set "BuildOutput", "textwidth", 4000 + + window set "BuildWindow", "moveto", x, y + + if(left$(system$("gcc 2>&1"),4) <> "gcc:") then + alert "The compiler GCC was not found!\n\nPlease install a complete Haiku system.", "Ok", "stop" + window close "BuildWindow" + return + endif + + textedit add "BuildOutput", MyTranslate$("Build Factory Output\n\n") + + inloop = true + while(inloop) + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + switch(msg$(i)) + case "BuildBuild" + option set "BuildBuild", "enabled", false + option set "BuildPath", "enabled", false + //option set "BuildBrowse", "enabled", false + option set "AppSig", "enabled", false + AppSig$=textcontrol get$ "AppSig" + if AppSig$="" AppSig$="application/x-vnd.yab-app" + binName$=textcontrol get$ "BuildPath" + textedit add "BuildOutput", MyTranslate$("Please wait, processing... (this may take a long time!)\n\n") + print "cd "+buildDir$+"; "+yabDir$+" BuildFactory.yab "+binName$+" "+globalAllNames$(globalCurrentText)+" "+AppSig$+" 2>&1\n\n" + result$ = system$("cd "+buildDir$+"; yab BuildFactory.yab "+binName$+" "+globalAllNames$(globalCurrentText)+" "+AppSig$+" yab-ide 2>&1") + textedit add "BuildOutput", result$ + + + option set "BuildBuild", "enabled", true + option set "BuildPath", "enabled", true + //option set "BuildBrowse", "enabled", true + option set "AppSig", "enabled", true + + if(IfExists(buildDir$+"/"+binName$)) then + alert "Build was successful", "Ok", "info" + else + alert "Build failed!", "Ok", "warning" + endif + system("rm "+ buildDir$+"/"+binName$) + break + //case "BuildBrowse" + // t$ = filepanel "save-file", "Save", GetDirectory$(binName$) + // if(t$<>"") then + // textcontrol set "BuildPath", t$ + // binName$ = t$ + // endif + // break + case "_QuitRequested" + case "BuildWindow:_QuitRequested" + inloop = false + break + end switch + next i + if(not isEmpty and textcontrol get$ "BuildPath" = "") then + AppSig$=textcontrol get$ "AppSig" + option set "BuildBuild", "enabled", false + isEmpty = true + endif + if(isEmpty and textcontrol get$ "BuildPath" <> "") then + AppSig$=textcontrol get$ "AppSig" + option set "BuildBuild", "enabled", true + isEmpty = false + endif + + + + wend + window close "BuildWindow" + return +end sub + +// open the option window +sub OptionWindow() + local x, y, inloop + local msg$(1), style$(1) + local styleNum, styleCount + local i, n, optCurrent + local tmp$ + local handle, j, hasItem + local family$, style$, size$ + local defaultFamily + + x = (peek("desktopwidth")-650)/2 + y = (peek("desktopheight")-400)/2-50 + if(y<50) y=50 + + window open x+100-3000,y+150-3000 to x+750-3000,y+550-3000, "OptWindow", "yab-IDE Options" + window set "OptWindow", "Feel", "Modal-App" + window set "OptWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Options", "OptWindow", 650) + + draw set "highcolor", 185,185,185, "OptWindow" + draw line 11,51 to 138,51, "OptWindow" + draw line 10,50 to 139,50, "OptWindow" + draw line 11,51 to 11,388, "OptWindow" + draw line 10,50 to 10,389, "OptWindow" + draw set "highcolor", 239,239,239, "OptWindow" + draw line 12,389 to 139,389, "OptWindow" + draw line 11,390 to 139,390, "OptWindow" + draw line 139,52 to 139,389, "OptWindow" + draw line 140,51 to 140,390, "OptWindow" + draw set "highcolor", 0,0,0, "OptWindow" + + treebox 12,52 to 138,388, "OptTree", 0, "OptWindow" + // treebox add "OptTree", "Interpreter" + // treebox add "OptTree", "Interpreter", "Libraries", true + // treebox add "OptTree", "Interpreter", "Execution", true + treebox add "OptTree", "Editor" + treebox add "OptTree", "Editor", "Auto completion", true + // treebox add "OptTree", "Editor", "Syntax Highlighting", true + treebox add "OptTree", "Editor", "General", true + treebox add "OptTree", "Environment" + if(not settingsRCSOff) treebox add "OptTree", "Environment", "Version Control", true + treebox add "OptTree", "Environment", "Language", true + treebox add "OptTree", "Environment", "Directories", true + treebox select "OptTree", 2 + + // button 430,370 to 530,390, "OptDefault", "Default", "OptWindow" + // button 540,370 to 640,390, "OptOk", "Close", "OptWindow" + + // MyLine(0,362,650,362,"OptWindow") + + optCurrent = 1 + stackview 150,50 to 640,390, "OptStack", 4, "OptWindow" + + // General + boxview 0,0 to 490, 340, "OptBox3", "General", 2, "OptStack1" + spincontrol 10,5, "OptGenSpin", "Number of spaces per tab:", 1,20,1, "OptBox3" + spincontrol set "OptGenSpin", settingsTabSpaces + MyLine(10,35,470,35, "OptBox3") + checkbox 10,45, "OptGenSaving", "Ask about saving before running a program", settingsAskForSaving, "OptBox3" + checkbox 10,65, "OptGenReformat", "Show warning when reformating sourcecode did not close all loops and conditions", settingsReformatAlert, "OptBox3" + checkbox 10,85, "OptGenReformatUndo", "Show warning before undo reformating", settingsReformatUndoAlert, "OptBox3" + checkbox 10,105, "OptGenReplaceAll", "Show warning before applying Replace All", settingsFindAlert, "OptBox3" + MyLine(10,135,470,135, "OptBox3") + + text 10,145, "OptGenTxt", "Select font for editor:", "OptBox3" + dropbox 12,165 to 240,185, "OptGenFontFamily", "Font Family", "OptBox3" + dropbox 250,165 to 370,185, "OptGenFontStyle", "Font Style", "OptBox3" + spincontrol 380,160, "OptGenFontSize", "Font Size", 8,50,1, "OptBox3" + + n = token(draw get$ "FontFamily", msg$(), "|") + for i = 1 to n + dropbox add "OptGenFontFamily", msg$(i) + if(msg$(i) = settingsFontFamily$) j = i + if(msg$(i) = "Courier10 BT") defaultFamily = i + next i + if(j>0) then + dropbox select "OptGenFontFamily", j + n = token(draw get$ settingsFontFamily$, msg$(), "|") + for i = 1 to n + dropbox add "OptGenFontStyle", msg$(i) + if(msg$(i) = settingsFontStyle$) j = i + next i + if(j>0) dropbox select "OptGenFontStyle", j + endif + spincontrol set "OptGenFontSize", settingsFontSize + + view 20,205 to 460,255, "OptGenSample", "OptBox3" + draw set "bgcolor", 255,255,255, "OptGenSample" + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "OptGenSample" + n = draw get "text-width", MyTranslate$("My hovercraft is full of eels."), "OptGenSample" + draw text (440-n)/2,(50-settingsFontSize)/2+settingsFontSize, "My hovercraft is full of eels.", "OptGenSample" + MyLine(10,290,470,290,"OptBox3") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox3" + + // Syntax Highlighing + // boxview 0,0 to 490, 340, "OptBox4", "Syntax Highlighting", 2, "OptStack2" + + // Auto completion + boxview 0,0 to 490, 340, "OptBox5", "Auto completion", 2, "OptStack2" + checkbox 10,10, "OptACCheck", "Enable auto completion", settingsAutoCompletion, "OptBox5" + spincontrol 10,30, "OptACNum", "Number of characters for starting completion:", 1,20,1, "OptBox5" + spincontrol set "OptACNum", settingsACNumChar + MyLine(10,60,470,60,"OptBox5") + listbox 10,75 to 180,275, "OptACList", 1, "OptBox5" + textcontrol 190,185 to 470,205, "OptACTC", "New Entry:", "", "OptBox5" + button 320,215 to 470,235, "OptACAdd", "Add New Entry", "OptBox5" + MyLine(190,245,470,245,"OptBox5") + MyLine(190,175,470,175,"OptBox5") + button 370,255 to 470,275, "OptACRemove", "Remove Entry", "OptBox5" + text 190,75, "OptACText1", "Note: You have to restart the IDE to update the", "OptBox5" + text 190,90, "OptACText2", "autocompletion when removing entries.", "OptBox5" + handle = open(ideDir$+"data/autocompletion", "r") + if(handle) then + while(not eof(handle)) + tmp$ = GetLine$(handle)+"\n" + listbox add "OptACList", left$(tmp$, len(tmp$)-1) + wend + close(handle) + endif + MyLine(10,290,470,290,"OptBox5") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox5" + + // Dirs + boxview 0,0 to 490, 340, "OptBox6", "Directories", 2, "OptStack3" + text 10,10, "OptDirTxt", "Note: Only change the directories, when you know what you are doing!", "OptBox6" + MyLine(10,30,470,30, "OptBox6") + textcontrol 10,45 to 470,65, "OptDirBinDir", "Default yab Binary", yabDir$, "OptBox6" + // MyLine(10,45,470,45, "OptBox6") + // textcontrol 10,60 to 360,80, "OptDirProjDir", "Project Directory", globalProjectDir$, "OptBox6" + textcontrol 10,80 to 470,100, "OptDirYabDir", "Default yab Directory", settingsYabDir$, "OptBox6" + MyLine(10,115,470,115, "OptBox6") + MyLine(10,290,470,290,"OptBox6") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox6" + + // Language + boxview 0,0 to 490, 340, "OptBox8", "Language", 2, "OptStack4" + checkbox 10,10, "OptLangCheck", "Use automatic localization", restartSettingsLangUse, "OptBox8" + MyLine(10,40,470,40,"OptBox8") + columnbox 10,55 to 470,275, "OptLangList", false, "", "OptBox8" + columnbox column "OptLangList", "Supported Languages", 1, 460,460,460, "align-left" + MyLine(10,290,470,290,"OptBox8") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox8" + columnbox color "OptLangList", "Selection-Active", 220,220,250 + columnbox color "OptLangList", "Row-Divider", 255,255,255 + tmp$ = system$("ls /boot/common/data/locale/catalogs/"+settingsLangPath$+"/*.catalog") + n = token(tmp$, msg$(), "\n") + for i = 1 to n + columnbox add "OptLangList", 1,i,18,msg$(i) + next i + + window set "OptWindow", "moveto", x,y + + inloop = true + while(inloop) + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + switch(msg$(i)) + case "_QuitRequested" + // emergency quit + exit(1) + break + case "OptOk" + case "OptWindow:_QuitRequested" + inloop = false + break + + // General + case "OptGenSaving:ON" + case "OptGenSaving:OFF" + settingsAskForSaving = not settingsAskForSaving + break + case "OptGenReformat:ON" + case "OptGenReformat:OFF" + settingsReformatAlert = not settingsReformatAlert + break + case "OptGenReformatUndo:ON" + case "OptGenReformatUndo:OFF" + settingsReformatUndoAlert = not settingsReformatUndoAlert + break + case "OptGenReplaceAll:ON" + case "OptGenReplaceAll:OFF" + settingsFindAlert = not settingsFindAlert + break + + // Autocompletion + case "OptACCheck" + settingsAutoCompletion = not settingsAutoCompletion + break + case "OptACRemove" + break + case "OptACAdd" + tmp$ = textcontrol get$ "OptACTC" + if(tmp$<>"") then + hasItem = false + for j=1 to listbox count "OptACList" + if(tmp$ = listbox get$ "OptACList", i) then + hasItem = true + break + endif + next j + if(not hasItem) then + listbox add "OptACList", tmp$ + listbox sort "OptACList" + else + alert "Entry already exists.", "Ok", "info" + endif + endif + break + + // Language + case "OptLangCheck:ON" + case "OptLangCheck:OFF" + restartSettingsLangUse = not restartSettingsLangUse + alert "Restart yab-IDE to change localization", "Ok", "info" + break + + // Default + case "OptDefault" + t = stackview get "OptStack" + switch(t) + case 1 + settingsAskForSaving = true + settingsReformatAlert = true + settingsReformatUndoAlert = true + settingsFindAlert = true + settingsTabSpaces = 4 + settingsFontStyle$ = "Roman" + settingsFontSize = 12 + spincontrol set "OptGenSpin", settingsTabSpaces + checkbox set "OptGenSaving", settingsAskForSaving + checkbox set "OptGenReformat", settingsReformatAlert + checkbox set "OptGenReformatUndo", settingsReformatUndoAlert + checkbox set "OptGenReplaceAll", settingsFindAlert + dropbox select "OptGenFontFamily", defaultFamily + if(settingsFontFamily$<> "Courier10 BT") then + settingsFontFamily$ = "Courier10 BT" + dropbox clear "OptGenFontStyle" + styleCount = token(draw get$ settingsFontFamily$, style$(), "|") + for styleNum = 1 to styleCount + dropbox add "OptGenFontStyle", style$(styleNum) + next styleNum + dropbox select "OptGenFontStyle", 1 + OptionUpdateSample() + endif + spincontrol set "OptGenFontSize", settingsFontSize + for j = 1 to MAXFILES + textedit set "Text"+str$(j), "TabWidth", settingsTabSpaces*7 + next j + break + case 2 + settingsAutoCompletion = true + settingsACNumChar = 2 + checkbox set "OptACCheck", settingsAutoCompletion + spincontrol set "OptACNum", settingsACNumChar + break + case 3 + if(system("test -d /boot/apps/Development/yab-1.0/") = 0) then + settingsYabDir$ = "/boot/apps/Development/yab-1.0/" + elsif(system("test -d /boot/apps/yab-1.0/") = 0) then + settingsYabDir$ = "/boot/apps/yab-1.0/" + else + alert "Could not find yab 1.0 directory!\n\nPlease do a proper installation.", "Ok", "warning" + endif + textcontrol set "OptDirYabDir", settingsYabDir$ + + if(system("test -e /boot/home/config/bin/yab") = 0) then + yabDir$ = "/boot/home/config/bin/yab" + else + alert "Could not find yab binary!\n\nPlease do a proper installation.", "Ok", "warning" + endif + textcontrol set "OptDirBinDir", yabDir$ + break + case 4 + if(restartSettingsLangUse = false) then + restartSettingsLangUse = true + checkbox set "OptLangCheck",restartSettingsLangUse + alert "Restart yab-IDE to change localization", "Ok", "info" + endif + break + end switch + break + end switch + + // Font stuff + if(left$(msg$(i), 17) = "OptGenFontFamily:") then + settingsFontFamily$ = right$(msg$(i), len(msg$(i))-17) + dropbox clear "OptGenFontStyle" + styleCount = token(draw get$ settingsFontFamily$, style$(), "|") + for styleNum = 1 to styleCount + dropbox add "OptGenFontStyle", style$(styleNum) + next styleNum + dropbox select "OptGenFontStyle", 1 + settingsFontStyle$ = style$(1) + OptionUpdateSample() + endif + if(left$(msg$(i), 16) = "OptGenFontStyle:") then + settingsFontStyle$ = right$(msg$(i), len(msg$(i))-16) + OptionUpdateSample() + endif + + if(left$(msg$(i), 8) = "OptACTC:") then + option set "OptACAdd", "focus", true + endif + if(left$(msg$(i), 16) = "OptTree:_Select:") then + t = val(right$(msg$(i), len(msg$(i))-16)) + tmp$ = treebox get$ "OptTree", t + switch(tmp$) + case MyTranslate$("General"): t = 1: break + // case MyTranslate$("Syntax Highlighting"): t = 2: break + case MyTranslate$("Auto completion"): t = 2: break + case MyTranslate$("Directories"): t = 3: break + case MyTranslate$("Language"): t = 4: break + // case MyTranslate$("Version Control"): t = 6: break + default: t = 0: break + end switch + if(t>0) then + stackview set "OptStack", t + optCurrent = t + endif + endif + + if(left$(msg$(i), 13) = "OptDirYabDir:") then + tmp$ = right$(msg$(i), len(msg$(i))-13) + if(system("test -d "+tmp$) = 0) then + settingsYabDir$ = tmp$ + alert MyTranslate$("New yab directory set to:\n\n")+tmp$+MyTranslate$("\n\nRestart the IDE using the new directory."), "Ok", "info" + else + alert MyTranslate$("Invalid directory:\n\n")+tmp$, "Ok", "warning" + textcontrol set "OptDirYabDir", settingsYabDir$ + endif + endif + if(left$(msg$(i), 13) = "OptDirBinDir:") then + tmp$ = right$(msg$(i), len(msg$(i))-13) + if(system("test -e "+tmp$) = 0) then + yabDir$ = tmp$ + alert MyTranslate$("yab binary set to:\n\n")+tmp$, "Ok", "info" + else + alert MyTranslate$("Invalid file:\n\n")+tmp$, "Ok", "warning" + textcontrol set "OptDirBinDir", yabDir$ + endif + endif + next i + if(spincontrol get "OptGenFontSize" <> settingsFontSize) then + settingsFontSize = spincontrol get "OptGenFontSize" + OptionUpdateSample() + endif + if(spincontrol get "OptGenSpin" <> settingsTabSpaces) then + settingsTabSpaces = spincontrol get "OptGenSpin" + for j = 1 to MAXFILES + textedit set "Text"+str$(j), "TabWidth", settingsTabSpaces*7 + next j + endif + wend + + window close "OptWindow" + + return +end sub + +// draw the example text (OptionWindow) +sub OptionUpdateSample() + local n + local scroll, scrollLine, scrollPos + + draw flush "OptGenSample" + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "OptGenSample" + n = draw get "text-width", MyTranslate$("My hovercraft is full of eels."), "OptGenSample" + draw text (440-n)/2,50-(50-settingsFontSize)/2, "My hovercraft is full of eels.", "OptGenSample" + for n = 1 to MAXFILES + textedit set "Text"+str$(n), "font", settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize) + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "Lines"+str$(n) + next n + if(globalCurrentText>0) then + globalRealFontSize = textedit get "Text"+str$(globalCurrentText), "line-height", 1 + scroll = textedit get "Text"+str$(globalCurrentText), "vertical-scrollbar" + scrollLine = int(scroll/globalRealFontSize) + scrollPos = mod(scroll,globalRealFontSize) + UpdateLines(scrollPos, 1200, scrollLine, globalRealFontSize) + endif + return +end sub + +// draw a sort of 3D line +sub MyLine(x1,y1,x2,y2,View$) + draw set "highcolor", 185,185,185, View$ + draw line x1,y1 to x2,y2, View$ + draw set "highcolor", 239,239,239, View$ + if(x1=x2) then + draw line x1+1,y1 to x2+1,y2, View$ + else + draw line x1,y1+1 to x2,y2+1, View$ + endif + draw set "highcolor", 0,0,0, View$ + return +end sub + +// only translates when a translation is wanted +sub MyTranslate$(txt$) + if(settingsLangUse) return menu translate$(txt$) + return txt$ +end sub + +// returns true if filename$ exists +sub IfExists(filename$) + return not system("test -e "+filename$) +end sub + +// Create a new toolbar. +// +// x1,y1 is the upper left starting point +// x2 is the right border of the toolbar +// note: the toolbar is always 30 pixels in height! +// id$ is the toolbar ID +// dir$ is the directory, where the icons can be found +// view$ is the view on which the Toolbar is created +// +// Note: this will change the layout of your view view$. +sub ToolbarCreate(x1,y1,x2, id$, dir$, view$) + layout "left, right", view$ + view x1,y1 to x2,y1+32, id$, view$ + // layout "left,right", id$ + draw set "bgcolor", 222,219,222, id$ + // view 0,30 to x2,32, id$+"line", id$ + // draw set "bgcolor", 185,185,185, id$+"line" + layout "none", id$ + position = 10 + directory$ = dir$ + toolbarview$ = id$ + return +end sub + +// Add an icon to the toolbar. +sub ToolbarAddIcon(id$, tooltip$, pressed$, normal$, disabled$) + button image position,7, id$, directory$+pressed$, directory$+normal$, directory$+disabled$, toolbarview$ + tooltip id$, tooltip$ + position = position + 25 + return +end sub + +// Add a separator to the toolbar. +sub ToolbarAddSeparator() + draw set "highcolor", 185,185,185, toolbarview$ + draw line position-2,5 to position-2,25,toolbarview$ + draw set "highcolor", 239,239,239, toolbarview$ + draw line position-1,5 to position-1,25, toolbarview$ + position = position + 5 + return +end sub + +// Open the pattern calculation window +sub OpenCalcPattern(x,y) + local i, j, w + local msg$(1) + local inloop, n + + window open x,y to x+259,y+400, "CalcPattern", "yab-IDE Pattern editor" + window set "CalcPattern", "Feel", "Modal-App" + window set "CalcPattern", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Pattern editor", "CalcPattern", 260) + + draw set "highcolor", 239,239,239, "CalcPattern" + draw line 0,300 to 259,300, "CalcPattern" + draw set "highcolor", 185,185,185, "CalcPattern" + draw line 0,299 to 259,299, "CalcPattern" + + view 10,50 to 249,289, "VDraw", "CalcPattern" + draw set "bgcolor", 255, 255, 255, "VDraw" + draw set "lowcolor", 0, 0, 0, "VDraw" + + view 10,310 to 90,390, "VPattern", "CalcPattern" + draw set "bgcolor", 255, 255, 255, "VPattern" + draw set "lowcolor", 0, 0, 0, "VPattern" + draw set "highcolor", 255, 255, 255, "VPattern" + + button 100,370 to 249,390, "CalcPatternInsert", "Insert Pattern", "CalcPattern" + + UpdatePattern(pattern()) + draw set 0, "LowSolidFill" + draw set "lowcolor", 0, 0, 0, "VDraw" + for i = 0 to 7 + for j = 0 to 7 + if(pattern(i,j) = 1) then + draw rect i*30,j*30 to i*30+29,j*30+29, "VDraw" + endif + next j + next i + draw set 0, "HighSolidFill" + + inloop = true + while(inloop) + CalcPatternMouse(pattern()) + n = token(message$, msg$(), "|") + for i = 1 to n + switch(msg$(i)) + case "CalcPatternInsert" + textedit add "Text"+str$(globalCurrentText), CalcPatternInsert$(pattern()) + break + case "CalcPattern:_QuitRequested" + settingsCalcPatternX = window get "CalcPattern", "Position-X" + settingsCalcPatternY = window get "CalcPattern", "Position-Y" + window close "CalcPattern" + inloop = false + break + case "_QuitRequested" + //emergency break + exit(1) + break + end switch + next i + wend + return +end sub + +// mouse stuff (PatternEditor) +sub CalcPatternMouse(pattern()) + local help$ + local i, j, refresh + + mousex = 0 + mousey = 0 + mouselmb = 0 + mousemmb = 0 + mousermb = 0 + + + refresh = 0 + + if(ismousein("VDraw")) then + GetMouseData("VDraw",239,239) + endif + + if(mouselmb) then + x = int(mousex/30) + y = int(mousey/30) + if(pattern(x,y) = 0) then + pattern(x,y) = 1 + draw set "lowcolor", 0, 0, 0, "VDraw" + draw set 0, "LowSolidFill" + draw rect x*30,y*30 to x*30+29,y*30+29, "VDraw" + UpdatePattern(pattern()) + refresh = refresh + 1 + endif + endif + + if(mousermb) then + x = int(mousex/30) + y = int(mousey/30) + if(pattern(x,y) = 1) then + pattern(x,y) = 0 + draw set "lowcolor", 255, 255, 255, "VDraw" + draw set 0, "LowSolidFill" + draw rect x*30,y*30 to x*30+29,y*30+29, "VDraw" + draw set "lowcolor", 0, 0, 0, "VDraw" + UpdatePattern(pattern()) + refresh = refresh + 1 + endif + endif + + if(refresh = 15) then + draw flush "VDraw" + draw flush "VPattern" + draw set "lowcolor", 0, 0, 0, "VDraw" + for i = 0 to 7 + for j = 0 to 7 + if(pattern(i,j)) then + draw set 0, "LowSolidFill" + draw rect i*30,j*30 to i*30+29,j*30+29, "VDraw" + draw set 0, "HighSolidFill" + endif + next j + next i + UpdatePattern(pattern()) + refresh = 0 + endif + + return +end sub + +// get pattern string (PatternEditor) +sub CalcPatternInsert$(pattern()) + local i, j + local t$, p$ + + p$ = "\"" + for i = 0 to 7 + t$ = "" + for j = 0 to 7 + t$ = t$ + str$(1-pattern(j,i)) + next j + t = dec(t$,2) + if(t<100) p$ = p$ + "0" + if(t<10) p$ = p$ + "0" + p$ = p$ + str$(t) + next i + p$ = p$ + "\"" + return p$ +end sub + +// get mouse stuff (PatternEditor) +sub GetMouseData(view$,maxx, maxy) + local n + local mouse$(1) + + mousemsg$ = mouse message$(view$) + n = split(mousemsg$, mouse$(), ":") + mousex = val(mouse$(1)) + mousey = val(mouse$(2)) + mouselmb = val(mouse$(3)) + mousemmb = val(mouse$(4)) + mousermb = val(mouse$(5)) + if(mousex<0) mousex = 0 + if(mousey<0) mousey = 0 + if(mousex>maxx) mousex = maxx + if(mousey>maxy) mousey = maxy + + return +end sub + +// update pattern (PatternEditor) +sub UpdatePattern(pattern()) + local i, j + local t$, p$ + + for i = 0 to 7 + t$ = "" + for j = 0 to 7 + t$ = t$ + str$(1-pattern(j,i)) + next j + t = dec(t$,2) + if(t<100) p$ = p$ + "0" + if(t<10) p$ = p$ + "0" + p$ = p$ + str$(t) + next i + draw flush "VPattern" + draw set 0, p$ + draw rect 0,0 to 80,80, "VPattern" + draw set 0, "HighSolidFill" + return +end sub + +// Open the color selection window +sub OpenColorSelection(x,y,r,g,b) + local i, j, w, n, num + local tmp$, msg$(1), col$(1) + local inloop + + window open x,y to x+366,y+270, "ColorSelect", "yab-IDE Color selection" + window set "ColorSelect", "Feel", "Modal-App" + window set "ColorSelect", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Color selection", "ColorSelect", 366) + + draw set "highcolor", 239,239,239, "ColorSelect" + draw line 0,233 to 366,233, "ColorSelect" + draw line 71,55 to 71,116, "ColorSelect" + draw line 10,116 to 71,116, "ColorSelect" + draw set "highcolor", 185,185,185, "ColorSelect" + draw line 0,232 to 366,232, "ColorSelect" + draw line 9,54 to 9,115, "ColorSelect" + draw line 9,54 to 70,54, "ColorSelect" + + view 10,55 to 70,115, "ColorSelectRect", "ColorSelect" + draw set "highcolor", r,g,b, "ColorSelectRect" + draw rect 0,0 to 60,60, "ColorSelectRect" + colorcontrol 80,59, "ColorControl", "ColorSelect" + colorcontrol set "ColorControl", r,g,b + + draw set "highcolor", 0,0,0, "ColorSelect" + draw text 10,140, "Default Colors:", "ColorSelect" + draw set 1, "HighSolidFill" + for i = 45 to 305 step 30 + for j=155 to 186 step 30 + draw set 1, "HighSolidFill" + draw rect i,j to i+30,j+30, "ColorSelect" + draw set 0, "HighSolidFill" + tmp$ = str$((j-125)/30)+str$((i-15)/30) + view i+1,j+1 to i+29,j+29, "Color"+tmp$, "ColorSelect" + switch tmp$ + case "11" + draw set "bgcolor", 0,0,0, "Color11" + tooltip "Color11", "Black" + break + case "12" + draw set "bgcolor", 96,96,96, "Color12" + tooltip "Color12", "Darken 4" + break + case "13" + draw set "bgcolor", 128,128,128, "Color13" + tooltip "Color13", "Darken 3" + break + case "14" + draw set "bgcolor", 152,152,152, "Color14" + tooltip "Color14", "Darken 2" + break + case "15" + draw set "bgcolor", 184,184,184, "Color15" + tooltip "Color15", "Darken 1" + break + case "16" + draw set "bgcolor", 216,216,216, "Color16" + tooltip "Color16", "Default Background" + break + case "17" + draw set "bgcolor", 232,232,232, "Color17" + tooltip "Color17", "Lighten 1" + break + case "18" + draw set "bgcolor", 240,240,240, "Color18" + tooltip "Color18", "Lighten 2" + break + case "19" + draw set "bgcolor", 255,255,255, "Color19" + tooltip "Color19", "White" + break + case "21" + draw set "bgcolor", 255,0,0, "Color21" + tooltip "Color21", "Red" + break + case "22" + draw set "bgcolor", 192,128,0, "Color22" + tooltip "Color22", "Brown" + break + case "23" + draw set "bgcolor", 255,255,0, "Color23" + tooltip "Color23", "Yellow" + break + case "24" + draw set "bgcolor", 0,255,0, "Color24" + tooltip "Color24", "Green" + break + case "25" + draw set "bgcolor", 0,255,255, "Color25" + tooltip "Color25", "Cyan" + break + case "26" + draw set "bgcolor", 128,192,255, "Color26" + tooltip "Color26", "Light Blue" + break + case "27" + draw set "bgcolor", 0,0,255, "Color27" + tooltip "Color27", "Blue" + break + case "28" + draw set "bgcolor", 255,0,255, "Color28" + tooltip "Color28", "Magenta" + break + case "29" + draw set "bgcolor", 192,128,255, "Color29" + tooltip "Color29", "Light Magenta" + break + end switch + next j + next i + + draw set 0, "HighSolidFill" + + button 256,240 to 356,260, "ColorSelectInsert", "Insert Color", "ColorSelect" + + inloop = true + while(inloop) + ColorSelectMouse() + n = token(message$, msg$(), "|") + for i = 1 to n + if(left$(msg$(i),13) = "ColorControl:") then + tmp$ = right$(msg$(i), len(msg$(i))-13) + dim col$(3) + num = token(tmp$, col$(), ":") + if(num = 3) then + draw flush "ColorSelectRect" + draw set "highcolor", val(col$(1)), val(col$(2)), val(col$(3)), "ColorSelectRect" + draw rect 0,0 to 60,60, "ColorSelectRect" + endif + endif + switch(msg$(i)) + case "ColorSelectInsert" + textedit add "Text"+str$(globalCurrentText), ColorSelectInsert$() + break + case "ColorSelect:_QuitRequested" + settingsColorSelectX = window get "ColorSelect", "Position-X" + settingsColorSelectY = window get "ColorSelect", "Position-Y" + settingsColorSelectR = colorcontrol get "ColorControl", "red" + settingsColorSelectG = colorcontrol get "ColorControl", "green" + settingsColorSelectB = colorcontrol get "ColorControl", "blue" + window close "ColorSelect" + inloop = false + break + case "_QuitRequested" + //emergency break + exit(1) + break + end switch + next i + wend + return +end sub + +// get the color string (ColorSelect) +sub ColorSelectInsert$() + local r, g, b + + r = colorcontrol get "ColorControl", "red" + g = colorcontrol get "ColorControl", "green" + b = colorcontrol get "ColorControl", "blue" + + return " "+str$(r)+", "+str$(g)+", "+str$(b) +end sub + +// check mouse in ColorSelect +sub ColorSelectMouse() + local i, j + local tmp$ + + for i = 1 to 9 + for j = 1 to 2 + tmp$ = "Color"+str$(j)+str$(i) + if(ismousein(tmp$) and IsButtonPressed(tmp$)) then + switch tmp$ + case "Color11" + SetColor(0,0,0) + break + case "Color12" + SetColor(96,96,96) + break + case "Color13" + SetColor(128,128,128) + break + case "Color14" + SetColor(152,152,152) + break + case "Color15" + SetColor(184,184,184) + break + case "Color16" + SetColor(216,216,216) + break + case "Color17" + SetColor(232,232,232) + break + case "Color18" + SetColor(240,240,240) + break + case "Color19" + SetColor(255,255,255) + break + case "Color21" + SetColor(255,0,0) + break + case "Color22" + SetColor(192,128,0) + break + case "Color23" + SetColor(255,255,0) + break + case "Color24" + SetColor(0,255,0) + break + case "Color25" + SetColor(0,255,255) + break + case "Color26" + SetColor(128,192,255) + break + case "Color27" + SetColor(0,0,255) + break + case "Color28" + SetColor(255,0,255) + break + case "Color29" + SetColor(192,128,255) + break + end switch + endif + next j + next i +end sub + +// check for pressed mouse button (ColorSelect) +sub IsButtonPressed(view$) + local n, t + local mouselmb + + t = false + dim mouse$(1) + repeat + mousemsg$ = mouse message$(view$) + n = split(mousemsg$, mouse$(), ":") + mouselmb = val(mouse$(3)) + if(mouselmb) t = true + if(not ismousein(view$)) then + t = false + mouselmb = 0 + endif + until (mouselmb = 0) + return t +end sub + +// set a color to RGB (ColorSelect) +sub SetColor(r,g,b) + colorcontrol set "ColorControl", r,g,b + draw flush "ColorSelectRect" + draw set "highcolor", r,g,b, "ColorSelectRect" + draw rect 0,0 to 60,60, "ColorSelectRect" + return +end sub + +// beautify the code by reformating it +sub ReformatSource$(code$) + local tablevel, num, i, j, k + local tmp$, returnSource$ + local hasThen, isInTicks, firstcase + + dim beginCommand$(12) + dim endCommand$(15) + + beginCommand$(1) = "if" + beginCommand$(2) = "switch" + beginCommand$(3) = "for" + beginCommand$(4) = "while" + beginCommand$(5) = "do" + beginCommand$(6) = "repeat" + beginCommand$(7) = "case" + beginCommand$(8) = "default" + beginCommand$(9) = "else" + beginCommand$(10) = "elsif" + beginCommand$(11) = "sub" + beginCommand$(12) = "export" + + endCommand$(1) = "end if" + endCommand$(2) = "end-if" + endCommand$(3) = "endif" + endCommand$(4) = "fi" + endCommand$(5) = "end switch" + endCommand$(6) = "end-switch" + endCommand$(7) = "next" + endCommand$(8) = "wend" + endCommand$(9) = "loop" + endCommand$(10) = "until" + endCommand$(11) = "else" + endCommand$(12) = "elsif" + endCommand$(13) = "end sub" + endCommand$(14) = "case" + endCommand$(15) = "default" + + dim reformat$(1) + tablevel = 0 + firstcase = 0 + num = split(code$, reformat$(), "\n") + + for i=1 to num + tmp$ = ltrim$(lower$(reformat$(i))) + for j=1 to 15 + if(left$(tmp$, len(endCommand$(j))) = endCommand$(j) and (len(tmp$) = len(endCommand$(j)) or instr(" \n\t\f\v\r(:/", mid$(tmp$,len(endCommand$(j))+1,1)))) then + if(not firstcase) then + if(j = 5 or j = 6) tablevel = tablevel - 1 + tablevel = tablevel - 1 + // if(tablevel<0) tablevel = 0 + endif + firstcase = 0 + break + endif + next j + + for j=1 to tablevel + returnSource$ = returnSource$ + "\t" + next j + + for j=1 to 12 + if(left$(tmp$, len(beginCommand$(j))) = beginCommand$(j) and (len(tmp$) = len(beginCommand$(j)) or instr(" \n\t\f\v\r(:/", mid$(tmp$,len(beginCommand$(j))+1,1)))) then + hasThen = true + if(beginCommand$(j) = "switch") then + firstcase = 1 + elsif(beginCommand$(j) = "if") then + isInTicks = false + hasThen = false + for k=1 to len(tmp$)-3 + if(mid$(tmp$,k,1)="\"" and mid$(tmp$,k-1,1)<>"\\") isInTicks = not isInTicks + if(not isInTicks and mid$(tmp$,k,4) = "then") then + hasThen = true + break + endif + next k + endif + if(hasThen) tablevel = tablevel + 1 + break + endif + next j + returnSource$ = returnSource$ + ltrim$(reformat$(i)) + if(i0 and left$(tmp$,10) <> "/bin/grep ") then + ret = val(mid$(tmp$, t+7+len(programName$), len(tmp$)-t-7-len(programName$))) + endif + + return ret +end sub + +// Send the kill signal to all members of the team of programName$ +// Returns true when successful and false otherwise +sub KillTeam(programName$) + local ps$(1) + local found + local i, n + + n = token(system$("ps "+programName$), ps$(), chr$(10)) + found = false + + while(i<=n) + if(instr(ps$(i), programName$)) then + found = true + i = i + 1 + while(val(ps$(i))>0 and i<=n) + system("kill "+str$(val(ps$(i)))) + i = i + 1 + wend + endif + i = i + 1 + wend + + return found +end sub + +// Load the syntax tree into the given tree box from the TreeFile$ file. +sub SyntaxLoadTree(TreeFile$, TreeBoxID$) + local info, level, handle, inloop + local tmp$ + + + // Clear the treebox first + treebox clear TreeBoxID$ + + // count the number of info texts + info = 0 + // three levels: toplevel, sublevel and info text level + level = 0 + // read data from file return the file handle + handle = open (TreeFile$, "r") + if(not handle) return 0 + + // read the file + inloop = true + while(not eof(handle) and inloop) + tmp$ = GetLine$(handle) + // if it is not a comment... + if(not (left$(tmp$,1) = "&")) then + switch level + case 0 // toplevel + treebox add TreeBoxID$, tmp$ + break + case 1 // sublevel + n = instr(tmp$, ":") + treebox add TreeBoxID$, left$(tmp$,n-1), right$(tmp$, len(tmp$)-n), 0 + break + end switch + else + if(instr(tmp$, "toplevel")) level = 0 + if(instr(tmp$, "sublevel")) level = 1 + if(instr(tmp$, "infotext")) inloop = false + endif + wend + close handle + return 1 +end sub + +// Read the info text for Command$ from TreeFile$ with the index file IndexFile$. +sub SyntaxGetInfoText$(TreeFile$, IndexFile$, Command$) + local handle, position, inloop + local infotext$ + + // first read the seek position + inloop = true + handle = open (IndexFile$, "r") + if(not handle) return "" + + while(not eof(handle) and inloop) + tmp$ = GetLine$(handle) + if(tmp$=Command$) then + if (not eof(handle)) then + tmp$ = GetLine$(handle) + position = val(tmp$) + endif + inloop = false + endif + wend + close handle + + // a seek position is found; return the info text. + handle = open (TreeFile$, "r") + if(not handle) return "" + seek handle, position, "begin" + tmp$ = GetLine$(handle) + inloop = true + while(not eof(handle) and inloop) + tmp$ = GetLine$(handle) + if(left$(tmp$,1) = "&") then + inloop = false + else + infotext$ = infotext$ + tmp$ + chr$(10) + endif + wend + close handle + + return infotext$ +end sub + +// Read a line from a file +sub GetLine$(handle) + local tmp$, retString$ + + while(tmp$<>chr$(10) and tmp$<>chr$(13) and not eof(handle)) + tmp$ = chr$(peek(handle)) + if(tmp$<>chr$(10) and tmp$<>chr$(13)) retString$ = retString$ + tmp$ + wend + + return retString$ +end sub + +// Open ASCII table window +sub AsciiWindow() + local n, x, y + + window open 200,100 to 600,515, "AsciiView", "yab-IDE ASCII table" + window set "AsciiView", "flags", "Not-Zoomable, not-h-resizable, not-v-resizable" + + Header("ASCII table", "AsciiView", 400) + + draw set "highcolor", 239,239,239, "AsciiView" + draw line 6,405 to 395,405, "AsciiView" + draw line 395,51 to 395,405, "AsciiView" + draw set "highcolor", 185,185,185, "AsciiView" + draw line 5,50 to 394,50, "AsciiView" + draw line 5,50 to 5,404, "AsciiView" + draw set "highcolor", 255,255,255, "AsciiView" + draw rect 6,51 to 394,404, "AsciiView" + draw set "highcolor", 0,0,0, "AsciiView" + + x = 10 + y = 65 + for n = 32 TO 126 + draw text x,y, str$(n)+chr$(32)+chr$(n), "AsciiView" + x = x+50 + if x >= 365 then + x = 10 + y = y+30 + end if + next n + + while(not instr(message$, "Quit")) + wend + window close "AsciiView" + return +end sub + +// set the run parameters +sub SetRunParameters() + local tmp$ + local inloop + + window open 200,100 to 500,215, "RunParam", "yab-IDE Set run parameters" + window set "RunParam", "flags", "Not-Zoomable, not-h-resizable, not-v-resizable" + + Header("Set run parameters", "RunParam", 300) + + textcontrol 10,50 to 290,70, "RunParamYab", "yab Parameters:", settingsYabParam$, "RunParam" + textcontrol 10,80 to 290,110, "RunParamProg", "Program Parameters:", settingsProgParam$, "RunParam" + + inloop = true + while(inloop) + if(instr(message$, "Quit")) then + settingsYabParam$ = textcontrol get$ "RunParamYab" + settingsProgParam$ = textcontrol get$ "RunParamProg" + inloop = false + endif + wend + + window close "RunParam" + return +end sub + +// load settings on start-up +sub LoadSettings() + local handle, i, j + local tmp$ + + handle = open(globalConfigDir$+"ide-settings", "r") + if(not handle) return 1 + + while(not eof(handle)) + line input #handle tmp$ + if(left$(tmp$, 1)<>"#") then + i = i + 1 + switch(i) + case 1: settingsYabDir$ = tmp$: break + case 2: globalProjectDir$ = tmp$: break + case 3: yabDir$ = tmp$: break + case 4: ideDir$ = tmp$: break + case 5: buildDir$ = tmp$: break + case 6: globalHelpDir$ = tmp$: break + case 7: settingsLangUse = val(tmp$): break + case 8: settingsLangPath$ = tmp$: break + case 9: settingsAutoIndent = val(tmp$): break + case 10: settingsAutoCompletion = val(tmp$): break + case 11: settingsACNumChar = val(tmp$): break + case 12: settingsX = val(tmp$): break + case 13: settingsY = val(tmp$): break + case 14: settingsWidth = val(tmp$): break + case 15: settingsHeight = val(tmp$): break + case 16: settingsFullScreen = val(tmp$): break + case 17: settingsFullEditor = val(tmp$): break + case 18: settingsVSplitDivider = val(tmp$): break + case 19: settingsV2SplitDivider = val(tmp$): break + case 20: settingsHSplitDivider = val(tmp$): break + case 21: settingsCalcPatternX = val(tmp$): break + case 22: settingsCalcPatternY = val(tmp$): break + case 23: settingsColorSelectX = val(tmp$): break + case 24: settingsColorSelectY = val(tmp$): break + case 25: settingsColorSelectR = val(tmp$): break + case 26: settingsColorSelectG = val(tmp$): break + case 27: settingsColorSelectB = val(tmp$): break + case 28: settingsAskForSaving = val(tmp$): break + case 29: settingsFindCS = val(tmp$): break + case 30: settingsOldSearch$ = tmp$: break + case 31: settingsFindAlert = val(tmp$): break + case 32: settingsReformatAlert = val(tmp$): break + case 33: settingsReformatUndoAlert = val(tmp$): break + case 34: settingsTabSpaces = val(tmp$): break + case 35: break + case 36: settingsFontFamily$ = tmp$: break + case 37: settingsFontStyle$ = tmp$: break + case 38: settingsFontSize = val(tmp$): break + case 39: globalRealFontSize = val(tmp$): break + case 40: DEBUG = val(tmp$): break + case 41: MAXFILES = val(tmp$): break + case 42: settingsYabParam$ = tmp$: break + case 43: settingsProgParam$ = tmp$: break + end switch + endif + wend + close(handle) + + dim globalAllNames$(MAXFILES) + dim globalTextFinder(MAXFILES) + + for j=1 to MAXFILES + globalAllNames$(j) = "" + globalTextFinder(j) = 0 + next j + + if(i = 43) return 0 + return 1 +end sub + +// load last opened files on start-up +sub LoadOpenFiles() + local handle, mainhandle, j, t + local text$, t$ + + mainhandle = open(globalConfigDir$+"ide-openfiles", "r") + if(mainhandle) then + j = 1 + while(not eof(mainhandle) and j<=MAXFILES) + globalAllNames$(j) = GetLine$(mainhandle) + handle = open(globalAllNames$(j), "r") + if(handle) then + WaitWindow(globalAllNames$(j)) + text$ = "" + while(not eof(handle)) + t$ = GetLine$(handle)+"\n" + if(len(t$)*8>4000) textedit set "Text"+str$(j), "textwidth", len(t$)*8+8 + text$ = text$ + t$ + wend + close(handle) + globalCurrentText = j + textedit add "Text"+str$(globalCurrentText), text$ + textedit set "Text"+str$(globalCurrentText), "changed", false + textedit set "Text"+str$(globalCurrentText), "gotoline", ReadLineFromAttr(globalAllNames$(j)) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/gespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(globalAllNames$(j)) // "Filename", t, GetFileName$(tmp$) + columnbox select "FileBox", t+1 + globalTextFinder(globalCurrentText) = t+1 + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + globalNumOpenFiles = globalNumOpenFiles + 1 + if(globalNumOpenFiles = 1) then + ActivateMenus(true) + splitview set "V2Split", "Divider", settingsV2SplitDivider + endif + window close "WaitWindow" + else + globalAllNames$(j) = "" + endif + j = j + 1 + wend + close(mainhandle) + endif + + return +end sub + +// Export as HTML +sub ExportAsHTML() + local browse$ + + browse$ = filepanel "Save-File", "Export as HTML", globalProjectDir$ + if(browse$<>"") then + + handle = open(browse$, "w") + if(handle) then + print #handle "" + print #handle "" + print #handle " " + print #handle " " + GetFileName$(globalAllNames$(globalCurrentText)) + "" + print #handle " " + print #handle " " + print #handle " " + print #handle " " + print #handle "
"
+        		print #handle textedit get$ "Text"+str$(globalCurrentText);
+			print #handle "    
" + print #handle " " + print #handle "" + close(handle) + else + alert "File could not be saved!", "Ok", "warning" + return false + endif + endif +end sub + +// Save all settings before exiting +sub SaveSettings() + local handle, i + + if(system("test -d "+globalConfigDir$) = 1) then + system("mkdir "+left$(globalConfigDir$, len(globalConfigDir$)-1)) + endif + + handle = open(globalConfigDir$+"ide-settings", "w") + if(handle) then + print #handle "# yab IDE 2.2 config file" + print #handle "# " + print #handle "# Comments start with a # as first character on a line" + print #handle "# Only change this file when you know what you are doing!" + print #handle "# Do not change the order of the lines in this file!" + print #handle "# " + print #handle "# yab directory (ends on /)" + print #handle settingsYabDir$ + print #handle "# Program directory (ends on /)" + print #handle globalProjectDir$ + print #handle "# yab binary location" + print #handle yabDir$ + print #handle "# IDE directory (ends on /)" + print #handle ideDir$ + print #handle "# BuildFactory directory (ends on /)" + print #handle buildDir$ + print #handle "# Help directory (ends on /)" + print #handle globalHelpDir$ + print #handle "# Use localization (0 = false, 1 = true)" + print #handle restartSettingsLangUse + print #handle "# localization mimetype" + print #handle settingsLangPath$ + print #handle "# Auto indent (0 = false, 1 = true)" + print #handle settingsAutoIndent + print #handle "# Auto completion (0 = false, 1 = true)" + print #handle settingsAutoCompletion + print #handle "# Auto completion starts at character count:" + print #handle settingsACNumChar + print #handle "# X-coordinates of main window" + print #handle settingsX + print #handle "# Y-coordinates of main window" + print #handle settingsY + print #handle "# Width of main window" + print #handle settingsWidth + print #handle "# Height of main window" + print #handle settingsHeight + print #handle "# Start in fullscreen (0 = false, 1 = true)" + print #handle settingsFullScreen + print #handle "# Start in maximized editor (0 = false, 1 = true)" + print #handle settingsFullEditor + print #handle "# Position of main vertical divider" + print #handle settingsVSplitDivider + print #handle "# Position of the vertical divider for the line numbers" + print #handle settingsV2SplitDivider + print #handle "# Position of main horizontal divider" + print #handle settingsHSplitDivider + print #handle "# X-coordinate of the pattern editor window" + print #handle settingsCalcPatternX + print #handle "# Y-coordinate of the pattern editor window" + print #handle settingsCalcPatternY + print #handle "# X-coordinate of the color selection window" + print #handle settingsColorSelectX + print #handle "# Y-coordinate of the color selection window" + print #handle settingsColorSelectY + print #handle "# Red value for last selected color in color selection window" + print #handle settingsColorSelectR + print #handle "# Green value for last selected color in color selection window" + print #handle settingsColorSelectG + print #handle "# Blue value for last selected color in color selection window" + print #handle settingsColorSelectB + print #handle "# Ask for saving before running a program (0 = false, 1 = true)" + print #handle settingsAskForSaving + print #handle "# Is \"find\" case sensitive? (0 = false, 1 = true)" + print #handle settingsFindCS + print #handle "# Last search string" + print #handle settingsOldSearch$ + print #handle "# Show warning before applying Replace All (0 = false, 1 = true)" + print #handle settingsFindAlert + print #handle "# Show warning when reformating sourcecode did not close all loops and conditions (0 = false, 1 = true)" + print #handle settingsReformatAlert + print #handle "# Show warning before undo reformating (0 = false, 1 = true)" + print #handle settingsReformatUndoAlert + print #handle "# Number of spaces per tab" + print #handle settingsTabSpaces + print #handle "# Unused field (was: use Haiku tabs on ZETA)." + print #handle 0 + print #handle "# Font family name" + print #handle settingsFontFamily$ + print #handle "# Font style" + print #handle settingsFontStyle$ + print #handle "# Font size" + print #handle settingsFontSize + print #handle "# Real font size" + print #handle globalRealFontSize + print #handle "# Print out IDE debug information (0 = false, 1 = true)" + print #handle DEBUG + print #handle "# Maximum number of files the IDE can handle" + print #handle MAXFILES + print #handle "# yab runtime parameters (default is empty)" + print #handle settingsYabParam$ + print #handle "# Program runtime parameters (default is empty)" + print #handle settingsProgParam$ + + close(handle) + endif + + handle = open(globalConfigDir$+"ide-openfiles", "w") + if(handle) then + for i=1 to MAXFILES + if(globalAllNames$(i)<>"") print #handle globalAllNames$(i) + next i + close(handle) + endif + return +end sub + +sub path() +if (!peek("isbound")) then +path$=system$("ps") +x=instr(path$,"/yab-IDE.yab") +path$=left$(path$,x) +for x=len(path$)-1 to 1 step -1 + if (instr(path$," ",x) and catch=0) catch=x+1 +next +path$=right$(path$,len(path$)-catch) +path$=trim$(path$) +path$="/"+path$ +else +path$=trim$(peek$("directory") ) +path$=path$+"/" +end if + +end sub + + +sub yabpath$() + +if system("test -e /boot/home/config/non-packaged/bin/yab") = 0 then + return "/boot/home/config/non-packaged/bin/yab" +elseif system("test -e /boot/home/config/bin/yab") = 0 then + return "/boot/home/config/bin/yab" +elseif system("test -e /boot/system/bin/yab") = 0 then + return "/boot/system/bin/yab" + +endif + +local cmd$ +cmd$="test -e "+settingsYabDir$ +if system(cmd$)=0 then + return settingsYabDir$ +endif + +return "error" +end sub + +sub set_up_BuildFactory() +local DataDir$ + +local handel +local ddir$ + +DataDir$=trim$(system$("finddir B_USER_DIRECTORY")) + + + + +x=system("mkdir "+DataDir$+"/yab_work") +system("mkdir ~/config/settings/yab") +y=system("ls "+DataDir$+"/yab_work/BuildFactory") +y=y+system("ls "+DataDir$+"/yab_work/Programs") +if x=0 or y>0 then + system("cp -ur "+ideDir$+"/BuildFactory "+DataDir$+"/yab_work") + system("cp -ur "+ideDir$+"Programs "+DataDir$+"/yab_work") + system ("cp -ur "+ideDir$+"img "+DataDir$+"/yab_work/Programs") + system("cp -ur "+ideDir$+"Programs/libs/* /boot/home/config/settings/yab") + + + handle=open(DataDir$+"/yab_work/BuildFactory/srcfiles","r") + + + while(not eof(#handle)) + input #handle a$ + system("cp -u "+ideDir$+"/src/"+a$+" "+DataDir$+"/yab_work/BuildFactory/"+a$) + end while + close handle + + system("cp -ur "+ideDir$+"/src/column "+DataDir$+"/yab_work/BuildFactory") +end if + +x=1 +open #1, ideDir$+"/src/YabMain.cpp","r" +open #2, DataDir$+"/yab_work/BuildFactory/parts/YabMain.cpp.end","w" + +while(not eof(#1)) + line input #1 a$ + if x>9 then + print #2 a$ + end if + x=x+1 +wend +close #1 +close #2 + +end sub + + + + +sub changestring() + +TextLine$ = TEXTEDIT GET$"Text"+str$(globalCurrentText), searchLineNum +TextLine$=rtrim$(TextLine$ ) +FindPart$=textcontrol get$ "FindTCFind" +FindPart$=trim$(FindPart$) +if(settingsFindCS) then + x=instr(TextLine$, FindPart$) +else + x=instr(upper$(TextLine$), upper$(FindPart$)) + +endif +if x>0 then + x=x-1 + TextPart$= textcontrol get$ "FindTCReplace" + TextPart$=rtrim$(TextPart$) + TextLine$=left$(TextLine$,x)+TextPart$+right$(TextLine$,len(TextLine$)-(x+(len(FindPart$)))) + TEXTEDIT SET "Text"+str$(globalCurrentText), "select", searchLineNum + TEXTEDIT SET "Text"+str$(globalCurrentText), "cut" + TEXTEDIT SET "Text"+str$(globalCurrentText), "select", searchLineNum + TEXTEDIT ADD "Text"+str$(globalCurrentText), TextLine$ + TEXTEDIT SET "Text"+str$(globalCurrentText), "gotoline", searchLineNum + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", TextPart$ + +endif + +end sub diff --git a/src/yabasic.bison b/src/yabasic.bison new file mode 100644 index 0000000..366497b --- /dev/null +++ b/src/yabasic.bison @@ -0,0 +1,940 @@ +%{ +/* + + YABASIC --- a simple Basic Interpreter + written by Marc-Oliver Ihm 1995-2004 + homepage: www.yabasic.de + + BISON part + + This file is part of yabasic and may be copied only + under the terms of either the Artistic License or + the GNU General Public License (GPL), both of which + can be found at www.yabasic.de + +*/ + + +#ifndef YABASIC_INCLUDED +#include "yabasic.h" /* definitions of yabasic */ +#endif + +#include + +#if HAVE_ALLOCA_H +#ifndef WINDOWS +#include +#endif +#endif + +void __yy_bcopy(char *,char *,int); /* prototype missing */ + +int tileol; /* true, read should go to eon of line */ +int mylineno=1; /* line number; counts fresh in every new file */ +int main_lineno=1; /* line number of main */ +int function_type=ftNONE; /* contains function type while parsing function */ +char *current_function=NULL; /* name of currently parsed function */ +int exported=FALSE; /* true, if function is exported */ +int yylex(void); +extern struct libfile_name *current_libfile; /* defined in main.c: name of currently parsed file */ +int missing_endif=0; +int missing_endif_line=0; +int missing_endsub=0; +int missing_endsub_line=0; +int missing_next=0; +int missing_next_line=0; +int missing_wend=0; +int missing_wend_line=0; +int missing_until=0; +int missing_until_line=0; +int missing_loop=0; +int missing_loop_line=0; +int in_loop=0; + +void report_missing(int severity,char *text) { + if (missing_loop || missing_endif || missing_next || missing_until || missing_wend) { + error(severity,text); + string[0]='\0'; + if (missing_endif) + sprintf(string,"if statement starting at line %d has seen no 'endif' yet",missing_endif_line); + else if (missing_next) + sprintf(string,"for-loop starting at line %d has seen no 'next' yet",missing_next_line); + else if (missing_wend) + sprintf(string,"while-loop starting at line %d has seen no 'wend' yet",missing_wend_line); + else if (missing_until) + sprintf(string,"repeat-loop starting at line %d has seen no 'until' yet",missing_until_line); + else if (missing_loop) + sprintf(string,"do-loop starting at line %d has seen no 'loop' yet",missing_wend_line); + if (string[0]) error(severity,string); + } +} + +%} + +%union { + double fnum; /* double number */ + int inum; /* integer number */ + int token; /* token of command */ + int sep; /* number of newlines */ + char *string; /* quoted string */ + char *symbol; /* general symbol */ + char *digits; /* string of digits */ + char *docu; /* embedded documentation */ +} + +%type const +%type number +%type symbol_or_lineno +%type function_name +%type function_or_array +%type stringfunction_or_array +%type tSEP sep_list + +%token tFNUM +%token tSYMBOL +%token tSTRSYM +%token tDOCU +%token tDIGITS +%token tSTRING + +%token tFOR tTO tSTEP tNEXT tWHILE tWEND tREPEAT tUNTIL tIMPORT +%token tGOTO tGOSUB tLABEL tON tSUB tENDSUB tLOCAL tSTATIC tEXPORT tERROR +%token tEXECUTE tEXECUTE2 tCOMPILE tRUNTIME_CREATED_SUB +%token tINTERRUPT tBREAK tCONTINUE tSWITCH tSEND tCASE tDEFAULT tLOOP tDO tSEP tEOPROG +%token tIF tTHEN tELSE tELSIF tENDIF tUSING +%token tPRINT tINPUT tLINE tRETURN tDIM tEND tEXIT tAT tSCREEN tSCREENSHOT +%token tREVERSE tCOLOUR +%token tAND tOR tNOT tEOR +%token tNEQ tLEQ tGEQ tLTN tGTN tEQU tPOW +%token tREAD tDATA tRESTORE +%token tOPEN tCLOSE tSEEK tTELL tAS tREADING tWRITING +%token tWAIT tBELL tLET tARDIM tARSIZE tBIND +%token tWINDOW tDOT tCIRCLE tCLEAR tFILL tPRINTER tSETUP +%token tBUTTON tALERT tMENU tCHECKBOX tRADIOBUTTON tTEXTCONTROL +%token tLISTBOX tDROPBOX tADD tREMOVE tLOCALIZE tFILEPANEL tSLIDER tSTATUSBAR +%token tLAYOUT tSET tTEXTEDIT tCOUNT tVIEW tBOXVIEW tTABVIEW tTEXTURL tBITMAP tCANVAS +%token tOPTION tDROPZONE tCOLORCONTROL tTREEBOX tCOLUMNBOX tCOLUMN tSORT tTOOLTIP tCALENDAR +%token tCLIPBOARD tCOPY tSUBMENU tSELECT tSCROLLBAR tEXPAND tCOLLAPSE tSPLITVIEW tSTACKVIEW +%token tPOPUPMENU tSPINCONTROL tMSEND tNUMMESSAGE tTHREAD tSOUND tPLAY tSTOP tSHORTCUT tISCOMPUTERON +%token tDRAW tTEXT tFLUSH tELLIPSE tSAVE +%token tRECT tGETCHAR tPUTCHAR tNEW tCURVE tLAUNCH tATTRIBUTE + +%token tSIN tASIN tCOS tACOS tTAN tATAN tEXP tLOG +%token tSQRT tSQR tMYEOF tABS tSIG +%token tINT tFRAC tMOD tRAN tLEN tVAL tLEFT tRIGHT tMID tMIN tMAX +%token tSTR tINKEY tCHR tASC tHEX tDEC tBIN tUPPER tLOWER +%token tTRIM tLTRIM tRTRIM tINSTR tRINSTR +%token tSYSTEM tSYSTEM2 tPEEK tPEEK2 tPOKE +%token tDATE tTIME tTOKEN tTOKENALT tSPLIT tSPLITALT tGLOB +%token tMESSAGE tIMAGE tSVG tTRANSLATE tGET tMOUSE tISMOUSEIN +%token tKEYBOARD tPASTE tGETNUM + +%left tOR +%left tAND +%left tNOT +%left tNEQ +%left tGEQ +%left tLEQ +%left tLTN +%left tGTN +%left tEQU +%left '-' '+' +%left '*' '/' +%left tPOW +%nonassoc UMINUS + +%% + +program: statement_list tEOPROG {YYACCEPT;} + ; + +statement_list: statement + | statement_list {if (errorlevel<=ERROR) {YYABORT;}} + tSEP {if ($3>=0) mylineno+=$3; else switchlib();} statement + ; + +statement: /* empty */ + | string_assignment + | tLET string_assignment + | assignment + | tLET assignment + | tIMPORT {report_missing(ERROR,"do not import a library in a loop or an if-statement");switchlib();} + | tERROR string_expression {add_command(cERROR,NULL);} + | for_loop + | switch_number_or_string + | repeat_loop + | while_loop + | do_loop + | tBREAK {add_command(cBREAK,NULL);if (!in_loop) error(ERROR,"break outside loop");} + | tCONTINUE {add_command(cCONTINUE,NULL);if (!in_loop) error(ERROR,"continue outside loop");} + | function_definition + | function_or_array {create_call($1);add_command(cPOP,NULL);} + | stringfunction_or_array {create_call($1);add_command(cPOP,NULL);} + | tLOCAL {if (function_type==ftNONE) error(ERROR,"no use for 'local' outside functions");} local_list + | tSTATIC {if (function_type==ftNONE) error(ERROR,"no use for 'static' outside functions");} static_list + | if_clause + | short_if + | tGOTO symbol_or_lineno {create_goto((function_type!=ftNONE)?dotify($2,TRUE):$2);} + | tGOSUB symbol_or_lineno {create_gosub((function_type!=ftNONE)?dotify($2,TRUE):$2);} + | tON tINTERRUPT tBREAK {create_exception(TRUE);} + | tON tINTERRUPT tCONTINUE {create_exception(FALSE);} + | tON expression tGOTO {add_command(cSKIPPER,NULL);} + goto_list {add_command(cNOP,NULL);} + | tON expression tGOSUB {add_command(cSKIPPER,NULL);} + gosub_list {add_command(cNOP,NULL);} + | tLABEL symbol_or_lineno {create_label((function_type!=ftNONE)?dotify($2,TRUE):$2,cLABEL);} + | open_clause {add_command(cCHECKOPEN,NULL);} + | tCLOSE hashed_number {add_command(cCLOSE,NULL);} + | seek_clause {add_command(cCHECKSEEK,NULL);} + | tCOMPILE string_expression {add_command(cCOMPILE,NULL);} + | tEXECUTE '(' call_list ')' {create_execute(0);add_command(cPOP,NULL);add_command(cPOP,NULL);} + | tEXECUTE2 '(' call_list ')' {create_execute(1);add_command(cPOP,NULL);add_command(cPOP,NULL);} + | tPRINT printintro printlist {create_colour(0);create_print('n');create_pps(cPOPSTREAM,0);} + | tPRINT printintro printlist ';' {create_colour(0);create_pps(cPOPSTREAM,0);} + | tPRINT printintro printlist ',' {create_colour(0);create_print('t');create_pps(cPOPSTREAM,0);} + | tINPUT {tileol=FALSE;} inputbody + | tLINE tINPUT {tileol=TRUE;} inputbody + | tREAD readlist + | tDATA datalist + | tRESTORE {create_restore("");} + | tRESTORE symbol_or_lineno {create_restore((function_type!=ftNONE)?dotify($2,TRUE):$2);} + | tRESTORE string_expression {add_command(cRESTORE2, NULL);} + | tRETURN {if (get_switch_id()) create_clean_switch_mark(0,TRUE); + if (function_type!=ftNONE) { + add_command(cCLEARREFS,NULL);lastcmd->nextref=firstref; + add_command(cPOPSYMLIST,NULL); + create_retval(ftNONE,function_type); + add_command(cRET_FROM_FUN,NULL); + } else { + add_command(cRETURN,NULL); + }} + | tRETURN expression {if (get_switch_id()) create_clean_switch_mark(1,TRUE); if (function_type==ftNONE) {error(ERROR,"can not return value"); YYABORT;} add_command(cCLEARREFS,NULL);lastcmd->nextref=firstref;add_command(cPOPSYMLIST,NULL);create_retval(ftNUMBER,function_type);add_command(cRET_FROM_FUN,NULL);} + | tRETURN string_expression {if (get_switch_id()) create_clean_switch_mark(1,TRUE); if (function_type==ftNONE) {error(ERROR,"can not return value"); YYABORT;} add_command(cCLEARREFS,NULL);lastcmd->nextref=firstref;add_command(cPOPSYMLIST,NULL);create_retval(ftSTRING,function_type);add_command(cRET_FROM_FUN,NULL);} + | tDIM dimlist +/* | tOPEN tWINDOW expression ',' expression {create_openwin(FALSE);} */ + | tWINDOW tOPEN coordinates to coordinates ',' string_expression ',' string_expression {create_openwin(TRUE);} + | tBUTTON coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cBUTTON,NULL);} + | tMENU string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cMENU,NULL);} + | tCHECKBOX coordinates ',' string_expression ',' string_expression ',' expression ',' string_expression {add_command(cCHECKBOX,NULL);} + | tRADIOBUTTON coordinates ',' string_expression ',' string_expression ',' expression ',' string_expression {add_command(cRADIOBUTTON,NULL);} + | tTEXTCONTROL coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression ',' string_expression{add_command(cTEXTCONTROL,NULL);} + | tLISTBOX coordinates to coordinates ',' string_expression ',' expression ',' string_expression {add_command(cLISTBOX,NULL);} + | tLISTBOX tCLEAR string_expression {add_command(cITEMCLEAR, NULL);} + | tLISTBOX tADD string_expression ',' string_expression {add_command(cLISTBOXADD1, NULL);} + | tLISTBOX tADD string_expression ',' expression ',' string_expression {add_command(cLISTBOXADD2, NULL);} + | tDROPBOX coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cDROPBOX,NULL);} + | tDROPBOX tADD string_expression ',' string_expression {add_command(cITEMADD,NULL);} + | tDROPBOX tCLEAR string_expression {add_command(cDROPBOXCLEAR,NULL);} + | tDROPBOX tREMOVE string_expression ',' expression {add_command(cDROPBOXREMOVE,NULL);} + | tLISTBOX tREMOVE string_expression ',' string_expression {add_command(cITEMDEL,NULL);} + | tLISTBOX tREMOVE string_expression ',' expression {add_command(cLISTBOXDEL2,NULL);} + | tLISTBOX tSELECT string_expression ',' expression {add_command(cLISTBOXSELECT,NULL);} + | tALERT string_expression ',' string_expression ',' string_expression {add_command(cALERT,NULL);} + | tTEXT coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cTEXT,NULL);} + | tTEXT coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cTEXT2, NULL);} + | tTEXT tSET string_expression ',' string_expression {add_command(cTEXTALIGN,NULL);} + | tLOCALIZE {add_command(cLOCALIZE,NULL);} + | tLOCALIZE string_expression {add_command(cLOCALIZE2,NULL);} + | tLOCALIZE tSTOP {add_command(cLOCALIZESTOP, NULL);} + | tDRAW tTEXT coordinates ',' string_expression ',' string_expression {add_command(cDRAWTEXT,NULL);} + | tDRAW tRECT coordinates to coordinates ',' string_expression {add_command(cDRAWRECT,NULL);} + | tDRAW tFLUSH string_expression {add_command(cDRAWCLEAR,NULL);} + | tWINDOW tCLOSE string_expression {add_command(cCLOSEWIN,NULL);} + | tLAYOUT string_expression ',' string_expression {add_command(cLAYOUT,NULL);} + | tWINDOW tSET string_expression ',' string_expression {add_command(cWINSET4,NULL);} + | tWINDOW tSET string_expression ',' string_expression ',' string_expression {add_command(cWINSET1,NULL);} + | tWINDOW tSET string_expression ',' string_expression ',' expression ',' expression {add_command(cWINSET3,NULL);} + /* + | tWINDOW tSET string_expression ',' string_expression ',' expression ',' expression ',' expression {add_command(cWINSET2,NULL);} + this tWINDOW tSET was replaced by tDRAW tSET ... cWINSET2 + tWINDOW tCLEAR string_expression {add_command(cWINCLEAR,NULL);}*/ + | tSHORTCUT string_expression ',' string_expression ',' string_expression {add_command(cSHORTCUT,NULL);} + | tTEXTEDIT coordinates to coordinates ',' string_expression ',' expression ',' string_expression {add_command(cTEXTEDIT,NULL);} + | tTEXTEDIT tADD string_expression ',' string_expression {add_command(cTEXTADD,NULL);} + | tTEXTEDIT tSET string_expression ',' string_expression {add_command(cTEXTSET,NULL);} + | tTEXTEDIT tSET string_expression ',' string_expression ',' expression {add_command(cTEXTSET2,NULL);} + | tTEXTEDIT tSET string_expression ',' string_expression ',' string_expression {add_command(cTEXTSET3,NULL);} + | tTEXTEDIT tCOLOUR string_expression ',' string_expression ',' string_expression {add_command(cTEXTCOLOR1,NULL);} + | tTEXTEDIT tCOLOUR string_expression ',' string_expression ',' expression ',' expression ',' expression {add_command(cTEXTCOLOR2,NULL);} + | tTEXTEDIT tCLEAR string_expression {add_command(cTEXTCLEAR,NULL);} + | tDRAW tSET string_expression ',' string_expression {add_command(cDRAWSET1,NULL);} + | tDRAW tSET expression ',' string_expression {add_command(cDRAWSET2,NULL);} + | tDRAW tSET string_expression ',' expression ',' expression ',' expression ',' string_expression {add_command(cWINSET2,NULL);} + | tDRAW tSET string_expression ',' expression {add_command(cDRAWSET3,NULL);} + | tDRAW tSET string_expression ',' string_expression ',' string_expression {add_command(cDRAWSET4,NULL);} + | tVIEW coordinates to coordinates ',' string_expression ',' string_expression {add_command(cVIEW,NULL);} + | tVIEW tREMOVE string_expression {add_command(cWINCLEAR,NULL);} + | tBOXVIEW coordinates to coordinates ',' string_expression ',' string_expression ',' expression ',' string_expression {add_command(cBOXVIEW,NULL);} + | tBOXVIEW tSET string_expression ',' string_expression ',' string_expression {add_command(cBOXVIEWSET,NULL);} + | tTABVIEW coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cTAB,NULL);} + | tTABVIEW tSET string_expression ',' expression {add_command(cTABSET,NULL);} + | tTABVIEW tADD string_expression ',' string_expression {add_command(cTABADD, NULL);} + | tTABVIEW tREMOVE string_expression ',' expression {add_command(cTABDEL, NULL);} + | tDRAW tDOT coordinates ',' string_expression {add_command(cDOT,NULL);} + | tDRAW tLINE coordinates to coordinates ',' string_expression {add_command(cLINE,NULL);} + | tDRAW tCIRCLE coordinates ',' expression ',' string_expression {add_command(cCIRCLE,NULL);} + | tDRAW tELLIPSE coordinates ',' expression ',' expression ',' string_expression {add_command(cELLIPSE,NULL);} + | tDRAW tCURVE coordinates ',' coordinates ',' coordinates ',' coordinates ',' string_expression {add_command(cCURVE,NULL);} + | tSLIDER coordinates to coordinates ',' string_expression ',' string_expression ',' expression ',' expression ',' string_expression {add_command(cSLIDER1,NULL);} + | tSLIDER coordinates to coordinates ',' string_expression ',' string_expression ',' expression ',' expression ',' string_expression ',' string_expression {add_command(cSLIDER2,NULL);} + | tSLIDER tLABEL string_expression ',' string_expression ',' string_expression {add_command(cSLIDER3,NULL);} + | tSLIDER tSET string_expression ',' string_expression ',' expression {add_command(cSLIDER4,NULL);} + | tSLIDER tCOLOUR string_expression ',' string_expression ',' expression ',' expression ',' expression {add_command(cSLIDER5,NULL);} + | tSLIDER tSET string_expression ',' expression {add_command(cSLIDER6,NULL);} + | tLAUNCH string_expression {add_command(cLAUNCH,NULL);} + | tOPTION tSET string_expression ',' string_expression ',' string_expression {add_command(cOPTION1,NULL);} + | tOPTION tCOLOUR string_expression ',' string_expression ',' expression ',' expression ',' expression {add_command(cOPTION2,NULL);} + /* + | tOPTION tRESIZE string_expression ',' coordinates to coordinates {add_command(cOPTION3,NULL);} + */ + | tOPTION tSET string_expression ',' string_expression {add_command(cOPTION4,NULL);} + | tOPTION tSET string_expression ',' string_expression ',' expression {add_command(cOPTION5,NULL);} + | tOPTION tSET string_expression ',' string_expression ',' expression ',' expression {add_command(cOPTION3,NULL);} + | tBITMAP coordinates ',' string_expression {add_command(cBITMAP,NULL);} + | tBITMAP tGETNUM coordinates to coordinates ',' string_expression ',' string_expression {add_command(cBITMAPGET, NULL);} + | tBITMAP tGETNUM expression ',' string_expression ',' string_expression {add_command(cBITMAPGET2, NULL);} + | tBITMAP tGETNUM string_expression ',' string_expression ',' string_expression {add_command(cBITMAPGETICON, NULL);} + | tDRAW tBITMAP coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cBITMAPDRAW,NULL);} + | tDRAW tBITMAP coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression {add_command(cBITMAPDRAW2,NULL);} + /* + | tCANVAS tDRAG string_expression {add_command(cBITMAPDRAG,NULL);} + */ + | tBITMAP tREMOVE string_expression {add_command(cBITMAPREMOVE,NULL);} + | tSCREENSHOT coordinates to coordinates ',' string_expression {add_command(cSCREENSHOT,NULL);} + | tCANVAS coordinates to coordinates ',' string_expression ',' string_expression {add_command(cCANVAS,NULL);} + | tVIEW tDROPZONE string_expression {add_command(cDROPZONE,NULL);} + | tCOLORCONTROL coordinates ',' string_expression ',' string_expression {add_command(cCOLORCONTROL1,NULL);} + | tCOLORCONTROL tSET string_expression ',' expression ',' expression ',' expression {add_command(cCOLORCONTROL2,NULL);} + | tTEXTCONTROL tSET string_expression ',' string_expression {add_command(cTEXTCONTROL2,NULL);} + | tTEXTCONTROL tSET string_expression ',' expression {add_command(cTEXTCONTROL3,NULL);} + | tTEXTCONTROL tSET string_expression ',' string_expression ',' string_expression {add_command(cTEXTCONTROL4,NULL);} + | tTEXTCONTROL tCLEAR string_expression {add_command(cTEXTCONTROL5,NULL);} + | tTREEBOX coordinates to coordinates ',' string_expression ',' expression ',' string_expression {add_command(cTREEBOX1,NULL);} + | tTREEBOX tADD string_expression ',' string_expression {add_command(cTREEBOX2,NULL);} + | tTREEBOX tADD string_expression ',' string_expression ',' string_expression ',' expression {add_command(cTREEBOX3,NULL);} + | tTREEBOX tADD string_expression ',' string_expression ',' expression ',' expression ',' expression {add_command(cTREEBOX13,NULL);} + | tTREEBOX tADD string_expression ',' string_expression ',' expression {add_command(cTREEBOX12,NULL);} + | tTREEBOX tCLEAR string_expression {add_command(cTREEBOX4,NULL);} + | tTREEBOX tREMOVE string_expression ',' string_expression {add_command(cTREEBOX5,NULL);} + | tTREEBOX tSELECT string_expression ',' expression {add_command(cTREEBOX7,NULL);} + | tTREEBOX tREMOVE string_expression ',' expression {add_command(cTREEBOX8,NULL);} + | tTREEBOX tREMOVE string_expression ',' string_expression ',' string_expression {add_command(cTREEBOX9,NULL);} + | tTREEBOX tEXPAND string_expression ',' string_expression {add_command(cTREEBOX10,NULL);} + | tTREEBOX tCOLLAPSE string_expression ',' string_expression {add_command(cTREEBOX11,NULL);} + | tBUTTON tIMAGE coordinates ',' string_expression ',' string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cBUTTONIMAGE,NULL);} + | tCHECKBOX tIMAGE coordinates ',' string_expression ',' string_expression ',' string_expression ',' string_expression ',' string_expression ',' expression ',' string_expression {add_command(cCHECKBOXIMAGE,NULL);} + | tCHECKBOX tSET string_expression ',' expression {add_command(cCHECKBOXSET,NULL);} + | tRADIOBUTTON tSET string_expression ',' expression {add_command(cRADIOSET,NULL);} + | tTOOLTIP string_expression ',' string_expression {add_command(cTOOLTIP,NULL);} + | tTOOLTIP tCOLOUR string_expression ',' expression ',' expression ',' expression {add_command(cTOOLTIPCOLOR,NULL);} + | tLISTBOX tSORT string_expression {add_command(cLISTSORT,NULL);} + | tTREEBOX tSORT string_expression {add_command(cTREESORT,NULL);} + | tCOLUMNBOX coordinates to coordinates ',' string_expression ',' expression ',' string_expression ',' string_expression {add_command(cFILEBOX,NULL);} + | tCOLUMNBOX tADD string_expression ',' expression ',' expression ',' expression ',' string_expression {add_command(cCOLUMNBOXADD,NULL);} + | tCOLUMNBOX tCOLUMN string_expression ',' string_expression ',' expression ',' expression ',' expression ',' expression ',' string_expression {add_command(cFILEBOXADD2,NULL);} + | tCOLUMNBOX tCLEAR string_expression {add_command(cFILEBOXCLEAR,NULL);} + | tCOLUMNBOX tREMOVE string_expression ',' expression {add_command(cCOLUMNBOXREMOVE,NULL);} + | tCOLUMNBOX tSELECT string_expression ',' expression {add_command(cCOLUMNBOXSELECT,NULL);} + | tCOLUMNBOX tCOLOUR string_expression ',' string_expression ',' expression ',' expression ',' expression {add_command(cCOLUMNBOXCOLOR,NULL);} + | tCALENDAR coordinates ',' string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cCALENDAR,NULL);} + | tCALENDAR tSET string_expression ',' string_expression {add_command(cCALENDARSET,NULL);} + | tSCROLLBAR string_expression ',' expression ',' string_expression {add_command(cSCROLLBAR,NULL);} + | tSCROLLBAR tSET string_expression ',' string_expression ',' expression {add_command(cSCROLLBARSET1,NULL);} + | tSCROLLBAR tSET string_expression ',' string_expression ',' expression ',' expression {add_command(cSCROLLBARSET2,NULL);} + | tSCROLLBAR tSET string_expression ',' string_expression {add_command(cSCROLLBARSET3,NULL);} + | tDROPBOX tSELECT string_expression ',' expression {add_command(cDROPBOXSELECT,NULL);} + | tMENU tSET string_expression ',' expression ',' string_expression {add_command(cMENU2,NULL);} + | tMENU tSET string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cMENU3,NULL);} + | tSUBMENU string_expression ',' string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cSUBMENU1,NULL);} + | tSUBMENU tSET string_expression ',' string_expression ',' expression ',' string_expression {add_command(cSUBMENU2,NULL);} + | tSUBMENU tSET string_expression ',' string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cSUBMENU3,NULL);} + | tSTATUSBAR coordinates to coordinates ',' string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cSTATUSBAR,NULL);} + | tSTATUSBAR tSET string_expression ',' string_expression ',' string_expression ',' expression {add_command(cSTATUSBARSET,NULL);} + | tSTATUSBAR tSET string_expression ',' expression ',' expression ',' expression {add_command(cSTATUSBARSET3,NULL);} + | tSPINCONTROL coordinates ',' string_expression ',' string_expression ',' expression ',' expression ',' expression ',' string_expression {add_command(cSPINCONTROL1,NULL);} + | tSPINCONTROL tSET string_expression ',' expression {add_command(cSPINCONTROL2,NULL);} + | tCLIPBOARD tCOPY string_expression {add_command(cCLIPBOARDCOPY,NULL);} + | tPRINTER tSETUP string_expression {add_command(cPRINTERCONFIG,NULL);} + | tMOUSE tSET string_expression {add_command(cMOUSESET,NULL);} + | tSOUND tSTOP expression {add_command(cSOUNDSTOP,NULL);} + | tSOUND tSTOP '(' expression ')' {add_command(cSOUNDSTOP,NULL);} + | tSOUND tWAIT expression {add_command(cSOUNDWAIT,NULL);} + | tSOUND tWAIT '(' expression ')' {add_command(cSOUNDWAIT,NULL);} + | tSPLITVIEW coordinates to coordinates ',' string_expression ',' expression ',' expression ',' string_expression {add_command(cSPLITVIEW1,NULL);} + | tSPLITVIEW tSET string_expression ',' string_expression ',' expression {add_command(cSPLITVIEW2,NULL);} + | tSPLITVIEW tSET string_expression ',' string_expression ',' expression ',' expression {add_command(cSPLITVIEW3,NULL);} + | tSTACKVIEW coordinates to coordinates ',' string_expression ',' expression ',' string_expression {add_command(cSTACKVIEW1,NULL);} + | tSTACKVIEW tSET string_expression ',' expression {add_command(cSTACKVIEW2,NULL);} + | tTEXTURL coordinates ',' string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cTEXTURL1, NULL);} + | tTEXTURL tCOLOUR string_expression ',' string_expression ',' expression ',' expression ',' expression {add_command(cTEXTURL2, NULL);} + | tATTRIBUTE tSET string_expression ',' string_expression ',' string_expression ',' string_expression {add_command(cATTRIBUTE1, NULL);} + | tATTRIBUTE tCLEAR string_expression ',' string_expression {add_command(cATTRIBUTECLEAR, NULL);} + | tPUTCHAR string_expression to expression ',' expression {add_command(cPUTCHAR,NULL);} + | tCLEAR tSCREEN {add_command(cCLEARSCR,NULL);} + | tWAIT expression {add_command(cWAIT,NULL);} + | tBELL {add_command(cBELL,NULL);} + | tINKEY {create_pushdbl(-1);create_function(fINKEY);add_command(cPOP,NULL);} + | tINKEY '(' ')' {create_pushdbl(-1);create_function(fINKEY);add_command(cPOP,NULL);} + | tINKEY '(' expression ')' {create_function(fINKEY);add_command(cPOP,NULL);} + | tSYSTEM2 '(' string_expression ')' {create_function(fSYSTEM2); + add_command(cPOP,NULL);} + | tPOKE string_expression ',' string_expression {create_poke('s');} + | tPOKE string_expression ',' expression {create_poke('d');} + | tPOKE hashed_number ',' string_expression {create_poke('S');} + | tPOKE hashed_number ',' expression {create_poke('D');} + | tEND {add_command(cEND,NULL);} + | tEXIT {create_pushdbl(0);add_command(cEXIT,NULL);} + | tEXIT expression {add_command(cEXIT,NULL);} + | tDOCU {create_docu($1);} + | tBIND string_expression {add_command(cBIND,NULL);} + ; + +/* +clear_fill_clause: * empty * {drawmode=0;} + | tCLEAR {drawmode=dmCLEAR;} + | tFILL {drawmode=dmFILL;} + | tCLEAR tFILL {drawmode=dmFILL+dmCLEAR;} + | tFILL tCLEAR {drawmode=dmFILL+dmCLEAR;} + ;*/ + + +string_assignment: tSTRSYM tEQU string_expression {add_command(cPOPSTRSYM,dotify($1,FALSE));} + | tMID '(' string_scalar_or_array ',' expression ',' expression ')' tEQU string_expression {create_changestring(fMID);} + | tMID '(' string_scalar_or_array ',' expression ')' tEQU string_expression {create_changestring(fMID2);} + | tLEFT '(' string_scalar_or_array ',' expression ')' tEQU string_expression {create_changestring(fLEFT);} + | tRIGHT '(' string_scalar_or_array ',' expression ')' tEQU string_expression {create_changestring(fRIGHT);} + | stringfunction_or_array tEQU string_expression {create_doarray(dotify($1,FALSE),ASSIGNSTRINGARRAY);} + ; + +to: ',' + | tTO + ; + +open_clause: tOPEN hashed_number ',' string_expression ',' string_expression {create_myopen(OPEN_HAS_STREAM+OPEN_HAS_MODE);} + | tOPEN hashed_number ',' string_expression {create_myopen(OPEN_HAS_STREAM);} +/* | tOPEN hashed_number ',' tPRINTER {create_myopen(OPEN_HAS_STREAM+OPEN_PRINTER);} */ + | tOPEN string_expression tFOR tREADING tAS hashed_number {add_command(cSWAP,NULL);create_pushstr("r");create_myopen(OPEN_HAS_STREAM+OPEN_HAS_MODE);} + | tOPEN string_expression tFOR tWRITING tAS hashed_number {add_command(cSWAP,NULL);create_pushstr("w");create_myopen(OPEN_HAS_STREAM+OPEN_HAS_MODE);} + ; + +seek_clause: tSEEK hashed_number ',' expression {add_command(cSEEK,NULL);} + | tSEEK hashed_number ',' expression ',' string_expression {add_command(cSEEK2,NULL);} + ; + +string_scalar_or_array: tSTRSYM {add_command(cPUSHSTRPTR,dotify($1,FALSE));} + | tSTRSYM '(' call_list ')' {create_doarray(dotify($1,FALSE),GETSTRINGPOINTER);} + ; + +string_expression: tSTRSYM {add_command(cPUSHSTRSYM,dotify($1,FALSE));} + | string_function + | stringfunction_or_array {add_command(cSTRINGFUNCTION_OR_ARRAY,$1);} + | tSTRING {if ($1==NULL) {error(ERROR,"String not terminated");create_pushstr("");} else {create_pushstr($1);}} + | string_expression '+' string_expression {add_command(cCONCAT,NULL);} + | '(' string_expression ')' + ; + +string_function: tLEFT '(' string_expression ',' expression ')' {create_function(fLEFT);} + | tRIGHT '(' string_expression ',' expression ')' {create_function(fRIGHT);} + | tMID '(' string_expression ',' expression ',' expression ')' {create_function(fMID);} + | tMID '(' string_expression ',' expression ')' {create_function(fMID2);} + | tSTR '(' expression ')' {create_function(fSTR);} + | tSTR '(' expression ',' string_expression ')' {create_function(fSTR2);} + | tSTR '(' expression ',' string_expression ',' string_expression ')' {create_function(fSTR3);} + | tINKEY {create_pushdbl(-1);create_function(fINKEY);} + | tINKEY '(' ')' {create_pushdbl(-1);create_function(fINKEY);} + | tINKEY '(' expression ')' {create_function(fINKEY);} + | tCHR '(' expression ')' {create_function(fCHR);} + | tUPPER '(' string_expression ')' {create_function(fUPPER);} + | tLOWER '(' string_expression ')' {create_function(fLOWER);} + | tLTRIM '(' string_expression ')' {create_function(fLTRIM);} + | tRTRIM '(' string_expression ')' {create_function(fRTRIM);} + | tTRIM '(' string_expression ')' {create_function(fTRIM);} + | tSYSTEM '(' string_expression ')' {create_function(fSYSTEM);} + | tDATE {create_function(fDATE);} + | tDATE '(' ')' {create_function(fDATE);} + | tTIME {create_function(fTIME);} + | tTIME '(' ')' {create_function(fTIME);} + | tPEEK2 '(' string_expression ')' {create_function(fPEEK2);} + | tPEEK2 '(' string_expression ',' string_expression ')' {create_function(fPEEK3);} + | tTOKENALT '(' string_scalar_or_array ',' string_expression ')' {add_command(cTOKENALT2,NULL);} + | tTOKENALT '(' string_scalar_or_array ')' {add_command(cTOKENALT,NULL);} + | tSPLITALT '(' string_scalar_or_array ',' string_expression ')' {add_command(cSPLITALT2,NULL);} + | tSPLITALT '(' string_scalar_or_array ')' {add_command(cSPLITALT,NULL);} + | tGETCHAR '(' expression ',' expression to expression ',' expression ')' {create_function(fGETCHAR);} + | tHEX '(' expression ')' {create_function(fHEX);} + | tBIN '(' expression ')' {create_function(fBIN);} + | tEXECUTE2 '(' call_list ')' {create_execute(1);add_command(cSWAP,NULL);add_command(cPOP,NULL);} + | tMESSAGE {create_function(fMESSAGE);} + | tMESSAGE '(' ')' {create_function(fMESSAGE);} + | tMOUSE tMESSAGE {create_function(fMOUSEMOVE);} + | tMOUSE tMESSAGE '(' ')' {create_function(fMOUSEMOVE);} + | tTRANSLATE '(' string_expression ')' {create_function(fTRANSLATE);} + | tMENU tTRANSLATE '(' string_expression ')' {create_function(fMENUTRANSLATE);} + | tTEXTEDIT tGET string_expression {create_function(fTEXTGET);} + | tTEXTEDIT tGET string_expression ',' expression {create_function(fTEXTGET3);} + | tTEXTEDIT tGET string_expression ',' string_expression {create_function(fTEXTGET6);} + | tTEXTCONTROL tGET string_expression {create_function(fTEXTCONTROLGET);} + | tFILEPANEL string_expression ',' string_expression ',' string_expression {create_function(fLOAD);} + | tFILEPANEL string_expression ',' string_expression ',' string_expression ',' string_expression {create_function(fSAVE);} + | tMOUSE tMESSAGE string_expression {create_function(fMOUSE);} + //| tMOUSE tMESSAGE '(' string_expression ')' {create_function(fMOUSE);} + | tKEYBOARD tMESSAGE string_expression {create_function(fKEYBOARD);} + //| tKEYBOARD tMESSAGE '(' string_expression ')' {create_function(fKEYBOARD);} + | tCLIPBOARD tPASTE {create_function(fCLIPBOARDPASTE);} + | tCOLUMNBOX tGET string_expression ',' expression ',' expression {create_function(fCOLUMNBOXGET);} + | tCALENDAR tGET string_expression {create_function(fCALENDAR);} + | tLISTBOX tGET string_expression ',' expression {create_function(fLISTBOXGET);} + | tTREEBOX tGET string_expression ',' expression {create_function(fTREEBOXGET);} + | tPOPUPMENU coordinates ',' string_expression ',' string_expression {create_function(fPOPUPMENU);} + | tDROPBOX tGET string_expression ',' expression {create_function(fDROPBOXGET);} + | tDRAW tGET string_expression {create_function(fDRAWGET3);} + | tATTRIBUTE tGET string_expression ',' string_expression {create_function(fATTRIBUTEGET1);} + ; + +assignment: tSYMBOL tEQU expression {add_command(cPOPDBLSYM,dotify($1,FALSE));} + | function_or_array tEQU expression {create_doarray($1,ASSIGNARRAY);} + ; + +expression: expression tOR {add_command(cORSHORT,NULL);pushlabel();} expression {poplabel();create_boole('|');} + | expression tAND {add_command(cANDSHORT,NULL);pushlabel();} expression {poplabel();create_boole('&');} + | tNOT expression {create_boole('!');} + | expression tEQU expression {create_dblrelop('=');} + | expression tNEQ expression {create_dblrelop('!');} + | expression tLTN expression {create_dblrelop('<');} + | expression tLEQ expression {create_dblrelop('{');} + | expression tGTN expression {create_dblrelop('>');} + | expression tGEQ expression {create_dblrelop('}');} + | tMYEOF '(' hashed_number ')' {add_command(cTESTEOF,NULL);} + | tGLOB '(' string_expression ',' string_expression ')' {add_command(cGLOB,NULL);} + | number {create_pushdbl($1);} + | tARDIM '(' arrayref ')' {add_command(cARDIM,"");} + | tARDIM '(' string_arrayref ')' {add_command(cARDIM,"");} + | tARSIZE '(' arrayref ',' expression ')' {add_command(cARSIZE,"");} + | tARSIZE '(' string_arrayref ',' expression ')' {add_command(cARSIZE,"");} + | function_or_array {add_command(cFUNCTION_OR_ARRAY,$1);} + | tSYMBOL {add_command(cPUSHDBLSYM,dotify($1,FALSE));} + | expression '+' expression {create_dblbin('+');} + | expression '-' expression {create_dblbin('-');} + | expression '*' expression {create_dblbin('*');} + | expression '/' expression {create_dblbin('/');} + | expression tPOW expression {create_dblbin('^');} + | '-' expression %prec UMINUS {add_command(cNEGATE,NULL);} + | string_expression tEQU string_expression {create_strrelop('=');} + | string_expression tNEQ string_expression {create_strrelop('!');} + | string_expression tLTN string_expression {create_strrelop('<');} + | string_expression tLEQ string_expression {create_strrelop('{');} + | string_expression tGTN string_expression {create_strrelop('>');} + | string_expression tGEQ string_expression {create_strrelop('}');} + | function + | '(' expression ')' + ; + +arrayref: tSYMBOL '(' ')' {create_pusharrayref(dotify($1,FALSE),stNUMBERARRAYREF);} + ; + +string_arrayref: tSTRSYM '(' ')' {create_pusharrayref(dotify($1,FALSE),stSTRINGARRAYREF);} + ; + +coordinates: expression ',' expression + ; + +function: tSIN '(' expression ')' {create_function(fSIN);} + | tASIN '(' expression ')' {create_function(fASIN);} + | tCOS '(' expression ')' {create_function(fCOS);} + | tACOS '(' expression ')' {create_function(fACOS);} + | tTAN '(' expression ')' {create_function(fTAN);} + | tATAN '(' expression ')' {create_function(fATAN);} + | tATAN '(' expression ',' expression ')' {create_function(fATAN2);} + | tEXP '(' expression ')' {create_function(fEXP);} + | tLOG '(' expression ')' {create_function(fLOG);} + | tLOG '(' expression ',' expression ')' {create_function(fLOG2);} + | tSQRT '(' expression ')' {create_function(fSQRT);} + | tSQR '(' expression ')' {create_function(fSQR);} + | tINT '(' expression ')' {create_function(fINT);} + | tFRAC '(' expression ')' {create_function(fFRAC);} + | tABS '(' expression ')' {create_function(fABS);} + | tSIG '(' expression ')' {create_function(fSIG);} + | tMOD '(' expression ',' expression ')' {create_function(fMOD);} + | tRAN '(' expression ')' {create_function(fRAN);} + | tRAN '(' ')' {create_function(fRAN2);} + | tMIN '(' expression ',' expression ')' {create_function(fMIN);} + | tMAX '(' expression ',' expression ')' {create_function(fMAX);} + | tLEN '(' string_expression ')' {create_function(fLEN);} + | tVAL '(' string_expression ')' {create_function(fVAL);} + | tASC '(' string_expression ')' {create_function(fASC);} + | tDEC '(' string_expression ')' {create_function(fDEC);} + | tDEC '(' string_expression ',' expression ')' {create_function(fDEC2);} + | tINSTR '(' string_expression ',' string_expression ')' {if (check_compat) error(WARNING,"instr() has changed in version 2.712"); create_function(fINSTR);} + | tINSTR '(' string_expression ',' string_expression ',' expression ')' {create_function(fINSTR2);} + | tRINSTR '(' string_expression ',' string_expression ')' {create_function(fRINSTR);} + | tRINSTR '(' string_expression ',' string_expression ',' expression ')' {create_function(fRINSTR2);} + | tSYSTEM2 '(' string_expression ')' {create_function(fSYSTEM2);} + | tPEEK '(' hashed_number ')' {create_function(fPEEK4);} + | tPEEK '(' string_expression ')' {create_function(fPEEK);} +/* + | tMOUSEX '(' string_expression ')' {create_function(fMOUSEX);} + | tMOUSEX {create_pushstr("");create_function(fMOUSEX);} + | tMOUSEX '(' ')' {create_pushstr("");create_function(fMOUSEX);} + | tMOUSEY '(' string_expression ')' {create_function(fMOUSEY);} + | tMOUSEY {create_pushstr("");create_function(fMOUSEY);} + | tMOUSEY '(' ')' {create_pushstr("");create_function(fMOUSEY);} + | tMOUSEB '(' string_expression ')' {create_function(fMOUSEB);} + | tMOUSEB {create_pushstr("");create_function(fMOUSEB);} + | tMOUSEB '(' ')' {create_pushstr("");create_function(fMOUSEB);} + | tMOUSEMOD '(' string_expression ')' {create_function(fMOUSEMOD);} + | tMOUSEMOD {create_pushstr("");create_function(fMOUSEMOD);} + | tMOUSEMOD '(' ')' {create_pushstr("");create_function(fMOUSEMOD);}*/ + | tAND '(' expression ',' expression ')' {create_function(fAND);} + | tOR '(' expression ',' expression ')' {create_function(fOR);} + | tEOR '(' expression ',' expression ')' {create_function(fEOR);} + | tTELL '(' hashed_number ')' {create_function(fTELL);} + | tTOKEN '(' string_expression ',' string_arrayref ',' string_expression ')' {add_command(cTOKEN2,NULL);} + | tTOKEN '(' string_expression ',' string_arrayref ')' {add_command(cTOKEN,NULL);} + | tSPLIT '(' string_expression ',' string_arrayref ',' string_expression ')' {add_command(cSPLIT2,NULL);} + | tSPLIT '(' string_expression ',' string_arrayref ')' {add_command(cSPLIT,NULL);} + | tEXECUTE '(' call_list ')' {create_execute(0);add_command(cSWAP,NULL);add_command(cPOP,NULL);} + | tOPEN '(' string_expression ')' {create_myopen(0);} + | tOPEN '(' string_expression ',' string_expression ')' {create_myopen(OPEN_HAS_MODE);} + | tOPEN '(' hashed_number ',' string_expression ')' {create_myopen(OPEN_HAS_STREAM);} + | tOPEN '(' hashed_number ',' string_expression ',' string_expression ')' {create_myopen(OPEN_HAS_STREAM+OPEN_HAS_MODE);} + | tDRAW tIMAGE expression ',' expression ',' string_expression ',' string_expression {create_function(fDRAWIMAGE);} + | tDRAW tIMAGE coordinates to coordinates ',' string_expression ',' string_expression {create_function(fDRAWIMAGE2);} + | tSVG coordinates to coordinates ',' string_expression ',' string_expression {create_function(fDRAWSVG);} + | tWINDOW tCOUNT {create_function(fNUMWINDOWS);} + // | tISMOUSEIN '(' string_expression ')' {create_function(fISMOUSEIN);} + | tISMOUSEIN string_expression {create_function(fISMOUSEIN);} + | tCOLUMNBOX tCOUNT string_expression {create_function(fCOLUMNBOXCOUNT);} + | tWINDOW tGETNUM string_expression ',' string_expression {create_function(fWINDOWGET);} + | tVIEW tGETNUM string_expression ',' string_expression {create_function(fVIEWGET);} + | tALERT string_expression ',' string_expression ',' string_expression ',' string_expression ',' string_expression {create_function(fALERT);} + | tLISTBOX tCOUNT string_expression {create_function(fLISTBOXCOUNT);} + | tTREEBOX tCOUNT string_expression {create_function(fTREEBOXCOUNT);} + | tSCROLLBAR tGETNUM string_expression ',' string_expression {create_function(fSCROLLBARGET);} + | tSPLITVIEW tGETNUM string_expression ',' string_expression {create_function(fSPLITVIEWGET);} + | tSTACKVIEW tGETNUM string_expression {create_function(fSTACKVIEWGET);} + | tTABVIEW tGETNUM string_expression {create_function(fTABVIEWGET);} + | tSPINCONTROL tGETNUM string_expression {create_function(fSPINCONTROLGET);} + | tDROPBOX tCOUNT string_expression {create_function(fDROPBOXCOUNT);} + | tSLIDER tGETNUM string_expression {create_function(fSLIDERGET);} + | tCOLORCONTROL tGETNUM string_expression ',' string_expression {create_function(fCOLORCONTROLGET);} + | tTEXTEDIT tGETNUM string_expression ',' string_expression {create_function(fTEXTGET2);} + | tTEXTEDIT tGETNUM string_expression ',' string_expression ',' expression {create_function(fTEXTGET4);} + | tTEXTEDIT tGETNUM string_expression ',' string_expression ',' string_expression {create_function(fTEXTGET5);} + | tDRAW tGETNUM string_expression ',' string_expression ',' string_expression {create_function(fDRAWGET1);} + | tDRAW tGETNUM string_expression ',' string_expression {create_function(fDRAWGET2);} + | tDRAW tGETNUM coordinates ',' string_expression ',' string_expression {create_function(fDRAWGET4);} + | tNUMMESSAGE tMSEND string_expression ',' string_expression {create_function(fMESSAGESEND);} + | tTHREAD tREMOVE string_expression ',' expression {create_function(fTHREADKILL);} + | tTHREAD tGETNUM string_expression ',' string_expression {create_function(fTHREADGET);} + | tPRINTER string_expression ',' string_expression ',' string_expression {create_function(fPRINTER);} + | tSOUND tPLAY string_expression {create_function(fSOUND);} + | tISCOMPUTERON {create_function(fISCOMPUTERON);} + | tLISTBOX tGETNUM string_expression {create_function(fLISTBOXGETNUM);} + | tDROPBOX tGETNUM string_expression {create_function(fDROPBOXGETNUM);} + | tTREEBOX tGETNUM string_expression {create_function(fTREEBOXGETNUM);} + | tCOLUMNBOX tGETNUM string_expression {create_function(fCOLUMNBOXGETNUM);} + | tTREEBOX tGETNUM string_expression ',' string_expression ',' expression {create_function(fTREEBOXGETOPT);} + | tBITMAP tSAVE string_expression ',' string_expression ',' string_expression {create_function(fBITMAPSAVE);} + | tBITMAP tIMAGE string_expression ',' string_expression {create_function(fBITMAPLOAD);} + | tBITMAP tGETNUM string_expression ',' string_expression {create_function(fBITMAPGET);} + | tBITMAP tCOLOUR expression ',' expression ',' string_expression ',' string_expression {create_function(fBITMAPCOLOR);} + | tATTRIBUTE tGETNUM string_expression ',' string_expression {create_function(fATTRIBUTEGET2);} + ; + +const: number {$$=$1;} + | '+' number {$$=$2;} + | '-' number {$$=-$2;} + ; + +number: tFNUM {$$=$1;} + | tDIGITS {$$=strtod($1,NULL);} + ; + +symbol_or_lineno: tDIGITS {$$=my_strdup(dotify($1,FALSE));} + | tSYMBOL {$$=my_strdup(dotify($1,FALSE));} + ; + +dimlist: tSYMBOL '(' call_list ')' {create_dim(dotify($1,FALSE),'D');} + | dimlist ',' tSYMBOL '(' call_list ')' {create_dim(dotify($3,FALSE),'D');} + | tSTRSYM '(' call_list ')' {create_dim(dotify($1,FALSE),'S');} + | dimlist ',' tSTRSYM '(' call_list ')' {create_dim(dotify($3,FALSE),'S');} + ; + +function_or_array: tSYMBOL '(' call_list ')' {$$=my_strdup(dotify($1,FALSE));} + ; + +stringfunction_or_array: tSTRSYM '(' call_list ')' {$$=my_strdup(dotify($1,FALSE));} + ; + +call_list: {add_command(cPUSHFREE,NULL);} calls + ; + +calls: /* empty */ + | call_item + | calls ',' call_item + ; + +call_item: string_expression + | expression + ; + +function_definition: export tSUB {missing_endsub++;missing_endsub_line=mylineno;pushlabel();report_missing(WARNING,"do not define a function in a loop or an if-statement");if (function_type!=ftNONE) {error(ERROR,"nested functions not allowed");YYABORT;}} + function_name {if (exported) create_sublink($4); create_label($4,cUSER_FUNCTION); + add_command(cPUSHSYMLIST,NULL);add_command(cCLEARREFS,NULL);firstref=lastref=lastcmd; + create_numparam();} + '(' paramlist ')' {create_require(stFREE);add_command(cPOP,NULL);} + statement_list + endsub {add_command(cCLEARREFS,NULL);lastcmd->nextref=firstref;add_command(cPOPSYMLIST,NULL);create_retval(ftNONE,function_type);function_type=ftNONE;add_command(cRET_FROM_FUN,NULL);lastref=NULL;create_endfunction();poplabel();} + ; + +endsub: tEOPROG {if (missing_endsub) {sprintf(string,"%d end-sub(s) are missing (last at line %d)",missing_endsub,missing_endsub_line);error(ERROR,string);} YYABORT;} + | tENDSUB {missing_endsub--;} + ; + +function_name: tSYMBOL {function_type=ftNUMBER;current_function=my_strdup(dotify($1,FALSE));$$=my_strdup(dotify($1,FALSE));} + | tSTRSYM {function_type=ftSTRING;current_function=my_strdup(dotify($1,FALSE));$$=my_strdup(dotify($1,FALSE));} + ; + +export: /* empty */ {exported=FALSE;} + | tEXPORT {exported=TRUE;} + | tRUNTIME_CREATED_SUB {exported=FALSE;} + | tRUNTIME_CREATED_SUB tEXPORT {exported=TRUE;} + ; + +local_list: local_item + | local_list ',' local_item + ; + +local_item: tSYMBOL {create_makelocal(dotify($1,FALSE),syNUMBER);} + | tSTRSYM {create_makelocal(dotify($1,FALSE),sySTRING);} + | tSYMBOL '(' call_list ')' {create_makelocal(dotify($1,FALSE),syARRAY);create_dim(dotify($1,FALSE),'d');} + | tSTRSYM '(' call_list ')' {create_makelocal(dotify($1,FALSE),syARRAY);create_dim(dotify($1,FALSE),'s');} + ; + +static_list: static_item + | static_list ',' static_item + ; + +static_item: tSYMBOL {create_makestatic(dotify($1,TRUE),syNUMBER);} + | tSTRSYM {create_makestatic(dotify($1,TRUE),sySTRING);} + | tSYMBOL '(' call_list ')' {create_makestatic(dotify($1,TRUE),syARRAY);create_dim(dotify($1,TRUE),'D');} + | tSTRSYM '(' call_list ')' {create_makestatic(dotify($1,TRUE),syARRAY);create_dim(dotify($1,TRUE),'S');} + ; + +paramlist: /* empty */ + | paramitem + | paramlist ',' paramitem + ; + +paramitem: tSYMBOL {create_require(stNUMBER);create_makelocal(dotify($1,FALSE),syNUMBER);add_command(cPOPDBLSYM,dotify($1,FALSE));} + | tSTRSYM {create_require(stSTRING);create_makelocal(dotify($1,FALSE),sySTRING);add_command(cPOPSTRSYM,dotify($1,FALSE));} + | tSYMBOL '(' ')' {create_require(stNUMBERARRAYREF);create_arraylink(dotify($1,FALSE),stNUMBERARRAYREF);} + | tSTRSYM '(' ')' {create_require(stSTRINGARRAYREF);create_arraylink(dotify($1,FALSE),stSTRINGARRAYREF);} + ; + +for_loop: tFOR {missing_next++;missing_next_line=mylineno;} tSYMBOL tEQU + {pushname(dotify($3,FALSE)); /* will be used by next_symbol to check equality */ + add_command(cRESETSKIPONCE,NULL); + pushgoto();add_command(cCONTINUE_HERE,NULL);create_break_mark(0,1);} + expression tTO expression + step_part { /* pushes another expression */ + add_command(cSKIPONCE,NULL); + pushlabel(); + add_command(cSTARTFOR,NULL); + add_command(cPOPDBLSYM,dotify($3,FALSE)); + poplabel(); + add_command(cPUSHDBLSYM,dotify($3,FALSE)); + add_command(cFORINCREMENT,NULL); + add_command(cPOPDBLSYM,dotify($3,FALSE)); + add_command(cPUSHDBLSYM,dotify($3,FALSE)); + add_command(cFORCHECK,NULL); + add_command(cDECIDE,NULL); + pushlabel();} + statement_list { + swap();popgoto();poplabel();} + next next_symbol {create_break_mark(0,-1);add_command(cBREAK_HERE,NULL);} + ; + +next: tEOPROG {if (missing_next) {sprintf(string,"%d next(s) are missing (last at line %d)",missing_next,missing_next_line);error(ERROR,string);} YYABORT;} + | tNEXT {missing_next--;} + ; + +step_part: {create_pushdbl(1);} /* can be omitted */ + | tSTEP expression + ; + +next_symbol: {pop(stSTRING);}/* can be omitted */ + | tSYMBOL {if (strcmp(pop(stSTRING)->pointer,dotify($1,FALSE))) + {error(ERROR,"'for' and 'next' do not match"); YYABORT;} + } + ; + +switch_number_or_string: tSWITCH {push_switch_id();add_command(cPUSH_SWITCH_MARK,NULL);create_break_mark(0,1); + add_command(cCONTINUE_CORRECTION,NULL);} + number_or_string sep_list case_list default tSEND {create_break_mark(-1,0);add_command(cBREAK_HERE,NULL);create_break_mark(0,-1);add_command(cBREAK_HERE,NULL);create_clean_switch_mark(0,FALSE);pop_switch_id();} + ; + +sep_list: tSEP {if ($1>=0) mylineno+=$1;} + | sep_list tSEP {if ($2>=0) mylineno+=$2;} + ; + +number_or_string: expression + | string_expression + ; + + +case_list: /* empty */ + | case_list tCASE {create_break_mark(-1,0);add_command(cBREAK_HERE,NULL);} number_or_string + {add_command(cSWITCH_COMPARE,NULL);add_command(cDECIDE,NULL);add_command(cMINOR_BREAK,NULL);create_break_mark(1,0);} statement_list {add_command(cNEXT_CASE,NULL);} + ; + + +default: /* empty */ + | tDEFAULT tSEP {if ($2>=0) mylineno+=$2; create_break_mark(-1,0);add_command(cBREAK_HERE,NULL);} statement_list + ; + + +do_loop: tDO {add_command(cCONTINUE_HERE,NULL);create_break_mark(0,1);missing_loop++;missing_loop_line=mylineno;pushgoto();} + statement_list + loop + ; + + +loop: tEOPROG {if (missing_loop) {sprintf(string,"%d loop(s) are missing (last at line %d)",missing_loop,missing_loop_line);error(ERROR,string);} YYABORT;} + | tLOOP {missing_loop--;popgoto();create_break_mark(0,-1);add_command(cBREAK_HERE,NULL);} + ; + + +while_loop: tWHILE {add_command(cCONTINUE_HERE,NULL);create_break_mark(0,1);missing_wend++;missing_wend_line=mylineno;pushgoto()} '(' expression ')' + {add_command(cDECIDE,NULL); + pushlabel();} + statement_list + wend + ; + +wend: tEOPROG {if (missing_wend) {sprintf(string,"%d wend(s) are missing (last at line %d)",missing_wend,missing_wend_line);error(ERROR,string);} YYABORT;} + | tWEND {missing_wend--;swap();popgoto();poplabel();create_break_mark(0,-1);add_command(cBREAK_HERE,NULL);} + ; + + +repeat_loop: tREPEAT {add_command(cCONTINUE_HERE,NULL);create_break_mark(0,1);missing_until++;missing_until_line=mylineno;pushgoto();} + statement_list + until + ; + +until: tEOPROG {if (missing_until) {sprintf(string,"%d until(s) are missing (last at line %d)",missing_until,missing_until_line);error(ERROR,string);} YYABORT;} + | tUNTIL '(' expression ')' + {missing_until--;add_command(cDECIDE,NULL);popgoto();create_break_mark(0,-1);add_command(cBREAK_HERE,NULL);} + ; + +if_clause: tIF expression {add_command(cDECIDE,NULL);storelabel();pushlabel();} + tTHEN {missing_endif++;missing_endif_line=mylineno;} statement_list {swap();matchgoto();swap();poplabel();} + elsif_part + else_part {poplabel();} + endif + ; + +endif: tEOPROG {if (missing_endif) {sprintf(string,"%d endif(s) are missing (last at line %d)",missing_endif,missing_endif_line);error(ERROR,string);} YYABORT;} + | tENDIF {missing_endif--;} + ; + +short_if: tIF expression {fi_pending++;add_command(cDECIDE,NULL);pushlabel();} + statement_list tENDIF {poplabel();} + ; + +else_part: /* can be omitted */ + | tELSE statement_list + ; + +elsif_part: /* can be omitted */ + | tELSIF expression maybe_then + {add_command(cDECIDE,NULL);pushlabel();} + statement_list + {swap();matchgoto();swap();poplabel();} + elsif_part + ; + +maybe_then: /* can be omitted */ + | tTHEN + ; + +inputlist: input + | input ',' {add_command(cCHKPROMPT,NULL);} inputlist + ; + +input: tSYMBOL {create_myread('d',tileol);add_command(cPOPDBLSYM,dotify($1,FALSE));} + | tSYMBOL '(' call_list ')' + {create_myread('d',tileol);create_doarray(dotify($1,FALSE),ASSIGNARRAY);} + | tSTRSYM {create_myread('s',tileol);add_command(cPOPSTRSYM,dotify($1,FALSE));} + | tSTRSYM '(' call_list ')' + {create_myread('s',tileol);create_doarray(dotify($1,FALSE),ASSIGNSTRINGARRAY);} + ; + +readlist: readitem + | readlist ',' readitem + ; + +readitem: tSYMBOL {create_readdata('d');add_command(cPOPDBLSYM,dotify($1,FALSE));} + | tSYMBOL '(' call_list ')' + {create_readdata('d');create_doarray(dotify($1,FALSE),ASSIGNARRAY);} + | tSTRSYM {create_readdata('s');add_command(cPOPSTRSYM,dotify($1,FALSE));} + | tSTRSYM '(' call_list ')' + {create_readdata('s');create_doarray(dotify($1,FALSE),ASSIGNSTRINGARRAY);} + ; + +datalist: tSTRING {create_strdata($1);} + | const {create_dbldata($1);} + | datalist ',' tSTRING {create_strdata($3);} + | datalist ',' const {create_dbldata($3);} + ; + +printlist: /* possible empty */ + | expression using + | printlist ',' expression using + | string_expression {create_print('s');} + | printlist ',' string_expression {create_print('s');} + ; + +using: {create_print('d');} /* possible empty */ + | tUSING string_expression {create_print('u');} + | tUSING '(' string_expression ',' string_expression ')' {create_print('U');} + ; + +inputbody: '#' tSYMBOL {add_command(cPUSHDBLSYM,dotify($2,FALSE));create_pps(cPUSHSTREAM,1);} inputlist {create_pps(cPOPSTREAM,0);} + | '#' tDIGITS {create_pushdbl(atoi($2));create_pps(cPUSHSTREAM,1);} inputlist {create_pps(cPOPSTREAM,0);} + | '#' '(' expression ')' {create_pps(cPUSHSTREAM,1);} inputlist {create_pps(cPOPSTREAM,0);} + | tAT '(' expression ',' expression ')' {add_command(cMOVE,NULL);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,1);} prompt inputlist {create_pps(cPOPSTREAM,0);} + | {create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,1);} prompt inputlist {create_pps(cPOPSTREAM,0);} + ; + +prompt: /* empty */ {create_pushstr("?");create_print('s');} + | tSTRING {create_pushstr($1);create_print('s');} + ; + +printintro: /* may be empty */ {create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | '#' tSYMBOL {add_command(cPUSHDBLSYM,dotify($2,FALSE));create_pps(cPUSHSTREAM,0);} + | '#' tDIGITS {create_pushdbl(atoi($2));create_pps(cPUSHSTREAM,0);} + | '#' '(' expression ')' {create_pps(cPUSHSTREAM,0);} + | tREVERSE {create_colour(1);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | tCOLOUR '(' string_expression ')' {create_colour(2);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | tCOLOUR '(' string_expression ',' string_expression ')' {create_colour(3);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | tAT '(' expression ',' expression ')' {add_command(cMOVE,NULL);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | tREVERSE tAT '(' expression ',' expression ')' {add_command(cMOVE,NULL);create_colour(1);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | tCOLOUR '(' string_expression ')' tAT '(' expression ',' expression ')' {add_command(cMOVE,NULL);create_colour(2);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | tCOLOUR '(' string_expression ',' string_expression ')' tAT '(' expression ',' expression ')' {add_command(cMOVE,NULL);create_colour(3);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);} + | tAT '(' expression ',' expression ')' tREVERSE {create_colour(1);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);add_command(cMOVE,NULL);} + | tAT '(' expression ',' expression ')' tCOLOUR '(' string_expression ')' {create_colour(2);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);add_command(cMOVE,NULL);} + | tAT '(' expression ',' expression ')' tCOLOUR '(' string_expression ',' string_expression ')' {create_colour(3);create_pushdbl(STDIO_STREAM);create_pps(cPUSHSTREAM,0);add_command(cMOVE,NULL);} + ; + +hashed_number: '#' expression + | expression; + +goto_list: symbol_or_lineno {create_goto((function_type!=ftNONE)?dotify($1,TRUE):$1);add_command(cFINDNOP,NULL);} + | goto_list ',' symbol_or_lineno {create_goto((function_type!=ftNONE)?dotify($3,TRUE):$3);add_command(cFINDNOP,NULL);} + ; + +gosub_list: symbol_or_lineno {create_gosub((function_type!=ftNONE)?dotify($1,TRUE):$1);add_command(cFINDNOP,NULL);} + | gosub_list ',' symbol_or_lineno {create_gosub((function_type!=ftNONE)?dotify($3,TRUE):$3);add_command(cFINDNOP,NULL);} + ; + diff --git a/src/yabasic.flex b/src/yabasic.flex new file mode 100644 index 0000000..83bcf50 --- /dev/null +++ b/src/yabasic.flex @@ -0,0 +1,560 @@ +%{ +/* + + YABASIC --- a simple Basic Interpreter + written by Marc-Oliver Ihm 1995-2004 + homepage: www.yabasic.de + + FLEX part + + This file is part of yabasic and may be copied only + under the terms of either the Artistic License or + the GNU General Public License (GPL), both of which + can be found at www.yabasic.de + +*/ + +#include +#undef WINDOWS + +#include "bison.h" /* get tokens from BISON */ +#ifndef YABASIC_INCLUDED +#include "yabasic.h" /* definitions of yabasic */ +#endif +extern int main_lineno; /* defined in yabasic.bison: line number of main file */ +extern int mylineno; /* defined in yabasic.bison: line number of main file */ +int import_lib(char *); /* import library */ + +#define MAX_INCLUDE_DEPTH 5 +#define MAX_INCLUDE_NUMBER 100 +static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; /* stack for included libraries */ +int include_stack_ptr; /* current position in libfile_stack */ +struct libfile_name *libfile_stack[MAX_INCLUDE_DEPTH]; /* stack for library file names */ +int libfile_chain_length=0; /* length of libfile_chain */ +struct libfile_name *libfile_chain[MAX_INCLUDE_NUMBER]; /* list of all library file names */ +struct libfile_name *currlib; /* current libfile as relevant to bison */ +int inlib; /* true, while in library */ +int fi_pending=0; /* true, if within a short if */ +int flex_line=0; /* line number counted in flex */ +%} + +WS [ \t\f\r\v] +NAME ([A-Za-z_][A-za-z0-9_]*\.[A-Za-z_][A-za-z0-9_]*)|([A-Za-z_][A-za-z0-9_]*) + +%option noyywrap +%x PRELNO +%x PASTLNO +%x IMPORT +%x IMPORT_DONE + +%% +<> { + if (--include_stack_ptr<0) { + return tEOPROG; + } else { + if (!is_bound) { + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(include_stack[include_stack_ptr]); + } + flex_line+=yylval.sep=-1; + return tSEP; + } +} + +{WS}+ {BEGIN(INITIAL);} /* ignore whitespace */ + +^{WS}*/[0-9]+ {BEGIN(PRELNO);return tLABEL;} +[0-9]+ { + BEGIN(PASTLNO); + yylval.symbol=(char *)my_strdup(yytext); + return tSYMBOL; +} +.* {BEGIN(INITIAL);flex_line+=yylval.sep=0;yyless(0);return tSEP;} +\n {if (fi_pending) {fi_pending--;yyless(0);return tENDIF;}BEGIN(INITIAL);flex_line+=yylval.sep=1;return tSEP;} + +\n\n {if (fi_pending) {fi_pending--;yyless(0);return tENDIF;}if (interactive && !inlib) {return tEOPROG;} else {flex_line+=yylval.sep=2;return tSEP;}} +\n {if (fi_pending) {fi_pending--;yyless(0);return tENDIF;}flex_line+=yylval.sep=1;return tSEP;} +: {if (fi_pending && check_compat) error_with_line(WARNING,"short-if has changed in version 2.71",flex_line);flex_line+=yylval.sep=0;return tSEP;} + +REM{WS}+.* {flex_line+=yylval.sep=0;return tSEP;} /* comments span 'til end of line */ +\/\/.* {flex_line+=yylval.sep=0;return tSEP;} /* comments span 'til end of line */ +REM\n {if (fi_pending) {fi_pending--;yyless(0);return tENDIF;}flex_line+=yylval.sep=1;return tSEP;} +REM {yymore();} + +IMPORT {BEGIN(IMPORT);} +{WS}+{NAME} {if (!import_lib(yytext)) return 0;BEGIN(IMPORT_DONE);return tIMPORT;} +(.|\n) {if (yytext[0]=='\n' && fi_pending) {fi_pending--;yyless(0);return tENDIF;}BEGIN(INITIAL);yyless(0);flex_line+=yylval.sep=0;return tSEP;} + +((DOCU|DOC|DOCUMENTATION)({WS}+.*)?) { + char *where=strpbrk(yytext," \t\r\f\v"); + yylval.docu=(char *)my_strdup(where ? where+1 : NULL); + return tDOCU; +} + +^#.*\n {flex_line+=yylval.sep=1;return tSEP;} /* '#' as first character may introduce comments too */ +^'.*\n {flex_line+=yylval.sep=1;return tSEP;} /* ' as first character may introduce comments too */ + +EXECUTE return tEXECUTE; +"EXECUTE$" return tEXECUTE2; +COMPILE return tCOMPILE; +RUNTIME_CREATED_SUB return tRUNTIME_CREATED_SUB; +END{WS}+SUB return tENDSUB; +END{WS}+IF return tENDIF; +END-IF return tENDIF; +END{WS}+WHILE return tWEND; +END-WHILE return tWEND; +END{WS}+SWITCH return tSEND; +END-SWITCH return tSEND; +END{WS}+"SWITCH$" return tSEND; +END-"SWITCH$" return tSEND; +EXPORT return tEXPORT; +ERROR return tERROR; +FOR return tFOR; +BREAK return tBREAK; +SWITCH return tSWITCH; +CASE return tCASE; +DEFAULT return tDEFAULT; +LOOP return tLOOP; +DO return tDO; +TO return tTO; +AS return tAS; +READING return tREADING; +WRITING return tWRITING; +STEP return tSTEP; +NEXT return tNEXT; +WHILE return tWHILE; +WEND return tWEND; +REPEAT return tREPEAT; +UNTIL return tUNTIL; +GOTO return tGOTO; +GOSUB return tGOSUB; +SUB return tSUB; +SUBROUTINE return tSUB; +LOCAL return tLOCAL; +STATIC return tSTATIC; +ON return tON; +INTERRUPT return tINTERRUPT; +CONTINUE return tCONTINUE; +LABEL return tLABEL; +IF return tIF; +THEN return tTHEN; +ELSE return tELSE; +ELSIF return tELSIF; +ELSEIF return tELSIF; +ENDIF return tENDIF; +FI return tENDIF; +OPEN return tOPEN; +CLOSE return tCLOSE; +SEEK return tSEEK; +TELL return tTELL; +PRINT return tPRINT; +USING return tUSING; +REVERSE return tREVERSE; +COLOR return tCOLOUR; +COLOUR return tCOLOUR; +\? return tPRINT; +INPUT return tINPUT; +RETURN return tRETURN; +DIM return tDIM; +REDIM return tDIM; +END return tEND; +EXIT return tEXIT; +READ return tREAD; +DATA return tDATA; +RESTORE return tRESTORE; +AND return tAND; +OR return tOR; +NOT return tNOT; +EOR return tEOR; +XOR return tEOR; +WINDOW return tWINDOW; +PRINTER return tPRINTER; +SETUP return tSETUP; +PUTSCREEN return tPUTCHAR; +"GETSCREEN$" return tGETCHAR; +NEW return tNEW; +WAIT return tWAIT; +PAUSE return tWAIT; +SLEEP return tWAIT; +BELL return tBELL; +BEEP return tBELL; +LET return tLET; +ARRAYDIM return tARDIM; +ARRAYDIMENSION return tARDIM; +ARRAYSIZE return tARSIZE; +NUMPARAM(S)?({WS}*\({WS}*\))? {yylval.symbol=(char *)my_strdup("numparams"); return tSYMBOL;} +BIND return tBIND; +SET return tSET; + +LOCALIZE return tLOCALIZE; +BUTTON return tBUTTON; +ALERT return tALERT; +MENU return tMENU; +CHECKBOX return tCHECKBOX; +RADIOBUTTON return tRADIOBUTTON; +TEXTCONTROL return tTEXTCONTROL; +LISTBOX return tLISTBOX; +DROPBOX return tDROPBOX; +ADD return tADD; +REMOVE return tREMOVE; +TEXT return tTEXT; +RECT return tRECT; +DRAW return tDRAW; +FLUSH return tFLUSH; +FILEPANEL return tFILEPANEL; +LAYOUT return tLAYOUT; +TEXTEDIT return tTEXTEDIT; +COUNT return tCOUNT; +VIEW return tVIEW; +BOXVIEW return tBOXVIEW; +TABVIEW return tTABVIEW; +ELLIPSE return tELLIPSE; +DOT return tDOT; +LINE return tLINE; +CURVE return tCURVE; +CIRCLE return tCIRCLE; +CLEAR return tCLEAR; +TEXT return tTEXT; +RECT return tRECT; +SLIDER return tSLIDER; +OPTION return tOPTION; +DROPZONE return tDROPZONE; +COLORCONTROL return tCOLORCONTROL; +TREEBOX return tTREEBOX; +SORT return tSORT; +TOOLTIP return tTOOLTIP; +COLUMNBOX return tCOLUMNBOX; +COLUMN return tCOLUMN; +CLIPBOARD return tCLIPBOARD; +COPY return tCOPY; +SUBMENU return tSUBMENU; +KEYBOARD return tKEYBOARD; +SELECT return tSELECT; +CALENDAR return tCALENDAR; +SCROLLBAR return tSCROLLBAR; +COLLAPSE return tCOLLAPSE; +EXPAND return tEXPAND; +SOUND return tSOUND; +PLAY return tPLAY; +STOP return tSTOP; +SPLITVIEW return tSPLITVIEW; +STACKVIEW return tSTACKVIEW; +TEXTURL return tTEXTURL; +SPINCONTROL return tSPINCONTROL; +POPUPMENU return tPOPUPMENU; +SEND return tMSEND; +MESSAGE return tNUMMESSAGE; +THREAD return tTHREAD; +BITMAP return tBITMAP; +CANVAS return tCANVAS; +SHORTCUT return tSHORTCUT; +SAVE return tSAVE; +ISCOMPUTERON return tISCOMPUTERON; +SCREENSHOT return tSCREENSHOT; +STATUSBAR return tSTATUSBAR; +LAUNCH return tLAUNCH; +ATTRIBUTE return tATTRIBUTE; + +"PASTE$" return tPASTE; +IMAGE return tIMAGE; +SVG return tSVG; +"MESSAGE$" return tMESSAGE; +"TRANSLATE$" return tTRANSLATE; +"GET$" return tGET; +MOUSE return tMOUSE; +ISMOUSEIN return tISMOUSEIN; +GET return tGETNUM; + +SIN return tSIN; +ASIN return tASIN; +COS return tCOS; +ACOS return tACOS; +TAN return tTAN; +ATAN return tATAN; +EXP return tEXP; +LOG return tLOG; +SQRT return tSQRT; +SQR return tSQR; +INT return tINT; +FRAC return tFRAC; +ABS return tABS; +SIG return tSIG; +MOD return tMOD; +RAN return tRAN; +MIN return tMIN; +MAX return tMAX; +"LEFT$" return tLEFT; +"RIGHT$" return tRIGHT; +"MID$" return tMID; +"LOWER$" return tLOWER; +"UPPER$" return tUPPER; +"LTRIM$" return tLTRIM; +"RTRIM$" return tRTRIM; +"TRIM$" return tTRIM; +INSTR return tINSTR; +RINSTR return tRINSTR; +LEN return tLEN; +VAL return tVAL; +EOF return tMYEOF; +"STR$" return tSTR; +"INKEY$" return tINKEY; +"CHR$" return tCHR; +ASC return tASC; +"HEX$" return tHEX; +"BIN$" return tBIN; +DEC return tDEC; +AT return tAT; +@ return tAT; +SCREEN return tSCREEN; +"SYSTEM$" return tSYSTEM; +SYSTEM return tSYSTEM2; +"DATE$" return tDATE; +"TIME$" return tTIME; +PEEK return tPEEK; +"PEEK$" return tPEEK2; +POKE return tPOKE; +TOKEN return tTOKEN; +"TOKEN$" return tTOKENALT; +SPLIT return tSPLIT; +"SPLIT$" return tSPLITALT; +GLOB return tGLOB; +"^" return tPOW; +"**" return tPOW; + +"<>" return tNEQ; +"<=" return tLEQ; +">=" return tGEQ; +"=" return tEQU; +"<" return tLTN; +">" return tGTN; +"!" return tNOT; + +[-+*/:(),.;] {return yytext[0];} + +[0-9]+ { + yylval.digits=(char *)my_strdup(yytext); + return tDIGITS; +} + +(([0-9]+|([0-9]*\.[0-9]*))([eE][-+]?[0-9]+)?) { + { double d; + sscanf(yytext,"%lg",&d); + yylval.fnum=d; + return tFNUM; + } +} + +pi {yylval.fnum=3.1415926535897932;return tFNUM;} +euler {yylval.fnum=2.7182818284590452;return tFNUM;} +TRUE {yylval.fnum=1; return tFNUM;} +FALSE {yylval.fnum=0; return tFNUM;} + +{NAME} { + yylval.symbol=(char *)my_strdup(yytext); + return tSYMBOL; +} + + /* Symbols with a trailing $-sign are treated special */ +{NAME}\$ { + yylval.symbol=(char *)my_strdup(yytext); + return tSTRSYM; +} + +\"[^"]*(\"|\n) { + int cnt; + if (yytext[yyleng-1]=='\n' && fi_pending) {fi_pending--;yyless(0);return tENDIF;} + if (yytext[yyleng-1]=='\n') { + yylval.string=NULL; + return tSTRING; + } + for(cnt=0;yytext[yyleng-cnt-2]=='\\';cnt++) ; + if (cnt%2) { + yyless(yyleng-1); + yymore(); + } else { + yylval.string=(char *)my_strdup(yytext+1); + *(yylval.string+yyleng-2)='\0'; + replace(yylval.string); + return tSTRING; + } +} + + +. {if (isprint(yytext[0])) return yytext[0]; else return ' ';} + +%% +void yyerror(char *msg) +{ + int i,j; + + sprintf(string,"%s at %n",msg,&j); + if (*yytext=='\n' || *yytext=='\0') { + sprintf(string+j,"end of line"); + } else { + i=0; + string[j++]='\"'; + while(yytext[i]) { + if (isprint(yytext[i])) string[j++]=yytext[i++]; + else { + sprintf(string+j,"0x%02x",yytext[i]); + j+=4; + break; + } + } + string[j++]='\"'; + string[j]='\0'; + } + error(ERROR,string); + return; +} + + +void open_main(FILE *file,char *explicit,char *main_file_name) /* open main file */ +{ + include_stack_ptr=0; + + if (explicit) + include_stack[include_stack_ptr]=yy_scan_string(explicit); + else + include_stack[include_stack_ptr]=yy_create_buffer(file,YY_BUF_SIZE); + libfile_stack[include_stack_ptr]=new_file(main_file_name,"main"); + libfile_chain[libfile_chain_length++]=libfile_stack[include_stack_ptr]; + if (!explicit) yy_switch_to_buffer(include_stack[include_stack_ptr]); + currlib=libfile_stack[0]; + inlib=FALSE; + + return; +} + +void open_string(char *cmd) /* open string with commands */ +{ + yy_switch_to_buffer(yy_scan_string(cmd)); +} + + +int import_lib(char *name) /* import library */ +{ + char *full; + static int end_of_import=FALSE; + + if (!*name) name=pop(stSTRING)->pointer; + while(isspace(*name)) name++; + + if (!strcmp(name,"__END_OF_IMPORT")) end_of_import=TRUE; + if (end_of_import) return TRUE; + + /* start line numbers anew */ + libfile_stack[include_stack_ptr]->lineno=mylineno; + + include_stack_ptr++; + if (include_stack_ptr>=MAX_INCLUDE_DEPTH) { + sprintf(string,"Could not import '%s': nested too deep",name); + error(ERROR,string); + return FALSE; + } + + if (is_bound) { + full=name; + } else { + yyin=open_library(name,&full,FALSE); + if (!yyin) return FALSE; + yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE)); + include_stack[include_stack_ptr]=YY_CURRENT_BUFFER; + } + libfile_stack[include_stack_ptr]=new_file(full,NULL); + libfile_chain[libfile_chain_length++]=libfile_stack[include_stack_ptr]; + if (libfile_chain_length>=MAX_INCLUDE_NUMBER) { + sprintf(string,"Cannot import more than %d libraries",MAX_INCLUDE_NUMBER); + error(ERROR,string); + return FALSE; + } + if (!libfile_stack[include_stack_ptr]) { + sprintf(string,"library '%s' has already been imported",full); + error(ERROR,string); + return FALSE; + } + + if (infolevel>=NOTE && !is_bound) { + sprintf(string,"importing from file '%s'",full); + error(NOTE,string); + } + return TRUE; +} + + +FILE *open_library(char *name,char **fullreturn,int without) /* search and open a library */ +{ + static char full[200]; + char unquoted[200]; + char *p; + FILE *lib; + int i; + char *trail; + + if (fullreturn) *fullreturn=full; + + for(p=name;strchr(" \"'`",*p);p++) if (!*p) break; + strncpy(unquoted,p,200); + for(;!strchr(" \"'`",*p);p++) if (!*p) break; + if (*p) unquoted[p-name-2]='\0'; + name=unquoted; + if (strchr(name,'.')) { + sprintf(string,"library name '%s' contains '.'",name); + error(ERROR,string); + return NULL; + } + if (!strcmp(name,"main")) { + if (is_bound) return NULL; + error(ERROR,"invalid library name 'main'"); + return NULL; + } + + /* search local */ + trail=".yab"; + for(i=0;i<2;i++) { + strcpy(full,name); + if (!strchr(full,'.')) strcat(full,trail); + lib=fopen(full,"r"); + if (lib) return lib; + trail=""; + if (!without) break; + } + + /* search in global location */ + trail=".yab"; + for(i=0;i<2;i++) { + strcpy(full,library_path); + if (full[0] && !strchr("\\/",full[strlen(full)-1])) { +#ifdef UNIX + strcat(full,"/"); +#else + strcat(full,"\\"); +#endif + } + strcat(full,name); + if (!strchr(full,'.')) strcat(full,trail); + lib=fopen(full,"r"); + if (lib) return lib; + trail=""; + if (!without) break; + } + + sprintf(string,"couldn't open library '%s'",full); + error(ERROR,string); + return NULL; +} + + +void switchlib(void) /* switch library, called by bison */ +{ + if (include_stack_ptr<0) return; + if (infolevel>=DEBUG) { + sprintf(string,"switching from '%s' to '%s'",currlib->s,libfile_stack[include_stack_ptr]->s); + error(DEBUG,string); + } + currlib=libfile_stack[include_stack_ptr]; + mylineno=currlib->lineno; + inlib=(include_stack_ptr>0); +} + + diff --git a/src/yabasic.h b/src/yabasic.h new file mode 100644 index 0000000..b3b103a --- /dev/null +++ b/src/yabasic.h @@ -0,0 +1,885 @@ +/* + + YABASIC --- a simple Basic Interpreter + written by Marc-Oliver Ihm 1995-2004 + homepage: www.yabasic.de + + yabasic.h --- function prototypes and global variables + + This file is part of yabasic and may be copied only + under the terms of either the Artistic License or + the GNU General Public License (GPL), both of which + can be found at www.yabasic.de + +*/ + + +#define YABLICENSE \ +"\n"\ +" Yab may only be copied under the terms of the Artistic \n"\ +" License which can be found at yab-interpreter.sourceforge.net. \n"\ +"\n"\ +" The Artistic License gives you the right to use and distribute \n"\ +" yab in a more-or-less customary fashion, plus the right to make \n"\ +" reasonable modifications and distribute (or even sell) such a \n"\ +" modified version under a different name. \n"\ +" However, the original author and copyright holder still reserves \n"\ +" himself some sort of artistic control over the development \n"\ +" of yab itself. \n"\ + + + +#define YABASIC_INCLUDED + +/* ------------- defines ---------------- */ + +/* + Define one and only one of the following symbols, depending on your + System: + - UNIX: uses some UNIX-features and X11 + - WINDOWS: uses WIN32-features + Define UNIX and BEOS for a BeOS build +*/ + +#if defined(UNIX) && defined(WINDOWS) +UNIX and WINDOWS are defined at once; check your compiler settings +#endif + + +/* ------------- includes ---------------- */ + +#include "global.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef WINDOWS +#include +#include +#include +#define ARCHITECTURE "windows" +#ifdef __LCC__ /* fix for lccwin32 */ +#include +#endif +#endif + +#include "YabInterface.h" + + +#ifdef UNIX +#define ARCHITECTURE UNIX_ARCHITECTURE +#ifdef HAS_STRING_HEADER +#include +#elif HAS_STRINGS_HEADER +#include +#endif + +#include +#include + +#ifndef BEOS + #include + #include + #include + #include + #define XK_LATIN1 + #define XK_MISCELLANY + #include +#endif + +#include +#include +#ifdef BUILD_NCURSES +#include +// #else +// #ifdef HAVE_CURSES_HEADER +// #include +// #endif +#endif +#ifndef KEY_MAX +#define KEY_MAX 0777 +#endif +#endif + +#ifndef FOPEN_MAX +#define FOPEN_MAX 24 +#endif + +#include +#include + +#ifdef UNIX +#ifndef LIBRARY_PATH +#define LIBRARY_PATH "/boot/home/config/settings/yab" +#endif +#endif + +#define OPEN_HAS_STREAM 1 +#define OPEN_HAS_MODE 2 +#define OPEN_PRINTER 8 +#define STDIO_STREAM 1234 + +/* -------- variables needed in all files and defined in ... -------- */ + +/* main.c */ +extern struct command *current; /* currently executed command */ +extern struct command *cmdroot; /* first command */ +extern struct command *cmdhead; /* next command */ +extern struct command *lastcmd; /* last command */ +extern int infolevel; /* controls issuing of error messages */ +extern int errorlevel; /* highest level of error message seen til now */ +extern int interactive; /* true, if commands come from stdin */ +extern char *progname; /* name of yabasic-program */ +extern char *explanation[]; /* explanations of commands */ +extern char **yabargv; /* arguments for yabasic */ +extern int yabargc; /* number of arguments in yabargv */ +extern time_t compilation_start,compilation_end,execution_end; +extern char *string; /* for trash-strings */ +extern char *errorstring; /* for error-strings */ +extern int errorcode; /* error-codes */ +extern char library_path[]; /* full path to search libraries */ +extern int program_state; /* state of program */ +extern int check_compat; /* true, if compatibility should be checked */ +extern int is_bound; /* true, if this executable is bound */ +extern char* appdirectory; /* appdir */ + + +/* io.c */ +extern FILE *streams[]; /* file streams */ +extern int read_controls; /* TRUE, if input should read control characters */ +extern int stream_modes[]; /* modes for streams */ +extern int curinized; /* true, if curses has been initialized */ +extern int badstream(int,int); /* test for valid stream id */ +void myseek(struct command *); /* reposition file pointer */ +#ifdef WINDOWS +extern HANDLE wantkey; /* mutex to signal key desire */ +extern HANDLE gotkey; /* mutex to signal key reception */ +extern HANDLE wthandle; /* handle of win thread */ +extern HANDLE kthandle; /* handle of inkey thread */ +extern DWORD ktid; /* id of inkey thread */ +extern int LINES; /* number of lines on screen */ +extern int COLS; /* number of columns on screen */ +extern HANDLE ConsoleInput; /* handle for console input */ +extern HANDLE ConsoleOutput; /* handle for console output */ +#else +extern int winpid; /* pid of process waiting for window keys */ +extern int termpid; /* pid of process waiting for terminal keys */ +#ifndef BUILD_NCURSES +extern int LINES; /* number of lines on screen */ +extern int COLS; /* number of columns on screen */ +#endif +#endif + +/* graphic.c */ +/* printing and plotting */ +extern int print_to_file; /* print to file ? */ +#ifdef WINDOWS +extern HFONT printerfont; /* handle of printer-font */ +extern HDC printer; /* handle of printer */ +#endif +extern FILE *printerfile; /* file to print on */ +extern double xoff; /* offset for x-mapping */ +extern double xinc; /* inclination of x-mapping */ +extern double yoff; /* offset for y-mapping */ +extern double yinc; /* inclination for y-mapping */ +/* window coordinates */ +extern int winopened; /* flag if window is open already */ +extern char *winorigin; /* e.g. "lt","rc"; defines origin of grafic window */ +extern int winwidth,winheight; /* size of window */ +/* mouse, console and keyboard */ +/* extern int mousex,mousey,mouseb,mousemod; */ /* last know mouse coordinates */ +extern char *ykey[]; /* keys returned by inkey */ +/* text and font */ +extern char *getreg(char *); /* get defaults from Registry */ +extern char *text_align; /* specifies alignement of text */ +extern int fontheight; /* height of font in pixel */ +#ifdef WINDOWS +extern HFONT myfont; /* handle of font for screen */ +#endif +/* general window stuff */ +extern char *foreground; +extern char *background; +extern char *geometry; +extern char *displayname; +extern char *font; +extern int drawmode; +#ifdef WINDOWS +extern HWND window; /* handle of my window */ +extern HANDLE mainthread; /* handle to main thread */ +extern HANDLE this_instance; +extern WNDCLASS myclass; /* window class for my program */ +extern char *my_class; +extern BOOL Commandline; /* true if launched from command line */ +#else +extern int backpid; /* pid of process waiting for redraw events */ +#endif + + +/* function.c */ +extern struct command *datapointer; /* current location for read-command */ + +/* symbol.c */ +extern struct stackentry *stackroot; /* first element of stack */ +extern struct stackentry *stackhead; /* last element of stack */ +extern void query_array(struct command *cmd); /* query array */ +extern struct command *lastref; /* last command in UDS referencing a symbol */ +extern struct command *firstref; /* first command in UDS referencing a symbol */ +extern int labelcount; /* count self-generated labels */ + + +/* flex.c */ +extern int include_stack_ptr; /* Lex buffer for any imported file */ +extern struct libfile_name *libfile_stack[]; /* stack for library file names */ +extern struct libfile_name *currlib; /* current libfile as relevant to bison */ +extern int inlib; /* true, while in library */ +extern int fi_pending; /* true, if within a short if */ +extern int libfile_chain_length; /* length of libfile_chain */ +extern struct libfile_name *libfile_chain[]; /* list of all library file names */ + + +/* bison.c */ +extern char *current_function; /* name of currently parsed function */ +extern int yydebug; +extern int missing_endif; +extern int missing_endif_line; +extern int in_loop; + +/*-------------------------- defs and undefs ------------------------*/ + +/* undef symbols */ +#undef FATAL +#undef ERROR +#undef WARNING +#undef NOTE +#undef DEBUG +#undef DUMP + +#if !defined(TRUE) +#define TRUE (1==1) +#endif + +#ifndef FALSE +#define FALSE (1!=1) +#endif + +/* I've been told, that some symbols are missing under SunOs ... */ +#ifndef RAND_MAX +#define RAND_MAX 32767 +#endif + +/* length of buffers for system() and input */ +#define SYSBUFFLEN 100 +#define INBUFFLEN 10000 + + +/* ---------------------- enum types ------------------------------- */ + +enum error { /* error levels */ + FATAL,ERROR,INFO,DUMP,WARNING,NOTE,DEBUG +}; + +enum endreasons { /* ways to end the program */ + erNONE,erERROR,erREQUEST,erEOF +}; + +enum streammodes { /* ways to access a stream */ + smCLOSED=0,smREAD=1,smWRITE=2,smPRINT=4 +}; + +enum functions { /* functions in yabasic (sorted by number of arguments) */ + fRAN2,fDATE,fTIME,fMESSAGE,fNUMWINDOWS,fCLIPBOARDPASTE,fISCOMPUTERON,fMOUSEMOVE, + fZEROARGS, + fINKEY,/* fMOUSEX,fMOUSEY,fMOUSEB,fMOUSEMOD,*/ + fSIN,fASIN,fCOS,fACOS,fTAN, + fATAN,fSYSTEM,fSYSTEM2,fPEEK,fPEEK2,fPEEK4,fTELL,fEXP,fLOG,fLEN,fSTR, + fSQRT,fSQR,fFRAC,fABS,fSIG,fRAN,fINT,fVAL,fASC,fHEX,fBIN,fDEC,fUPPER,fLOWER, + fLTRIM,fRTRIM,fTRIM,fCHR,fTRANSLATE,fMENUTRANSLATE,fMOUSE, fISMOUSEIN,fTEXTCONTROLGET, + fKEYBOARD,fCOLUMNBOXCOUNT, fCALENDAR, fLISTBOXCOUNT, fTREEBOXCOUNT, fSTACKVIEWGET, + fSPINCONTROLGET, fDROPBOXCOUNT, fSLIDERGET, fTEXTGET, fDRAWGET3, fTABVIEWGET, + fLISTBOXGETNUM, fDROPBOXGETNUM, fCOLUMNBOXGETNUM, fTREEBOXGETNUM, fSOUND, + fONEARGS, + fDEC2,fATAN2,fLEFT,fAND,fOR,fEOR,fLOG2, + fRIGHT,fINSTR,fRINSTR,fSTR2,fMOD,fMIN,fMAX,fPEEK3,fMID2,fWINDOWGET, fVIEWGET /* vasper */, + fLISTBOXGET, fTREEBOXGET, fSCROLLBARGET, fSPLITVIEWGET, fDROPBOXGET, fCOLORCONTROLGET, + fTEXTGET2,fTEXTGET6,fDRAWGET2, fTEXTGET3, fMESSAGESEND, fTHREADKILL, fTHREADGET, fBITMAPGET, + fBITMAPLOAD, fATTRIBUTEGET1, fATTRIBUTEGET2, + fTWOARGS, + fMID,fINSTR2,fRINSTR2,fSTR3,fCOLUMNBOXGET,fDRAWGET1,fTEXTGET4,fTEXTGET5,fPRINTER, + fLOAD, fTREEBOXGETOPT,fBITMAPSAVE, + fTHREEARGS, + fGETCHAR,fDRAWIMAGE,fPOPUPMENU,fSAVE,fDRAWGET4,fBITMAPCOLOR, + fFOURARGS, + fALERT, + fFIVEARGS, + fDRAWSVG,fDRAWIMAGE2, + fSIXARGS +}; + +enum arraymode { /* type of array access */ + CALLARRAY,ASSIGNARRAY,CALLSTRINGARRAY,ASSIGNSTRINGARRAY,GETSTRINGPOINTER +}; + +enum drawing_modes { /* various ways to draw */ + dmNORMAL=0,dmCLEAR=1,dmFILL=2 +}; + +enum cmd_type { /* type of command */ + cFIRST_COMMAND, /* no command, just marks start of list */ + + cLABEL,cSUBLINK,cGOTO,cQGOTO,cGOSUB,cQGOSUB,cRETURN, /* flow control */ + cEND,cEXIT,cBIND,cDECIDE,cSKIPPER,cNOP,cFINDNOP,cEXCEPTION,cANDSHORT, + cORSHORT,cSKIPONCE,cRESETSKIPONCE,cCOMPILE,cEXECUTE,cEXECUTE2, + + cDIM,cFUNCTION,cDOARRAY,cARRAYLINK,cPUSHARRAYREF,cCLEARREFS, /* everything with "()" */ + cARDIM,cARSIZE,cTOKEN,cTOKEN2,cTOKENALT,cTOKENALT2, + cSPLIT,cSPLIT2,cSPLITALT,cSPLITALT2, + cSTARTFOR,cFORCHECK,cFORINCREMENT, /* for for-loops */ + + cSWITCH_COMPARE,cNEXT_CASE,cBREAK,cMINOR_BREAK, /* break-continue-switch */ + cCONTINUE,cBREAK_HERE,cCONTINUE_HERE,cCONTINUE_CORRECTION, + cBREAK_MARK,cPUSH_SWITCH_MARK,cCLEAN_SWITCH_MARK, + + cDBLADD,cDBLMIN,cDBLMUL,cDBLDIV,cDBLPOW, /* double operations */ + cNEGATE,cPUSHDBLSYM,cPOP,cPOPDBLSYM,cPUSHDBL, + + cREQUIRE,cPUSHFREE,cMAKELOCAL,cMAKESTATIC,cNUMPARAM, /* functions and procedures */ + cCALL,cQCALL,cPUSHSYMLIST,cPOPSYMLIST,cRET_FROM_FUN, + cUSER_FUNCTION,cRETVAL,cEND_FUNCTION, + cFUNCTION_OR_ARRAY,cSTRINGFUNCTION_OR_ARRAY, + + cPOKE,cPOKEFILE,cSWAP,cDUPLICATE,cDOCU, /* internals */ + + cAND,cOR,cNOT,cLT,cGT,cLE,cGE,cEQ,cNE, /* comparisons */ + cSTREQ,cSTRNE,cSTRLT,cSTRLE,cSTRGT,cSTRGE, + + cPUSHSTRSYM,cPOPSTRSYM,cPUSHSTR,cCONCAT, /* string operations */ + cPUSHSTRPTR,cCHANGESTRING,cGLOB, + + cPRINT,cREAD,cRESTORE,cQRESTORE,cONESTRING, /* i/o operations */ + cREADDATA,cDATA,cOPEN,cCHECKOPEN,cCHECKSEEK,cCLOSE,cPUSHSTREAM,cPOPSTREAM, + cSEEK,cSEEK2,cTESTEOF,cWAIT,cBELL,cMOVE, + cCLEARSCR,cCOLOUR,cCHKPROMPT,cERROR, + + /* + cDOT,cLINE,cCIRCLE,cCLEARWIN, + cOPENPRN,cCLOSEPRN,cMOVEORIGIN,cRECT, + cPUTBIT, */ + + cPUTCHAR, + + cOPENWIN, cCLOSEWIN, cLAYOUT, cWINSET1, cWINSET2, cWINSET3, cWINSET4, /* Be Graphics */ + cBUTTON, cALERT, cMENU, cTEXTCONTROL, cCHECKBOX, cRADIOBUTTON, cWINCLEAR, + cLISTBOX, cDROPBOX, cITEMADD, cITEMDEL, cITEMCLEAR, cLOCALIZE, cLOCALIZE2, cLOCALIZESTOP, cTEXT, cTEXT2, cTEXTALIGN, + cTEXTEDIT, cTEXTADD, cTEXTSET, cTEXTSET2, cTEXTCOLOR1, cTEXTCOLOR2, cTEXTSET3, cTEXTCLEAR, + cVIEW, cBOXVIEW, cBOXVIEWSET, cTAB, cSLIDER1, cSLIDER2, cSLIDER3, cSLIDER4, cSLIDER5, cSLIDER6, + cOPTION1, cOPTION2, cOPTION3, cDROPZONE, cTEXTCONTROL2, cTEXTCONTROL3, cTEXTCONTROL4, cTEXTCONTROL5, + cCOLORCONTROL1, cCOLORCONTROL2, cTREEBOX1, cTREEBOX2, cTREEBOX3, cTREEBOX4, cTREEBOX5, + cBUTTONIMAGE, cCHECKBOXIMAGE, cCHECKBOXSET, cRADIOSET, cTOOLTIP, cTOOLTIPCOLOR, cTREESORT, + cLISTSORT, cFILEBOX, cFILEBOXADD2, cFILEBOXCLEAR, cCOLUMNBOXREMOVE, + cCOLUMNBOXSELECT, cCOLUMNBOXADD, cDROPBOXSELECT, cMENU2, cSUBMENU1, cSUBMENU2, cCLIPBOARDCOPY, + cCOLUMNBOXCOLOR, cPRINTERCONFIG, cCALENDAR, cLISTBOXSELECT, cLISTBOXADD1, cLISTBOXADD2, + cLISTBOXDEL2, cSCROLLBAR, cSCROLLBARSET1, cSCROLLBARSET2, cSCROLLBARSET3, cTREEBOX7, cTREEBOX8, + cTREEBOX9, cTREEBOX10, cTREEBOX11, cSPLITVIEW1, cSPLITVIEW2, cSPLITVIEW3, + cSTACKVIEW1, cSTACKVIEW2, cTEXTURL1, cTEXTURL2, cDRAWSET3, cSPINCONTROL1, cTABSET, cTABDEL, cTABADD, + cSPINCONTROL2, cDROPBOXREMOVE, cDROPBOXCLEAR, cSUBMENU3, cMENU3, cCALENDARSET, + cDOT, cLINE, cCIRCLE, cDRAWTEXT, cDRAWRECT, cTREEBOX12, cOPTION4, cOPTION5, + cDRAWCLEAR, cDRAWSET1, cDRAWSET2, cELLIPSE, cCURVE, /* Drawing */ + cBITMAP, cBITMAPDRAW, cBITMAPDRAW2, cBITMAPGET, cBITMAPGET2, cBITMAPGETICON, cBITMAPDRAG, cBITMAPREMOVE, cCANVAS, /* Bitmaps */ + cSOUNDSTOP, cSOUNDWAIT, /* Sound */ + cTREEBOX13, cDRAWSET4, cSHORTCUT, cMOUSESET, + cSCREENSHOT, cSTATUSBAR, cSTATUSBARSET, cSTATUSBARSET2, cSTATUSBARSET3, cLAUNCH, cRESTORE2, cRESTORE3, + cATTRIBUTE1, cATTRIBUTE2, cATTRIBUTECLEAR, + cLAST_COMMAND /* no command, just marks end of list */ +}; + +enum stackentries { /* different types of stackentries */ + stGOTO,stSTRING,stSTRINGARRAYREF,stNUMBER,stNUMBERARRAYREF,stLABEL,stRETADD,stRETADDCALL,stFREE,stROOT, + stANY,stSTRING_OR_NUMBER,stSTRING_OR_NUMBER_ARRAYREF, /* these will never appear on stack but are used to check with pop */ + stSWITCH_MARK, /* used to clean up stack after switch-statement */ + stSWITCH_STRING,stSWITCH_NUMBER /* only used in switch statement, compares true to every string or number */ +}; + +enum symbols { /* different types of symbols */ + sySTRING,syNUMBER,syFREE,syARRAY +}; + +enum function_type { /* different types of functions */ + ftNONE,ftNUMBER,ftSTRING +}; + +enum addmodes { /* different modes for adding symbols */ + amSEARCH,amSEARCH_PRE,amADD_LOCAL,amADD_GLOBAL,amSEARCH_VERY_LOCAL +}; + +enum states { /* current state of program */ + HATCHED,INITIALIZED,COMPILING,RUNNING,FINISHED +}; + +enum yabkeys { /* recognized special keys */ + kERR,kUP,kDOWN,kLEFT,kRIGHT,kDEL,kINS,kCLEAR,kHOME,kEND, + kF0,kF1,kF2,kF3,kF4,kF5,kF6,kF7,kF8,kF9,kF10,kF11,kF12, + kF13,kF14,kF15,kF16,kF17,kF18,kF19,kF20,kF21,kF22,kF23,kF24, + kBACKSPACE,kSCRNDOWN,kSCRNUP,kENTER,kESC,kTAB,kLASTKEY +}; + +enum searchmodes { /* modes for searching labels */ + smSUB=1,smLINK=2,smLABEL=4,smGLOBAL=8 +}; + +/* ------------- global types ---------------- */ + +struct stackentry { /* one element on stack */ + int type; /* contents of entry */ + struct stackentry *next; + struct stackentry *prev; + void *pointer; /* multiuse ptr */ + double value; /* double value, only one of pointer or value is used */ +}; + +/* + symbols are organized as a stack of lists: for every procedure call + a new list is pushed onto the stack; all local variables of this + function are chained into this list. After return from this procedure, + the whole list is discarded and one element is popped from + the stack. +*/ + +struct symstack { /* stack of symbol lists */ + struct symbol *next_in_list; + struct symstack *next_in_stack; + struct symstack *prev_in_stack; +}; + +struct symbol { /* general symbol; either variable, string */ + int type; + struct symbol *link; /* points to linked symbol, if any */ + struct symbol *next_in_list; /* next symbol in symbollist */ + char *name; /* name of symbol */ + void *pointer; /* pointer to string contents (if any) */ + char *args; /* used to store number of arguments for functions/array */ + double value; +}; + +struct command { /* one interpreter command */ + int type; /* type of command */ + int cnt; /* count of this command */ + struct command *prev; /* link to previous command */ + struct command *next; /* link to next command */ + void *pointer; /* pointer to data */ + void *symbol; /* pointer to symbol (or data within symbol) associated with command */ + struct command *jump; /* pointer to jump destination */ + char *name; /* name of symbol associated with command */ + struct command *nextref; /* next cmd within function referencing a symbol */ + struct command *nextassoc; /* next cmd within within chain of associated commands */ + int args; /* number of arguments for function/array call */ + /* or stream number for open/close */ + int tag; /* char/int to pass some information */ + int line; /* line this command has been created for */ + struct libfile_name *lib; /* associated library */ + int switch_id; /* TRUE, if in switch, FALSE else; used to check gotos */ +}; + +struct array { /* data structure for arrays */ + int bounds[10]; /* index boundaries */ + int dimension; /* dimension of array */ + void *pointer; /* contents of array */ + char type; /* decide between string- ('s') and double-Arrays ('d') */ +}; + +struct buff_chain { /* buffer chain for system-input */ + char buff[SYSBUFFLEN+1]; /* content of buffer */ + int len; /* used length of buff */ + struct buff_chain *next; /* next buffer in chain */ +}; + +struct libfile_name { /* used to store library names */ + char *l; /* long version, including path */ + int llen; /* length of l */ + char *s; /* short version */ + int slen; /* length of s */ + int lineno; /* linenumber within file */ + struct command *datapointer; /* data pointer of this library */ + struct command *firstdata; /* first data-command in library */ + struct libfile_name *next; /* next in chain */ +}; + +/* ------------- function prototypes defined in ... ---------------- */ + +/* main.c */ +void error(int,char *); /* reports an error and possibly exits */ +void error_with_line(int,char *,int); /* reports an error and possibly exits */ +void *my_malloc(unsigned); /* my own version of malloc */ +void my_free(void *); /* free memory */ +char *my_strerror(int); /* return description of error messages */ +struct command *add_command(int,char *); /* get room for new command */ +void signal_handler(int); /* handle various signals */ +char *my_strdup(char *); /* my own version of strdup */ +char *my_strndup(char *,int); /* own version of strndup */ +struct libfile_name *new_file(char *,char *); /* create a new structure for library names */ +char *dotify(char *,int); /* add library name, if not already present */ +char *strip(char *); /* strip off to minimal name */ +void do_error(struct command *); /* issue user defined error */ +void create_docu(char *); /* create command 'docu' */ +extern void add_variables(char *); /* add pi and e to symbol table */ +void compile(void); /* create a subroutine at runtime */ +void create_execute(int); /* create command 'cEXECUTE' */ +void execute(struct command *); /* execute a subroutine */ +int isbound(void); /* check if this interpreter is bound to a program */ + + +/* io.c */ +void checkopen(void); /* check, if open has been sucessfull */ +void create_colour(int); /* create command 'reverse' */ +void colour(struct command *cmd); /* switch reverse-printing */ +void create_print(char); /* create command 'print' */ +void print(struct command *); /* print on screen */ +void create_myread(char,int); /* create command 'read' */ +void myread(struct command *); /* read from file or stdin */ +void create_onestring(char *); /* write string to file */ +void onestring(char *); /* write string to file */ +void chkprompt(void); /* print an intermediate prompt if necessary */ +void create_myopen(int); /* create command 'myopen' */ +void myopen(struct command *); /* open specified file for given name */ +void testeof(struct command *); /* close the specified stream */ +void myclose(); /* close the specified stream */ +void create_pps(int,int); /* create command pushswitch or popswitch */ +void push_switch(struct command *); /* push current stream on stack and switch to new one */ +void pop_switch(void); /* pop current stream from stack and switch to it */ +void mymove(); /* move to specific position on screen */ +void clearscreen(); /* clear entire screen */ +char *inkey(double); /* gets char from keyboard, blocks and doesn´t print */ +char *replace(char *); /* replace \n,\a, etc. */ + +/* graphic.c */ +void create_openwin(int); /* create Command 'openwin' */ +void openwin(struct command *, YabInterface* yab); /* open a Window */ +void closewin(struct command *, YabInterface* yab); /* close the window */ +int numwindows(); /* number of windows opened */ +void createbutton(struct command *, YabInterface* yab); /* create a Button */ +int createimage(double x, double y, const char* imagefile, const char* window, YabInterface* yab, int line, const char* libname); /* insert an image*/ +int createimage2(double x1, double y1, double x2, double y2, const char* imagefile, const char* window, YabInterface* yab, int line, const char* libname); /* insert an image*/ +int createsvg(double x1, double y1, double x2, double y2, const char* imagefile, const char* window, YabInterface* yab, int line, const char* libname); /* insert a svg image*/ +int ismousein(const char* view, YabInterface *yab, int line, const char* libname); /* check if mouse is in view */ +char* getmousein(YabInterface *yab, int line, const char* libname); /* check which view the mouse is in */ //vasper +void drawtext(struct command *, YabInterface* yab); /* draw text */ +void drawrect(struct command *, YabInterface* yab); /* draw rectangle */ +void drawclear(struct command *, YabInterface* yab); /* clears canvas */ +void createmenu(struct command *, YabInterface* yab); /* add a menu */ +void createalert(struct command *, YabInterface* yab); /* alert */ +void createtext(struct command *, YabInterface* yab); /* text */ +void text2(struct command *, YabInterface* yab); /* text */ +void textalign(struct command *, YabInterface* yab); /* align text */ +void createtextcontrol(struct command *, YabInterface* yab); /* textcontrol */ +void createcheckbox(struct command *, YabInterface* yab); /* checkbox*/ +void createradiobutton(struct command *, YabInterface* yab); /* radio button */ +void createlistbox(struct command *, YabInterface* yab); /* list box */ +void createdropbox(struct command *, YabInterface* yab); /* drop box */ +void createitem(struct command *, YabInterface* yab); /* item add*/ +void removeitem(struct command *, YabInterface* yab); /* item del*/ +void clearitems(struct command *, YabInterface* yab); /* clears itemlist */ +void localize(); +void localizestop(); +void localize2(struct command *, YabInterface* yab); +void setlayout(struct command *, YabInterface* yab); /* set layout */ +void winset1(struct command *, YabInterface* yab); +void winset2(struct command *, YabInterface* yab); +void winset3(struct command *, YabInterface* yab); +void winset4(struct command *, YabInterface* yab); +void winclear(struct command *, YabInterface* yab); +void textedit(struct command *, YabInterface* yab); +void textadd(struct command *, YabInterface* yab); +void textset(struct command *, YabInterface* yab); +void textset2(struct command *, YabInterface* yab); +void textset3(struct command *, YabInterface* yab); +void textcolor1(struct command *, YabInterface* yab); +void textcolor2(struct command *, YabInterface* yab); +void textclear(struct command *, YabInterface* yab); +char* textget(const char*, YabInterface* yab, int line, const char* libname); +int textget2(const char*, const char*, YabInterface* yab, int line, const char* libname); +char* textget3(const char*, int, YabInterface* yab, int line, const char* libname); +double textget4(const char*, const char*, int, YabInterface* yab, int line, const char* libname); +int textget5(const char*, const char*, const char*, YabInterface* yab, int line, const char* libname); +char* textget6(const char*, const char*, YabInterface *yab, int line, const char* libname); +char* textcontrolget(const char*, YabInterface* yab, int line, const char* libname); +void drawset1(struct command *, YabInterface* yab); +void drawset2(struct command *, YabInterface* yab); +char* getmessages(YabInterface* yab, int line, const char* libname); /* get message string */ +char* getmousemessages(const char* view, YabInterface* yab, int line, const char* libname); /* get mouse message string */ +char* gettranslation(const char*,YabInterface* yab, int line, const char* libname); /* get translation string */ +char* getmenutranslation(const char*,YabInterface* yab, int line, const char* libname); /* get translation string */ +char* getloadfilepanel(const char*, const char*, const char*, YabInterface *yab, int line, const char* libname); /* open a load filepanel */ +char* getsavefilepanel(const char*, const char*, const char*, const char*, YabInterface *yab, int line, const char* libname); /* open a save filepanel */ +void view(struct command *, YabInterface *yab); /* add a view */ +void boxview(struct command *, YabInterface *yab); /* add a boxview */ +void boxviewset(struct command *, YabInterface *yab);/*boxview options*/ +void tab(struct command *, YabInterface *yab); /* add a tab */ +void tabset(struct command *, YabInterface *yab); /* set a tab */ +void tabadd(struct command *, YabInterface *yab); +void tabdel(struct command *, YabInterface *yab); +int tabviewget(const char* tab, YabInterface *yab, int line, const char* libname); /* get a tab */ +void drawdot(struct command *, YabInterface *yab); /* draw a dot */ +void drawline(struct command *, YabInterface *yab); /* draw a line */ +void drawcircle(struct command *, YabInterface *yab); /* draw a circle */ +void drawellipse(struct command *, YabInterface *yab); /* draw a ellipse */ +void drawcurve(struct command *, YabInterface *yab); /* draw a curve */ +void slider1(struct command *, YabInterface *yab); +void slider2(struct command *, YabInterface *yab); +void slider3(struct command *, YabInterface *yab); +void slider4(struct command *, YabInterface *yab); +void slider5(struct command *, YabInterface *yab); +void slider6(struct command *, YabInterface *yab); +void option1(struct command *, YabInterface *yab); +void option2(struct command *, YabInterface *yab); +void option3(struct command *, YabInterface *yab); +void dropzone(struct command *, YabInterface *yab); +void colorcontrol1(struct command *, YabInterface *yab); +void colorcontrol2(struct command *, YabInterface *yab); +void textcontrol2(struct command *, YabInterface *yab); +void textcontrol3(struct command *, YabInterface *yab); +void textcontrol4(struct command *, YabInterface *yab); +void textcontrol5(struct command *, YabInterface *yab); +void treebox1(struct command *, YabInterface *yab); +void treebox2(struct command *, YabInterface *yab); +void treebox3(struct command *, YabInterface *yab); +void treebox4(struct command *, YabInterface *yab); +void treebox5(struct command *, YabInterface *yab); +void treebox7(struct command *, YabInterface *yab); +void treebox8(struct command *, YabInterface *yab); +void treebox9(struct command *, YabInterface *yab); +void treebox10(struct command *, YabInterface *yab); +void treebox11(struct command *, YabInterface *yab); +void buttonimage(struct command *, YabInterface *yab); +void checkboximage(struct command *, YabInterface *yab); +void checkboxset(struct command *, YabInterface *yab); +void radioset(struct command *, YabInterface *yab); +void tooltip(struct command *, YabInterface *yab); +void tooltipcolor(struct command *, YabInterface *yab); +void listsort(struct command *, YabInterface *yab); +void treesort(struct command *, YabInterface *yab); +void filebox(struct command *, YabInterface *yab); +void fileboxadd2(struct command *, YabInterface *yab); +void fileboxclear(struct command *, YabInterface *yab); +void columnboxadd(struct command *, YabInterface *yab); +void columnboxremove(struct command *, YabInterface *yab); +void columnboxselect(struct command *, YabInterface *yab); +void columnboxcolor(struct command *, YabInterface *yab); +void dropboxselect(struct command *, YabInterface *yab); +void menu2(struct command *, YabInterface *yab); +void submenu1(struct command *, YabInterface *yab); +void submenu2(struct command *, YabInterface *yab); +void clipboardcopy(struct command *, YabInterface *yab); +void launch(struct command *, YabInterface *yab); +int printer(const char* docname, const char *view, const char* config, YabInterface *yab, int line, const char* libname); +void printerconfig(struct command *, YabInterface *yab); +char* keyboardmessages(const char* view, YabInterface* yab, int line, const char* libname); +char* clipboardpaste(YabInterface* yab, int line, const char* libname); +char* columnboxget(const char* columnbox, int column, int position, YabInterface* yab, int line, const char* libname); +int columnboxcount(const char* columnbox, YabInterface* yab, int line, const char* libname); +int windowgetnum(const char* view, const char *option, YabInterface* yab, int line, const char* libname); +int viewgetnum(const char* view, const char *option, YabInterface* yab, int line, const char* libname); //vasper +int newalert(const char* text, const char* button1, const char* button2, const char* button3, const char* option, YabInterface* yab, int line, const char* libname); +void calendar1(struct command *, YabInterface *yab); +char* calendar2(const char* calendar, YabInterface *yab, int line, const char* libname); +void calendar3(struct command *, YabInterface *yab); +void listboxadd1(struct command *, YabInterface *yab); +void listboxadd2(struct command *, YabInterface *yab); +void listboxselect(struct command *, YabInterface *yab); +void listboxremove(struct command *, YabInterface *yab); +int listboxcount(const char* listbox, YabInterface *yab, int line, const char* libname); +char* treeboxget(const char* treebox, int position, YabInterface *yab, int line, const char* libname); +int treeboxcount(const char* treebox, YabInterface *yab, int line, const char* libname); +char* listboxget(const char* listbox, int position, YabInterface *yab, int line, const char* libname); +void scrollbar(struct command *, YabInterface *yab); +void scrollbarset1(struct command *, YabInterface *yab); +void scrollbarset2(struct command *, YabInterface *yab); +void scrollbarset3(struct command *, YabInterface *yab); +double scrollbarget(const char* scrollbar, const char* option, YabInterface *yab, int line, const char* libname); +void splitview1(struct command *, YabInterface *yab); +void splitview2(struct command *, YabInterface *yab); +void splitview3(struct command *, YabInterface *yab); +double splitviewget(const char* splitview, const char* option, YabInterface *yab, int line, const char* libname); +void stackview1(struct command *, YabInterface *yab); +void stackview2(struct command *, YabInterface *yab); +int stackviewget(const char* stackview, YabInterface *yab, int line, const char* libname); +void texturl1(struct command *, YabInterface *yab); +void texturl2(struct command *, YabInterface *yab); +void drawset3(struct command *, YabInterface *yab); +void spincontrol1(struct command *, YabInterface *yab); +void spincontrol2(struct command *, YabInterface *yab); +int spincontrol(const char* spincontrol, YabInterface *yab, int line, const char* libname); +char* popupmenu(double x, double y, const char* messages, const char* id, YabInterface *yab, int line, const char* libname); +void dropboxremove(struct command *, YabInterface *yab); +void dropboxclear(struct command *, YabInterface *yab); +int dropboxcount(const char* id, YabInterface *yab, int line, const char* libname); +char* dropboxget(const char* id, int position, YabInterface *yab, int line, const char* libname); +int sliderget(const char *slider, YabInterface *yab, int line, const char* libname); +int colorcontrolget(const char* colorcontrol, const char* option, YabInterface *yab, int line, const char* libname); +void submenu3(struct command *, YabInterface *yab); +void menu3(struct command *, YabInterface *yab); +double drawget1(const char*, const char*, const char*, YabInterface *yab, int line, const char* libname); +double drawget2(const char*, const char*, YabInterface *yab, int line, const char* libname); +char* drawget3(const char*, YabInterface *yab, int line, const char* libname); +int drawget4(double, double, const char*, const char*, YabInterface *yab, int line, const char* libname); +void option4(struct command *, YabInterface *yab); +void option5(struct command *, YabInterface *yab); +void treebox12(struct command *, YabInterface *yab); +int messagesend(const char*, const char*, YabInterface *yab, int line, const char* libname); +int threadkill(const char*, int, YabInterface *yab, int line, const char* libname); +int threadget(const char*, const char*, YabInterface *yab, int line, const char* libname); +void bitmap(struct command *, YabInterface *yab); +void bitmapdraw(struct command *, YabInterface *yab); +void bitmapdraw2(struct command *, YabInterface *yab); +void bitmapget(struct command *, YabInterface *yab); +void bitmapget2(struct command *, YabInterface *yab); +void bitmapgeticon(struct command *, YabInterface *yab); +void bitmapdrag(struct command *, YabInterface *yab); +void bitmapremove(struct command *, YabInterface *yab); +void screenshot(struct command *, YabInterface *yab); +void statusbar(struct command *, YabInterface *yab); +void statusbarset(struct command *, YabInterface *yab); +void statusbarset2(struct command *, YabInterface *yab); +void statusbarset3(struct command *, YabInterface *yab); +void canvas(struct command *, YabInterface *yab); +int bitmapsave(const char*, const char*, const char*, YabInterface *yab, int line, const char* libname); +int bitmapload(const char*, const char*, YabInterface *yab, int line, const char* libname); +int bitmapgetnum(const char*, const char*, YabInterface *yab, int line, const char* libname); +int bitmapcolor(double x, double y, const char* id, const char* option, YabInterface *yab, int line, const char* libname); +int listboxgetnum(const char*, YabInterface *yab, int line, const char* libname); +int dropboxgetnum(const char*, YabInterface *yab, int line, const char* libname); +int columnboxgetnum(const char*, YabInterface *yab, int line, const char* libname); +int treeboxgetnum(const char*, YabInterface *yab, int line, const char* libname); +int treeboxgetopt(const char*, const char*, int, YabInterface *yab, int line, const char* libname); +void treebox13(struct command *, YabInterface *yab); +void drawset4(struct command *, YabInterface *yab); +int sound(const char*, YabInterface *yab, int line, const char* libname); +void soundstop(struct command *, YabInterface *yab); +void soundwait(struct command *, YabInterface *yab); +void shortcut(struct command *, YabInterface *yab); +int iscomputeron(YabInterface *yab, int line, const char* libname); +void mouseset(struct command *, YabInterface *yab); +void gettermkey(char *); /* read a key from terminal */ +void attribute1(struct command *, YabInterface *yab); +void attributeclear(struct command *, YabInterface *yab); +char* attributeget1(const char*, const char*, YabInterface *yab, int line, const char* libname); +double attributeget2(const char*, const char*, YabInterface *yab, int line, const char* libname); + +/* function.c */ +void create_exception(int); /* create command 'exception' */ +void exception(struct command *); /* change handling of exceptions */ +void create_poke(char); /* create Command 'POKE' */ +void poke(); /* poke in internals */ +void pokefile(struct command *); /* poke into file */ +void create_dblrelop(char); /* create command dblrelop */ +void dblrelop(struct command *); /* compare topmost double-values */ +void concat(void); /* concetenates two strings from stack */ +void create_strrelop(char); /* create command strrelop */ +void strrelop(struct command *); /* compare topmost string-values */ +void create_changestring(int); /* create command 'changestring' */ +void changestring(struct command *); /* changes a string */ +void glob(void); /* check, if pattern globs string */ +void create_boole(char); /* create command boole */ +void boole(struct command *); /* perform and/or/not */ +void create_function(int); /* create command 'function' */ +void function(struct command *, YabInterface* yab); /* performs a function */ +int myformat(char *,double,char *,char *); /* format number */ +void create_restore(char *); /* create command 'restore' */ +void restore(struct command *); /* reset data pointer to given label */ +void create_dbldata(double); /* create command dbldata */ +void create_strdata(char *); /* create command strdata */ +void create_readdata(char); /* create command readdata */ +void readdata(struct command *); /* read data items */ +void mywait(); /* wait given number of seconds */ +void mybell(); /* ring ascii bell */ +void getmousexybm(char *,int *,int *,int *,int *); /* get mouse coordinates */ +void token(struct command *); /* extract token from variable */ +void tokenalt(struct command *); /* extract token from variable with alternate semantics */ + + +/* symbol.c */ +struct array *create_array(int,int); /* create an array */ +void clearrefs(struct command *); /* clear references for commands within function */ +void duplicate(void); /* duplicate topmost element of stack */ +void negate(void); /* negates top of stack */ +void create_require(int); /* create command 'cREQUIRE' */ +void require(struct command *); /* check item on stack has right type */ +void create_makelocal(char *,int); /* create command 'cMAKELOCAL' */ +void create_makestatic(char *,int); /* create command 'cMAKESTATIC' */ +void create_arraylink(char *,int); /* create command 'cARRAYLINK' */ +void create_pusharrayref(char *,int); /* create command 'cPUSHARRAYREF' */ +void pusharrayref(struct command *); /* push an array reference onto stack */ +void arraylink(struct command *); /* link a local symbol to a global array */ +void makestatic(struct command *); /* makes symbol static */ +void makelocal(struct command *); /* makes symbol local */ +void create_numparam(void); /* create command 'cNUMPARAM' */ +void numparam(struct command *); /* count number of function parameters */ +void pushdblsym(struct command *); /* push double symbol onto stack */ +void popdblsym(struct command *); /* pop double from stack */ +void create_pushdbl(double); /* create command 'pushdbl' */ +void pushdbl(struct command *); /* push double onto stack */ +void create_dblbin(char); /* create binary expression calculation */ +void dblbin(struct command *); /* compute with two numbers from stack */ +void pushstrsym(struct command *); /* push string symbol onto stack */ +void popstrsym(struct command *); /* pop string from stack */ +void create_pushstr(char *); /* creates command pushstr */ +void pushstr(struct command *); /* push string onto stack */ +void pushname(char *); /* push a name on stack */ +void pushstrptr(struct command *); /* push string-pointer onto stack */ +void forcheck(void); /* check, if for-loop is done */ +void forincrement(void); /* increment value on stack */ +void startfor(void); /* compute initial value of for-variable */ +void create_goto(char *); /* creates command goto */ +void create_gosub(char *); /* creates command gosub */ +void create_call(char *); /* creates command function call */ +void create_label(char *,int); /* creates command label */ +void create_sublink(char *); /* create link to subroutine */ +void pushgoto(void); /* generate label and push goto on stack */ +void popgoto(void); /* pops a goto and generates the matching command */ +void jump(struct command *); /* jump to specific Label */ +void myreturn(struct command *); /* return from gosub */ +void findnop(); /* used for on_gosub, find trailing nop command */ +void skipper(void); /* used for on_goto/gosub, skip commands */ +void skiponce(struct command *); /* skip next command once */ +void resetskiponce(struct command *); /* find and reset next skip */ +void decide(void); /* skips next command, if not 0 on stack */ +void logical_shortcut(struct command *type); /* shortcut and/or if possible */ +void create_doarray(char *,int); /* creates array-commands */ +void doarray(struct command *); /* call an array */ +void create_dim(char *,char); /* create command 'dim' */ +void dim(struct command *); /* get room for array */ +void pushlabel(void); /* generate goto and push label on stack */ +void poplabel(void); /* pops a label and generates the matching command */ +void storelabel(); /* push label on stack */ +void matchgoto(); /* generate goto matching label on stack */ +void swap(void); /*swap topmost elements on stack */ +struct stackentry *push(void); /* push element on stack and enlarge it*/ +struct stackentry *pop(int); /* pops element to memory */ +struct symbol *get_sym(char *,int,int); /* find and/or add a symbol */ +void link_symbols(struct symbol *,struct symbol *); /* link one symbol to the other */ +void pushsymlist(void); /* push a new list on symbol stack */ +void popsymlist(void); /* pop list of symbols and free symbol contents */ +void dump_sym(); /* dump the stack of lists of symbols */ +void dump_sub(int); /* dump the stack of subroutine calls */ +void create_retval(int,int); /* create command 'cRETVAL' */ +void retval(struct command *); /* check return value of function */ +void create_endfunction(void); /* create command cEND_FUNCTION */ +void function_or_array(struct command *); /* decide whether to do perform function or array */ +struct command *search_label(char *,int); /* search label */ +void reshufflestack(struct stackentry *); /* reorganize stack for function call */ +void push_switch_mark(void); /* push a switch mark */ +void create_clean_switch_mark(int,int); /* add command clean_switch_mark */ +void clean_switch_mark(struct command *); /* pop everything up to (and including) first switch_mark from stack */ +void push_switch_id(void); /* generate a new switch id */ +void pop_switch_id(void); /* get previous switch id */ +int get_switch_depth(void); /* get current depth of switch id stack */ + + +/* flex.c */ +void yyerror(char *); /* yyerror message */ +void open_main(FILE *,char *,char *); /* switch to file */ +void open_string(char *); /* open string with commands */ +FILE *open_library(char *,char **,int); /* search and open a library */ +void switchlib(void); /* switch library, called by bison */ diff --git a/yab-IDE/BuildFactory/AutoFooter.mak b/yab-IDE/BuildFactory/AutoFooter.mak new file mode 100644 index 0000000..1330d8e --- /dev/null +++ b/yab-IDE/BuildFactory/AutoFooter.mak @@ -0,0 +1,77 @@ +## +## GCC Options +## + +SH=$(shell finddir B_SYSTEM_HEADERS_DIRECTORY) +UH= $(shell finddir B_USER_HEADERS_DIRECTORY) +GCC = gcc +GCC_OPT = $(DBG) $(OPT) -I. $(addprefix -I,$(SH)) $(addprefix -I,$(UH)) -DHAVE_CONFIG -DUNIX $(HAIKUOPT) +GPP = g++ +GPP_OPT = $(DBG) $(OPT) -I. -DHAVE_CONFIG -DUNIX $(HAIKUOPT) + + +## +## Compile and link +## +yab: YabMain.o YabInterface.o YabWindow.o YabView.o YabBitmapView.o YabFilePanel.o YabFilePanelLooper.o YabList.o \ + YabText.o flex.o bison.o symbol.o function.o graphic.o io.o main.o $(COLUMN) column/YabColumnType.o column/ColorTools.o YabStackView.o SplitPane.o URLView.o YabControlLook.o \ + $(HAIKUTAB) Spinner.o column/ColumnListView.o CalendarControl.o + $(GPP) $(GPP_OPT) -o $(TARGET) YabMain.o YabInterface.o YabWindow.o YabView.o YabBitmapView.o YabText.o YabFilePanel.o \ + YabFilePanelLooper.o YabList.o main.o function.o io.o graphic.o symbol.o bison.o flex.o $(COLUMN) column/YabColumnType.o column/ColorTools.o \ + YabStackView.o SplitPane.o URLView.o YabControlLook.o $(HAIKUTAB) Spinner.o $(TABLIB) CalendarControl.o \ + $(LIBPATH) $(LIB) +YabMain.o: YabMain.cpp + $(GPP) $(GPP_OPT) -c YabMain.cpp -o YabMain.o +YabInterface.o: YabInterface.cpp YabInterface.h global.h YabMenu.h + $(GPP) $(GPP_OPT) -c YabInterface.cpp -o YabInterface.o +YabWindow.o: YabWindow.cpp YabWindow.h global.h + $(GPP) $(GPP_OPT) -c YabWindow.cpp -o YabWindow.o +YabView.o: YabView.cpp YabView.h + $(GPP) $(GPP_OPT) -c YabView.cpp -o YabView.o +YabBitmapView.o: YabBitmapView.cpp YabBitmapView.h + $(GPP) $(GPP_OPT) -c YabBitmapView.cpp -o YabBitmapView.o +YabFilePanel.o: YabFilePanel.cpp YabFilePanel.h + $(GPP) $(GPP_OPT) -c YabFilePanel.cpp -o YabFilePanel.o +YabFilePanelLooper.o: YabFilePanelLooper.cpp YabFilePanelLooper.h + $(GPP) $(GPP_OPT) -c YabFilePanelLooper.cpp -o YabFilePanelLooper.o +YabList.o: YabList.cpp YabList.h + $(GPP) $(GPP_OPT) -c YabList.cpp -o YabList.o +YabText.o: YabText.cpp YabText.h + $(GPP) $(GPP_OPT) -c YabText.cpp -o YabText.o +bison.o: bison.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c bison.c -o bison.o +flex.o: flex.c bison.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c flex.c -o flex.o +function.o: function.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c function.c -o function.o +io.o: io.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c io.c -o io.o +graphic.o: graphic.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c graphic.c -o graphic.o +symbol.o: symbol.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c symbol.c -o symbol.o +main.o: main.c yabasic.h config.h + $(GCC) $(GCC_OPT) -c main.c -o main.o +YabStackView.o: YabStackView.cpp YabStackView.h + $(GPP) $(GPP_OPT) -c YabStackView.cpp -o YabStackView.o +SplitPane.o: SplitPane.cpp SplitPane.h + $(GPP) $(GPP_OPT) -c SplitPane.cpp -o SplitPane.o +URLView.o: URLView.cpp URLView.h + $(GPP) $(GPP_OPT) -c URLView.cpp -o URLView.o +Spinner.o: Spinner.cpp Spinner.h + $(GPP) $(GPP_OPT) -c Spinner.cpp -o Spinner.o +column/ColumnListView.o: column/ColumnListView.cpp column/ColumnListView.h column/ObjectList.h + $(GPP) $(GPP_OPT) -c column/ColumnListView.cpp -o column/ColumnListView.o +column/ColorTools.o: column/ColorTools.cpp column/ColorTools.h + $(GPP) $(GPP_OPT) -c column/ColorTools.cpp -o column/ColorTools.o +column/YabColumnType.o: column/YabColumnType.cpp column/YabColumnType.h + $(GPP) $(GPP_OPT) -c column/YabColumnType.cpp -o column/YabColumnType.o +$(HAIKUTAB): YabTabView.cpp YabTabView.h + $(GPP) $(GPP_OPT) -c YabTabView.cpp -o YabTabView.o +CalendarControl.o: CalendarControl.cpp CalendarControl.h DateTextView.cpp MonthWindow.cpp MonthView.cpp MouseSenseStringView.cpp + $(GPP) $(GPP_OPT) -c CalendarControl.cpp -o CalendarControl.o +YabControlLook.o: YabControlLook.h YabControlLook.cpp + $(GPP) $(GPP_OPT) -c YabControlLook.cpp -o YabControlLook.o + +clean: + rm -f core *.o column/*.o yabasic.output diff --git a/yab-IDE/BuildFactory/AutoHeader.mak b/yab-IDE/BuildFactory/AutoHeader.mak new file mode 100644 index 0000000..7caf9b6 --- /dev/null +++ b/yab-IDE/BuildFactory/AutoHeader.mak @@ -0,0 +1,40 @@ +## +## yab Haiku BuildFactory Makefile +## +## (c) Jan Bungeroth 2009 - 2011 +## Artistic License. +## + +## +## Haiku stuff +## +HAIKUTAB = YabTabView.o +HAIKUOPT = -DHAIKU + +## +## Use our own column list view +## +COLUMN = column/ColumnListView.o + +## +## enable debug +## +# DBG = -g +# + +## +## enable optimization +## +OPT = -O +# + +## +## Libraries +## +##LIBPATH = -L/boot/home/config/lib +##LIBPATH = -L/boot/system/lib +LIBPATHS = $(shell findpaths B_FIND_PATH_DEVELOP_LIB_DIRECTORY) +LIBPATH=$(addprefix -L,$(LIBPATHS)) + +LIB = -lbe -lroot -ltranslation -ltracker -lmedia -lz + diff --git a/yab-IDE/BuildFactory/BuildFactory.yab b/yab-IDE/BuildFactory/BuildFactory.yab new file mode 100755 index 0000000..275caa9 --- /dev/null +++ b/yab-IDE/BuildFactory/BuildFactory.yab @@ -0,0 +1,488 @@ +#!yab + +////////////////////////////////////// +// BuildFactory v 2.4 +////////////////////////////////////// + +// find out in which directory we are +if (peek("isbound")) then + This_dir$ = peek$("directory")+"/" +else + This_dir$ = trim$(system$("pwd"))+"/" +fi + +if (system("test -e \""+This_dir$+"yab\"")) then + YAB$ = "yab" +else + YAB$ = This_dir$+"yab" +fi + +///////////////////////////////////////////////////////////// +// if yab gives us its version, we know that it exists. +// Otherwise we tell the user to make sure that there is one +///////////////////////////////////////////////////////////// +if (system(YAB$+" -version")) then + print "Please make sure you have a yab binary in" + print "\t"+left$(This_dir$, len(This_dir$)-1) + print "or" + print "\t/home/config/bin" + print "or" + print "\t/system/bin\n" + exit 1 +fi + +// set some global variables here +AppName$ = "BuildFactory" +VERSION$ = " 2.4.1" +TMP_folder$ = "/boot/var/tmp/BUILD_FACTORY_TMP/" +Lib_path$ = "/boot/home/config/settings/yab/" + +dim Library$(1) +dim Is_in_lib_path(1) +dim Found_sub$(1) + +///////////////////////////////////////////////////////////// +// Program starts here +// + +if (not open(1,"flex.c")) then +system("yab flex-bison.yab") // make flex.c and modify it for BuildFactory +else +close #1 +endif + +if (peek("argument") < 2) then + UsageAdvise(1) +fi + +// in- and outputfiles +Output_file$ = peek$("argument") +Input_file$ = peek$("argument") +appsig$ = peek$("argument") +run_from_ide$ = peek$("argument") +if appsig$="" appsig$="application/x-vnd.yab-app" +SetAppSig(appsig$) + +Input_dir$ = left$(Input_file$, rinstr(Input_file$, "/")) +Library$(0) = right$(Input_file$, len(Input_file$)-rinstr(Input_file$, "/")) + +if (trim$(Input_dir$) = "") Input_dir$ = This_dir$ + +// create the temp folder +if (system("test -d \""+TMP_folder$+"\"")) then + if (system("mkdir -p \""+TMP_folder$+"\"")) then + print "-- Error while creating temp folder!" + UsageAdvise(1) + fi +fi + +// We clean up all the files including the libs, if existing +for NL = 0 to num_lib + if (Is_in_lib_path(NL)) then + lib$ = Lib_path$+Library$(NL) + else + lib$ = Input_dir$+Library$(NL) + fi + num_lib = CleanUpCode(lib$) +next NL + +// writing all the libs into the mainfile +// because the BuildFactory can not handle libs +err = JoinFiles(Output_file$+"_bf.yab") + +// here it comes - the BuildFactory +BuildFactory(Output_file$+"_bf.yab") + +// cleaning up +RmErr = RemoveTemp() +system ("RdefApply parts/YAB.bf.rdef "+Output_file$) +system ("addattr -t mime BEOS:APP_SIG "+appsig$+" "+Output_file$) +system ("addattr -t mime BEOS:TYPE application/x-vnd.be-elfexecutable "+Output_file$) + + +// check if the BuildFactory was envoked by the yab-ide. +// if so, copy the output file to the inmputfile's directory and open the directory. +// the IDE will delete the output file from the BuildFactory directory. + + +if run_from_ide$ = "yab-ide" then + system ("cp "+Output_file$+" "+Input_dir$) + system ("open "+Input_dir$) +endif + +print "--------" +print "-- Info:" +print "\tNumber of libs:\t\t", num_lib +print "\tNumber of subs:\t\t", num_sub +print "\tNumber of lines:\t", num_line + +exit + +// +// programm ends here +///////////////////////////////////////////////////////////// + +/////////////////////////////////////////// +// joining all files to one +/////////////////////////////////////////// +sub JoinFiles(the_file$) + local in_file, out_file + + out_file = OpenWriteFile(the_file$) + for NL = 0 to num_lib + // contents of each file is written to our joined temp file + in_file = OpenReadFile(TMP_folder$+Library$(NL)) + while (not eof(in_file)) + print #out_file LineInput$(in_file) + num_line = num_line + 1 + wend + close in_file + next NL + close out_file + + return +end sub + +/////////////////////////////////////////// +// here we are cleaning up the files +/////////////////////////////////////////// +sub CleanUpCode(the_file$) + local the_filename$, out_file$ + local in_file, out_file + local Current_line$ + + the_filename$ = right$(the_file$, len(the_file$)-rinstr(the_file$, "/")) + out_file$ = TMP_folder$+the_filename$ + + out_file = OpenWriteFile(out_file$) + in_file = OpenReadFile(the_file$) + + if (min(out_file, in_file) = 0) return -1 + + print "\t-- removing not needed stuff ..." + while (not eof(in_file)) + Current_line$ = LineInput$(in_file) + + if (double_sub) then + if (upper$(left$(Current_line$, 7)) = "END SUB") double_sub = false + continue + fi + + // remove empty lines and commented lines and stuff + if (Current_line$ = "") continue + if (left$(Current_line$, 2) = "//") continue + if (left$(Current_line$, 1) = "#") continue + if (upper$(left$(Current_line$, 11)) = "EXPORT SUB ") then + Current_line$ = trim$(right$(Current_line$, len(Current_line$)-6)) + fi + Current_line$ = CheckOnLineComments$(Current_line$) + if (upper$(left$(Current_line$, 4)) = "SUB ") then + curr_sub$ = right$(Current_line$, len(Current_line$)-4) + curr_sub$ = left$(curr_sub$, instr(curr_sub$, "(")) + for NS = 0 to num_sub + if (Found_sub$(NS) = curr_sub$) then + double_sub = true + break + fi + next NS + + if (double_sub) then + continue + else + num_sub = num_sub + 1 + dim Found_sub$(num_sub+1) + Found_sub$(num_sub) = curr_sub$ + fi + fi + if (upper$(left$(Current_line$, 6)) = "IMPORT") then + found_lib = FindLibraries(Current_line$) + continue + fi + if (upper$(Current_line$) = "ENDIF") Current_line$ = "fi" + + print #out_file Current_line$ + wend + + close in_file + close out_file + + return found_lib +end sub + +//////////////////////////////////////////// +// search for comments behind a needed line +// if found, remove it. Exept there is a " +//////////////////////////////////////////// +sub CheckOnLineComments$(the_line$) + D = instr(the_line$, "//") + + if (D) then + local is_comment + local A : local B + local C : local E + + for B = 1 to len(the_line$) + A = asc(mid$(the_line$, B, 1)) + if (B > D) then + if (A = 34 and is_comment) then + C = true + break + fi + else + E = asc(mid$(the_line$, B+1, 1)) + if (E = 34 and not A = 92) then + if (is_comment) then + is_comment = false + else + is_comment = true + fi + fi + fi + next B + + if (not C) the_line$ = left$(the_line$, D-1) + fi + + return trim$(the_line$) +end sub + +///////////////////////////////////////////////// +// search for libraries, to prepare them as well +///////////////////////////////////////////////// +sub FindLibraries(the_line$) + local Library$ + + Library$ = right$(the_line$, len(the_line$)-7) + + if (upper$(right$(Library$, 4)) <> ".YAB") then + Library$ = Library$+".yab" + fi + + num_lib = num_lib + 1 + dim Library$(num_lib+1) + dim Is_in_lib_path(num_lib+1) + + if (system("test -e \""+Input_dir$+Library$+"\"")) then + if (system("test -e \""+Lib_path$+Library$+"\"")) then + print "-- Could not find lib\n\t"+Library$ + num_lib = num_lib - 1 + return num_lib + else + Is_in_lib_path(num_lib) = true + fi + fi + + Library$(num_lib) = Library$ + + print "-- Found lib: "+Library$ + return num_lib +end sub + +///////////////////////////////////////////////////////////// +// open the inputfile for reading +///////////////////////////////////////////////////////////// +sub OpenReadFile(the_file$) + local READ_FILE + READ_FILE = 22 + + if (not open(#READ_FILE,the_file$,"r")) then + print "-- Could not open "+the_file$ + print "-- for reading!" + exit + fi + + return READ_FILE +end sub + +///////////////////////////////////////////////////////////// +// open the outputfile for writing +///////////////////////////////////////////////////////////// +sub OpenWriteFile(the_file$) + local WRITE_FILE + WRITE_FILE = 23 + + if (not open(#WRITE_FILE,the_file$,"w")) then + print "-- Could not open "+the_file$ + print "-- for writing!" + exit + fi + + return WRITE_FILE +end sub + +///////////////////////////////////////// +// read in one line from the given file +///////////////////////////////////////// +sub LineInput$(n) + local tmp : local tmp$ + while (tmp <> 10) + tmp = peek(n) + if (tmp < 0) continue + tmp$ = tmp$ + chr$(tmp) + wend + + return trim$(tmp$) +end sub + +///////////////////////////////////////////////////////////// +// Remove our tempfolder +///////////////////////////////////////////////////////////// +sub RemoveTemp() + if (not system("test -d \""+TMP_folder$+"\"")) then + RmErr = system("rm -rf \""+TMP_folder$+"\"") + fi + + return RmErr +end sub + +///////////////////////////////////////////////////////////// +// tell the user how to use this app +///////////////////////////////////////////////////////////// +sub UsageAdvise(n) + print "\n"+AppName$+VERSION$ + print "Usage:" + print "\t"+AppName$+" outputfile inputfile < applicationsignature >\n" + print "\tFilenames may have no spaces!\n" + print "\tapplicationsignature default is: application/x-vnd.yab-app\n" + RemoveTemp() + + exit n +end sub + +///////////////////////////////////////////////////////////// +// set the application signature in YabMain.cpp +///////////////////////////////////////////////////////////// +sub SetAppSig(sig$) + app_sig$="\n\tBString tmp(\""+sig$+"\");\n" + open #1, This_dir$+"parts/YabMain.cpp.appsig","w" + print #1 app_sig$ + close #1 + cmd$="cat "+This_dir$+"parts/YabMain.cpp.start "+This_dir$+"parts/YabMain.cpp.appsig "+This_dir$+"parts/YabMain.cpp.end > "+This_dir$+"YabMain.cpp" + system(cmd$) + +end sub + +//////////////////////////////////////// +//////////////////////////////////////// +// the BuildFactory starts here +//////////////////////////////////////// +//////////////////////////////////////// +sub BuildFactory(f$) + handle = open(f$, "r") + if(not handle) then + print "Error: Could not open file "+f$ + exit(1) + endif + + print "Reading file "+f$+"..." + print + + while(not eof(handle)) + numRead = numRead + 1 + dim line$(numRead) + line$(numRead) = GetLine$(handle) + wend + close(handle) + + print "Dumping file..." + print + DumpProg(f$) + + // times have changed :) + hasZeta = false + + print "This yab version was compiled on "+peek$("os")+"." + realOS$ = upper$(system$("uname -o")) + realOS$ = left$(realOS$, len(realOS$)-1) + print "This system is running "+realOS$ + + print "Writing Automakefile and global.h..." + print + + system("cp AutoHeader.mak Automakefile") + + handle = open("Automakefile", "a") + if(not handle) then + print "Error: Could not write file Automakefile" + exit(1) + endif + + print #handle "TARGET = "+left$(f$, len(f$)-7) + + close(handle) + + system("cat AutoFooter.mak >> Automakefile") + + print "Starting make (ignore warnings)..." + print + system("make -f Automakefile clean") + system("make -f Automakefile") + system("make -f Automakefile clean") + system("rm -f program.h Automakefile "+f$) + print + print "Finished" + print + + return +end sub + +sub GetFirstCommand$(line$) + local t$: local ret$ + local i + + t$ = ltrim$(line$) + for i=1 to len(t$) + if(mid$(t$,i,1) = " " or mid$(t$,i,1) = "\t" or mid$(t$,i,1) = "\n" or mid$(t$,i,1) = "(") break + ret$ = ret$ + mid$(t$,i,1) + next i + return ret$ +end sub + +sub DumpProg(fileName$) + local handle + local t$ + local i + + if(val(system$("wc -c "+fileName$)) < 100) then + print "WARNING: File too small, filling up program with comments" + handle = open(fileName$, "a") + if(handle) then + print #handle "rem ~~ This comment was added by the ~~" + print #handle "rem ~~ BuildFactory because your program ~~" + print #handle "rem ~~ was too small. ~~" + close(handle) + else + print "ERROR: Could not add comments, is "+fileName$+" write-protected?" + exit(1) + endif + endif + + system("yab-compress "+fileName$) + handle = open("program.h", "a") + if(handle) then + print #handle "#define PROGLEN "; + t$ = system$("wc -c "+fileName$) + i = 1 + while(mid$(t$,i,1) = " ") + i = i + 1 + wend + if(i>1) t$ = right$(t$,len(t$)-i+1) + t$ = left$(t$, instr(t$, " ")-1) + print #handle t$ + close(handle) + endif + return +end sub + +sub GetLine$(handle) + local tmp$ + local retString$ + + while(tmp$<>chr$(10) and tmp$<>chr$(13) and not eof(handle)) + tmp$ = chr$(peek(handle)) + retString$ = retString$ + tmp$ + wend + + return retString$ +end sub + diff --git a/yab-IDE/BuildFactory/README b/yab-IDE/BuildFactory/README new file mode 100644 index 0000000..a4b7978 --- /dev/null +++ b/yab-IDE/BuildFactory/README @@ -0,0 +1,64 @@ +-- English -- Englisch -- -- German below -- Deutsch unten -- + +Some rules you have to know: + +Names of sub functions are only to be used once. This is for all affected files. +If there are subs with the same name, only the first one will be taken over while +the second will simply be ignored! + + +In libraries only subs and export subs are to be entered. Additional code not within +a sub or export sub are senseless later on, because libraries are simply added at the +end of the main file, so that one big file is generated. +So such additional lines are between the subs and are never read. + +All libraries that are imported with import are recognized. Also libraries that were +imported from within libraries. + +Libraries have to be placed either in the folder of the main file or in the yab lib +folder "/boot/home/config/settings/yab"! + +The BuildFactory is to be used as follows: + +yab BuildFactory Outputfile Inputfile.yab < applicationsig > + +from within the folder of the BuildFactory. The Outputfile is also placed there at the end. +The Inputfile has to have its relative or complete path included of course. + +The file which contains the total of the code is also stored in the folder of the BuildFactory, +for the case the created binary gives out error messages with line number. Those are of course +regarded to this certain file. + + +-- German -- Deutsch -- + +Ein paar Regeln, die man befolgen muss: + +Namen für sub-Funktionen dürfen nur einmal vergeben werden. Das gilt für +den Umfang aller Dateien. Sollten zwei subs mit gleichem Namen vorkommen, +wird nur das erste eingebaut, während das zweite einfach ignoriert wird! + +In libraries dürfen nur subs und export subs vorkommen. Zusätzliche +Funktionen, die nicht in einer Sub-Funktion stehen machen später keinen +Sinn, dadurch dass die libs einfach hinten an die Hauptdatei angefügt +werden, so dass eine einzige Datei entsteht. +Also sind zusätzliche Funktionen zwischen den subs und werden nie gelesen. + +Alle libraries, die mit import importiert werden, werden beachtet. Auch +Libraries, die aus Libraries heraus importiert werden. + +Libraries haben entweder in dem Verzeichnis der Hauptdatei oder in dem +yab-lib-Ordner "/boot/home/config/settings/yab/" zu liegen! + +Aufgerufen muss die BuildFactory wie folgt: + +yab BuildFactory.yab OutputFile InputFile.yab < applicationsig > + +aus dem Verzeichnis der BuildFactory heraus. Dort landet auch das +OutputFile. Zu dem InputFile.yab muss natürlich ein relativer oder +vollständiger Pfad angegeben werden. + +Die Datei, in dem der gesamte Source zusammengefasst ist, wird ebenfalls in +dem Verzeichnis der BuildFactory abgelegt, für den Fall, dass das erzeugte +Binary Fehler mit Zeilenangabe ausgibt. Diese beziehen sich dann natürlich +auf jene Datei. diff --git a/yab-IDE/BuildFactory/flex-bison.yab b/yab-IDE/BuildFactory/flex-bison.yab new file mode 100644 index 0000000..e351eec --- /dev/null +++ b/yab-IDE/BuildFactory/flex-bison.yab @@ -0,0 +1,138 @@ +#!yab + +doc This program modifies flex.c and main.c for the Buildfactory +doc It accomplishes the seteps documented in HowToMakeABuildFactory.txt. +doc The BuildFactory calls this program if flex.c is missing. +doc +doc by Jim Saxton, 2015, Artistic license + +system("flex -i -I -L -s -t yabasic.flex >flex.c") +system("perl -i -n -e 'if (!/^\#include\s+\s+$$/) {print if $$i;$$i++}' flex.c") +system("bison -d -l -t -v --output-file bison.c yabasic.bison ") +system ("mv flex.c tmpflex.c") + +open #1, "tmpflex.c", "r" +open #2, "outflex.c", "w" + +while (a$<>"#include ") + line input #1 a$ + print #2 a$ +wend + +print #2 "#include " +print #2 "#include "+chr$(34)+"program.h"+chr$(34) +print #2 "static int isparsed = 0;" + +while (a$<>"#define YY_BUF_SIZE 16384") + line input #1 a$ + if (a$<>"#define YY_BUF_SIZE 16384") print #2 a$ +wend + +print #2 "#define YY_BUF_SIZE PROGLEN" + +found=0 + +while (found=0) + line input #1 a$ + if (!instr(a$,"while ( (result = fread"))then + print #2 a$ + else + found=1 + endif +wend + +print #2 " while ( (result = zread(buf, 1, max_size, yyin))==0 && ferror(yyin)) "+chr$(92) +found=0 + +while (found=0) + line input #1 a$ + if (!instr(a$,"int ret_val;")) then + print #2 a$ + else + found=1 + endif +wend + +print #2 a$ +print #2 " if(isparsed) return EOB_ACT_END_OF_FILE;" + +while (! eof(#1)) + line input #1 a$ + print #2 a$ +wend + +print #2 "int zread(char* dest, size_t memb_size, size_t num_memb, FILE *file)" +print #2 "{" +print #2 " long destlen = PROGLEN;" +print #2 " if(isparsed==1)" +print #2 " return 0;" +print #2 " isparsed = 1;" +print #2 " uncompress(dest,&destlen,myProg,sizeof(myProg));" +print #2 " return destlen;" +print #2 "}" + +system("mv outflex.c flex.c") +system("rm tmpflex.c") + +close #1 +close #2 + +// fix main.c + +system ("mv main.c tmpmain.c") + +open #1, "tmpmain.c", "r" +open #2, "outmain.c", "w" + +found=0 + +while (found = 0) + line input #1 a$ + if (not instr(a$, "int isbound(void)")) then + print #2 a$ + else + found=1 + print #2 a$ + end if +wend + +print #2 "{" +print #2 " FILE *interpreter;" +print #2 " if (!interpreter_path || !interpreter_path[0]) {" +print #2 " error(FATAL,"+chr$(34)+"interpreter_path is not set !"+chr$(34)+");" +print #2 " return 0;" +print #2 " }" +print #2 " if (!(interpreter=fopen(interpreter_path,"+chr$(34)+"r"+chr$(34)+"))) {" +print #2 " sprintf(string,"+chr$(34)+"Couldn't open '%s' to check, if it is bound: %s"+chr$(34)+",interpreter_path,my_strerror(errno));" +print #2 " error(WARNING,string);" +print #2 " return 0;" +print #2 " }" +print #2 " return 1;" +print #2 "}" +print #2 "" +print #2 "" + +found = 0 + +while (found = 0) + line input #1 a$ + if (not instr(a$, "static int mybind(char *bound)")) then + found = 0 + else + found = 1 + print #2 a$ + end if +wend + +while (not eof(1)) + line input #1 a$ + print #2 a$ +wend + +close #1 +close #2 +system("mv outmain.c main.c") +system("rm tmpmain.c") + + + diff --git a/yab-IDE/BuildFactory/parts/YAB-IDE.bf.rdef b/yab-IDE/BuildFactory/parts/YAB-IDE.bf.rdef new file mode 100644 index 0000000..2e9c666 --- /dev/null +++ b/yab-IDE/BuildFactory/parts/YAB-IDE.bf.rdef @@ -0,0 +1,38 @@ + +resource vector_icon { + $"6E6369660E0500020006023C43C6B9E5E23A85A83CEE414268F44A445900C6D7" + $"F5FF6B94DD03EC66660200060238C5F1BB105D3DFDC23B9CD045487847B50700" + $"FFFFFFFFC1CCFF020006023B3049396B0ABA90833C646E4A101543299500FFFF" + $"FFFFEBEFFF020006023C71E33A0C78BA15E43C7D2149055549455700E3EDFFFF" + $"9EC2FF03FFACAC0200060239D53438FFCBBBC1973C666F4ADC3246DC6C00C1CC" + $"FFFFFFFFFF03003CB0020006023C0AE63B3927BC611E3D03FF4C25624A1A9600" + $"A3043CFFFF90AF03C93B3B030D296402000602BD498B3E1159BF219BBE7D2F4C" + $"1B8F4A331300BD0F0FFFE98484040174100A08325E385E40564E5E545E605058" + $"4C3E510A062E2C2E3E3E454A3C4A2A3A250A042E2C2E3E3E453E320A042E2C3E" + $"324A2A3A250A043E323E454A3C4A2A0A0338423C4D3C440A0622422254325C3E" + $"513E402E3A0A0422422254325C32490A04224232493E402E3A0A043249325C3E" + $"513E400A063E423E544E5C5A505A3F4A390A04C222C20F4E495A3F523C0A043E" + $"42C222C20F523C4A390A054151C08BC8834E5C4E49C22AC2130A053E423E54C0" + $"8BC8834151C22AC2130A044E494E5C5A505A3F110A0D0100000A0001061815FF" + $"01178400040A00010618001501178600040A010107000A080109000A0B010520" + $"20210A050108000A00010A1001178400040A02010D000A0A010E000A0902040F" + $"000A06010B000A0C010C000A0001011001178400040A030102000A040103000A" + $"07010400" +}; + + +resource app_signature "application/x-vnd.yab-IDE"; + +resource app_version { + major = 2, + middle = 2, + minor = 4, + + variety = B_APPV_FINAL, + internal = 1, + + short_info = "yab IDE", + long_info = "An integrated development environment for yab." +}; + +resource app_flags 1; diff --git a/yab-IDE/BuildFactory/parts/YAB.bf.rdef b/yab-IDE/BuildFactory/parts/YAB.bf.rdef new file mode 100644 index 0000000..b91bbe2 --- /dev/null +++ b/yab-IDE/BuildFactory/parts/YAB.bf.rdef @@ -0,0 +1,38 @@ + +resource vector_icon { + $"6E6369660E0500020006023C43C6B9E5E23A85A83CEE414268F44A445900C6D7" + $"F5FF6B94DD03EC66660200060238C5F1BB105D3DFDC23B9CD045487847B50700" + $"FFFFFFFFC1CCFF020006023B3049396B0ABA90833C646E4A101543299500FFFF" + $"FFFFEBEFFF020006023C71E33A0C78BA15E43C7D2149055549455700E3EDFFFF" + $"9EC2FF03FFACAC0200060239D53438FFCBBBC1973C666F4ADC3246DC6C00C1CC" + $"FFFFFFFFFF03003CB0020006023C0AE63B3927BC611E3D03FF4C25624A1A9600" + $"A3043CFFFF90AF03C93B3B030D296402000602BD498B3E1159BF219BBE7D2F4C" + $"1B8F4A331300BD0F0FFFE98484040174100A08325E385E40564E5E545E605058" + $"4C3E510A062E2C2E3E3E454A3C4A2A3A250A042E2C2E3E3E453E320A042E2C3E" + $"324A2A3A250A043E323E454A3C4A2A0A0338423C4D3C440A0622422254325C3E" + $"513E402E3A0A0422422254325C32490A04224232493E402E3A0A043249325C3E" + $"513E400A063E423E544E5C5A505A3F4A390A04C222C20F4E495A3F523C0A043E" + $"42C222C20F523C4A390A054151C08BC8834E5C4E49C22AC2130A053E423E54C0" + $"8BC8834151C22AC2130A044E494E5C5A505A3F110A0D0100000A0001061815FF" + $"01178400040A00010618001501178600040A010107000A080109000A0B010520" + $"20210A050108000A00010A1001178400040A02010D000A0A010E000A0902040F" + $"000A06010B000A0C010C000A0001011001178400040A030102000A040103000A" + $"07010400" +}; + + +resource app_signature "application/x-vnd.yab-app"; + +resource app_version { + major = 1, + middle = 7, + minor = 4, + + variety = B_APPV_FINAL, + internal = 1, + + short_info = "Yab BASIC programming language", + long_info = "Yab allows fast prototyping with simple and clean code. yab contains a large number of BeAPI specific commands for GUI creation and much, much more." +}; + +resource app_flags 1; diff --git a/yab-IDE/BuildFactory/parts/YabMain.cpp.appsig b/yab-IDE/BuildFactory/parts/YabMain.cpp.appsig new file mode 100644 index 0000000..306eb8b --- /dev/null +++ b/yab-IDE/BuildFactory/parts/YabMain.cpp.appsig @@ -0,0 +1,3 @@ + + BString tmp("application/x-vnd.yab-app"); + diff --git a/yab-IDE/BuildFactory/parts/YabMain.cpp.end b/yab-IDE/BuildFactory/parts/YabMain.cpp.end new file mode 100644 index 0000000..2142aa8 --- /dev/null +++ b/yab-IDE/BuildFactory/parts/YabMain.cpp.end @@ -0,0 +1,43 @@ + for(int i=1; iRun(); + ret = yabInterface->GetErrorCode(); + delete yabInterface; + return ret; +} diff --git a/yab-IDE/BuildFactory/parts/YabMain.cpp.start b/yab-IDE/BuildFactory/parts/YabMain.cpp.start new file mode 100644 index 0000000..4757ed3 --- /dev/null +++ b/yab-IDE/BuildFactory/parts/YabMain.cpp.start @@ -0,0 +1,8 @@ +#include +#include +#include +#include "YabInterface.h" + +char t[1024]; +const char* readSignature(int argc, char** argv) +{ \ No newline at end of file diff --git a/yab-IDE/BuildFactory/srcfiles b/yab-IDE/BuildFactory/srcfiles new file mode 100644 index 0000000..fa89210 --- /dev/null +++ b/yab-IDE/BuildFactory/srcfiles @@ -0,0 +1,50 @@ +CalendarControl.cpp +CalendarControl.h +config.h +ControlLook.cpp +DateTextView.cpp +function.c +global.h +graphic.c +io.c +main.c +MonthView.cpp +MonthWindow.cpp +MouseSenseStringView.cpp +README.Compile +RdefApply +Spinner.cpp +Spinner.h +SplitPane.cpp +SplitPane.h +symbol.c +URLView.cpp +URLView.h +yabasic.bison +yabasic.flex +yabasic.h +YabBitmapView.cpp +YabBitmapView.h +YabControlLook.cpp +YabControlLook.h +YabFilePanel.cpp +YabFilePanel.h +YabFilePanelLooper.cpp +YabFilePanelLooper.h +YabInterface.cpp +YabInterface.h +YabList.cpp +YabList.h +YabMain.cpp +YabMenu.h +YabStackView.cpp +YabStackView.h +YabTabView.cpp +YabTabView.h +YabText.cpp +YabText.h +YabToolTip.cpp +YabView.cpp +YabView.h +YabWindow.cpp +YabWindow.h \ No newline at end of file diff --git a/yab-IDE/BuildFactory/yab-compress.c b/yab-IDE/BuildFactory/yab-compress.c new file mode 100644 index 0000000..7f5dced --- /dev/null +++ b/yab-IDE/BuildFactory/yab-compress.c @@ -0,0 +1,50 @@ +#include +#include +#include + +unsigned long file_size(char *filename) +{ + unsigned long size; + FILE *pFile = fopen(filename, "rb"); + fseek (pFile, 0, SEEK_END); + size = ftell(pFile); + fclose (pFile); + return size; +} + +int main(int argc, char *argv[]) +{ + unsigned long filesize; + char *buffer; + FILE *fi, *fo; + char *dest; + unsigned long destlen; + unsigned long i; + + if(argc != 2) { + printf("Usage: yab-compress \n\n"); + return 1; + } + + filesize = file_size(argv[1]); + buffer = (char*)malloc(filesize); + dest = (char*)malloc(filesize); + + // read source file into buffer + fi = fopen(argv[1], "r"); + fread(buffer, sizeof(char), filesize, fi); + fclose(fi); + + // compress buffer + compress(dest, &destlen, buffer, filesize); + + // write compressed buffer to output + fo = fopen("program.h", "w"); + fprintf(fo, "const char myProg[] = {"); + for(i=0; i < destlen; i++) + fprintf(fo, "%i,", dest[i]); + fprintf(fo, "' ' };\n"); + fclose(fo); + + return 0; +} diff --git a/yab-IDE/Language/de.catalog b/yab-IDE/Language/de.catalog new file mode 100644 index 0000000..a43289e --- /dev/null +++ b/yab-IDE/Language/de.catalog @@ -0,0 +1,215 @@ +1 de x-vnd.yab-IDE 2612525067 +File Datei +New... Neu... +Open... Öffnen... +Close Schließen +Save Speichern +Save As... Speichern als... +Save As Template... Als Vorlage speichern... +Page Setup... Seiteneinrichtung... +Print... Drucken... +Quit Beenden +Edit Bearbeiten +Undo Rückgängig +Cut Ausschneiden +Copy Kopieren +Paste Einfügen +Select All Alles auswählen +Find Suchen +Find Again Weitersuchen +Find and Replace Suchen und ersetzen +Program Programm +Run Ausführen +Run in Terminal Im Terminal ausführen +Set Run Parameters... Parameter setzen... +Build Factory... Build-Factory... +Tools Werkzeuge +Pattern Editor... Muster erstellen... +Color Selection... Farbe auswählen... +ASCII Table... ASCII Tabelle... +View Ansicht +Next File Nächste Datei +Previous File Vorherige Datei +Full Screen Vollbild +Maximize Editor Editor maximieren +Auto Indent Automatisch einrücken +Auto Completion Automatisch ergänzen +Refresh Colors Farben wiederherstellen +Reformat Sourcecode Quelltext formatieren +Undo Reformat Formatierung zurücksetzen +Options... Einstellungen... +Introduction to the IDE... Einführung zur IDE... +yab Help... yab Hilfe... +Yabasic Manual... Yabasic Handbuch... +Online Resources Webseiten online +yab Homepage... yab Homepage... +yab Forums... yab Foren... +Yabasic Homepage... Yabasic Homepage... +Team Maui... Team Maui... +About... Über yab-IDE... +New Neu +Open Öffnen +Build Factory Build Factory +Pattern Editor Muster erstellen +Options Einstellungen +yab Help yab Hilfe +Go to Line: Gehe zu Zeile: + Files Dateien + Help Hilfe +Filename Dateiname +Command Befehl +yab Output yab Ausgabe +Immediate Sofort ausführen +Execute Ausführen +Find: Suche: +Replace: Ersetze: +Case Sensitive Groß-/Kleinschreibung beachten +Replace All Alles ersetzen +Suspecting user input, therefore starting in a terminal. Eine Benutzereingabe wird erwartet, Programm startet deshalb im Terminal. +Ok Ok +File: Datei: + (not saved) (nicht gespeichert) +Line Zeile +Please wait... Bitte warten... +Loading Program Lade Programm +Running Ausführung +Running Program Ausführung +Error! Program could not be killed. Fehler! Programm konnte nicht beendet werden. +Oops Oops +Close terminal to break program Terminal schließen um Programm zu beenden +yab-IDE Set Run Parameters yab-IDE Parameter setzen +Set Run Parameters Parameter setzen +yab Parameters: yab Parameter: +Program Parameters: Programm Parameter: +yab-IDE New Program yab-IDE Neues Programm +New yab Program Neues yab Programm +Please select one of the available templates for your program: Bitte eine der verfügbaren Vorlagen auswählen: +Name: Name: +Browse... Wählen... +Advanced Options Weitere Optionen +Remove Template Vorlage löschen +Project Directory Projektverzeichnis +Could not open template: Vorlage konnte nicht geladen werden: +Opening an empty file instead. Öffne eine leere Datei stattdessen. +Really delete template Vorlage wirklich löschen +Yes Ja +Cancel Abbrechen +This standard template can not be deleted! Diese Standardvorlage kann nicht gelöscht werden! +Template successfully removed. Vorlage erfolgreich gelöscht. +Error while deleting template! Fehler beim Löschen der Vorlage! +Empty Leere Datei +Basic Template Einfache Vorlage +Editor Template Vorlage für einen Editor +Command Line Template Kommandozeilenvorlage + +Create an empty file. Erstelle eine leere Datei. +Create a new program with a bare Erstelle ein neues Programm +window. mit einem leeren Fenster. +Create a new program with menus Erstelle ein neues Programm mit +and an editor. Menüs und einem Editor. + Erstelle ein neues +Create a new command line program. Kommandozeilenprogramm. +yab-IDE Save As Template yab-IDE Als Vorlage speichern +Save As Template Als Vorlage speichern +Save your code as a template for other programs: Quellcode als Vorlage speichern +Template Name Vorlagenname +Description (not more than 30 characters per line) Beschreibung (nicht mehr als 30 Zeichen pro Zeile) +Drop image here Bilddatei hierher ziehen +Could not load image! Bilddatei konnte nicht geladen werden +Error while saving template! Fehler beim Speichern der Vorlage! +File could not be saved! Datei konnte nicht gespeichert werden! +Sorry, you can not open more than Achtung, es können nicht mehr als + files at once!\n\nPlease close one or more other files first. Dateien auf einmal geöffnet werden!\n\nBitte zunächst eine oder mehrere andere Dateien schließen. +File is already open. Datei ist bereits geöffnet. +Error while loading file:\n\n Fehler beim Laden der Datei:\n\n +File \" Datei \" +\" not saved!\n\nSave the file now? \" ist nicht gespeichert\n\nDatei jetzt speichern? +Error while printing! Fehler beim Drucken! +Some files are not saved!\n\nDo you really want to quit? Es gibt nicht gesicherte Dateien!\n\nSoll yab-IDE dennoch beendet werden? +Program is not saved.\n\nSave it now? Programm ist nicht gesichert.\n\nJetzt speichern? +Save Always Immer speichern +Save Now Jetzt speichern +Reformating did not close all open loops and conditions.\nReformating currently does not support loops and conditions opened and closed by a colon (:).\nE.g. while(loop):wend\n\nYou can undo the reformating before doing any further changes. Das Formatieren hat nicht alle Schleifen und Konditionen schließen können.\nDas Formatieren unterstützt momentan keine Verschachtelungen mit Doppelpunkten (:).\nZ.B.. while(loop):wend\n\nDas Formatieren kann rückgängig gemacht werden, solange der Text nicht geändert wird. +Do not show this warning again Diese Warnung nicht mehr zeigen +Changes made since reformating will be lost! Änderungen seit dem letzten Formatieren gehen verloren! +The operation \"Replace All\" can not be reverted!\n\nDo you want to continue? \"Alles ersetzen\" kann nicht rückgängig gemacht werden\n\nDennoch fortfahren? +yab-IDE Build Factory yab-IDE Build-Factory +Target file name: Zieldatei: +Use the Haiku tab view instead of the ZETA native tab view Verwende Haiku-Tabviews anstatt ZETA-eigenen Tabviews +Create Binary Kompiliere Zieldatei +The compiler GCC was not found!\n\nPlease install the development tools from your ZETA CD. Der GCC-Compiler wurde nicht gefunden!\n\nBitte die Entwicklungsprogramme von der ZETA CD nachinstallieren. +The compiler GCC was not found!\n\nPlease install the development tools. Der GCC-Compiler wurde nicht gefunden!\n\nBitte die Entwicklungsprogramme nachinstallieren. +Visit Download Site GCC jetzt herunterladen +Warning: Although you are using the BeOS yab, the resulting binary will be ZETA only! Achtung: Obwohl gerade BeOS yab verwendet wird, wird die Zieldatei nur auf ZETA laufen! +Build Factory Output\n\n Build-Factory Ausgabe\n\n +Please wait, processing... (this may take a while)\n\n Bitte warten... (die Bearbeitung kann einige Zeit dauern)\n\n +Build was successful Die Erstellung war erfolgreich +Build failed! Die Erstellung ist fehlgeschlagen! +yab-IDE Pattern Editor yab-IDE Muster erstellen +Insert Pattern Muster einfügen +yab-IDE Color Selection yab-IDE Farbauswahl +Color Selection Farbauswahl +Default Colors: Standardfarben: +Black Schwarz +Darken 4 Dunkler 4 +Darken 3 Dunkler 3 +Darken 2 Dunkler 2 +Darken 1 Dunkler 1 +Default Background Standardhintergrund +Lighten 1 Heller 1 +Lighten 2 Heller 2 +White Weiß +Red Rot +Brown Braun +Yellow Gelb +Green Grün +Cyan Türkis +Light Blue Hellblau +Blue Blau +Magenta Violett +Light Magenta Hellviolett +Insert Color Farbe einfügen +yab-IDE ASCII Table yab-IDE ASCII Tabelle +ASCII Table ASCII Tabelle +yab-IDE Options yab-IDE Einstellungen +Editor Editor +General Allgemein +Environment Arbeitsumgebung +Directories Verzeichnisse +Language Sprachen +Number of spaces per tab: Anzahl Leerzeichen pro Tab: +Ask about saving before running a program Frage nach Speicherung vor der Programmausführung +Show warning when reformating sourcecode did not close all loops and conditions Zeige Warnung wenn die Formatierung nicht alle Schleifen und Konditionen schließen konnte +Show warning before undo reformating Zeige Warnung vor dem Zurücksetzem der Formatierung +Show warning before applying Replace All Zeige Warnung vor der Anwendung von Alles ersetzen +Select font for editor: Schriftart für den Editor wählen: +Font Family Schriftart +Font Style Schriftstil +Font Size Schriftgröße +My hovercraft is full of eels. Mein Luftkissenfahrzeug ist voller Aale. +Factory Settings Standardeinstellungen +Enable auto completion Automatisches Ergänzen +Number of characters for starting completion: Anzahl Startzeichen für die Ergänzung: +New Entry: Neuer Eintrag: +Add New Entry Neuen Eintrag hinzufügen +Remove Entry Eintrag löschen +Note: You have to restart the IDE to update the Achtung: Die IDE muß neugestartet werden +autocompletion when removing entries. damit gelöschte Einträge nicht mehr erscheinen. +Note: Only change the directories, when you know what you are doing! Achtung: Verzeichnisse nur ändern, wenn man weiß was man tut! +Default yab Binary Standard yab-Interpreter +Default yab Directory Standard yab-Verzeichnis +Use the automatic localization Die automatische Lokalisierung verwenden +Supported Languages Unterstützte Sprachen +Entry already exists. Eintrag existiert bereits +Restart yab-IDE to change localization yab-IDE neustarten um die Lokalisierung zu ändern +Could not find yab 1.0 directory!\n\nPlease do a proper installation. Das Verzeichnis von yab 1.0 konnte nicht gefunden werden!\n\nBitte yab sauber installieren. +Could not find yab binary!\n\nPlease do a proper installation. Der Interpreter von yab 1.0 konnte nicht gefunden werden!\n\nBitte yab sauber installieren. +New yab directory set to:\n\n Neues yab-Verzeichnis gesetzt zu:\n\n +\n\nRestart the IDE using the new directory. \n\nyab-IDE neustarten um die Lokalisierung zu ändern. +Invalid directory:\n\n Ungültiges Verzeichnis:\n\n +yab binary set to:\n\n yab-Interpreter gesetzt zu:\n\n +Invalid file:\n\n Ungültige Datei:\n\n +Export As HTML... Exportieren als HTML... +Open Project Folder... Öffne Projektordner... +Help Hilfe +Short Command Help... Kurzanleitung... diff --git a/yab-IDE/Language/en.catalog b/yab-IDE/Language/en.catalog new file mode 100644 index 0000000..d749526 --- /dev/null +++ b/yab-IDE/Language/en.catalog @@ -0,0 +1,214 @@ +1 english x-vnd.yab-IDE 1378724574 +File File +New... New... +Open... Open... +Close Close +Save Save +Save As... Save As... +Save As Template... Save As Template... +Page Setup... Page Setup... +Print... Print... +Quit Quit +Edit Edit +Undo Undo +Cut Cut +Copy Copy +Paste Paste +Select All Select All +Find Find +Find Again Find Again +Find and Replace Find and Replace +Program Program +Run Run +Run in Terminal Run in Terminal +Set Run Parameters... Set Run Parameters... +Build Factory... Build Factory... +Tools Tools +Pattern Editor... Pattern Editor... +Color Selection... Color Selection... +ASCII Table... ASCII Table... +View View +Next File Next File +Previous File Previous File +Full Screen Full Screen +Maximize Editor Maximize Editor +Auto Indent Auto Indent +Auto Completion Auto Completion +Refresh Colors Refresh Colors +Reformat Sourcecode Reformat Sourcecode +Undo Reformat Undo Reformat +Options... Options... +Introduction to the IDE... Introduction to the IDE... +yab Help... yab Help... +Yabasic Manual... Yabasic Manual... +Online Resources Online Resources +yab Homepage... yab Homepage... +yab Forums... yab Forums... +Yabasic Homepage... Yabasic Homepage... +Team Maui... Team Maui... +About... About... +New New +Open Open +Build Factory Build Factory +Pattern Editor Pattern Editor +Options Options +yab Help yab Help +Go to Line: Go to Line: +Go to Line Go to Line + Files Files + Help Help +Filename Filename +Command Command +yab Output yab Output +Immediate Immediate +Execute Execute +Find: Find: +Replace: Replace: +Case Sensitive Case Sensitive +Replace All Replace All +Suspecting user input, therefore starting in a terminal. Suspecting user input, therefore starting in a terminal. +Ok Ok +File: File: + (not saved) (not saved) +Line Line +Please wait... Please wait... +Loading Program Loading Program +Running Running +Running Program Running Program +Error! Program could not be killed. Error! Program could not be killed. +Oops Oops +Close terminal to break program Close terminal to break program +yab-IDE Set Run Parameters yab-IDE Set Run Parameters +Set Run Parameters Set Run Parameters +yab Parameters: yab Parameters: +Program Parameters: Program Parameters: +yab-IDE New Program yab-IDE New Program +New yab Program New yab Program +Please select one of the available templates for your program: Please select one of the available templates for your program: +Name: Name: +Browse... Browse... +Advanced Options Advanced Options +Remove Template Remove Template +Project Directory Project Directory +Could not open template: Could not open template: +Opening an empty file instead. Opening an empty file instead. +Really delete template Really delete template +Yes Yes +Cancel Cancel +This standard template can not be deleted! This standard template can not be deleted! +Template successfully removed. Template successfully removed. +Error while deleting template! Error while deleting template! +Empty Empty +Basic Template Basic Template +Editor Template Editor Template +Command Line Template Command Line Template + +Create an empty file. Create an empty file. +Create a new program with a bare Create a new program with a bare +window. window. +Create a new program with menus Create a new program with menus +and an editor. and an editor. + +Create a new command line program. Create a new command line program. +yab-IDE Save As Template yab-IDE Save As Template +Save As Template Save As Template +Save your code as a template for other programs: Save your code as a template for other programs: +Template Name Template Name +Description (not more than 30 characters per line) Description (not more than 30 characters per line) +Drop image here Drop image here +Could not load image! Could not load image! +Error while saving template! Error while saving template! +File could not be saved! File could not be saved! +Sorry, you can not open more than Sorry, you can not open more than + files at once!\n\nPlease close one or more other files first. files at once!\n\nPlease close one or more other files first. +File is already open. File is already open. +Error while loading file:\n\n Error while loading file:\n\n +File \" File \" +\" not saved!\n\nSave the file now? \" not saved!\n\nSave the file now? +Error while printing! Error while printing! +Some files are not saved!\n\nDo you really want to quit? Some files are not saved!\n\nDo you really want to quit? +Program is not saved.\n\nSave it now? Program is not saved.\n\nSave it now? +Save Always Save Always +Save Now Save Now +Reformating did not close all open loops and conditions.\nReformating currently does not support loops and conditions opened and closed by a colon (:).\nE.g. while(loop):wend\n\nYou can undo the reformating before doing any further changes. Reformating did not close all open loops and conditions.\nReformating currently does not support loops and conditions opened and closed by a colon (:).\nE.g. while(loop):wend\n\nYou can undo the reformating before doing any further changes. +Do not show this warning again Do not show this warning again +Changes made since reformating will be lost! Changes made since reformating will be lost! +The operation \"Replace All\" can not be reverted!\n\nDo you want to continue? The operation \"Replace All\" can not be reverted!\n\nDo you want to continue? +yab-IDE Build Factory yab-IDE Build Factory +Target file name: Target file name: +Use the Haiku tab view instead of the ZETA native tab view Use the Haiku tab view instead of the ZETA native tab view +Create Binary Create Binary +The compiler GCC was not found!\n\nPlease install the development tools from your ZETA CD. The compiler GCC was not found!\n\nPlease install the development tools from your ZETA CD. +The compiler GCC was not found!\n\nPlease install the development tools. The compiler GCC was not found!\n\nPlease install the development tools. +Visit Download Site Visit Download Site +Warning: Although you are using the BeOS yab, the resulting binary will be ZETA only! Warning: Although you are using the BeOS yab, the resulting binary will be ZETA only! +Build Factory Output\n\n Build Factory Output\n\n +Please wait, processing... (this may take a while)\n\n Please wait, processing... (this may take a while)\n\n +Build was successful Build was successful +Build failed! Build failed! +yab-IDE Pattern Editor yab-IDE Pattern Editor +Insert Pattern Insert Pattern +yab-IDE Color Selection yab-IDE Color Selection +Color Selection Color Selection +Default Colors: Default Colors: +Black Black +Darken 4 Darken 4 +Darken 3 Darken 3 +Darken 2 Darken 2 +Darken 1 Darken 1 +Default Background Default Background +Lighten 1 Lighten 1 +Lighten 2 Lighten 2 +White White +Red Red +Brown Brown +Yellow Yellow +Green Green +Cyan Cyan +Light Blue Light Blue +Blue Blue +Magenta Magenta +Light Magenta Light Magenta +Insert Color Insert Color +yab-IDE ASCII Table yab-IDE ASCII Table +ASCII Table ASCII Table +yab-IDE Options yab-IDE Options +Editor Editor +General General +Environment Environment +Directories Directories +Language Language +Number of spaces per tab: Number of spaces per tab: +Ask about saving before running a program Ask about saving before running a program +Show warning when reformating sourcecode did not close all loops and conditions Show warning when reformating sourcecode did not close all loops and conditions +Show warning before undo reformating Show warning before undo reformating +Show warning before applying Replace All Show warning before applying Replace All +Select font for editor: Select font for editor: +Font Family Font Family +Font Style Font Style +Font Size Font Size +My hovercraft is full of eels. My hovercraft is full of eels. +Factory Settings Factory Settings +Enable auto completion Enable auto completion +Number of characters for starting completion: Number of characters for starting completion: +New Entry: New Entry: +Add New Entry Add New Entry +Remove Entry Remove Entry +Note: You have to restart the IDE to update the Note: You have to restart the IDE to update the +autocompletion when removing entries. autocompletion when removing entries. +Note: Only change the directories, when you know what you are doing! Note: Only change the directories, when you know what you are doing! +Default yab Binary Default yab Binary +Default yab Directory Default yab Directory +Use the automatic localization Use the automatic localization +Supported Languages Supported Languages +Entry already exists. Entry already exists. +Restart yab-IDE to change localization Restart yab-IDE to change localization +Could not find yab 1.0 directory!\n\nPlease do a proper installation. Could not find yab 1.0 directory!\n\nPlease do a proper installation. +Could not find yab binary!\n\nPlease do a proper installation. Could not find yab binary!\n\nPlease do a proper installation. +New yab directory set to:\n\n New yab directory set to:\n\n +\n\nRestart the IDE using the new directory. \n\nRestart the IDE using the new directory. +Invalid directory:\n\n Invalid directory:\n\n +yab binary set to:\n\n yab binary set to:\n\n +Invalid file:\n\n Invalid file:\n\n +Export As HTML... Export As HTML... +Open Project Folder... Open Project Folder... diff --git a/yab-IDE/Language/nl.catalog b/yab-IDE/Language/nl.catalog new file mode 100644 index 0000000..cb8fc83 --- /dev/null +++ b/yab-IDE/Language/nl.catalog @@ -0,0 +1,214 @@ +1 nl x-vnd.yab-IDE 1378724574 +File Bestand +New... Nieuw... +Open... Openen... +Close Sluiten +Save Opslaan +Save As... Opslaan als... +Save As Template... Als sjabloon opslaan... +Page Setup... Pagina instellingen... +Print... Afdrukken... +Quit Afsluiten +Edit Bewerken +Undo Ongedaan maken +Cut Knippen +Copy Kopiëren +Paste Plakken +Select All Alles selecteren +Find Zoek +Find Again Verder zoeken +Find and Replace Zoeken en vervangen +Program Toepassing +Run Uitvoeren +Run in Terminal In Terminal uitvoeren +Set Run Parameters... Parameter zetten... +Build Factory... Build-Factory... +Tools Werktuigen +Pattern Editor... Patroon aanmaken... +Color Selection... Kleur kiezen... +ASCII Table... ASCII lijst... +View Venster +Next File Volgend bestand +Previous File Vorig bestand +Full Screen Volledig scherm +Maximize Editor Editor maximaliseren +Auto Indent Automatisch inspringen +Auto Completion Automatisch aanvullen +Refresh Colors Kleuren verversen +Reformat Sourcecode Broncode herformateren +Undo Reformat Formatering ongedaan maken +Options... Instellingen... +Introduction to the IDE... Inleiding tot de IDE... +yab Help... yab help... +Yabasic Manual... Yabasic handboek... +Online Resources Website's online +yab Homepage... yab Homepage... +yab Forums... yab forums... +Yabasic Homepage... Yabasic Homepage... +Team Maui... Team Maui... +About... Over yab-IDE... +New Nieuw +Open Openen +Build Factory Build Factory +Pattern Editor Patroon aanmaken +Options Instellingen +yab Help yab help +Go to Line: Ga naar lijn: +Go to Line Ga naar lijn + Files Bestanden + Help Help +Filename Bestandsnaam +Command Commando +yab Output yab output +Immediate Onmiddelijk uitvoeren +Execute Uitvoeren +Find: Zoek: +Replace: Vervang: +Case Sensitive Hoofdlettergevoelig +Replace All Alles vervangen +Suspecting user input, therefore starting in a terminal. Eem gebruikers ingave wordt verwacht, de toepassing word gestart in een Terminal. +Ok Ok +File: Bestand: + (not saved) (niet opgeslagen) +Line Lijn +Please wait... Even wachten... +Loading Program Toepassing laden +Running Draait +Running Program In uitvoering +Error! Program could not be killed. Fout! Toepassing kan niet gestopt worden. +Oops Oeps +Close terminal to break program Terminal sluiten om toepassing te sluiten +yab-IDE Set Run Parameters yab-IDE parameter zetten +Set Run Parameters Parameter zetten +yab Parameters: yab Parameter: +Program Parameters: Toepassing parameter: +yab-IDE New Program yab-IDE nieuwe toepassing +New yab Program Nieuwe yab toepassing +Please select one of the available templates for your program: Gelieve een van de beschikbare sjablonen te kiezen: +Name: Naam: +Browse... Bladeren... +Advanced Options Geavanceerd +Remove Template Sjabloon wissen +Project Directory Projectmap +Could not open template: Sjabloon kon niet geladen worden: +Opening an empty file instead. Open een leeg bestand in de plaats. +Really delete template Sjabloon wissen +Yes Ja +Cancel Annuleren +This standard template can not be deleted! Dit standaard sjabloon kan niet verwijderd worden! +Template successfully removed. Sjabloon verwijderd. +Error while deleting template! Fout bij het verwijderen sjabloon! +Empty Leeg bestand +Basic Template Eenvoudig sjabloon +Editor Template Sjabloon voor een Editor +Command Line Template Sjabloon voor commandline + +Create an empty file. Leeg bestand aanmaken. +Create a new program with a bare Nieuwe toepassing aanmaken +window. met een leeg venster. +Create a new program with menus Nieuwe toepassing maken met +and an editor. menu's een een editor. + Nieuwe commandline +Create a new command line program. toepassing aanmaken. +yab-IDE Save As Template yab-IDE Opslaan als sjabloon +Save As Template Als sjabloon opslaan +Save your code as a template for other programs: Broncode als sjabloon opslaan +Template Name Sjabloonnaam +Description (not more than 30 characters per line) Beschrijving (niet meer dan 30 karakters per lijn) +Drop image here Afbeelding hier slepen +Could not load image! Afbeelding kon niet geladen worden +Error while saving template! Fout bij het opslaan van sjabloon! +File could not be saved! Bestand kon niet opgeslagen worden! +Sorry, you can not open more than Opgelet je kan niet meer dan + files at once!\n\nPlease close one or more other files first. bestanden openen in een keer!\n\nGelieve eerst een of meerdere bestanden te sluiten. +File is already open. Bestand is al open. +Error while loading file:\n\n Fout bij het laden van het bestand:\n\n +File \" Bestand \" +\" not saved!\n\nSave the file now? \" is niet opgeslagen\n\nBestand nu opslaan? +Error while printing! Fout bij het afdrukken! +Some files are not saved!\n\nDo you really want to quit? Enkele bestanden zijn niet opgeslagen!\n\nWil je werkelijk afsluiten? +Program is not saved.\n\nSave it now? Toepassing is niet opgeslagen.\n\nNu opslaan? +Save Always Altijd opslaan +Save Now Nu opslaan +Reformating did not close all open loops and conditions.\nReformating currently does not support loops and conditions opened and closed by a colon (:).\nE.g. while(loop):wend\n\nYou can undo the reformating before doing any further changes. Herformateren heeft niet alle loops en condities kunnen sluiten.\nHerformateren ondersteun momenteel geen loops en conditie's tussen duppelpunten (:).\nBv. while(loop):wend\n\nJe kan de herformatering ongedaan maken zolang de tekst niet veranderd wordt. +Do not show this warning again Deze waarschuwing niet meer tonen +Changes made since reformating will be lost! Aanpassingen sinds de laatste herformatering zullen verloren gaan! +The operation \"Replace All\" can not be reverted!\n\nDo you want to continue? De operatie \"Alles vervangen\" kan niet teruggedraaid worden!\n\nToch verdergaan? +yab-IDE Build Factory yab-IDE Build-Factory +Target file name: Doelbestand: +Use the Haiku tab view instead of the ZETA native tab view Gebruik de Haiku tabview in plaats van de ZETA eigen tabvies +Create Binary Compileer bin +The compiler GCC was not found!\n\nPlease install the development tools from your ZETA CD. De GCC compiler is niet gevonden!\n\nGelieve de ontwikkel toepassingen van de ZETA CD te installeren. +The compiler GCC was not found!\n\nPlease install the development tools. De GCC compiler is niet gevonden!\n\nGelieve de ontwikkel toepassingen te installeren. +Visit Download Site GCC nu downloaden +Warning: Although you are using the BeOS yab, the resulting binary will be ZETA only! Waarschuwing: Ondanks dat je BeOS yab gebruikt, zal de toepassing enkel op ZETA draaien! +Build Factory Output\n\n Build-Factory Output\n\n +Please wait, processing... (this may take a while)\n\n Even geduld... (de bewerking kan een tijdje duren)\n\n +Build was successful Aanmaken gelukt +Build failed! Aanmaken mislukt! +yab-IDE Pattern Editor yab-IDE patroon aanmaken +Insert Pattern Patroon invoegen +yab-IDE Color Selection yab-IDE kleurkiezer +Color Selection Kleurselectie +Default Colors: Standaardkleuren: +Black Zwart +Darken 4 Donker 4 +Darken 3 Donker 3 +Darken 2 Donker 2 +Darken 1 Donker 1 +Default Background Standaard achtergrond +Lighten 1 Lichter 1 +Lighten 2 Lichter 2 +White Wit +Red Rood +Brown Bruin +Yellow Geel +Green Groen +Cyan Cyaan +Light Blue Licht blauw +Blue Blauw +Magenta Magenta +Light Magenta Licht Magenta +Insert Color Kleur invoegen +yab-IDE ASCII Table yab-IDE ASCII tabel +ASCII Table ASCII tabel +yab-IDE Options yab-IDE Instellingen +Editor Editor +General Algemeen +Environment Omgeving +Directories Mappen +Language Talen +Number of spaces per tab: Aantal spaties per tab: +Ask about saving before running a program Vraag naar opslaan voor het draaien van de toepassing +Show warning when reformating sourcecode did not close all loops and conditions Toon waarschuwing als herformatering niet alle loops en condities sluiten kon +Show warning before undo reformating Toon waarschuwing voor het ongedaan maken van de herformatering +Show warning before applying Replace All Toon waarschuwing voor het toepassen \"Alles vervangen\" +Select font for editor: Selecteer een font voor de editor: +Font Family Font +Font Style Stijl +Font Size Grootte +My hovercraft is full of eels. Mijn hoovercraft zit vol met vissen. +Factory Settings Standaardinstellingen +Enable auto completion Auto-aanvullen inschakelen +Number of characters for starting completion: Aantal karakters voor het starten van het aanvullen: +New Entry: Nieuwe ingang: +Add New Entry Nieuwe ingang toevoegen +Remove Entry Ingang wissen +Note: You have to restart the IDE to update the Aandacht: de IDE moet herstart worden +autocompletion when removing entries. zodat gewiste ingangen niet meer verscheinen. +Note: Only change the directories, when you know what you are doing! Aandacht: Verander enkel de mappen als je weet wat je doet! +Default yab Binary Standaard yab-Interpreter +Default yab Directory Standaard yab-map +Use the automatic localization Gebruik Haiku's taalsysteem +Supported Languages Ondersteunde talen +Entry already exists. Ingang bestaat reeds +Restart yab-IDE to change localization yab-IDE herstarten om de localisering door te voeren +Could not find yab 1.0 directory!\n\nPlease do a proper installation. Kon de map yab 1.0 niet vinden!\n\nGelieve yab goed te installeren. +Could not find yab binary!\n\nPlease do a proper installation. Kon de interpreter van yab 1.0 niet vinden!\n\nGelieve yab goed te installeren. +New yab directory set to:\n\n Nieuwe yab map gezet naar:\n\n +\n\nRestart the IDE using the new directory. \n\nyab-IDE herstarten om de localisering door te voeren. +Invalid directory:\n\n Ongeldige map:\n\n +yab binary set to:\n\n yab-Interpreter insteld naar:\n\n +Invalid file:\n\n Ongeldig bestand:\n\n +Export As HTML... Als HTML opslaan... +Open Project Folder... Projectmap openen... diff --git a/yab-IDE/Programs/Examples/3D-Curve.yab b/yab-IDE/Programs/Examples/3D-Curve.yab new file mode 100755 index 0000000..ef95ba2 --- /dev/null +++ b/yab-IDE/Programs/Examples/3D-Curve.yab @@ -0,0 +1,60 @@ +doc Draw some nice 3D curves +doc Original by Martin Lehmann for QBasic +doc +doc change the function func for different curves +doc try smaller values of i for a lower resolution +doc try z = 1 for less dots +doc +doc Note: this demo shows one thing: yab is slow :) +doc The cleanup of the drawing takes alot of time too, +doc you can simply break the program if you don't want to wait +doc + +window open 100,100 to 739,579, "Win", "3D Curve" + +bitmap 640,480, "DoubleBuffer" +canvas 0,0 to 639,479, "MyCanvas", "Win" + +i = 128 // resolution +z = 0.5 // dot frequency +xk = 40 +yk = 30 + +draw set "highcolor", 0,0,0, "DoubleBuffer" +draw rect 0,0 to 639,479, "DoubleBuffer" +draw bitmap 0,0, "DoubleBuffer", "copy", "MyCanvas" + +for t = -144 to 144 step(288/i) + if(t=0) t=0.1 + r = int(0.5 + sqrt(20736 - t^2)) + for j = -r to r step z + p = func(sqrt(j^2 + t^2) * 0.0327) * 20 + x = int(1.7 * (j + (t/2.25) + 160)) + xk + y = int(1.8 * (199 - (p - t/2.25 + 90))) + yk + draw set "highcolor", 255-r,j+r,255-p, "DoubleBuffer" + draw line x,y to x,y, "DoubleBuffer" + draw set "highcolor", 0,0,0, "DoubleBuffer" + draw line x,y+1 to x,480, "DoubleBuffer" + next j + draw bitmap 0,0, "DoubleBuffer", "copy", "MyCanvas" +next t + +while(not instr(message$, "Quit")) +wend + +window close "Win" + +// Choose one of the functions below, comment out all others +sub func(n) + return cos(n) + cos(2*n) +cos(5*n) +// return -abs(1/n) +// return -abs(1/(n + j)) +// return sin(n) + sin(2*n) +sin(5*n) +// return cos(sin(n)) +// return cos(2*n) + cos((n+j)/16) +// return sqrt(abs(0.5*(16 - n^2))) + 1/(n*4) +// return cos(4*n) + 20/(n^2 + 3) +// return cos(1/n) + cos(2/n) + cos(5/n) - 3 +// return cos(sin(j/n)) +// return 1/sqrt(n) - 3 +end sub diff --git a/yab-IDE/Programs/Examples/AllInOne.yab b/yab-IDE/Programs/Examples/AllInOne.yab new file mode 100755 index 0000000..cfc7719 --- /dev/null +++ b/yab-IDE/Programs/Examples/AllInOne.yab @@ -0,0 +1,201 @@ +// This example demonstrates all widgets + +// open the window +window open 100,100 to 640,500, "Win", "yab Demo" +window set "Win", "Flags", "Not-Resizable, Not-Zoomable" + +// set the title +view 10,10 to 530,50, "Title", "Win" +draw set "bgcolor", 50,50,200, "Title" +draw set "lowcolor", 50,50,200, "Title" +draw set "highcolor", 255,255,255, "Title" +if(peek$("os") = "Haiku") then + draw set "DejaVu Sans,Condensed Bold,32", "Title" +else + draw set "Zurich,Bold,32", "Title" +endif +draw text 10,32, "yab Widgets and Views", "Title" + +// make the tabview +tabview 10,60 to 530,390, "Box", "top", "Win" +tabview add "Box", "Widgets" +tabview add "Box", "Views and More" + +// button +button 10,10 to 100,30, "Button", "Button", "Box1" +tooltip "Button", "BUTTON" + +// button image +button image 10,40, "ButtonImage", "img/button_pressed.png", "img/button_norm.png", "", "Box1" +tooltip "ButtonImage", "BUTTON IMAGE" + +// checkbox +checkbox 10,70, "Check", "Checkbox", true, "Box1" +tooltip "Check", "CHECKBOX" + +// checkbox image +checkbox image 10,92, "CheckImage", "img/checkbutton_enabledOn.png", "img/checkbutton_enabledOff.png", "", "", true, "Box1" +tooltip "CheckImage", "CHECKBOX IMAGE" + +// radiobutton +radiobutton 10,130, "Radio1", "1. Radiobutton", true, "Box1" +tooltip "Radio1", "RADIOBUTTON" +radiobutton 10,150, "Radio2", "2. Radiobutton", false, "Box1" +tooltip "Radio2", "RADIOBUTTON" + +// dropbox +dropbox 10,175 to 120,195, "Drop", "Dropbox", "Box1" +dropbox add "Drop", "Foo" +dropbox add "Drop", "Bar" +tooltip "Drop", "DROPBOX" + +// listbox +listbox 10,210 to 100,290, "List", 1, "Box1" +listbox add "List", "Foo" +listbox add "List", "Bar" +tooltip "List", "LISTBOX" + +// columnbox +columnbox 130,10 to 270,150, "Column", 1, "", "Box1" +columnbox column "Column", " ", 1, 30,30,30, "align-center" +columnbox column "Column", "Column", 2, 90,90,90, "align-center" +columnbox add "Column", 1,1, 20, "__Icon__=img/yab.png" +columnbox add "Column", 2,1, 20, "Foo" +columnbox add "Column", 2,2, 20, "Bar" +tooltip "Column", "COLUMNBOX" + +// treebox +treebox 130,160 to 270,290, "Tree", 1, "Box1" +treebox add "Tree", "Root" +treebox add "Tree", "Root", "Foo", true +treebox add "Tree", "Root", "Bar", true +tooltip "Tree", "TREEBOX" + +// text +text 300,10, "Text", "Text (cannot be flushed)", "Box1" +tooltip "Text", "TEXT" + +// texturl +texturl 300,30, "TextURL", "Team MAUI", "http://www.team-maui.de", "Box1" +tooltip "TextURL", "TEXTURL" + +// textcontrol +textcontrol 300,50 to 500,70, "TextCtrl", "TextControl", "", "Box1" +tooltip "TextCtrl", "TEXTCONTROL" + +// spincontrol +spincontrol 300,80, "Spin", "Spincontrol", 0,100,1, "Box1" +tooltip "Spin", "SPINCONTROL" + +// calendar +calendar 300,120, "Cal", "DDMMYYYY.", "01.01.1970", "Box1" +tooltip "Cal", "CALENDAR" + +// textedit +textedit 300,150 to 500,215, "TextEd", 3, "Box1" +textedit add "TextEd", "Simply edit your text..." +tooltip "TextEd", "TEXTEDIT" + +// slider +slider 300,225 to 500,245, "Slider", "Slider", 1, 23, "Box1" +tooltip "Slider", "SLIDER" + +// statusbar +statusbar 300,265 to 500,290, "Status", "Start", "Finish", "Box1" +statusbar set "Status", "Start", "Finish", 66 +tooltip "Status", "STATUSBAR" + +// view +view 10,10 to 100,100, "View", "Box2" +draw set "bgcolor", "jan-favorite-color", "View" +draw text 20,35, "Plain View", "View" +tooltip "View", "VIEW" + +// canvas +canvas 10,110 to 100,195, "Canvas", "Box2" +draw text 20,35, "Canvas", "Canvas" +tooltip "Canvas", "CANVAS" + +// boxview +boxview 10,205 to 100,290, "Boxview", "Boxview", 2, "Box2" +tooltip "Boxview", "BOXVIEW" + +// tabview +tabview 120,10 to 260,100, "Tab", "top", "Box2" +tabview add "Tab", "First" +tabview add "Tab", "Second" +tooltip "Tab", "TABVIEW" + +// splitview +splitview 120,110 to 260,195, "Split", true, false, "Box2" +draw set "bgcolor", "Panel-Background-Color, Darken-1-Tint", "Split1" +draw set "bgcolor", "Panel-Background-Color, Lighten-1-Tint", "Split2" +tooltip "Split", "SPLITVIEW" + +// colorcontrol +colorcontrol 120,203, "Color", "Box2" +tooltip "Color", "COLORCONTROL" + +// popupmenu (only button, code in messageloop) +button 120,270 to 245,290, "Popup", "Popupmenu", "Box2" +tooltip "Popup", "POPUPMENU" + +// filepanel (only button, code in messageloop) +button 255,270 to 350,290, "File", "Filepanel", "Box2" +tooltip "File", "FILEPANEL" + +// menu +view 280,10 to 500,100, "Menu", "Box2" +menu "Menu", "Foo", "", "Menu" +menu "Menu", "--", "", "Menu" +menu "Menu", "Bar", "", "Menu" +draw set "bgcolor", "Panel-Background-Color, Darken-1-Tint", "Menu" +draw text 20,35, "View with menu", "Menu" +tooltip "Menu", "MENU" + +// scrollbar +view 280,110 to 500-peek("scrollbarwidth"),195-peek("scrollbarwidth"), "ScrollView", "Box2" +scrollbar "Scroll", 3, "ScrollView" +scrollbar set "Scroll", "horizontal-range", 0,100 +scrollbar set "Scroll", "vertical-range", 0,50 +if(peek$("os") = "Haiku") then + draw set "DejaVu Sans,Condensed Bold,32", "ScrollView" +else + draw set "Zurich,Bold,32", "ScrollView" +endif +draw text 130,90, "Foobar", "ScrollView" +tooltip "Scroll", "SCROLLBAR" + +// stackview +stackview 420,205 to 500,260, "StackView", 2, "Box2" +button 360,270 to 425,290, "Stack1", "Stack1", "Box2" +button 435,270 to 500,290, "Stack2", "Stack2", "Box2" +draw set "bgcolor", 200,200,255, "StackView1" +draw text 10,20, "First view", "StackView1" +draw set "bgcolor", 200,255,255, "StackView2" +draw text 10,20, "Second view", "StackView2" +tooltip "StackView", "STACKVIEW" + +// messageloop +while(not quitting) + msg$ = message$ + if(instr(msg$, "Popup")) then + // popupmenu + select$ = popupmenu 120,270, "Foo|--|Bar", "Box2" + elsif(instr(msg$, "File")) then + // filepanel + select$ = filepanel "Load-File", "Example Filepanel", "/boot/home" + elsif(instr(msg$, "Stack1")) then + // set stackview + stackview set "StackView", 1 + elsif(instr(msg$, "Stack2")) then + // set stackview + stackview set "StackView", 2 + elsif(instr(msg$, "Quit")) then + // exit + quitting = true + endif +wend + +window close "Win" + diff --git a/yab-IDE/Programs/Examples/BoxWorld.yab b/yab-IDE/Programs/Examples/BoxWorld.yab new file mode 100755 index 0000000..b05d229 --- /dev/null +++ b/yab-IDE/Programs/Examples/BoxWorld.yab @@ -0,0 +1,64 @@ +#!yab + +window open 100,100 to 380,410,"MainView","BoxWorld.yab" + +window set "MainView", "flags", "not-zoomable, not-h-resizable, not-v-resizable" + +layout "none", "MainView" + +view 0,0 to 110,30, "CheckboxView","MainView" +checkbox 10,10, "checkbox1", "Please select", 0, "CheckboxView" + +view 0,31 to 110,120, "RadioView1","MainView" + radiobutton 10,10, "Radio11", "Radio 11", 0, "RadioView1" + radiobutton 10,30, "Radio12", "Radio 12", 0, "RadioView1" + radiobutton 10,50, "Radio13", "Radio 13", 1, "RadioView1" + +view 0,130 to 110,190,"RadioView2","MainView" + radiobutton 10,10, "Radio21", "Radio 21", 1, "RadioView2" + radiobutton 10,30, "Radio22", "Radio 22", 0, "RadioView2" + +view 0,195 to 110,280,"RadioView3","MainView" + radiobutton 10,5, "Radio31", "Radio 31", 0, "RadioView3" + radiobutton 10,25, "Radio32", "Radio 32", 0, "RadioView3" + radiobutton 10,45, "Radio33", "Radio 33", 1, "RadioView3" + radiobutton 10,65, "Radio34", "Radio 34", 0, "RadioView3" + +view 0, 285 to 280, 310, "CommandView","MainView" + +layout "leftright", "MainView" + +listbox 120,10 to 255,110, "List1", 1, "MainView" + +layout "standard", "MainView" + +listbox 120,120 to 255,230, "List2", 3, "MainView" + +listbox add "List1","Hello" +listbox add "List1","World" + +for i=1 to 20 + listbox add "List2","Number "+str$(i) +next i + +dropbox 120,250 to 265,270, "drop1", "MyDrop:", "MainView" +dropbox add "drop1", "Hello World" +dropbox add "drop1", "Foo Bar" +dropbox add "drop1", "--" +dropbox add "drop1", "Acme Ltd" +dropbox add "drop1", "Bobejaan" + +alert "BoxWorld shows how to use Radiobuttons, Checkboxes, Listboxes and Dropboxes.","Ok","idea" + +inloop = true +while(inloop) + a$ = message$ + if(a$<>"") then + print a$ + draw flush "CommandView" + draw text 5,15, left$(a$,len(a$)-1), "CommandView" + endif + if(instr(a$,"_QuitRequested|")) inloop = false +wend + +window close "MainView" diff --git a/yab-IDE/Programs/Examples/ButtonWorld.yab b/yab-IDE/Programs/Examples/ButtonWorld.yab new file mode 100755 index 0000000..156fab3 --- /dev/null +++ b/yab-IDE/Programs/Examples/ButtonWorld.yab @@ -0,0 +1,64 @@ +#!yab + +window open 400,400 to 550,500, "MainView1", "ButtonWorld1" +window open 600,400 to 750,500, "MainView2", "ButtonWorld2" + +mainview1 = true + +layout "left, right", "MainView1" +button 30,10 to 120,30, "EmptyAlert_", "Empty Alert", "MainView1" +layout "bottom, right", "MainView1" +button 30,40 to 120,60, "InfoAlert_", "Info Alert", "MainView1" +button 30,70 to 120,90, "IdeaAlert_", "Idea Alert", "MainView1" + +button 30,10 to 120,30, "WarningAlert_", "Warning Alert", "MainView2" +button 30,40 to 120,60, "StopAlert_", "Stop Alert", "MainView2" +button 30,70 to 120,90, "Quit_", "Quit", "MainView2" + +alert "ButtonWorld demonstrates how Buttons and Alerts can be used easily!", "Ok", "idea" + +inloop = true +while(inloop) + msg$ = message$ + switch msg$ + case "EmptyAlert_|": + alert "This is an empty alert!", "Dooh", "none" + break + + case "InfoAlert_|" + alert "This is an info alert!", "Dooh", "info" + break + + case "IdeaAlert_|" + alert "This is an idea alert!", "Dooh", "idea" + break + + case "WarningAlert_|" + alert "This is a warning alert!", "Dooh", "warning" + break + + case "StopAlert_|" + alert "This is a stop alert!", "Dooh", "stop" + break + + case "Quit_|" + inloop = false + if (mainview1) window close "MainView1" + window close "MainView2" + break + + case "MainView1:_QuitRequested|" + window close "MainView1" + mainview1 = false + break + + case "MainView2:_QuitRequested|" + window close "MainView2" + break + + end switch + + if(window count<1) inloop = false + +wend + diff --git a/yab-IDE/Programs/Examples/Calc.yab b/yab-IDE/Programs/Examples/Calc.yab new file mode 100755 index 0000000..6433372 --- /dev/null +++ b/yab-IDE/Programs/Examples/Calc.yab @@ -0,0 +1,202 @@ +#!yab +sleep .01 +This_dir$ = getdir$("Calc.yab") + +//localize +window open 100,50 to 320,320, "Calc", "CalcView" + + +draw set "bgcolor", 100, 150, 220, "Calc" +draw set "lowcolor", 100, 190, 100, "Calc" +draw set "highcolor", 255, 255, 255, "Calc" +window set "Calc", "minimumto", 220, 260 +window set "Calc", "maximumto", 220, 260 + +layout "all", "Calc" + +menu "File", "Reset", "R", "Calc" +menu "File", "--", "", "Calc" +menu "File", "Quit", "Q", "Calc" +menu "Help", "Help...", "H", "Calc" +menu "Help", "--", "", "Calc" +menu "Help", "About...", "", "Calc" + +button 20,70 to 55,105,"b7", "7", "Calc" +button 65,70 to 100,105,"b8", "8", "Calc" +button 110,70 to 145,105,"b9", "9", "Calc" +button 155,70 to 190,105,"b/", "/", "Calc" +button 20,115 to 55,150,"b4", "4", "Calc" +button 65,115 to 100,150,"b5", "5", "Calc" +button 110,115 to 145,150,"b6", "6", "Calc" +button 155,115 to 190,150,"b*", "*", "Calc" +button 20,160 to 55,195,"b1", "1", "Calc" +button 65,160 to 100,195,"b2", "2", "Calc" +button 110,160 to 145,195,"b3", "3", "Calc" +button 155,160 to 190,195,"b-", "-", "Calc" +button 20,205 to 55,240,"b0", "0", "Calc" +button 65,205 to 100,240,"b.", ".", "Calc" +button 110,205 to 145,240,"bC", "C", "Calc" +button 155,205 to 190,240,"b+/=", "+=", "Calc" + +draw text 20,50,"0","Calc" + +display$ = "0" +result = 0 +type$ = "+" + +dim msgbuffer$(1) +inloop = true +while(inloop) + msgnumber = split(message$, msgbuffer$(), "|") + for i=0 to msgnumber + switch msgbuffer$(i) + case "b." + case "b0" + case "b1" + case "b2" + case "b3" + case "b4" + case "b5" + case "b6" + case "b7" + case "b8" + case "b9" + if(len(display$)<10) display$ = display$ + right$(msgbuffer$(i),1) + while(left$(display$,1)="0") + display$ = right$(display$,len(display$)-1) + wend + if(display$="") display$="0" + draw rect 20,30 to 170,60, "Calc" + draw flush "Calc" + draw text 20,50, display$,"Calc" + break + case "b-" + result = calculate(result, type$, val(display$)) + type$ = "-" + draw rect 20,30 to 170,60, "Calc" + draw flush "Calc" + draw text 20,50, str$(result),"Calc" + display$="0" + break + case "b+/=" + result = calculate(result, type$, val(display$)) + type$ = "+" + draw rect 20,30 to 170,60, "Calc" + draw flush "Calc" + draw text 20,50, str$(result),"Calc" + display$="0" + break + case "b*" + result = calculate(result, type$, val(display$)) + type$ = "*" + draw rect 20,30 to 170,60, "Calc" + draw flush "Calc" + draw text 20,50, str$(result),"Calc" + display$="0" + break + case "b/" + result = calculate(result, type$, val(display$)) + type$ = "/" + draw rect 20,30 to 170,60, "Calc" + draw flush "Calc" + draw text 20,50, str$(result),"Calc" + display$="0" + break + case "bC" + case "Calc:File:Reset" + result=0 + draw rect 20,30 to 170,60, "Calc" + draw flush "Calc" + draw text 20,50, str$(result),"Calc" + display$="0" + type$ = "+" + break + case "Calc:File:Quit" + case "Calc:_QuitRequested" + window close "Calc" + break + case "Calc:Help:Help..." + alert "Calc demonstrates how to program\n a calculator in yab.\n\n", "Ok", "info" + break + case "Calc:Help:About..." + window open 250,100 to 570,291, "About", "About" + window set "About", "look", "bordered" + window set "About", "feel", "modal-app" + draw set "BGColor", 255,255,255, "About" + window set "About", "minimumto", 320, 191 + window set "About", "maximumto", 320, 191 + + err = draw image 0,0, This_dir$+"img/image.png", "About" + if(err>0) then + alert "Error loading image.png!"+str$(err), "Close", "warning" + window close "About" + else + button 20,163 to 300,183,"b", "Close", "About" + endif + + break + case translate$("b") + case translate$("About:_QuitRequested") + window close "About" + break + default + break + end switch + next i + + if(window count = 0) inloop = false + sleep 0.1 +wend + +sub calculate(a,type$,b) + ret = 0 + switch(type$) + case "+" + ret = a + b + break + case "-" + ret = a - b + break + case "*" + ret = a * b + break + case "/" + ret = a / b + break + end switch + return ret +end sub + +////////////////////////////////////////////////////////////////// +sub getdir$( programname$) +// find out in which directory we are in +//////////////////////////////////////////////////////////////// +local path$ +local catch +catch=0 +if (!peek("isbound")) then + path$=system$("ps") + x=instr(path$,"/"+programname$) + path$=left$(path$,x) + for x=len(path$)-1 to 1 step -1 + if (instr(path$," ",x) and catch=0) catch=x+1 + next + path$=right$(path$,len(path$)-catch) + path$=trim$(path$) + if path$="/" then + path$ = trim$(system$("pwd"))+"/" + else + path$="/"+path$ + endif + +else +path$=trim$(peek$("directory") ) +path$=path$+"/" + +end if + +return path$ +end sub + + + diff --git a/yab-IDE/Programs/Examples/Checkbox.yab b/yab-IDE/Programs/Examples/Checkbox.yab new file mode 100755 index 0000000..b887b6d --- /dev/null +++ b/yab-IDE/Programs/Examples/Checkbox.yab @@ -0,0 +1,43 @@ +#!yab + +dim Part$(1) +window open 100, 100, 240, 300, "A", "Checkboxes" +window set "A", "flags", "not-h-resizable, not-v-resizable, not-zoomable" + +// create the checkboxes +// with layout for left top +layout "left, top", "A" +for NP = 1 to 5 + Y = Y+25 + checkbox 10, Y, "CheckMe:"+str$(NP), "OFF", 0, "A" +next NP + +button 10, 170 to 130, 190, "Button_", "Check them", "A" + +while (not instr(msg$, "Quit")) + msg$ = message$ + if (split(msg$, Part$(), ":|") < 3) dim Part$(3) + + // if one of the checkboxes was used + if (msg$ = "CheckMe:"+Part$(2)+":"+Part$(3)+"|") then + option set "CheckMe:"+Part$(2), "label", Part$(3) + fi + + // if the button was pressed + if (msg$ = "Button_|") then + if (check$ = "ON") then + check$ = "OFF" + option set "Button_", "label", "Check them" + else + check$ = "ON" + option set "Button_", "label", "Uncheck them" + fi + for NP = 1 to 5 + checkbox set "CheckMe:"+str$(NP), (check$ = "ON") + option set "CheckMe:"+str$(NP), "label", check$ +// sleep 0.05 + next NP + fi + +wend +exit diff --git a/yab-IDE/Programs/Examples/Clock.yab b/yab-IDE/Programs/Examples/Clock.yab new file mode 100755 index 0000000..bf18699 --- /dev/null +++ b/yab-IDE/Programs/Examples/Clock.yab @@ -0,0 +1,34 @@ +#!yab + +window open 100,100 to 200,150, "MainView", "Clock" +window set "MainView", "flags", "Not-Zoomable" +window set "MainView", "minimumto", 100,50 +window set "MainView", "maximumto", 100,50 +layout "left, top, right", "MainView" +view 0,0 to 100,50, "clockview", "MainView" + +inloop = true +while(inloop) + msg$ = message$ + if(msg$<>"") print msg$ + if(instr(msg$,"_QuitRequested")) inloop = false + if(instr(msg$,"Quit")) inloop = false + draw_time_and_date() +sleep 0.01 +wend + +window close "MainView" +exit + +sub time_and_date() + zeit$ = left$(time$,2) + ":" + mid$(time$,4,2) + ":" + mid$(time$,7,2) + datum$ = mid$(date$,14,3) + ", " + mid$(date$,6,2) + "." + mid$(date$,3,2) + "." + mid$(date$,11,2) +end sub + +sub draw_time_and_date() + time_and_date() + draw flush "clockview" + draw text 10,20, datum$ ,"clockview" + draw text 10,35, zeit$ + " ","clockview" + wait 0.25 +end sub diff --git a/yab-IDE/Programs/Examples/ColorDemo.yab b/yab-IDE/Programs/Examples/ColorDemo.yab new file mode 100755 index 0000000..c0f08a0 --- /dev/null +++ b/yab-IDE/Programs/Examples/ColorDemo.yab @@ -0,0 +1,26 @@ +#!yab + +DOCU ColorDemo, Color select and show +DOCU by Stargater + +window open 100,100 to 420,420, "MainView", "ColorDemo" +window set "MainView", "flags", "not-zoomable, not-h-resizable, not-v-resizable" +view 20,20 to 300,220, "ViewColor", "MainView" +r = 140 +g = 140 +b = 240 +draw set "bgcolor", r,g,b, "ViewColor" + +colorcontrol 10,240, "Colorcontrol", "MainView" +colorcontrol set "Colorcontrol", 140,140,240 + + +while(not instr(message$,"_QuitRequested")) + r = colorcontrol get "Colorcontrol", "red" + g = colorcontrol get "Colorcontrol", "green" + b = colorcontrol get "Colorcontrol", "blue" + draw set "bgcolor", r,g,b, "ViewColor" +wend + +window close "MainView" + diff --git a/yab-IDE/Programs/Examples/DrawWorld.yab b/yab-IDE/Programs/Examples/DrawWorld.yab new file mode 100755 index 0000000..77d9a3a --- /dev/null +++ b/yab-IDE/Programs/Examples/DrawWorld.yab @@ -0,0 +1,197 @@ +#!yab + +window open 100,100 to 700,500, "MainView", "DrawWorld" + +// MainView +draw set "highcolor", 0,0,0, "MainView" +draw set "lowcolor", 235,235,235, "MainView" +draw set "bgcolor", 235,235,235, "MainView" + +draw set 0, "HighSolidFill" +if(peek$("os") = "Haiku") then + draw set "DejaVu Sans,Condensed Bold,48", "MainView" +else + draw set "Zurich,Bold,48", "MainView" +endif +draw text 175,50, "DrawWorld", "MainView" + +button 510,370 to 590,390, "NextButton", "Next", "MainView" + +// Our drawing pad +view 100,60 to 500,390, "DrawView", "MainView" +draw set "highcolor", 0,0,0, "DrawView" +draw set "lowcolor", 255,255,255, "DrawView" +draw set "bgcolor", 255,255,255, "DrawView" + +// Dot and line +draw set "Zurich,Bold,18", "DrawView" +draw text 135,20, "Dot and Line", "DrawView" + +xold = 40 +yold = 260 +for a=10 to 720 step 10 + x = 10+a*180/360 + y = 230+60*sin(a*pi/180) + draw line xold,yold to x,y, "DrawView" + xold = x + 30 + yold = y + 30 +next a + +for a = 0 to 720 step 10 + x = 10+a*180/360 + y = 100+60*sin(a*pi/180) + draw dot x,y, "DrawView" +next a + +while(not instr(msg$,"NextButton")) + msg$ = message$ + if(instr(msg$, "Quit")) then + window close "MainView" + end + endif + sleep 0.1 +wend +msg$ = "" + +draw rect 0,0 to 400,330, "DrawView" +draw flush "DrawView" +draw set 1, "HighSolidFill" + +// Circle and ellipse +draw set "Zurich,Bold,18", "DrawView" +draw text 135,20, "Circle and Ellipse", "DrawView" + +// draw set 1, "LowSolidFill" +draw circle 70,70, 36, "DrawView" +draw set "highcolor", 0,0,245, "DrawView" +draw dot 70,70, "DrawView" +draw line 72,70 to 105,70, "DrawView" +draw line 105,70 to 100,65, "DrawView" +draw line 105,70 to 100,75, "DrawView" +draw text 85,68, "r", "DrawView" + +draw set "highcolor", 0,0,0, "DrawView" +draw ellipse 210,70, 72, 36, "DrawView" +draw set "highcolor", 0,0,245, "DrawView" +draw dot 210,70, "DrawView" +draw line 212,70 to 282,70, "DrawView" +draw line 282,70 to 277,65, "DrawView" +draw line 282,70 to 277,75, "DrawView" +draw line 210,68 to 210,34, "DrawView" +draw line 210,34 to 215,39, "DrawView" +draw line 210,34 to 205,39, "DrawView" +draw text 235,68, "rx", "DrawView" +draw text 192,57, "ry", "DrawView" + +for i = 0 to 255 step 5 + draw set "highcolor", i,0,0, "DrawView" + draw ellipse i+90, 230, 72-i/5, 36+i/5, "DrawView" +next i +draw set "highcolor", 0,0,0, "DrawView" + + +while(not instr(msg$,"NextButton")) + msg$ = message$ + if(instr(msg$, "Quit")) then + window close "MainView" + end + endif + sleep 0.1 +wend +msg$ = "" + +draw rect 0,0 to 400,330, "DrawView" +draw flush "DrawView" +draw set "lowcolor", 255,255,255, "DrawView" +draw set 1, "HighSolidFill" + +// Bezier curve +draw set "Zurich,Bold,18", "DrawView" +draw text 135,20, "Bezier Curve", "DrawView" + +draw set "highcolor", 50,50,250, "DrawView" +draw circle 30,100, 3, "DrawView" +draw circle 70,60, 3, "DrawView" +draw circle 100,40, 3, "DrawView" +draw circle 140,90, 3, "DrawView" +draw line 30,100 to 70,60, "DrawView" +draw line 70,60 to 100,40, "DrawView" +draw line 100,40 to 140,90, "DrawView" +draw set "highcolor", 0,0,0, "DrawView" +draw curve 30,100, 70,60, 100,40, 140,90, "DrawView" + +draw set "highcolor", 50,50,250, "DrawView" +draw circle 170,100, 3, "DrawView" +draw circle 190,40, 3, "DrawView" +draw circle 250,40, 3, "DrawView" +draw circle 265,90, 3, "DrawView" +draw line 170,100 to 190,40, "DrawView" +draw line 190,40 to 250,40, "DrawView" +draw line 250,40 to 265,90, "DrawView" +draw set "highcolor", 0,0,0, "DrawView" +draw curve 170,100, 190,40, 250,40, 265,90, "DrawView" + +draw set "highcolor", 50,50,250, "DrawView" +draw circle 350,40, 3, "DrawView" +draw circle 300,10, 3, "DrawView" +draw circle 290,200, 3, "DrawView" +draw circle 350,140, 3, "DrawView" +draw line 350,40 to 300,10, "DrawView" +draw line 300,10 to 290,200, "DrawView" +draw line 290,200 to 350,140, "DrawView" +draw set "highcolor", 0,0,0, "DrawView" +draw set 0, "HighSolidFill" +draw curve 350,40, 300,10, 290,200, 350,140, "DrawView" + +draw set 1, "HighSolidFill" +draw curve 10,300, 120,100, 170,100, 390,300, "DrawView" + +while(not instr(msg$,"NextButton")) + msg$ = message$ + if(instr(msg$, "Quit")) then + window close "MainView" + end + endif + sleep 0.1 +wend +msg$ = "" + +draw rect 0,0 to 400,330, "DrawView" +draw flush "DrawView" + +// Pattern +draw set "Zurich,Bold,18", "DrawView" +draw text 165,20, "Pattern", "DrawView" + +draw text 47,40, "HighSolidFill", "DrawView" +draw text 247,40, "LowSolidFill", "DrawView" +draw text 43,190, "CheckeredFill", "DrawView" +draw text 247,190, "Userdefined", "DrawView" +draw set "highcolor", 50,50,250, "DrawView" +draw set "lowcolor", 250,50,50, "DrawView" +draw set 0, "HighSolidFill" +draw rect 40,50 to 160,130, "DrawView" +draw set 0, "LowSolidFill" +draw rect 240,50 to 360,130, "DrawView" +draw set 0, "CheckeredFill" +draw rect 40,200 to 160,280, "DrawView" +pattern$ = "255239171199001199171239" +draw set 0, pattern$ +draw rect 240,200 to 360,280, "DrawView" +draw set 0, "255255255255255255255255" +draw rect 40,50 to 160,130, "DrawView" + +draw set "highcolor", 0,0,0, "DrawView" +draw set "lowcolor", 255,255,255, "DrawView" + +while(not instr(msg$,"NextButton")) + msg$ = message$ + if(instr(msg$, "Quit")) then + window close "MainView" + end + endif + sleep 0.1 +wend + +window close "MainView" + diff --git a/yab-IDE/Programs/Examples/DropWorld.yab b/yab-IDE/Programs/Examples/DropWorld.yab new file mode 100755 index 0000000..1181812 --- /dev/null +++ b/yab-IDE/Programs/Examples/DropWorld.yab @@ -0,0 +1,33 @@ +#!yab + + +window open 100,100 to 300,300, "WView", "DropWorld" + +text 20,5, "Txt1", "Drop any file here:", "WView" +view 20,20 to 180,180, "DropView", "WView" +draw set "highcolor", 0,0,0, "DropView" +draw set "lowcolor", 255,255,0, "DropView" +pattern$ = "240225195135015030060120" +draw set 0, pattern$ +draw rect 0,0 to 160,160, "DropView" +draw set 0, "lowsolid" +view dropzone "DropView" + +dim msg$(1) +inloop = true +while(inloop) + n = split(message$, msg$(), "|:") + for i = 0 to n + if(msg$(i) = "_Dropped") then + draw rect 20,181 to 290,200, "WView" + draw flush "WView" + draw text 20,195, msg$(i+1), "WView" + endif + if(msg$(i) = "_QuitRequested") inloop = false + next i + + if(msg$<>"") print msg$ + sleep 0.1 +wend + +window close "WView" diff --git a/yab-IDE/Programs/Examples/EvenMoreControls.yab b/yab-IDE/Programs/Examples/EvenMoreControls.yab new file mode 100755 index 0000000..dad2df7 --- /dev/null +++ b/yab-IDE/Programs/Examples/EvenMoreControls.yab @@ -0,0 +1,18 @@ +#!yab +sleep .01 +window open 100,100 to 400, 200, "WView", "EvenMoreControls" +layout "none", "WView" +colorcontrol 10,10, "CC", "WView" +colorcontrol set "CC", 213,123,43 + +textcontrol 10,70 to 150,90, "TC", "Enter Password:","","WView" +textcontrol set "TC",1 + +inloop = true +while(inloop) + msg$ = message$ + if(msg$<>"") print msg$ + if(instr(msg$,"Quit")) inloop = false +wend + +window close "WView" diff --git a/yab-IDE/Programs/Examples/FakeTransparency.yab b/yab-IDE/Programs/Examples/FakeTransparency.yab new file mode 100755 index 0000000..654d77d --- /dev/null +++ b/yab-IDE/Programs/Examples/FakeTransparency.yab @@ -0,0 +1,58 @@ +#!yab + +SCREEN_W = peek("desktopwidth") +SCREEN_H = peek("desktopheight") + +W = 400 +H = 200 + +X = (SCREEN_W/2) - (W/2) +Y = (SCREEN_H/2) - (H/2) + +THE_TEXT$ = "HELLO" + +screenshot 0, 0 to SCREEN_W-1, SCREEN_H-1, "BMP_screen_" + +window open -10-W, 0 to -10, H, "Main_", "PAPA" + window set "Main_", "look", "modal" + window set "Main_", "flags", "not-h-resizable, not-v-resizable, not-zoomable" + +canvas 0, 0 to W, H, "CV_main_", "Main_" +if(peek$("os") = "Haiku") then + draw set "DejaVu Sans,Condensed Bold,122", "CV_main_" +else + draw set "Swis721 BT, Bold, 122", "CV_main_" +endif + +th = draw get "max-text-height", "CV_main_" +tw = draw get "text-width", THE_TEXT$, "CV_main_" + +tx = (W/2)-(tw/2) +ty = (H/3)*2 + +draw bitmap -X, -Y, "BMP_screen_", "copy", "CV_main_" +draw text tx, ty, THE_TEXT$, "CV_main_" + +window set "Main_", "moveto", X, Y + +dim m$(1) +while (not instr(msg$, "Quit")) + msg$ = message$ + + if (X <> window get "Main_", "position-x") then + X = window get "Main_", "position-x" + Moved = true + fi + if (Y <> window get "Main_", "position-y") then + Y = window get "Main_", "position-y" + Moved = true + fi + + if (Moved) then + draw bitmap -X, -Y, "BMP_screen_", "copy", "CV_main_" + draw text tx, ty, THE_TEXT$, "CV_main_" + Moved = false + fi + +wend +exit diff --git a/yab-IDE/Programs/Examples/Filebox.yab b/yab-IDE/Programs/Examples/Filebox.yab new file mode 100755 index 0000000..d9696c9 --- /dev/null +++ b/yab-IDE/Programs/Examples/Filebox.yab @@ -0,0 +1,97 @@ +// Filebox is a library to have an easy access to a list of files. +// This is easier than poking around with columnboxes yourself. + +// Open a new filebox from (x1,y1) to (x2,y2) +// with the id ID$, the type of scrollbar ScrollbarType on View$ +export sub Filebox(x1,y1,x2,y2, ID$, ScrollbarType, View$) + local myscrollbar + columnbox x1,y1 to x2,y2, ID$, ScrollbarType, "resizable", View$ + columnbox column ID$, " ", 1, 20, 20, 20, "align-center" + if(scrollbarType=1 or scrollbarType=3) myscrollbar = peek("scrollbarwidth") + columnbox column ID$, "Name", 2, 1000, 21, x2-x1-24-myscrollbar, "align-left" + columnbox color ID$, "Selection-Active", 220,220,250 + columnbox color ID$, "Row-Divider", 255,255,255 + return +end sub + +// Easy interface to a Filebox, simply name a directory +export sub FileboxDirectorySimple(ID$, dir$) + FileboxDirectory(ID$,dir$,false) + return +end sub + +// return the name of the row position +export sub FileboxName$(ID$, position) + return columnbox get$ ID$, 2, position +end sub + +// return true, if the row position is a directory +export sub FileboxIsDirectory(ID$, position) + local t$ + t$ = columnbox get$ ID$, 1, position + if(t$ = "__Mime__=application/x-vnd.Be-directory") return true + return false +end sub + +// Give a directory and the following options: +// showDot: set this to true to show hidden (dot) files +export sub FileboxDirectory(ID$, dir$, showDot) + local t$ + local i + local n + local arraysizeDir + local arraysizeFiles + + dim directories$(1) + dim files$(1) + + arraysizeDir = 0 + arraysizeFiles = 0 + + columnbox clear ID$ + if(showDot) then + t$ = system$("ls --format=single-column --color=none -a "+dir$+" |sort -f") + else + t$ = system$("ls --format=single-column --color=none "+dir$+" |sort -f") + endif + + dim splitdir$(1) + + n = split(t$, splitdir$(), "\n") + for i=1 to n-1 + if(system("test -d \""+ dir$+splitdir$(i)+"\"") = 0) then + // comment the if clause out if you want to have the direcotries "." and ".." listed + if(splitdir$(i)<>"." and splitdir$(i)<>"..") then + arraysizeDir = arraysizeDir + 1 + dim directories$(arraysizeDir) + directories$(arraysizeDir-1) = splitdir$(i) + endif + // handle files + else + arraysizeFiles = arraysizeFiles + 1 + dim files$(arraysizeFiles) + files$(arraysizeFiles-1) = splitdir$(i) + endif + next i + for i=0 to arraysizeDir-1 + FileboxAdd(ID$, directories$(i), true) + next i + for i=0 to arraysizeFiles-1 + FileboxAdd(ID$, files$(i), false) + next i + return +end sub + +sub FileboxAdd(ID$, Name$, IsFolder) + local maxpos + + maxpos = (columnbox count ID$) + 1 + + if(IsFolder) then + columnbox add ID$, 1, maxpos, 18, "__Mime__=application/x-vnd.Be-directory" + else + columnbox add ID$, 1, maxpos, 18, "__Mime__=application/octet-stream" + endif + columnbox add ID$, 2, maxpos, 20, Name$ + return +end sub diff --git a/yab-IDE/Programs/Examples/FileboxDemo.yab b/yab-IDE/Programs/Examples/FileboxDemo.yab new file mode 100755 index 0000000..b45bd09 --- /dev/null +++ b/yab-IDE/Programs/Examples/FileboxDemo.yab @@ -0,0 +1,46 @@ +import Filebox + + +dir$ = "/boot/home/" + +window open 100,100 to 500,500, "Demo","Demo" +Filebox(10,10,350,390,"Filebox", 1, "Demo") +FileboxDirectory("Filebox", dir$, false) +button 360,10,390,30, "DirUp", "..", "Demo" + +dim msg$(1) +inloop = true +while(inloop) + n = split(message$, msg$(), "|") + for i=1 to n + // Quit + if(msg$(i) = "Demo:_QuitRequested") inloop = false + + // Button pressed and we are not in the root directory + if(msg$(i) = "DirUp" and dir$<>"/") then + t = len(dir$)-1 + while(mid$(dir$,t,1)<>"/") + t = t - 1 + wend + dir$ = left$(dir$,t) + FileboxDirectory("Filebox", dir$, false) + endif + + // An item is invoked + if(instr(msg$(i),"Filebox:_Invoke:")) then + position = val(right$(msg$(i),len(msg$(i))-16)) + + // if the item is a directory, then update the filebox else print the filename + if(FileboxIsDirectory("Filebox", position)) then + dir$ = dir$ + FileboxName$("Filebox", position) + "/" + FileboxDirectory("Filebox", dir$, false) + else + print FileboxName$("Filebox", position) + endif + endif + next i + + sleep 0.01 +wend + +window close "Demo" diff --git a/yab-IDE/Programs/Examples/GUI-World.yab b/yab-IDE/Programs/Examples/GUI-World.yab new file mode 100755 index 0000000..ee0ddbe --- /dev/null +++ b/yab-IDE/Programs/Examples/GUI-World.yab @@ -0,0 +1,444 @@ +#!yab + +// Set Backgroundcolors as variables. +bgr = 216 : bgg = 216 : bgb = 226 + +window open 100, 100 to 610, 400, "MainView" ,"GUI - World" + window set "MainView", "flags", "not-h-resizable" + draw set "bgcolor", bgr, bgg, bgb, "MainView" + draw set "lowcolor", bgr, bgg, bgb, "MainView" + draw set "highcolor", 0, 0, 0, "MainView" + draw set "Zurich, Bold, 16", "MainView" + draw text 10, 20, "GUI - World", "MainView" + +listbox 200, 5 to 505, 235, "SourceView", 1, "MainView" + +view 5, 241 to 505, 265, "LineView", "MainView" + draw set "bgcolor", bgr-16, bgg-16, bgb-16, "LineView" + draw set "lowcolor", bgr-16, bgg-16, bgb-16, "LineView" + draw set "highcolor", 155, 0, 0, "LineView" + draw set "Zurich, Bold, 14", "LineView" + +view 0, 270 to 510, 300, "ButtonView", "MainView" + draw set "bgcolor", bgr, bgg, bgb, "ButtonView" + +button 10, 0 to 70, 20, "Quit_", "Quit", "ButtonView" +button 205, 0 to 500, 20, "Step_", "Next step", "ButtonView" + +layout "left, top", "MainView" +view 5, 25 to 190, 240, "StatusView", "MainView" + draw set "bgcolor", bgr, bgg, bgb, "StatusView" + draw set "Zurich, Roman, 10", "StatusView" + +NextStep(0) +option set "Step_", "focus", true + +dim choice$(1) +inloop = true +while (inloop) + msg$ = message$ + if (split(msg$, choice$(), ":|") > 2) btn$ = choice$(3) + if (msg$ <> "") print msg$ + + switch msg$ + + case "Step_|" + stp = stp+1 + NextStep(stp) + L = 0 + option set "Step_", "focus", true + break + + case "SourceView:_Invoke:"+btn$+"|" + if (L = 0) stp = stp-1 + L = 1 + NextStep(val(btn$)) + break + + case "Quit_|": + case "MainView:_QuitRequested|": + inloop = false + break + + end switch + sleep 0.01 +wend +exit + +sub NextStep(n) + draw flush "StatusView" + m = n + if (n = 0) then + draw text 5, 20, "With GUI-World you can", "StatusView" + draw text 5, 35, "create a window with a few", "StatusView" + draw text 5, 50, "contents, as examples.", "StatusView" + draw text 5, 75, "The currently executed line will be", "StatusView" + draw text 5, 90, "shown down above the buttons.", "StatusView" + draw text 5, 115, "The complete source will be", "StatusView" + draw text 5, 130, "collected in the right list.", "StatusView" + draw text 5, 200, "Click on 'Next step' to start ...", "StatusView" + ShowLine("Welcome to GUI-World!") + fi + + if (n = 1) then + draw text 5, 20, "At first, we need to create the window.", "StatusView" + draw text 5, 35, "We will create a window", "StatusView" + draw text 5, 60, "with a size of 400, 300 (x, y)", "StatusView" + draw text 5, 75, "at the position 200x200", "StatusView" + draw text 5, 90, "of your monitor.", "StatusView" + draw text 5, 110, "The name of the window is ''New App''.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("window open 200, 200 to 600, 500, ''View1'', ''New App''") + fi + + if (n = 2) then + if (L = 0) window open 200, 450 to 600, 750, "View1", "New App" + if (L = 0) listbox add "SourceView", "window open 200, 200 to 600, 500, ''View1'', ''New App''" + + draw text 5, 20, "The window should be opened now.", "StatusView" + draw text 5, 45, "It has no function yet,", "StatusView" + draw text 5, 60, "so we'll change that.", "StatusView" + draw text 5, 85, "But first let us define the", "StatusView" + draw text 5, 100, "background color of the window.", "StatusView" + draw text 5, 125, "We'll choose white for background.", "StatusView" + draw text 5, 140, "Red 255 + Green 255 + Green 255", "StatusView" + draw text 5, 155, " = white.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("draw set ''bgcolor'', 255, 255, 255, ''View1''") + fi + + if (n = 3) then + if (L = 0) draw set "bgcolor", 255, 255, 255, "View1" + if (L = 0) listbox add "SourceView", "draw set ''bgcolor'', 255, 255, 255, ''View1''" + if (L = 0) listbox add "SourceView", "" + + draw text 5, 20, "Ok, white. But still no function!!", "StatusView" + draw text 5, 45, "We can now drop in some widgets,", "StatusView" + draw text 5, 60, "such as buttons, checkboxes, etc.", "StatusView" + draw text 5, 85, "Let's start with a simple button.", "StatusView" + draw text 5, 100, "The button will be named 'Quit'", "StatusView" + draw text 5, 115, "and will appear down-right.", "StatusView" + draw text 5, 140, "Its ID is 'Button1' so it would return", "StatusView" + draw text 5, 155, "'Button1' if is pressed.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("button 330, 270 to 390, 270, ''Button1'', ''Quit'', ''View1''") + fi + + if (n = 4) then + if (L = 0) button 330, 270 to 390, 270, "Button1", "Quit", "View1" + if (L = 0) listbox add "SourceView", "button 330, 270 to 390, 270, ''Button1'', ''Quit'', ''View1''" + if (L = 0) listbox add "SourceView", "" + + draw text 5, 20, "Creating views.", "StatusView" + draw text 5, 45, "For further widgets, we should create", "StatusView" + draw text 5, 60, "extra views inside the View1", "StatusView" + draw text 5, 85, "The name of the view is 'View2'", "StatusView" + draw text 5, 100, "and we want it in the upper-left corner", "StatusView" + draw text 5, 115, "inside the Window (View1).", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("view 5, 5 to 150, 60, ''View2'', ''View1''") + fi + + if (n = 5) then + if (L = 0) view 5, 5 to 150, 60, "View2", "View1" + if (L = 0) listbox add "SourceView", "view 5, 5 to 150, 60, ''View2'', ''View1''" + + draw text 5, 60, "We'd like to change the background", "StatusView" + draw text 5, 75, "color of that new view...", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("draw set ''bgcolor'', 216, 230, 250, ''View2''") + fi + + if (n = 6) then + if (L = 0) draw set "bgcolor", 216, 230, 250, "View2" + if (L = 0) listbox add "SourceView", " draw set ''bgcolor'', 216, 230, 250, ''View2''" + if (L = 0) listbox add "SourceView", "" + + draw text 5, 20, "Radiobuttons.", "StatusView" + draw text 5, 45, "Now we drop a radiobutton", "StatusView" + draw text 5, 60, "in the new view.", "StatusView" + draw text 5, 85, "Note that we have to use the", "StatusView" + draw text 5, 100, "coordinates of 'View2' for everything", "StatusView" + draw text 5, 115, "we want to put into it!", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("radiobutton 5, 10, ''rb1'', ''Radiobutton 1'', 0, ''View2''") + fi + + if (n = 7) then + draw text 5, 20, "Our radiobutton should", "StatusView" + draw text 15, 45, "appear at 5, 10 on 'View2',", "StatusView" + draw text 15, 60, "be named 'RadioButton 1'", "StatusView" + draw text 15, 75, "have the ID 'rb1'", "StatusView" + draw text 15, 90, "not be activated (activated = 0)", "StatusView" + draw text 5, 115, "It will return the ID and if", "StatusView" + draw text 5, 130, "not activated = 0", "StatusView" + draw text 5, 145, "activated = 1", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + fi + + if (n = 8) then + if (L = 0) radiobutton 5, 10, "rb1", "Radiobutton 1", 0, "View2" + if (L = 0) listbox add "SourceView", "radiobutton 5, 10, ''rb1'', ''Radiobutton 1'', 0, ''View2''" + + draw text 5, 20, "What about another one?", "StatusView" + draw text 5, 45, "This time activated.", "StatusView" + draw text 5, 60, "Because they are on the same view,", "StatusView" + draw text 5, 85, "you can switch between them.", "StatusView" + draw text 5, 100, "Just try it out...", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on...", "StatusView" + ShowLine("radiobutton 5, 30, ''rb2'', ''Radiobutton 2'', 1, ''View2''") + fi + + if (n = 9) then + if (L = 0) radiobutton 5, 30, "rb2", "Radiobutton 2", 1, "View2" + if (L = 0) listbox add "SourceView", "radiobutton 5, 30, ''rb2'', ''Radiobutton 2'', 1, ''View2''" + if (L = 0) listbox add "SourceView", "" + + draw text 5, 20, "Checkbuttons.", "StatusView" + draw text 5, 45, "Let's make checkbuttons!", "StatusView" + draw text 5, 60, "This time placed on 'View1' again.", "StatusView" + draw text 5, 85, "It is named 'Checkbox 1',", "StatusView" + draw text 5, 100, "has the ID 'cb1' and is", "StatusView" + draw text 5, 115, "not activated.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("checkbox 10, 70, ''cb1'', ''Checkbox 1'', 0, ''View1''") + fi + + if (n = 10) then + if (L = 0) checkbox 10, 70, "cb1", "Checkbox 1", 0, "View1" + if (L = 0) listbox add "SourceView", "checkbox 10, 60, ''cb1'', ''Checkbox 1'', 0, ''View1''" + + draw text 5, 20, "And another one for switching...", "StatusView" + draw text 5, 45, "This time activated.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("checkbox 10, 90, ''cb2'', ''Checkbox 2'', 1, ''View1''") + fi + + if (n = 11) then + if (L = 0) checkbox 10, 90, "cb2", "Checkbox 2", 1, "View1" + if (L = 0) listbox add "SourceView", "checkbox 10, 60, ''cb2'', ''Checkbox 2'', 1, ''View1''" + if (L = 0) listbox add "SourceView", "" + + draw text 5, 20, "Textcontrol - Input from the user.", "StatusView" + draw text 5, 45, "This shows a text inputfield with a", "StatusView" + draw text 5, 60, "short text before it.", "StatusView" + draw text 5, 85, "It has the ID 'tc1' and returns it, if", "StatusView" + draw text 5, 100, "a user pressed enter after typing", "StatusView" + draw text 5, 115, "in the textfield.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("textcontrol 10, 120 to 180, 130, ''tc1'', ''Tell me:'', ''Text...'', ''View1''") + fi + + if (n = 12) then + if (L = 0) textcontrol 10, 120 to 180, 130, "tc1", "Tell me:", "Text...", "View1" + if (L = 0) listbox add "SourceView", "textcontrol 10, 120 to 180, 130, ''tc1'', ''Tell me:'', ''Text...'', ''View1''" + + draw text 5, 20, "And now a listbox.", "StatusView" + draw text 5, 45, "It's a list, where dropboxs can be added to.", "StatusView" + draw text 5, 60, "It has the ID 'list1' and returns it,", "StatusView" + draw text 5, 85, "followed by the chosen dropbox.", "StatusView" + draw text 5, 100, "The '1' in here affects the scrollbars", "StatusView" + draw text 15, 115, "0 = no scrollbar", "StatusView" + draw text 15, 130, "1 = vertikal scrollbar", "StatusView" + draw text 15, 145, "2 = horizontal scrollbar", "StatusView" + draw text 15, 160, "3 = both scrollbars", "StatusView" + draw text 5, 185, "We'll take just the vertikal one.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("listbox 200, 10 to 380, 260, ''list1'', 1, ''View1''") + fi + + if (n = 13) then + if (L = 0) listbox 200,10 to 380,260,"list1",1, "View1" + if (L = 0) listbox add "SourceView", "listbox 200, 10 to 380, 260, ''list1'', 1, ''View1''" + + draw text 5, 20, "Add items to the list.", "StatusView" + draw text 5, 45, "Now let's put some items into it.", "StatusView" + draw text 5, 60, "We will add 3 entries in the list.", "StatusView" + draw text 5, 85, "Look on the line and then watch out", "StatusView" + draw text 5, 100, "what happens.", "StatusView" + draw text 5, 125, "At first we enter 'Hello World'.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("listbox add ''list1'', ''Hello world!'''") + fi + + if (n = 14) then + if (L = 0) listbox add "list1", "Hello world!" + if (L = 0) listbox add "SourceView", "listbox add ''list1'', ''Hello world!''" + + draw text 5, 20, "Just another entry.", "StatusView" + draw text 5, 60, "Now we enter 'How are you?'.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("listbox add ''list1'', ''How are you?''") + fi + + if (n = 15) then + if (L = 0) listbox add "list1", "How are you?" + if (L = 0) listbox add "SourceView", "listbox add ''list1'', ''How are you?''" + + draw text 5, 20, "The third and last entry.", "StatusView" + draw text 5, 45, "Last but not least, we enter", "StatusView" + draw text 5, 60, "'I am fine' to the listbox.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + if (L = 0) ShowLine("listbox add ''list1'', ''I am fine!''") + fi + + if (n = 16) then + if (L = 0) listbox add "list1", "I am fine!" + if (L = 0) listbox add "SourceView", "''dropbox add ''list1'', ''I am fine!''" + if (L = 0) listbox add "SourceView", "" + + draw text 5, 20, "Selfexplaining...", "StatusView" + draw text 5, 45, "You see everything what differs them", "StatusView" + draw text 5, 60, "is the text for the entry.", "StatusView" + draw text 5, 85, "So it is important, where you place", "StatusView" + draw text 5, 100, "the entries in the sourcecode.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("...") + fi + + if (n = 17) then + if (L = 0) draw set "highcolor", 0, 0, 0, "View1" + if (L = 0) listbox add "SourceView", "draw set ''highcolor'', 0, 0, 0, ''View1''" + + draw text 5, 20, "Change highcolor.", "StatusView" + draw text 5, 45, "If you'd like to draw something", "StatusView" + draw text 5, 60, "e.g. a rectangle, you should control", "StatusView" + draw text 5, 75, "the background color of the view", "StatusView" + draw text 5, 90, "which shall appear in.", "StatusView" + draw text 5, 115, "We chose black (0, 0, 0).", "StatusView" + draw text 5, 130, "(see sourcecode)", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("draw set ''highcolor'', 0, 0, 0, ''View1''") + fi + + if (n = 18) then + draw text 5, 20, "Now we set the color, we can draw.", "StatusView" + draw text 5, 45, "A rectangle will now be drawn", "StatusView" + draw text 5, 60, " with the previously chosen color", "StatusView" + draw text 5, 75, "in the window.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("draw rect 10, 150 to 180, 190, ''View1''") + fi + + if (n = 19) then + if (L = 0) draw rect 10, 150 to 180, 190, "View1" + if (L = 0) listbox add "SourceView", "draw rect 10, 150 to 180, 190, ''View1''" + if (L = 0) listbox add "SourceView", "" + + draw text 5, 20, "Draw text on the rectangle.", "StatusView" + draw text 5, 45, "Now we'll do some writing but", "StatusView" + draw text 5, 60, "first we should control the color.", "StatusView" + draw text 5, 85, "The highcolor is the color the", "StatusView" + draw text 5, 100, "text will be in.", "StatusView" + draw text 5, 125, "We chose red here.", "StatusView" + draw text 5, 205, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("draw set ''highcolor'', 255, 0, 0, ''View1''") + fi + + if (n = 20) then + if (L = 0) draw set "highcolor", 255, 0, 0, "View1" + if (L = 0) draw set "lowcolor", 0, 0, 0, "View1" + if (L = 0) listbox add "SourceView", "draw set ''highcolor'', 255, 0, 0, ''View1''" + + draw text 5, 20, "Font -type and -size.", "StatusView" + draw text 5, 45, "Next we have to define the", "StatusView" + draw text 5, 60, "fonttype and its size.", "StatusView" + draw text 5, 85, "You can see the font-idents best", "StatusView" + draw text 5, 100, "in GoBe productive or something", "StatusView" + draw text 5, 115, "like that.", "StatusView" + draw text 5, 200, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("draw set ''Zurich, Bold, 24'', ''View1''") + fi + + if (n = 21) then + if (L = 0) draw set "Zurich, Bold, 24", "View1" + if (L = 0) listbox add "SourceView", "draw set ''Zurich, Bold, 24'', ''View1''" + + draw text 5, 20, "Let's go writing.", "StatusView" + draw text 5, 45, "The text shall appear in red", "StatusView" + draw text 5, 60, "right on the rectangle.", "StatusView" + draw text 5, 85, "We will write the word", "StatusView" + draw text 5, 100, "'easy", "StatusView" + draw text 5, 115, "", "StatusView" + draw text 5, 200, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("draw text 40, 180, ''easy'', ''View1''") + fi + + if (n = 22) then + if (L = 0) draw text 40, 180, "easy", "View1" + if (L = 0) listbox add "SourceView", "draw text 40, 180, ''easy'', ''View1''" + + draw text 5, 20, "Dropboxes.", "StatusView" + draw text 5, 45, "If you want to provide the user a selection", "StatusView" + draw text 5, 60, "on a small room, take a dropbox!", "StatusView" + draw text 5, 85, "This dropbox has the ID ''db1'' and returns", "StatusView" + draw text 5, 100, "it, if there are entries in it, together with", "StatusView" + draw text 5, 115, "that entry.", "StatusView" + draw text 5, 200, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("dropbox 10, 200 to 180, 220, ''db1'', ''Choose'', ''View1''") + fi + + if (n = 23) then + if (L = 0) dropbox 10, 200 to 180, 220, "db1", "Choose", "View1" + if (L = 0) listbox add "SourceView", "dropbox 10, 200 to 180, 220, ''db1'', ''Choose'', ''View1''" + + draw text 5, 20, "Add items to the dropbox.", "StatusView" + draw text 5, 45, "Adding items to a dropbox is the same", "StatusView" + draw text 5, 60, "procedure as for listboxes.", "StatusView" + draw text 5, 85, "We give the ID of the dropbox", "StatusView" + draw text 5, 100, "which is 'db1' and the name, the", "StatusView" + draw text 5, 115, "dropbox should have, followed by the", "StatusView" + draw text 5, 130, "view the dropbox is on.", "StatusView" + draw text 5, 155, "We'll make three entries again and", "StatusView" + draw text 5, 170, "start with that line below. ", "StatusView" + draw text 5, 200, "Click on 'Next step' to go on ...", "StatusView" + ShowLine("dropbox add ''db1'', ''yab interpreter''") + fi + + if (n = 24) then + if (L = 0) dropbox add "db1", "yab interpreter" + if (L = 0) listbox add "SourceView", "dropbox add ''db1'', ''yab interpreter''" + ShowLine("dropbox add ''db1'', ''yet another''") + sleep 0.5 + if (L = 0) dropbox add "db1", "yet another" + if (L = 0) listbox add "SourceView", "dropbox add ''db1'', ''yet another''" + ShowLine("dropbox add ''db1'', ''basic''") + sleep 0.5 + if (L = 0) dropbox add "db1", "basic" + if (L = 0) listbox add "SourceView", "dropbox add ''db1'', ''basic''" + + draw text 5, 20, "That's it for today, man!", "StatusView" + draw text 5, 45, "More help do you get from the file", "StatusView" + draw text 5, 60, "DONE_AND_TODO", "StatusView" + draw text 5, 85, "", "StatusView" + draw text 5, 100, "To be continued...", "StatusView" + draw text 5, 115, "", "StatusView" + draw text 5, 200, "Click on 'Next step' to go insane...", "StatusView" + ShowLine("Nothing more to tell ...") + fi + + if (n = 25) then + + + draw text 5, 20, "That's it for today, man!", "StatusView" + draw text 5, 45, "More help do you get from the file", "StatusView" + draw text 5, 60, "DONE_AND_TODO", "StatusView" + draw text 5, 85, "", "StatusView" + draw text 5, 100, "To be continued...", "StatusView" + draw text 5, 115, "", "StatusView" + draw text 5, 200, "Click on 'Next step' to go insane...", "StatusView" + ShowLine("Nothing more to tell ...") + + stp = stp-1 + fi + + return +end sub + +sub ShowLine(CurrLine$) + + draw flush "LineView" + draw text 10, 17, CurrLine$, "LineView" + + return +end sub diff --git a/yab-IDE/Programs/Examples/IconWorld.yab b/yab-IDE/Programs/Examples/IconWorld.yab new file mode 100755 index 0000000..be67013 --- /dev/null +++ b/yab-IDE/Programs/Examples/IconWorld.yab @@ -0,0 +1,30 @@ +#!yab + +window open 100,100 to 600,600, "Main", "IconWorld" + +systempath$ = "/boot/system/apps/Mail" + +draw text 70,30, "bitmap get \"BMP_icon\", \"path\", \"" + systempath$ +"\"", "Main" +bitmap get "BMP_icon", "path", systempath$ +draw bitmap 10, 10, "BMP_icon", "alpha", "Main" +bitmap remove "BMP_icon" + +draw text 70,70, "bitmap get \"BMP_icon\", \"mime16\", \"application/x-vnd.Be-MAIL\"", "Main" +bitmap get "BMP_icon", "mime16", "application/x-vnd.Be-MAIL" +draw bitmap 10, 60, "BMP_icon", "alpha", "Main" +bitmap remove "BMP_icon" + +draw text 70,110, "bitmap get \"BMP_icon\", \"mime32\", \"application/x-vnd.Be-MAIL\"", "Main" +bitmap get "BMP_icon", "mime32", "application/x-vnd.Be-MAIL" +draw bitmap 10, 90, "BMP_icon", "alpha", "Main" +bitmap remove "BMP_icon" + +draw text 70,150, "bitmap get 32, \"BMP_icon\", \"" + systempath$ + "\"", "Main" +bitmap get 32, "BMP_icon", systempath$ +draw bitmap 10, 130, "BMP_icon", "alpha", "Main" +bitmap remove "BMP_icon" + +while(not instr(message$, "Quit")) +wend + +window close "Main" diff --git a/yab-IDE/Programs/Examples/ImageWorld.yab b/yab-IDE/Programs/Examples/ImageWorld.yab new file mode 100755 index 0000000..52bd5de --- /dev/null +++ b/yab-IDE/Programs/Examples/ImageWorld.yab @@ -0,0 +1,32 @@ +#!yab + +window open 200,200 to 520,391, "MainView", "ImageWorld" +button 50,163 to 270,183, "Ok_", "Ok", "MainView" + +err = draw image 0,0, "img/image.png", "MainView" + +if(err = 1) then + alert "Problem while loading image.png!", "Quit", "stop" + window close "MainView" + exit 1 +endif + +alert "This shows how to show Images in your windows.", "Ok", "idea" + +inloop = true +while(inloop) + msg$ = message$ + + switch msg$ + case "Ok_|": + case "MainView:_QuitRequested|": + inloop = false + break + + end switch + +wend + +exit + + diff --git a/yab-IDE/Programs/Examples/JDemo.yab b/yab-IDE/Programs/Examples/JDemo.yab new file mode 100755 index 0000000..2eaa848 --- /dev/null +++ b/yab-IDE/Programs/Examples/JDemo.yab @@ -0,0 +1,69 @@ +#!yab + +// JDemo - just a smiley +// by DasJott + +window open 300,100 to 800,500,"mainview","Smiley - DEMO" +window set "mainview", "flags","not-zoomable, not-h-resizable, not-v-resizable" +draw set "bgcolor", 0,0,0,"mainview" +draw set "highcolor",255,255,0,"mainview" +draw circle 250,200,180,"mainview" + +// Eyes +draw set "highcolor",0,0,0,"mainview" +draw circle 170,110,20,"mainview" +view 310,90 to 350,130,"twinkleview","mainview" +draw set "bgcolor",255,255,0,"twinkleview" +draw set "highcolor",0,0,0,"twinkleview" +draw circle 20,20,20,"twinkleview" + +// Smiling mouth +view 140,220 to 360,320,"mouthview","mainview" +draw set "bgcolor",255,255,0,"mouthview" +draw set "highcolor",0,0,0,"mouthview" +draw set 1, "HighSolidFill" +draw circle 110,-11, 110,"mouthview" +draw set 0, "HighSolidFill" + +button 450,370 to 490,390,"Exit","Quit","mainview" + + + +inloop = true +while (inloop = true) + msg$ = message$ + + if (t < 20) then + draw flush "twinkleview" + draw ellipse 20,20, 20, 20-t,"twinkleview" + fi + + if (t > 20 and t < 41) then + draw flush "twinkleview" + draw ellipse 20,20, 20, t-20,"twinkleview" + fi + + if (t = 100) t = 0 + + t = t+1 + n = n+1 + + if(n = 200) then + draw flush "mouthview" + draw circle 110,-11, 110,"mouthview" + n = 0 + sleep 1 + fi + + if(n = 0) then + draw flush "mouthview" + draw set 1, "HighSolidFill" + draw circle 110,-11, 110,"mouthview" + draw set 0, "HighSolidFill" + fi + + if (msg$ = "Exit|") inloop = false + if (msg$ = "mainview:_QuitRequested|") inloop = false +wend + +window close "mainview" diff --git a/yab-IDE/Programs/Examples/Keyboard.yab b/yab-IDE/Programs/Examples/Keyboard.yab new file mode 100755 index 0000000..687e726 --- /dev/null +++ b/yab-IDE/Programs/Examples/Keyboard.yab @@ -0,0 +1,115 @@ +#!yab + +window open 200, 200 to 710, 600, "MainView" ,"YAB-Keyboard" +window set "MainView", "flags", "not-h-resizable, not-v-resizable" + +view 10,10 to 500, 180, "TextView", "MainView" + draw set "bgcolor", 0, 50, 0, "TextView" + draw set "lowcolor", 0, 50, 0, "TextView" + draw set "highcolor", 245, 245, 245, "TextView" + draw set "Zurich, Bold, 20", "TextView" + +button 10, 200 to 50, 240, "Button:Q", "Q", "MainView" +button 60, 200 to 100, 240, "Button:W", "W", "MainView" +button 110, 200 to 150, 240, "Button:E", "E", "MainView" +button 160, 200 to 200, 240, "Button:R", "R", "MainView" +button 210, 200 to 250, 240, "Button:T", "T", "MainView" +button 260, 200 to 300, 240, "Button:Z", "Z", "MainView" +button 310, 200 to 350, 240, "Button:U", "U", "MainView" +button 360, 200 to 400, 240, "Button:I", "I", "MainView" +button 410, 200 to 450, 240, "Button:O", "O", "MainView" +button 460, 200 to 500, 240, "Button:P", "P", "MainView" + +button 20, 250 to 60, 290, "Button:A", "A", "MainView" +button 70, 250 to 110, 290, "Button:S", "S", "MainView" +button 120, 250 to 160, 290, "Button:D", "D", "MainView" +button 170, 250 to 210, 290, "Button:F", "F", "MainView" +button 220, 250 to 260, 290, "Button:G", "G", "MainView" +button 270, 250 to 310, 290, "Button:H", "H", "MainView" +button 320, 250 to 360, 290, "Button:J", "J", "MainView" +button 370, 250 to 410, 290, "Button:K", "K", "MainView" +button 420, 250 to 460, 290, "Button:L", "L", "MainView" +button 465, 250 to 500, 340, "Enter_", "Enter", "MainView" + +button 30, 300 to 70, 340, "Button:Y", "Y", "MainView" +button 80, 300 to 120, 340, "Button:X", "X", "MainView" +button 130, 300 to 170, 340, "Button:C", "C", "MainView" +button 180, 300 to 220, 340, "Button:V", "V", "MainView" +button 230, 300 to 270, 340, "Button:B", "B", "MainView" +button 280, 300 to 320, 340, "Button:N", "N", "MainView" +button 330, 300 to 370, 340, "Button:M", "M", "MainView" +button 380, 300 to 415, 340, "Button:,", ",", "MainView" +button 425, 300 to 460, 340, "Button:.", ".", "MainView" + +button 10, 350 to 60, 390, "About_", "About", "MainView" +button 70, 350 to 430, 390, "Spacebar_", "", "MainView" +button 440, 350 to 500, 390, "Clear_", "Clear all", "MainView" + +a = 10 : b = 25 +dim choice$(1) +inloop = true +while (inloop) + msg$ = message$ + if (split(msg$, choice$(), ":|") >= 2) btn$ = choice$(2) + if (msg$ <> "") print msg$ + + switch msg$ + + case "MainView:_QuitRequested|" + inloop = false + break + + case "Button:"+btn$+"|" + draw text a, b, btn$, "TextView" + if (btn$ = "J" ) then + a = a+10 + elsif (btn$ = "I" or btn$ = "," or btn$ = ".") then + a = a+6 + elsif (btn$ = "W") then + a = a+20 + elsif (btn$ = "F" or btn$ = "T") then + a = a+12 + elsif (btn$ = "M") then + a = a+18 + elsif (btn$ = "N" or btn$ = "G" or btn$ = "Q" or btn$ = "O") then + a=a+15 + else + a = a+14 + fi + break + + case "Enter_|" + a = 10 : b = b+25 + break + + case "Spacebar_|" + a = a+12 + break + + case "Clear_|" + draw flush "TextView" + a = 10 : b = 25 + break + + case "About_|" + ShowAbout() + break + + end switch + sleep 0.01 +wend +exit + +sub ShowAbout() + for i = 0 to 215 + msg$ = message$ + draw flush "TextView" + draw text 200, 190-i, "This is:", "TextView" + draw text 160, 215-i, "YAB - Keyboard", "TextView" + if (msg$ = "About_|") break + sleep 0.01 + next i + a = 10 : b = 25 + draw flush "TextView" + return +end sub diff --git a/yab-IDE/Programs/Examples/Loop-World.yab b/yab-IDE/Programs/Examples/Loop-World.yab new file mode 100755 index 0000000..87c00f3 --- /dev/null +++ b/yab-IDE/Programs/Examples/Loop-World.yab @@ -0,0 +1,401 @@ +#!yab + +// Main background colors: +r = 206 : g = 226 : b = 236 + +// Open main window: +window open 100, 250 to 600, 650, "MainView", "Loop-World" + window set "MainView", "flags","not-zoomable" + window set "MainView", "minimumto",500,400 + window set "MainView", "maximumto",500,400 + draw set "bgcolor", r, g, b, "MainView" + draw set "lowcolor", r-75, g-75, b-75, "MainView" + draw line 10, 365 to 490, 365, "MainView" + draw set "lowcolor", r+40, g+40, b+40, "MainView" + draw line 10, 366 to 490, 366, "MainView" + draw set "lowcolor", r, g, b, "MainView" + draw set "Swis721 BT, Bold, 14", "MainView" + draw text 10, 20, "Loop-World", "MainView" + draw text 200, 20, "Sourcecode:", "MainView" + + + +// make views inside the main window: +view 0, 30 to 190, 360, "ExplainView", "MainView" + draw set "bgcolor", r, g, b, "ExplainView" + draw set "Swis721 BT, Roman, 10", "ExplainView" + +view 200, 30 to 490, 360, "SourceView", "MainView" + draw set "bgcolor", r+39, g+39, b+39, "SourceView" + draw set "Swis721 BT, Roman, 10", "SourceView" + +//draw text 10, 265, "Choose a kind of loop:", "MainView" +button 10, 370 to 60, 390, "For_Loop_", "for/next", "MainView" +button 65, 370 to 115, 390, "While_Loop_", "while", "MainView" +button 120, 370 to 170, 390, "Do_Loop_", "do/loop", "MainView" +button 175, 370 to 225, 390, "Sub_Loop_", "sub m(n)", "MainView" +button 230, 370 to 280, 390, "Other_Loop_", "Other", "MainView" +//button 285, 370 to 335, 390, "None_", "None", "MainView" +button 345, 370 to 395, 390, "None_", "Back", "MainView" +button 405, 370 to 490, 390, "Exec_", "Execute", "MainView" + +dim SourceLine$(20) +ShowSource("none") + +// mainloop of the program: +dim cmd$(1) +inloop = true +while (inloop) + msg$ = message$ + if (split(msg$, cmd$(), ":|") > 2) item$ = cmd$(2) + + if (msg$ <> "") print msg$ + + switch msg$ + + case "For_Loop_|" + if (CurrentSource$ = "For_Loop") break + ShowSource("For_Loop") + break + + case "While_Loop_|" + if (CurrentSource$ = "While_Loop") break + ShowSource("While_Loop") + break + + case "Do_Loop_|" + if (CurrentSource$ = "Do_Loop") break + ShowSource("Do_Loop") + break + + case "Sub_Loop_|" + if (CurrentSource$ = "Sub_Loop") break + ShowSource("Sub_Loop") + break + + case "Other_Loop_|" + if (CurrentSource$ = "Other_Loop") break + ShowSource("Other_Loop") + break + + case "None_|" + if (CurrentSource$ = "none") break + ShowSource("none") + break + + case "Exec_|" + if (DemoWin = true) break + if (CurrentSource$ = "none") break + ExecSource(CurrentSource$) + break + + case "Quit_|" + case "MainView:_QuitRequested|" + inloop = false + break + + end switch + sleep 0.01 +wend +exit + +sub ShowSource(CurrSource$) + CurrentSource$ = CurrSource$ + draw flush "SourceView" + draw flush "ExplainView" + + draw text 5, 10, "#!yab", "SourceView" + draw text 5, 35, "window open 100, 100 to 200, 200, ''MainView'', ''Loop''", "SourceView" + draw text 5, 50, "window set ''MainView'', ''minimumto'',100,100", "SourceView" + draw text 5, 65, "window set ''MainView'', ''maximumto'',100,100", "SourceView" + + if (CurrSource$ = "none") then + draw text 5, 10, "Welcome to LoopWorld!", "ExplainView" + draw text 5, 35, "This program will show you the different", "ExplainView" + draw text 5, 50, "kinds of loops in yab.", "ExplainView" + draw text 5, 75, "On the left you see the sourcecode", "ExplainView" + draw text 5, 90, "that is used in the examples.", "ExplainView" + draw text 5, 105, "Please see GUI-World(2), if you want to", "ExplainView" + draw text 5, 120, "know more about that code, as I won't", "ExplainView" + draw text 5, 135, "explain that here in Loop-World.", "ExplainView" + draw text 5, 160, "Each loop will run about 10 seconds", "ExplainView" + draw text 5, 175, "and show its loop number and its", "ExplainView" + draw text 5, 190, "name in the window.", "ExplainView" + draw text 5, 205, "Therefore I will simply execute the", "ExplainView" + draw text 5, 220, "whole sourcecode shown right.", "ExplainView" + draw text 5, 245, "Select the loop you want to know more", "ExplainView" + draw text 5, 260, "about with the buttons down right.", "ExplainView" + draw text 5, 285, "Note: While each loop is running", "ExplainView" + draw text 5, 300, "this main window will be blocked !", "ExplainView" + + z = 1 + SourceLine$(1) = "// the loop will appear here." + fi + + if (CurrSource$ = "For_Loop") then + draw text 5, 10, "The 'for next' loop.", "ExplainView" + + draw text 5, 35, "The 'for next' loop works in a defined", "ExplainView" + draw text 5, 50, "range that must be set.", "ExplainView" + + draw text 5, 75, "This loop is counting the range from", "ExplainView" + draw text 5, 90, "the first to the last number.", "ExplainView" + draw text 5, 105, "For each count it puts the number into", "ExplainView" + draw text 5, 120, "the given variable and executes the lines", "ExplainView" + draw text 5, 135, "down to 'next'.", "ExplainView" + + draw text 5, 160, "", "ExplainView" + draw text 5, 175, "", "ExplainView" + draw text 5, 190, "", "ExplainView" + draw text 5, 205, "", "ExplainView" + draw text 5, 220, "", "ExplainView" + draw text 5, 245, "", "ExplainView" + draw text 5, 260, "", "ExplainView" + + draw text 5, 285, "", "ExplainView" + draw text 5, 300, "", "ExplainView" + + z = 7 + SourceLine$(0) = "" + SourceLine$(1) = "for n = 1 to 10" + SourceLine$(2) = " draw flush ''MainView''" + SourceLine$(3) = " draw text 50, 50, str$(n), ''MainView''" + SourceLine$(4) = " draw text 10, 90, ''For_Loop'', ''MainView''" + SourceLine$(5) = " sleep 1" + SourceLine$(6) = "next n" + SourceLine$(7) = "exit" + fi + + if (CurrSource$ = "While_Loop") then + draw text 5, 10, "The 'while wend' loop.", "ExplainView" + + draw text 5, 35, "", "ExplainView" + draw text 5, 50, "", "ExplainView" + + draw text 5, 75, "", "ExplainView" + draw text 5, 90, "", "ExplainView" + draw text 5, 105, "", "ExplainView" + draw text 5, 120, "", "ExplainView" + draw text 5, 135, "", "ExplainView" + + draw text 5, 160, "", "ExplainView" + draw text 5, 175, "", "ExplainView" + draw text 5, 190, "", "ExplainView" + draw text 5, 205, "", "ExplainView" + draw text 5, 220, "", "ExplainView" + draw text 5, 245, "", "ExplainView" + draw text 5, 260, "", "ExplainView" + + draw text 5, 285, "", "ExplainView" + draw text 5, 300, "", "ExplainView" + + z = 9 + SourceLine$(0) = "" + SourceLine$(1) = "n = 1" + SourceLine$(2) = "while (n < 11)" + SourceLine$(3) = " draw flush ''MainView''" + SourceLine$(4) = " draw text 50, 50, str$(n), ''MainView''" + SourceLine$(5) = " draw text 10, 90, ''While_Loop'', ''MainView''" + SourceLine$(6) = " n = n+1" + SourceLine$(7) = " sleep 1" + SourceLine$(8) = "wend" + SourceLine$(9) = "exit" + fi + + if (CurrSource$ = "Do_Loop") then + draw text 5, 10, "The 'do loop' loop", "ExplainView" + + draw text 5, 35, "", "ExplainView" + draw text 5, 50, "", "ExplainView" + + draw text 5, 75, "", "ExplainView" + draw text 5, 90, "", "ExplainView" + draw text 5, 105, "", "ExplainView" + draw text 5, 120, "", "ExplainView" + draw text 5, 135, "", "ExplainView" + + draw text 5, 160, "", "ExplainView" + draw text 5, 175, "", "ExplainView" + draw text 5, 190, "", "ExplainView" + draw text 5, 205, "", "ExplainView" + draw text 5, 220, "", "ExplainView" + draw text 5, 245, "", "ExplainView" + draw text 5, 260, "", "ExplainView" + + draw text 5, 285, "", "ExplainView" + draw text 5, 300, "", "ExplainView" + + z = 8 + SourceLine$(0) = "" + SourceLine$(1) = "do" + SourceLine$(2) = " n = n+1" + SourceLine$(3) = " draw flush ''MainView''" + SourceLine$(4) = " draw text 50, 50, str$(n), ''MainView''" + SourceLine$(5) = " draw text 10, 90, ''Do_Loop'', ''MainView''" + SourceLine$(6) = " sleep 1" + SourceLine$(7) = "loop" + SourceLine$(8) = "exit" + fi + + if (CurrSource$ = "Sub_Loop") then + draw text 5, 10, "The 'sub' loop.", "ExplainView" + + draw text 5, 35, "", "ExplainView" + draw text 5, 50, "", "ExplainView" + + draw text 5, 75, "", "ExplainView" + draw text 5, 90, "", "ExplainView" + draw text 5, 105, "", "ExplainView" + draw text 5, 120, "", "ExplainView" + draw text 5, 135, "", "ExplainView" + + draw text 5, 160, "", "ExplainView" + draw text 5, 175, "", "ExplainView" + draw text 5, 190, "", "ExplainView" + draw text 5, 205, "", "ExplainView" + draw text 5, 220, "", "ExplainView" + draw text 5, 245, "", "ExplainView" + draw text 5, 260, "", "ExplainView" + + draw text 5, 285, "", "ExplainView" + draw text 5, 300, "", "ExplainView" + + z = 13 + SourceLine$(0) = "" + SourceLine$(1) = "Counter(n)" + SourceLine$(2) = "" + SourceLine$(3) = "sub Counter(n)" + SourceLine$(4) = " if (n < 11) then" + SourceLine$(5) = " draw flush ''MainView''" + SourceLine$(6) = " draw text 50, 50, str$(n), ''MainView''" + SourceLine$(7) = " draw text 10, 90, ''Sub_Loop'', ''MainView''" + SourceLine$(8) = " sleep 1" + SourceLine$(9) = " Counter(n+1)" + SourceLine$(10) = " fi" + SourceLine$(11) = " return" + SourceLine$(12) = "end sub" + SourceLine$(13) = "exit" + fi + + if (CurrSource$ = "Other_Loop") then + draw text 5, 10, "Other loops!", "ExplainView" + + draw text 5, 35, "There are no other loops known", "ExplainView" + draw text 5, 50, "or known to be described.", "ExplainView" + + draw text 5, 75, "If there is one it could be entered", "ExplainView" + draw text 5, 90, "very easily.", "ExplainView" + draw text 5, 105, "Just see the source, yabman! ;-)", "ExplainView" + + z = 2 + SourceLine$(0) = "" + SourceLine$(1) = "// there is no other loop, my friend." + SourceLine$(2) = "exit" + fi + + for s = 0 to z + draw text 5, 80+s*15, SourceLine$(s), "SourceView" + next s + + return +end sub + +sub ExecSource(ExecLoop$) + DemoWin = true + window open 100, 100 to 200, 200, "DemoView", "Loop" + window set "DemoView", "minimumto", 100, 100 + window set "DemoView", "maximumto", 100, 100 + + if (ExecLoop$ = "For_Loop") then + for n = 1 to 10 + draw flush "DemoView" + draw text 50, 50, str$(n), "DemoView" + draw text 10, 90, ExecLoop$, "DemoView" + sleep 1 + next n + window close "DemoView" + fi + + if (ExecLoop$ = "While_Loop") then + n = 1 + while (n < 11) + draw flush "DemoView" + draw text 50, 50, str$(n), "DemoView" + draw text 10, 90, ExecLoop$, "DemoView" + sleep 1 + n = n+1 + wend + window close "DemoView" + fi + + if (ExecLoop$ = "Do_Loop") then + n = 0 + do + msg$ = message$ + if (msg$ = "QuitDemo_|") break + n = n+1 + draw flush "DemoView" + draw text 50, 50, str$(n), "DemoView" + draw text 10, 90, ExecLoop$, "DemoView" + + if (n = 11) then + draw text 5, 100, "You see that this loop won't be ended", "ExplainView" + draw text 5, 115, "by itself.", "ExplainView" + fi + + if (n = 13) draw text 5, 130, "For this, we need a Quit-button!", "ExplainView" + + if (n = 15) then + draw flush "SourceView" + draw text 5, 10, "#!yab", "SourceView" + draw text 5, 35, "window open 100, 100 to 200, 200, ''MainView'', ''Loop''", "SourceView" + draw text 5, 50, "window set ''MainView'', ''minimumto'',100,100", "SourceView" + draw text 5, 65, "window set ''MainView'', ''maximumto'',100,100''", "SourceView" + SourceLine$(0) = "button 30, 70 to 90, 90, ''Quit_'', ''Quit'', ''MainView''" + SourceLine$(1) = "" + SourceLine$(2) = "do" + SourceLine$(3) = " msg$ = message$" + SourceLine$(4) = " if (msg$ = ''Quit_'') break" + SourceLine$(5) = " n = n+1" + SourceLine$(6) = " draw flush ''MainView''" + SourceLine$(7) = " draw text 50, 50, str$(n), ''MainView''" + SourceLine$(8) = " draw text 10, 90, ''Do_Loop'', ''MainView''" + SourceLine$(9) = " sleep 1" + SourceLine$(10) = "loop" + SourceLine$(11) = "exit" + for s = 0 to 11 + draw text 5, 80+s*15, SourceLine$(s), "SourceView" + next s + button 10, 10 to 90, 30, "QuitDemo_", "Quit", "DemoView" + draw text 5, 145, "Press the Quit button to exit that loop.", "ExplainView" + fi + sleep 1 + loop + window close "DemoView" + fi + + if (ExecLoop$ = "Sub_Loop") then + Counter(1) + window close "DemoView" + fi + + if (ExecLoop$ = "Other_Loop") then + sleep 0.1 + window close "DemoView" + fi + + msg$ = "" + DemoWin = false + return +end sub + +sub Counter(n) + if (n < 11) then + draw flush "DemoView" + draw text 50, 50, str$(n), "DemoView" + draw text 10, 90, "Sub_Loop", "DemoView" + sleep 1 + Counter(n+1) + fi + return +end sub diff --git a/yab-IDE/Programs/Examples/MessageWorld.yab b/yab-IDE/Programs/Examples/MessageWorld.yab new file mode 100755 index 0000000..d6c0d1f --- /dev/null +++ b/yab-IDE/Programs/Examples/MessageWorld.yab @@ -0,0 +1,283 @@ +#!yab + +// MessageWorld - shows the messages the widgets return +// by DasJott + +// Main background colors +r = 206 : g = 226 : b = 246 + +// open main window +window open 100, 200 to 600, 450, "MainView", "MessageWorld - Select a widget to be explained" + window set "MainView", "maximumto", 500, 250 + window set "MainView", "minimumto", 500, 250 + draw set "bgcolor", r, g, b, "MainView" + +// open view inside the main window +view 0, 0 to 500, 180, "ContentView", "MainView" // for the contents; widgets and text. + draw set "bgcolor", r+20, g+20, b+20, "ContentView" + draw text 210, 60, "MessageWorld", "ContentView" + draw text 150, 75, "Shows the messages the widgets return.", "ContentView" + draw text 149, 100, "Please select the widget to be explained.", "ContentView" + draw text 125, 125, "Please use each widget to get the message shown.", "ContentView" + draw text 135, 140, "The sourcecode is also shown for each widget.", "ContentView" + +view 0, 181 to 500, 199, "MessageView", "MainView" // for the message display + draw set "bgcolor", r+20, g+20, b+20, "MessageView" + draw set "lowcolor", r+10, g+10, b+10, "MessageView" + draw set "highcolor", 255, 0, 0, "MessageView" + draw set "Swis721 BT, Roman, 12", "MessageView" + +view 0, 200 to 500, 250, "SwitchView", "MainView" // for the buttons + draw set "bgcolor", r, g, b, "SwitchView" + + //color the buttons + for cc = 0 to 25 + draw set "highcolor", r+30-(2*cc), g+30-(2*cc), b+30-(2*cc), "SwitchView" + draw line 0, cc to 500, cc, "SwitchView" + next cc + for cc = 0 to 25 + draw set "highcolor", r+30-(2*cc), g+30-(2*cc), b+30-(2*cc), "SwitchView" + draw line 0, 25+cc to 500, 25+cc, "SwitchView" + next cc + + // draw lines between the buttons + draw set "highcolor", r-70, g-70, b-70, "SwitchView" + draw line 0, 0 to 500, 0, "SwitchView" + draw line 0, 25 to 500, 25, "SwitchView" + draw line 99, 0 to 99, 50, "SwitchView" + draw line 199, 0 to 199, 50, "SwitchView" + draw line 299, 0 to 299, 50, "SwitchView" + draw line 399, 0 to 399, 50, "SwitchView" + draw set "highcolor", r+35, g+35, b+35, "SwitchView" + draw line 0, 1 to 500, 1, "SwitchView" + draw line 0, 26 to 500, 26, "SwitchView" + draw line 100, 1 to 100, 50, "SwitchView" + draw line 200, 1 to 200, 50, "SwitchView" + draw line 300, 1 to 300, 50, "SwitchView" + draw line 400, 1 to 400, 50, "SwitchView" + draw set "highcolor", 0, 0, 0, "SwitchView" + draw text 10, 15, "Button", "SwitchView" + draw text 110, 15, "Menu", "SwitchView" + draw text 210, 15, "Listbox", "SwitchView" + draw text 310, 15, "Textcontrol", "SwitchView" + draw text 410, 15, "Checkbox", "SwitchView" + draw text 10, 40, "Radiobutton", "SwitchView" + draw text 110, 40, "Dropbox", "SwitchView" + draw text 210, 40, "Dropzone", "SwitchView" + draw text 310, 40, "Slider", "SwitchView" + draw text 410, 40, "Colorcontrol", "SwitchView" + +// main program loop +Xmouse = 1000 +dim cmd$(1) +dim mouse$(10) + +// NEU! +if(ismousein("SwitchView")) then + outsideButton = false +else + outsideButton = true +fi + +inloop = true +while (inloop) + msg$ = message$ + if (split(msg$, cmd$(), ":|") > 2) item$ = cmd$(2) + mmsg$ = mouse message$("SwitchView") + n = split(mmsg$, mouse$(), ":") + + if (msg$ <> "") then + draw flush "MessageView" + draw Text 10, 10, "Message: "+msg$, "MessageView" + fi + + if (ismousein("SwitchView")) then + // NEU! + if(outsideButton) then + while(ismousein("SwitchView") and mouse$(3) = "1") + mmsg$ = mousemessage$("SwitchView") + n = split(mmsg$, mouse$(), ":") + sleep 0.1 + wend + fi + if(ismousein("SwitchView")) then + outsideButton = false + Xmouse = val(mouse$(1)) + Ymouse = val(mouse$(2)) + BLmouse = val(mouse$(3)) + else + outsideButton = true + fi + else + outsideButton = true + fi + + if (BLmouse = 0) Fbl = 0 + + if (Ymouse < 25 and BLmouse = 1 and Ymouse > 0 and Fbl = 0) then + if (Xmouse < 100) then + VButton(0) + fi + + if (Xmouse > 100 and Xmouse < 200) then + VButton(1) + fi + + if (Xmouse > 200 and Xmouse < 300) then + VButton(2) + fi + + if (Xmouse > 300 and Xmouse < 400) then + VButton(3) + fi + + if (Xmouse > 400 and Xmouse < 500) then + VButton(4) + fi + Fbl = 1 + fi + + if (Ymouse > 25 and BLmouse = 1 and Fbl = 0) then + if (Xmouse < 100) then + VButton(5) + fi + + if (Xmouse > 100 and Xmouse < 200) then + VButton(6) + fi + + if (Xmouse > 200 and Xmouse < 300) then + VButton(7) + fi + + if (Xmouse > 300 and Xmouse < 400) then + VButton(8) + fi + + if (Xmouse > 400 and Xmouse < 500) then + VButton(9) + fi + Fbl = 1 + fi + + switch msg$ + + case "MainView:_QuitRequested|" + inloop = false + break + + end switch + sleep 0.01 +wend +exit + +sub VButton(n) + draw flush "MessageView" + if(ck) then + view remove "CBView" + ck = false + endif + view remove "ContentView" + view 0, 0 to 500, 200, "ContentView", "MainView" + draw set "bgcolor", r+20, g+20, b+20, "ContentView" + draw set "lowcolor", r, g, b, "ContentView" + draw set "Swis721 BT, Bold, 16", "ContentView" + + if (n = 0) then // Button + draw text 10, 25, "BUTTON x1,y1 TO x2,y2, ID$, Label$, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + button 100, 50 to 400, 70, "Button_", "Testbutton", "ContentView" + draw text 60, 130, "button 100, 50 to 400, 70, \"Button_\", \"Testbutton\", \"MainView\"", "ContentView" + fi + + if (n = 1) then // Menu + draw text 10, 25, "MENU Head$, Menu$, Shortcut$, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + view 40, 50 to 460, 100, "MenuView", "ContentView" + draw text 60, 130, "view 40, 50 to 460, 100, \"MenuView\", \"MainView\"", "ContentView" + menu "File", "Open file", "", "MenuView" + menu "File", "Quit", "", "MenuView" + draw text 60, 145, "menu \"File\", \"Open file\", \"\", \"MenuView\"", "ContentView" + draw text 60, 160, "menu \"File\", \"Quit\", \"\", \"MenuView\"", "ContentView" + fi + + if (n = 2) then // Listbox + draw text 10, 25, "LISTBOX x1,y1 TO x2,y2, ID$, ScrollbarType, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + listbox 40, 50 to 460, 100, "ListBox_", 1, "ContentView" + draw text 60, 130, "listbox 40, 50 to 460, 100, \"ListBox_\", 1, \"MainView\"", "ContentView" + listbox add "ListBox_", "First entry" + listbox add "ListBox_", "Second entry" + draw text 60, 145, "listbox add \"ListBox_\", \"First entry\"", "ContentView" + draw text 60, 160, "listbox add \"ListBox_\", \"Second entry\"", "ContentView" + fi + + if (n = 3) then // Textcontrol + draw text 10, 25, "TEXTCONTROL x1,y1 TO x2,y2, ID$, Label$, Text$, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + textcontrol 100, 50 to 400, 70, "Textcontrol-ID", "Label", "Text", "ContentView" + draw text 60, 130, "textcontrol 100, 50 to 400, 70, \"Textcontrol-ID\", \"Label\", \"Text\", \"MainView\"", "ContentView" + fi + + if (n = 4) then // Checkbox + draw text 10, 25, "CHECKBOX x1,y1, ID$, Label$, IsActivated, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + view 100, 50 to 400, 100, "CBView", "ContentView" + draw text 60, 130, "view 100, 50 to 400, 100, \"CBView\", \"MainView\"", "ContentView" + checkbox 10, 8, "Checkbox1-ID", "Label1", 0, "CBView" + checkbox 10, 28, "Checkbox2-ID", "Label2", 1, "CBView" + draw text 60, 145, "checkbox 10, 8, \"Checkbox1-ID\", \"Label1\", 0, \"CBView\"", "ContentView" + draw text 60, 160, "checkbox 10, 28, \"Checkbox2-ID\", \"Label2\", 1, \"CBView\"", "ContentView" + ck = true + fi + + if (n = 5) then // Radiobutton + draw text 10, 25, "RADIOBUTTON x1,y1, ID$, Label$, IsActivated, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + view 100, 50 to 400, 100, "RBView", "ContentView" + draw text 60, 130, "view 100, 50 to 400, 100, \"RBView\", \"MainView\"", "ContentView" + radiobutton 10, 8, "Radiobutton1-ID", "Label1", 0, "RBView" + radiobutton 10, 28, "Radiobutton2-ID", "Label2", 1, "RBView" + draw text 60, 145, "radiobutton 10, 8, \"Radiobutton1-ID\", \"Label1\", 0, \"RBView\"", "ContentView" + draw text 60, 160, "radiobutton 10, 28, \"Radiobutton2-ID\", \"Label2\", 1, \"RBView\"", "ContentView" + fi + + if (n = 6) then // Dropbox + draw text 10, 25, "DROPBOX x1,y1 TO x2,y2, ID$, Label$, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + dropbox 40, 50 to 460, 100, "DropBox_", "Label", "ContentView" + draw text 60, 130, "dropbox 40, 50 to 460, 100, \"DropBox_\", \"Label\", \"MainView\"", "ContentView" + dropbox add "DropBox_", "First entry" + dropbox add "DropBox_", "Second entry" + draw text 60, 145, "dropbox add \"DropBox_\", \"First entry\"", "ContentView" + draw text 60, 160, "dropbox add \"DropBox_\", \"Second entry\"", "ContentView" + fi + + if (n = 7) then // Dropzone + draw text 10, 25, "VIEW DROPZONE View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + view 100, 50 to 400, 100, "DropView", "ContentView" + draw text 60, 130, "view 100, 50 to 400, 100, \"DropView\", \"MainView\"", "ContentView" + view dropzone "DropView" + draw text 60, 145, "view dropzone \"DropView\"", "ContentView" + fi + + if (n = 8) then // Slider + draw text 10, 25, "SLIDER x1,y1 TO x2,y2, ID$, Label$, Min, Max, Option$, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + slider 100, 50 to 400, 70, "Slider-ID", "Label", 0, 255, "horizontal", "ContentView" + draw text 60, 130, "slider 100, 50 to 400, 70, \"slider-ID\", \"Label\", 0, 255, \"horizontal\", \"MainView\"", "ContentView" + fi + + if (n = 9) then // Colorcontrol + draw text 10, 25, "COLORCONTROL x,y, ID$, View$", "ContentView" + draw set "Swis721 BT, Roman, 12", "ContentView" + colorcontrol 100, 50, "ColCon-ID", "ContentView" + draw text 60, 130, "colorcontrol 100, 50, \"ColCon-ID\", \"MainView\"", "ContentView" + fi + + draw text 10, 130, "Source:", "ContentView" + + BLmouse = 0 + return +end sub diff --git a/yab-IDE/Programs/Examples/MouseWorld.yab b/yab-IDE/Programs/Examples/MouseWorld.yab new file mode 100755 index 0000000..f592bd1 --- /dev/null +++ b/yab-IDE/Programs/Examples/MouseWorld.yab @@ -0,0 +1,83 @@ +#!yab + +// MouseWorld - shows mousemessages +// by DasJott + +window open 100, 100 to 500, 400, "MainView", "Mouse-World" + window set "MainView", "flags","not-zoomable, not-h-resizable, not-v-resizable" + draw set "Zurich, Bold, 20", "MainView" + +view 0, 20 to 100, 110, "MouseView", "MainView" + draw set "bgcolor", 255, 255, 255, "MouseView" + draw set "lowcolor", 255, 255, 255, "MouseView" + draw set "highcolor", 0, 0, 0, "MouseView" + +draw text 60, 150, "Press the Quit button to Quit!", "MainView" +draw text 330, 290, "Haha!", "MainView" + +dim cmd$(1) +dim mouse$(1) +inloop = true +while (inloop) + msg$ = message$ + mmsg$ = mouse message$("MainView") + + if (not mmsg$ = Fmmsg$) then + Fmmsg$ = mmsg$ + n = split(mmsg$, mouse$(), ":") + Xmouse = val(mouse$(1)) + Ymouse = val(mouse$(2)) + BLmouse = val(mouse$(3)) + BCmouse = val(mouse$(4)) + BRmouse = val(mouse$(5)) + ShowMouseMessage() + fi + + if (Xmouse > 324 and Ymouse > 264) then + HideQbutton() + else + if (Qbutton = false) ShowQbutton() + fi + + switch msg$ + + case "MainView:_QuitRequested|" + inloop = false + break + + end switch + sleep 0.01 +wend +window close "MainView" + +sub ShowMouseMessage() + draw flush "MouseView" + draw text 10, 10, "Mouse X:", "MouseView" + draw text 10, 25, "Mouse Y:", "MouseView" + draw text 10, 40, "Mouse buttons:", "MouseView" + draw text 20, 55, "Button 1:", "MouseView" + draw text 20, 70, "Button 2:", "MouseView" + draw text 20, 85, "Button 3:", "MouseView" + + draw text 60, 10, str$(Xmouse), "MouseView" + draw text 60, 25, str$(Ymouse), "MouseView" + draw text 70, 55, str$(BLmouse), "MouseView" + draw text 70, 70, str$(BRmouse), "MouseView" + draw text 70, 85, str$(BCmouse), "MouseView" + return +end sub + +sub HideQbutton() + if(Qbutton) then + view remove "ButtonView" + endif + Qbutton = false + return +end sub + +sub ShowQbutton() + view 325, 265 to 395, 295, "ButtonView", "MainView" + button 5, 5 to 65, 25, "Quit_", "Quit", "ButtonView" + Qbutton = true + return +end sub diff --git a/yab-IDE/Programs/Examples/Ping.yab b/yab-IDE/Programs/Examples/Ping.yab new file mode 100755 index 0000000..effe745 --- /dev/null +++ b/yab-IDE/Programs/Examples/Ping.yab @@ -0,0 +1,33 @@ +#!yab + +doc Start Ping.yab first by double clicking it, +doc then start Pong.yab. +doc This demonstrates how yab sends messages to another yab application. +doc Note: don't start Ping.yab in the IDE as the IDE only allows one +doc running yab program at a time. + +window open 100,100 to 300,300, "Ping", "Ping" + +x = 20 +y = 50 +stepx = 5 +stepy = 5 + +while(not instr(message$, "Quit")) + x = x + stepx + y = y + stepy + if(x <= 0 or x >= 400) stepx = -stepx + if(y <= 0 or y >= 200) stepy = -stepy + if(x >= 190) then + ret = message send "application/x-vnd.Pong.yab", str$(x) + ":" + str$(y) + if(ret <> 0) then + stepx = -stepx + if(x > 190) x = 190 + endif + endif + + draw flush "Ping" + draw circle x,y, 8, "Ping" +wend + +window close "Ping" diff --git a/yab-IDE/Programs/Examples/Pong.yab b/yab-IDE/Programs/Examples/Pong.yab new file mode 100755 index 0000000..6540677 --- /dev/null +++ b/yab-IDE/Programs/Examples/Pong.yab @@ -0,0 +1,22 @@ +#!yab +# mimetype "application/x-vnd.Pong.yab" + +doc See Ping.yab for more information. + +window open 400,100 to 600,300, "Pong", "Pong" + +dim msg$(1) +while(not finished) + n = token(message$, msg$(), ":|") + for i = 1 to n + if(instr(msg$(i), "Quit")) finished = true + if(instr(msg$(i), "_Scripting") and n>=i+2) then + x = val(msg$(i+1)) - 200 + y = val(msg$(i+2)) + draw flush "Pong" + draw circle x,y, 8, "Pong" + endif + next i +wend + +window close "Pong" diff --git a/yab-IDE/Programs/Examples/SlideDemo.yab b/yab-IDE/Programs/Examples/SlideDemo.yab new file mode 100755 index 0000000..56b64e2 --- /dev/null +++ b/yab-IDE/Programs/Examples/SlideDemo.yab @@ -0,0 +1,36 @@ +#!yab + +DOCU SlideDemo, Object scale per Slidebar +DOCU by Stargater + +WINDOW OPEN 100,100 to 500,600, "MainView" ,"SlideDemo" +WINDOW SET "MainView", "MaximumTo", 400,500 + +VIEW 0,0 to 500,400, "CircleView", "MainView" +DRAW SET "bgcolor",000,000,000,"CircleView" +DRAW SET "lowcolor",140,140,240,"CircleView" + +SLIDER 20,430 to 380,430, "Slider", "Scale the Circle", 0, 190, "MainView" +SLIDER LABEL "Slider", "0", "190" +SLIDER COLOR "Slider", "barcolor", 140,140,240 +SLIDER SET "Slider", 20 + +DRAW SET 0, "LowSolidFill" +DRAW CIRCLE 200,200, 20, "CircleView" + +oldr=20 + +while(not instr(message$, "_QuitRequested")) + r = SLIDER GET "Slider" + + if(oldr<>r) then + oldr = r + draw flush "CircleView" + DRAW CIRCLE 200,200, r, "CircleView" + endif + +wend + +window close "MainView" + + diff --git a/yab-IDE/Programs/Examples/SliderWorld.yab b/yab-IDE/Programs/Examples/SliderWorld.yab new file mode 100755 index 0000000..c1330d3 --- /dev/null +++ b/yab-IDE/Programs/Examples/SliderWorld.yab @@ -0,0 +1,32 @@ +#!yab + +window open 100,100 to 560,320, "WView", "SliderWorld" + +slider 20,20 to 350,50, "Slider1", "1. Slider with block thumb from 0.1 to 1", 1, 10, "WView" + +slider 20,70 to 350,100, "Slider2", "2. Slider with triangle thumb from 1 to 100 and limit labels; set to 20", 1, 100, "triangle", "WView" +slider label "Slider2", "Foo", "Bar" +slider set "Slider2", 20 + +slider 20,120 to 350,150, "Slider3", "3. Slider from 50 to 75, with 5 bottom hash markings, disabled", 50, 75, "WView" +slider label "Slider3", "Foo", "Bar" +slider set "Slider3", "bottom", 5 +option set "Slider3", "enabled", false + +slider 20,170 to 350,200, "Slider4", "4. Slider from -20 to 20, with colors", -20, 20, "WView" +slider color "Slider4", "barcolor", 240,140,140 +slider color "Slider4", "fillcolor", 140,140,240 + +slider 360,20 to 440,200, "Slider5", "5. Slider vertical", 1, 100, "vertical", "WView" +slider set "Slider5", "left", 15 +slider color "Slider5", "barcolor", 240,140,140 +slider set "Slider5", 70 + +inloop = true +while(inloop) + msg$ = message$ + if(msg$<>"") print msg$ + if(instr(msg$,"Quit")) inloop = false +wend + +window close "WView" diff --git a/yab-IDE/Programs/Examples/Sokoban.yab b/yab-IDE/Programs/Examples/Sokoban.yab new file mode 100755 index 0000000..cf74212 --- /dev/null +++ b/yab-IDE/Programs/Examples/Sokoban.yab @@ -0,0 +1,305 @@ +doc Simple game example +doc based on the popular Sokoban +doc graphics taken from Rocks'n'Diamonds + + +// Initialize the window, load the sprites and put up the canvas +window open 100,100 to 484,484, "Win", "Simple Sokoban Example" +window set "Win", "flags", "not-zoomable, not-h-resizable, not-v-resizable" + +bitmap 32,32, "wall" +err = draw image 0,0 to 31,31, "img/wall.png", "wall" +bitmap 32,32, "front1" +err = err + draw image 0,0 to 31,31, "img/front.png", "front1" +bitmap 32,32, "bulb" +err = err + draw image 0,0 to 31,31, "img/bulb.png", "bulb" +bitmap 32,32, "target" +err = err + draw image 0,0 to 31,31, "img/target.png", "target" +bitmap 32,32, "final" +err = err + draw image 0,0 to 31,31, "img/final.png", "final" +bitmap 32,32, "background" +draw set "highcolor", 0,0,0, "background" +draw rect 0,0 to 31,31, "background" + +if(err>0) then + alert "Could not load images", "Ok", "stop" + window close "Win" + exit(1) +endif + +option set "Win", "focus", true + +canvas 0,0 to 384,384, "Canvas", "Win" + +draw set "highcolor", 0,0,0, "Canvas" +draw rect 0,0 to 384,384, "Canvas" + +// Read in the demo level and show it +dim levelline$(12) +for i=1 to 12 + read levelline$(i) + for j = 1 to 12 + switch(mid$(levelline$(i), j, 1)) + case " " + draw bitmap x,y, "background", "copy", "Canvas" + break + case "w" + draw bitmap x,y, "wall", "copy", "Canvas" + break + case "b" + draw bitmap x,y, "bulb", "copy", "Canvas" + break + case "t" + draw bitmap x,y, "target", "copy", "Canvas" + break + case "s" + draw bitmap x,y, "front1", "alpha", "Canvas" + mapx = j + mapy = i + mid$(levelline$(i), j, 1) = " " + break + end switch + x = x + 32 + next j + x = 0 + y = y + 32 +next i + +playerx = (mapx-1)*32 +playery = (mapy-1)*32 + +// soundplay "rhythmloop.wav", true + +// handle the movements +while(not quitting) + key$ = keyboard message$("Win") + switch(key$) + case "down" + if(instr(" t", mid$(levelline$(mapy+1), mapx, 1))) then + // soundplay "base.wav", false + WalkDown() + elseif(instr("bf", mid$(levelline$(mapy+1), mapx, 1)) and instr(" t", mid$(levelline$(mapy+2), mapx,1))) then + PushDown() + endif + sleep 0.10 + break + case "up" + if(instr(" t", mid$(levelline$(mapy-1), mapx, 1))) then + // soundplay "base.wav", false + WalkUp() + elseif(instr("bf", mid$(levelline$(mapy-1), mapx, 1)) and instr(" t", mid$(levelline$(mapy-2), mapx,1))) then + PushUp() + endif + sleep 0.10 + break + case "left" + if(instr(" t", mid$(levelline$(mapy), mapx-1, 1))) then + // soundplay "base.wav", false + WalkLeft() + elseif(instr("bf", mid$(levelline$(mapy), mapx-1, 1)) and instr(" t", mid$(levelline$(mapy), mapx-2,1))) then + PushLeft() + endif + sleep 0.10 + break + case "right" + if(instr(" t", mid$(levelline$(mapy), mapx+1, 1))) then + // soundplay "base.wav", false + WalkRight() + elseif(instr("bf", mid$(levelline$(mapy), mapx+1, 1)) and instr(" t", mid$(levelline$(mapy), mapx+2,1))) then + PushRight() + endif + sleep 0.10 + break + case "esc" + quitting = true + break + end switch + m$ = message$ + if(m$ = "Win:_QuitRequested|" or m$ = "_QuitRequested") quitting = true +wend + +window close "Win" + +sub WalkDown() + mapy = mapy + 1 + playery = playery + 32 + draw bitmap playerx, playery, "front1","alpha", "Canvas" + if(mid$(levelline$(mapy-1), mapx,1) = " ") then + draw bitmap playerx, playery-32, "background","copy", "Canvas" + elseif(mid$(levelline$(mapy-1), mapx,1) = "t") then + draw bitmap playerx, playery-32, "target","copy", "Canvas" + elseif(mid$(levelline$(mapy-1), mapx,1) = "f") then + draw bitmap playerx, playery-32, "final","copy", "Canvas" + endif + return +end sub + +sub WalkUp() + mapy = mapy - 1 + playery = playery - 32 + draw bitmap playerx, playery, "front1","alpha", "Canvas" + if(mid$(levelline$(mapy+1), mapx,1) = " ") then + draw bitmap playerx, playery+32, "background","copy", "Canvas" + elseif(mid$(levelline$(mapy+1), mapx,1) = "t") then + draw bitmap playerx, playery+32, "target","copy", "Canvas" + elseif(mid$(levelline$(mapy+1), mapx,1) = "f") then + draw bitmap playerx, playery+32, "final","copy", "Canvas" + endif + return +end sub + +sub WalkLeft() + mapx = mapx - 1 + playerx = playerx - 32 + draw bitmap playerx, playery, "front1","alpha", "Canvas" + if(mid$(levelline$(mapy), mapx+1,1) = " ") then + draw bitmap playerx+32, playery, "background","copy", "Canvas" + elseif(mid$(levelline$(mapy), mapx+1,1) = "t") then + draw bitmap playerx+32, playery, "target","copy", "Canvas" + elseif(mid$(levelline$(mapy), mapx+1,1) = "f") then + draw bitmap playerx+32, playery, "final","copy", "Canvas" + endif + return +end sub + +sub WalkRight() + mapx = mapx + 1 + playerx = playerx + 32 + draw bitmap playerx, playery, "front1","alpha", "Canvas" + if(mid$(levelline$(mapy), mapx-1,1) = " ") then + draw bitmap playerx-32, playery, "background","copy", "Canvas" + elseif(mid$(levelline$(mapy), mapx-1,1) = "t") then + draw bitmap playerx-32, playery, "target","copy", "Canvas" + elseif(mid$(levelline$(mapy), mapx-1,1) = "f") then + draw bitmap playerx-32, playery, "final","copy", "Canvas" + endif + return +end sub + +sub PushDown() + local t$ + + t$ = mid$(levelline$(mapy+1), mapx, 1) + if(t$ = "b") then + mid$(levelline$(mapy+1), mapx, 1) = " " + draw bitmap playerx,playery+32, "background", "copy", "Canvas" + else + mid$(levelline$(mapy+1), mapx, 1) = "t" + draw bitmap playerx,playery+32, "target", "copy", "Canvas" + endif + t$ = mid$(levelline$(mapy+2), mapx, 1) + if(t$ = " ") then + mid$(levelline$(mapy+2), mapx, 1) = "b" + draw bitmap playerx,playery+64, "bulb", "copy", "Canvas" + // soundplay "roehr.wav", false + else + mid$(levelline$(mapy+2), mapx, 1) = "f" + draw bitmap playerx,playery+64, "final", "copy", "Canvas" + // soundplay "pong.wav", false + endif + WalkDown() + CheckFinished() + return +end sub + +sub PushUp() + local t$ + + t$ = mid$(levelline$(mapy-1), mapx, 1) + if(t$ = "b") then + mid$(levelline$(mapy-1), mapx, 1) = " " + draw bitmap playerx,playery-32, "background", "copy", "Canvas" + else + mid$(levelline$(mapy-1), mapx, 1) = "t" + draw bitmap playerx,playery-32, "target", "copy", "Canvas" + endif + t$ = mid$(levelline$(mapy-2), mapx, 1) + if(t$ = " ") then + mid$(levelline$(mapy-2), mapx, 1) = "b" + draw bitmap playerx,playery-64, "bulb", "copy", "Canvas" + // soundplay "roehr.wav", false + else + mid$(levelline$(mapy-2), mapx, 1) = "f" + draw bitmap playerx,playery-64, "final", "copy", "Canvas" + // soundplay "pong.wav", false + endif + WalkUp() + CheckFinished() + return +end sub + +sub PushLeft() + local t$ + + t$ = mid$(levelline$(mapy), mapx-1, 1) + if(t$ = "b") then + mid$(levelline$(mapy), mapx-1, 1) = " " + draw bitmap playerx-32,playery, "background", "copy", "Canvas" + else + mid$(levelline$(mapy), mapx-1, 1) = "t" + draw bitmap playerx-32,playery, "target", "copy", "Canvas" + endif + t$ = mid$(levelline$(mapy), mapx-2, 1) + if(t$ = " ") then + mid$(levelline$(mapy), mapx-2, 1) = "b" + draw bitmap playerx-64,playery, "bulb", "copy", "Canvas" + // soundplay "roehr.wav", false + else + mid$(levelline$(mapy), mapx-2, 1) = "f" + draw bitmap playerx-64,playery, "final", "copy", "Canvas" + // soundplay "pong.wav", false + endif + WalkLeft() + CheckFinished() + return +end sub + +sub PushRight() + local t$ + + t$ = mid$(levelline$(mapy), mapx+1, 1) + if(t$ = "b") then + mid$(levelline$(mapy), mapx+1, 1) = " " + draw bitmap playerx+32,playery, "background", "copy", "Canvas" + else + mid$(levelline$(mapy), mapx+1, 1) = "t" + draw bitmap playerx+32,playery, "target", "copy", "Canvas" + endif + t$ = mid$(levelline$(mapy), mapx+2, 1) + if(t$ = " ") then + mid$(levelline$(mapy), mapx+2, 1) = "b" + draw bitmap playerx+64,playery, "bulb", "copy", "Canvas" + // soundplay "roehr.wav", false + else + mid$(levelline$(mapy), mapx+2, 1) = "f" + draw bitmap playerx+64,playery, "final", "copy", "Canvas" + // soundplay "pong.wav", false + endif + WalkRight() + CheckFinished() + return +end sub + +sub CheckFinished() + local i + for i = 1 to 12 + if(instr(levelline$(i), "b")) return + next i + // soundplay "halloffame.wav", false + alert "Solved! This was too easy ;)", "Ok", "info" + quitting = true + return +end sub + +data " ww " +data "wwwwww www " +data "wtt w wwsww" +data "wtt www w" +data "wtt bb w" +data "wtt w w b w" +data "wttwww w b w" +data "wwww b wb w" +data " w bw b w" +data " w b b w" +data " w ww w" +data " wwwwwwwww" diff --git a/yab-IDE/Programs/Examples/Timer.yab b/yab-IDE/Programs/Examples/Timer.yab new file mode 100755 index 0000000..7b01867 --- /dev/null +++ b/yab-IDE/Programs/Examples/Timer.yab @@ -0,0 +1,17 @@ +#!yab + +doc Place a description of your +doc program here. +doc +doc Author, date, license + + + +print date$ + +print time$ +print mid$(date$,3,10)+" "+time$ + +dim fields$(6) +a=split(date$,fields$(),"-") +print fields$(2),"-",fields$(3),"-",fields$(4) diff --git a/yab-IDE/Programs/Examples/TreeDemo.yab b/yab-IDE/Programs/Examples/TreeDemo.yab new file mode 100755 index 0000000..6dd6d92 --- /dev/null +++ b/yab-IDE/Programs/Examples/TreeDemo.yab @@ -0,0 +1,30 @@ +#!yab + +window open 100,100 to 500,300, "A", "TreeDemo" +window set "A", "flags", "not-h-resizable, not-v-resizable" + +treebox 10,10 to 380,190, "Tree1", 1, "A" + +treebox add "Tree1", "Hello1" +treebox add "Tree1", "Hello1", "Test1", 1 +treebox add "Tree1", "Test1", "foo", 0 +treebox add "Tree1", "Test1", "bar", 0 +treebox add "Tree1", "Hello2" +treebox add "Tree1", "Hello3" +treebox add "Tree1", "Hello3", "Test3",0 +treebox add "Tree1", "Test3", "gugst",0 +treebox add "Tree1", "gugst", "du",0 +treebox add "Tree1", "Hello4" + +print treebox get$ "Tree1", 1 + +inloop = true + +while(inloop) + m$ = message$ + if(m$<>"") print m$ + if(instr(m$, "Quit")) inloop = false +wend + +window close "A" +exit diff --git a/yab-IDE/Programs/Examples/Typewriter.yab b/yab-IDE/Programs/Examples/Typewriter.yab new file mode 100755 index 0000000..98bcca7 --- /dev/null +++ b/yab-IDE/Programs/Examples/Typewriter.yab @@ -0,0 +1,81 @@ +#!yab + + +window open 100,100 to 600,400, "Main", "Typewriter" +window set "Main", "minimumto",100,100 + +layout "all", "Main" +view 10,10 to 490,280, "Type", "Main" +option set "Type", "Focus", true + +oldx = 100 +oldy = 100 +oldw = 500 +oldh = 300 + +offsetx = 5 +offsety = 15 + +draw set "highcolor", 255,255,255, "Type" +draw set "lowcolor", 0,100,0, "Type" +draw set "bgcolor", 0,100,0, "Type" + +draw text 10,295, str$(oldx)+" "+str$(oldy)+" "+str$(oldw)+" "+str$(oldh), "Main" + +while(not instr(message$, "_QuitRequested|")) + x = window get "Main", "position-x" + if(oldx<>x) then + oldx = x + Update() + endif + y = window get "Main", "position-y" + if(oldy<>y) then + oldy = y + Update() + endif + w = window get "Main", "width" + if(oldw<>w) then + oldw = w + Update() + endif + h = window get "Main", "height" + if(oldh<>h) then + oldh = h + Update() + endif + + // option set "Type", "focus", true + TypeKey("Type") +wend +exit + +sub TypeKey(view$) + local k$ + local old$ + + k$ = keyboard message$(view$) + if(k$ = "") then + // sleep 0.001 + else + if(k$ = "enter") then + offsety = offsety + 12 + offsetx = 5 + else + if(len(k$)=1) then + draw text offsetx,offsety, k$, "Type" + offsetx = offsetx + 10 + endif + endif + old$ = k$ + while(old$ = k$) + k$ = keyboard message$(view$) + wend + endif + return +end sub + +sub Update() + draw flush "Main" + draw text 10,h-5, str$(x)+" "+str$(y)+" "+str$(w)+" "+str$(h), "Main" + return +end sub diff --git a/yab-IDE/Programs/Examples/Walk.yab b/yab-IDE/Programs/Examples/Walk.yab new file mode 100755 index 0000000..1e337c1 --- /dev/null +++ b/yab-IDE/Programs/Examples/Walk.yab @@ -0,0 +1,30 @@ +#!yab + +window open 100,100 to 500,160, "Win", "Walk" +window set "Win", "flags", "not-zoomable, not-h-resizable, not-v-resizable" + +bitmap 1152,256, "player" +err = draw image 0,0 to 1152,256, "img/player.png", "player" +for i=15 to 405 step 65 + bitmap get i,196 to i+30,252, str$((i+50)/65), "player" +next i + +canvas 0,0 to 400,400, "MyCanvas", "Win" + +while(not quitting) + + for a = 0 to 400 step (30/7) + DRAW SET "highcolor",255,255,255,"MyCanvas" + draw rect 0,0 to a+29,55, "MyCanvas" + draw bitmap a,0, str$(mod(a/(30/7),6) +1),"copy", "MyCanvas" + sleep 00.2 + + m$ = message$ + if(m$ = "Win:_QuitRequested|" or m$ = "_QuitRequested|") then + quitting = true + break + endif + next a + +wend +window close "Win" diff --git a/yab-IDE/Programs/Examples/WindowWorld.yab b/yab-IDE/Programs/Examples/WindowWorld.yab new file mode 100755 index 0000000..db4c61f --- /dev/null +++ b/yab-IDE/Programs/Examples/WindowWorld.yab @@ -0,0 +1,52 @@ +#!yab + +window open 100,100 to 230,200, "win0", "Window0" + +layout "V-Center, H-Center", "win0" + +button 10,10 to 120,30, "NewWin_", "New Window", "win0" +button 10,40 to 120,60, "NumWin_", "Show Number...", "win0" +button 10,70 to 120,90, "Quit_", "Close All", "win0" + +alert "WindowWorld demonstrates how Windows are created and closed!", "Ok", "idea" + +dim msgpart$(1) +maxcount = 1 + +inloop = true +while(inloop = true) + msg$= message$ + if (split(msg$, msgpart$(),":") = 2) item$ = msgpart$(1) + if (msg$ <> "") print msg$ + + switch msg$ + case "NumWin_|" + alert "The number of open windows is "+str$(window count), "Ok", "info" + break + + case "NewWin_|" + number$ = str$(maxcount) + i = maxcount * 10 + window open 100+i,100+i to 230+i,200+i, "win"+number$, "Window"+number$ + layout "v-center, h-center", "win"+number$ + button 10,10 to 120,30, "NewWin_","New Window", "win"+number$ + button 10,40 to 120,60, "NumWin_","Show Number...", "win"+number$ + button 10,70 to 120,90, "Quit_","Close All", "win"+number$ + maxcount = maxcount + 1 + break + + case "Quit_|" + inloop = false + break + + case item$+":_QuitRequested|" + window close item$ + break + + end switch + + if (window count < 1) inloop = false + +wend + +exit diff --git a/yab-IDE/Programs/Examples/img/bulb.png b/yab-IDE/Programs/Examples/img/bulb.png new file mode 100644 index 0000000..1cb4c69 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/bulb.png differ diff --git a/yab-IDE/Programs/Examples/img/button_disabled.png b/yab-IDE/Programs/Examples/img/button_disabled.png new file mode 100644 index 0000000..b525850 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/button_disabled.png differ diff --git a/yab-IDE/Programs/Examples/img/button_norm.png b/yab-IDE/Programs/Examples/img/button_norm.png new file mode 100644 index 0000000..ab52e23 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/button_norm.png differ diff --git a/yab-IDE/Programs/Examples/img/button_pressed.png b/yab-IDE/Programs/Examples/img/button_pressed.png new file mode 100644 index 0000000..558719b Binary files /dev/null and b/yab-IDE/Programs/Examples/img/button_pressed.png differ diff --git a/yab-IDE/Programs/Examples/img/checkbutton_disabledOff.png b/yab-IDE/Programs/Examples/img/checkbutton_disabledOff.png new file mode 100644 index 0000000..1ab6475 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/checkbutton_disabledOff.png differ diff --git a/yab-IDE/Programs/Examples/img/checkbutton_disabledOn.png b/yab-IDE/Programs/Examples/img/checkbutton_disabledOn.png new file mode 100644 index 0000000..5c5d892 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/checkbutton_disabledOn.png differ diff --git a/yab-IDE/Programs/Examples/img/checkbutton_enabledOff.png b/yab-IDE/Programs/Examples/img/checkbutton_enabledOff.png new file mode 100644 index 0000000..03cd1f5 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/checkbutton_enabledOff.png differ diff --git a/yab-IDE/Programs/Examples/img/checkbutton_enabledOn.png b/yab-IDE/Programs/Examples/img/checkbutton_enabledOn.png new file mode 100644 index 0000000..327bc18 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/checkbutton_enabledOn.png differ diff --git a/yab-IDE/Programs/Examples/img/final.png b/yab-IDE/Programs/Examples/img/final.png new file mode 100644 index 0000000..88b47ea Binary files /dev/null and b/yab-IDE/Programs/Examples/img/final.png differ diff --git a/yab-IDE/Programs/Examples/img/front.png b/yab-IDE/Programs/Examples/img/front.png new file mode 100644 index 0000000..cedd73f Binary files /dev/null and b/yab-IDE/Programs/Examples/img/front.png differ diff --git a/yab-IDE/Programs/Examples/img/image.png b/yab-IDE/Programs/Examples/img/image.png new file mode 100644 index 0000000..2da5021 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/image.png differ diff --git a/yab-IDE/Programs/Examples/img/player.png b/yab-IDE/Programs/Examples/img/player.png new file mode 100644 index 0000000..8449c12 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/player.png differ diff --git a/yab-IDE/Programs/Examples/img/target.png b/yab-IDE/Programs/Examples/img/target.png new file mode 100644 index 0000000..cd8ffe8 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/target.png differ diff --git a/yab-IDE/Programs/Examples/img/wall.png b/yab-IDE/Programs/Examples/img/wall.png new file mode 100644 index 0000000..1cebe2d Binary files /dev/null and b/yab-IDE/Programs/Examples/img/wall.png differ diff --git a/yab-IDE/Programs/Examples/img/yab.png b/yab-IDE/Programs/Examples/img/yab.png new file mode 100644 index 0000000..ac5fa68 Binary files /dev/null and b/yab-IDE/Programs/Examples/img/yab.png differ diff --git a/yab-IDE/Programs/libs/Toolbar.yab b/yab-IDE/Programs/libs/Toolbar.yab new file mode 100644 index 0000000..cde9449 --- /dev/null +++ b/yab-IDE/Programs/libs/Toolbar.yab @@ -0,0 +1,50 @@ +doc Toolbar.yab is a library to easily create a toolbar. +doc This is suitable for 16x16 icons + +// Create a new toolbar. +// +// x1,y1 is the upper left starting point +// x2 is the right border of the toolbar +// note: the toolbar is always 30 pixels in height! +// id$ is the toolbar ID +// dir$ is the directory, where the icons can be found +// view$ is the view on which the Toolbar is created +// +// Note: this will change the layout of your view view$. +export sub ToolbarCreate(x1,y1,x2, id$, dir$, view$) + layout "left, right", view$ + view x1,y1 to x2,y1+30, id$, view$ + layout "left,right", id$ + draw set "bgcolor", 222,219,222, id$ + view 0,30 to x2,30, id$+"line", id$ + draw set "bgcolor", 185,185,185, id$+"line" + layout "none", id$ + position = 10 + directory$ = dir$ + toolbarview$ = id$ + return +end sub + +// Add an icon to the toolbar. +// +// id$ is the ID of the icon; this ID is send as a message, when the icon is clicked on +// pressed$ is the image of the pressed icon +// normal$ is the image of the normal icon +// disabled$ is the image of the disabled icon +export sub ToolbarAddIcon( id1$,id$, pressed$, normal$, disabled$) + button image position,7, id$, directory$+pressed$, directory$+normal$, directory$+disabled$, toolbarview$ + tooltip id$, id$ + position = position + 25 + return +end sub + +// Add a separator to the toolbar. +export sub ToolbarAddSeparator() + draw set "highcolor", 198,198,198, toolbarview$ + draw line position-2,5 to position-2,25,toolbarview$ + draw set "highcolor", 152,152,152, toolbarview$ + draw line position-1,5 to position-1,25, toolbarview$ + position = position + 5 + return +end sub + diff --git a/yab-IDE/Programs/libs/readme b/yab-IDE/Programs/libs/readme new file mode 100644 index 0000000..0624d00 --- /dev/null +++ b/yab-IDE/Programs/libs/readme @@ -0,0 +1,9 @@ +The files in this folder are yab libraries, to use them, copy to your project folder or to: + + ~/config/settings/yab + +then use the include statement in your project. + +Example: + +include Toolbar \ No newline at end of file diff --git a/yab-IDE/Templates/Basic Template b/yab-IDE/Templates/Basic Template new file mode 100644 index 0000000..39fdf8b --- /dev/null +++ b/yab-IDE/Templates/Basic Template @@ -0,0 +1,49 @@ +#!yab + +doc Place a description of your +doc program here. +doc +doc Author, date, license + +// set DEBUG = 1 to print out all messages on the console +DEBUG = 0 + +OpenWindow() + +// Main Message Loop +dim msg$(1) +while(not leavingLoop) + nCommands = token(message$, msg$(), "|") + + for everyCommand = 1 to nCommands + if(DEBUG and msg$(everyCommand)<>"") print msg$(everyCommand) + + switch(msg$(everyCommand)) + case "_QuitRequested": + case "MainWindow:_QuitRequested": + leavingLoop = true + break + default: + break + end switch + + next everyCommand + +wend + +CloseWindow() + +end + + +// Setup the main window here +sub OpenWindow() + window open 100,100 to 600,500, "MainWindow", "Main Window" + return +end sub + +// Close down the main window +sub CloseWindow() + window close "MainWindow" + return +end sub diff --git a/yab-IDE/Templates/Command Line Template b/yab-IDE/Templates/Command Line Template new file mode 100644 index 0000000..ab5fd37 --- /dev/null +++ b/yab-IDE/Templates/Command Line Template @@ -0,0 +1,7 @@ +#!yab + +doc Place a description of your +doc program here. +doc +doc Author, date, license + diff --git a/yab-IDE/Templates/Empty b/yab-IDE/Templates/Empty new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/yab-IDE/Templates/Empty @@ -0,0 +1 @@ + diff --git a/yab-IDE/Templates/Menu Template b/yab-IDE/Templates/Menu Template new file mode 100644 index 0000000..84a4e17 --- /dev/null +++ b/yab-IDE/Templates/Menu Template @@ -0,0 +1,69 @@ +#!yab + +doc Place a description of your +doc program here. +doc +doc Author, date, license + +// set DEBUG = 1 to print out all messages on the console +DEBUG = 0 + +OpenWindow() + +// Main Message Loop +dim msg$(1) +while(not leavingLoop) + nCommands = token(message$, msg$(), "|") + + for everyCommand = 1 to nCommands + if(DEBUG and msg$(everyCommand)<>"") print msg$(everyCommand) + + switch(msg$(everyCommand)) + case "_QuitRequested": + case "MainView:_QuitRequested": + case translate$("MainView:File:Quit"): + leavingLoop = true + break + case translate$("MainView:Help:Help"): + alert "The Help button was pressed", "Cool !", "idea" + break + default: + break + end switch + + next everyCommand + +wend + +CloseWindow() + +end + + +// Setup the main window here +sub OpenWindow() + window open 100,100 to 600,500, "MainView", "Menu Template" + + menu "File", "New", "N", "MainView" + menu "File", "Open...", "O", "MainView" + menu "File", "Save", "S", "MainView" + menu "File", "Save As...", "", "MainView" + menu "File", "--", "", "MainView" + menu "File", "Quit", "Q", "MainView" + menu "Edit", "Cut", "X", "MainView" + menu "Edit", "Copy", "C", "MainView" + menu "Edit", "Paste", "V", "MainView" + menu "View", "Options...", "", "MainView" + menu "Help", "Help", "H", "MainView" + menu "Help", "About", "A", "MainView" + + + + return +end sub + +// Close down the main window +sub CloseWindow() + window close "MainView" + return +end sub diff --git a/yab-IDE/Templates/TemplateList b/yab-IDE/Templates/TemplateList new file mode 100644 index 0000000..fdc458f --- /dev/null +++ b/yab-IDE/Templates/TemplateList @@ -0,0 +1,28 @@ +# +Empty +Templates/img/emptytemplate.png + +Create an empty file. +# +Basic Template +Templates/img/basictemplate.png + +Create a new program with a window. +# +Command Line Template +Templates/img/terminaltemplate.png + +Create a new command line program. +# +Menu Template +Templates/img/menutemplate.png + +Create a new program with a menu bar. +# +Toolbar Template +Templates/img/toolbartemplate.png + +Create a new program with a toolbar. +# +# + diff --git a/yab-IDE/Templates/Toolbar Template b/yab-IDE/Templates/Toolbar Template new file mode 100644 index 0000000..96c8795 --- /dev/null +++ b/yab-IDE/Templates/Toolbar Template @@ -0,0 +1,91 @@ +#!yab + + +// This file uses the toolbar.yab library located in ~/config/settings/yab + +import Toolbar + +doc Place a description of your +doc program here. +doc +doc Author, date, license + +// set DEBUG = 1 to print out all messages on the console +DEBUG = 1 + +OpenWindow() + +// Main Message Loop +dim msg$(1) +while(not leavingLoop) + nCommands = token(message$, msg$(), "|") + + for everyCommand = 1 to nCommands + if(DEBUG and msg$(everyCommand)<>"") print msg$(everyCommand) + + switch(msg$(everyCommand)) + case "MainView:_QuitRequested": + case "_QuitRequested": + case translate$("MainView:File:Quit"): + leavingLoop = true + break + case "Help": + case translate$("MainView:Help:Help"): + alert "The Help button was pressed", "Cool !", "idea" + break + default: + break + end switch + + next everyCommand + +wend + +CloseWindow() + +end + + +// Setup the main window here +sub OpenWindow() + window open 100,100 to 500,300, "MainView", "Toolbar Template" + window set "MainView","MinimumTo", 190,50 + menu "File", "New", "N", "MainView" + menu "File", "Open...", "O", "MainView" + menu "File", "Save", "S", "MainView" + menu "File", "Save As...", "", "MainView" + menu "File", "--", "", "MainView" + menu "File", "Quit", "Q", "MainView" + menu "Edit", "Cut", "X", "MainView" + menu "Edit", "Copy", "C", "MainView" + menu "Edit", "Paste", "V", "MainView" + menu "View", "Options...", "", "MainView" + menu "Help", "Help", "H", "MainView" + menu "Help", "About", "A", "MainView" + +// Toolbar Template uses /boot/home/yab_work/Programs/img for the image path. +MainDir$="/boot/home/yab_work/Programs/" +// Use your own path to your images. + + + + + ToolbarCreate(0,peek("menuheight"),400, "Toolbar", MainDir$+"img/", "MainView") + ToolbarAddIcon("ToolbarNew", "New", "newp.png", "newn.png", "newd.png") + ToolbarAddIcon("ToolbarOpen", "Open", "openp.png", "openn.png", "opend.png") + ToolbarAddIcon("ToolbarSave", "Save", "savep.png", "saven.png", "saved.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarCut", "Cut", "cutp.png", "cutn.png", "cutd.png") + ToolbarAddIcon("ToolbarCopy", "Copy", "copyp.png", "copyn.png", "copyd.png") + ToolbarAddIcon("ToolbarPaste", "Paste", "pastep.png", "pasten.png", "pasted.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarHelp", "Help", "helpp.png", "helpn.png", "helpd.png") + + return +end sub + +// Close down the main window +sub CloseWindow() + window close "MainView" + return +end sub diff --git a/yab-IDE/Templates/img/basictemplate.png b/yab-IDE/Templates/img/basictemplate.png new file mode 100644 index 0000000..5a96456 Binary files /dev/null and b/yab-IDE/Templates/img/basictemplate.png differ diff --git a/yab-IDE/Templates/img/emptytemplate.png b/yab-IDE/Templates/img/emptytemplate.png new file mode 100644 index 0000000..5da81cd Binary files /dev/null and b/yab-IDE/Templates/img/emptytemplate.png differ diff --git a/yab-IDE/Templates/img/menutemplate.png b/yab-IDE/Templates/img/menutemplate.png new file mode 100644 index 0000000..589252e Binary files /dev/null and b/yab-IDE/Templates/img/menutemplate.png differ diff --git a/yab-IDE/Templates/img/terminaltemplate.png b/yab-IDE/Templates/img/terminaltemplate.png new file mode 100644 index 0000000..c3abf23 Binary files /dev/null and b/yab-IDE/Templates/img/terminaltemplate.png differ diff --git a/yab-IDE/Templates/img/toolbartemplate.png b/yab-IDE/Templates/img/toolbartemplate.png new file mode 100644 index 0000000..5804391 Binary files /dev/null and b/yab-IDE/Templates/img/toolbartemplate.png differ diff --git a/yab-IDE/data/GenerateIndex.yab b/yab-IDE/data/GenerateIndex.yab new file mode 100755 index 0000000..ea6971b --- /dev/null +++ b/yab-IDE/data/GenerateIndex.yab @@ -0,0 +1,19 @@ +f1 = open("data/Help_En.dat", "r") +f2 = open("data/Help_En_Index.dat", "w") + +while(instr(a$, "& infotext") = 0) + line input #f1 a$ +wend + +while(not eof(f1)) + line input #f1 a$ + print #f2 a$ + print #f2 tell(#f1) + while(left$(a$,1)<>"&" or left$(a$,10)="&exverbatim") + line input #f1 a$ + print a$ + wend +wend + +close(f2) +close(f1) diff --git a/yab-IDE/data/Help_En.dat b/yab-IDE/data/Help_En.dat new file mode 100644 index 0000000..626d6ef --- /dev/null +++ b/yab-IDE/data/Help_En.dat @@ -0,0 +1,7888 @@ +& This is the data file for the help syntax of the yab-IDE 2.0 +& DO NOT CHANGE ANYTHING IN THIS FILE (unless you do a reindexing!) +& +& Comments start at the beginning of the line with a & +& +& Here the top level starts with the keyword: +& toplevel +Arithmetic +Conditions and Loops +Data Processing +Input and Output +Graphical User Interface +&Localization +Sound +String Handling +Subroutines +System +& Here the sub levels start (they are added as TREEBOX ADD adds). +& sublevel +Arithmetic:** or ^ +Arithmetic:xor() +Arithmetic:tan() +Arithmetic:sqrt() +Arithmetic:sqr() +Arithmetic:sin() +Arithmetic:sig() +Arithmetic:ran() +Arithmetic:pi +Arithmetic:or() +Arithmetic:mod() +Arithmetic:min() +Arithmetic:max() +Arithmetic:log() +Arithmetic:int() +Arithmetic:frac() +Arithmetic:exp() +Arithmetic:euler +Arithmetic:eor() +Arithmetic:dec() +Arithmetic:cos() +Arithmetic:bin$() +Arithmetic:atan() +Arithmetic:asin() +Arithmetic:and() +Arithmetic:acos() +Arithmetic:abs() +Conditions and Loops:while +Conditions and Loops:wend +Conditions and Loops:until +Conditions and Loops:true +Conditions and Loops:then +Conditions and Loops:switch +Conditions and Loops:step +Conditions and Loops:return +Conditions and Loops:repeat +Conditions and Loops:logical or +Conditions and Loops:on interrupt +Conditions and Loops:on goto +Conditions and Loops:on gosub +Conditions and Loops:not +Conditions and Loops:next +Conditions and Loops:loop +Conditions and Loops:label +Conditions and Loops:if +Conditions and Loops:goto +Conditions and Loops:gosub +Conditions and Loops:for +Conditions and Loops:fi +Conditions and Loops:false +Conditions and Loops:endif +Conditions and Loops:end +Conditions and Loops:elsif +Conditions and Loops:else +Conditions and Loops:do +Conditions and Loops:default +Conditions and Loops:continue +Conditions and Loops:case +Conditions and Loops:break +Conditions and Loops:and +Data Processing:restore +Data Processing:redim +Data Processing:read +Data Processing:dim +Data Processing:data +Data Processing:arraysize() +Data Processing:arraydim() +Input and Output:; +Input and Output:using +Input and Output:tell +Input and Output:seek() +Input and Output:screen +Input and Output:reverse +Input and Output:putscreen +Input and Output:print +Input and Output:open +Input and Output:line input +Input and Output:input +Input and Output:inkey$ +Input and Output:getscreen$() +Input and Output:eof +Input and Output:colour +Input and Output:color +Input and Output:close +Input and Output:clear screen +Input and Output:at() +Graphical User Interface:Window +Window :window set +Window :window open +Window :window get +Window :window count +Window :window close +Window :filepanel +Window :alert +Graphical User Interface:Widgets +Widgets:Treebox +Treebox:treebox sort +Treebox:treebox select +Treebox:treebox remove +Treebox:treebox get$ +Treebox:treebox expand +Treebox:treebox count +Treebox:treebox collapse +Treebox:treebox clear +Treebox:treebox add +Treebox:treebox +Widgets:Tooltip +Tooltip:tooltip color +Tooltip:tooltip +Widgets:TextURL +TextURL:texturl color +TextURL:texturl +Widgets:Textedit +Textedit:textedit set +Textedit:textedit get$ +Textedit:textedit get +Textedit:textedit color +Textedit:textedit clear +Textedit:textedit add +Textedit:textedit +Widgets:Textcontrol +Textcontrol:textcontrol set +Textcontrol:textcontrol get$ +Textcontrol:textcontrol clear +Textcontrol:textcontrol +Widgets:Text +Text:text set +Text:text +Widgets:Statusbar +Statusbar:statusbar set +Statusbar:statusbar +Widgets:Spincontrol +Spincontrol:spincontrol set +Spincontrol:spincontrol get +Spincontrol:spincontrol +Widgets:Slider +Slider:slider set +Slider:slider label +Slider:slider get +Slider:slider hashmarks +Slider:slider color +Slider:slider +Widgets:Radiobutton +Radiobutton:radiobutton set +Radiobutton:radiobutton +Widgets:Options +Options:option set +Options:option color +Widgets:Listbox +Listbox:listbox sort +Listbox:listbox select +Listbox:listbox remove +Listbox:listbox get$ +Listbox:listbox get +Listbox:listbox count +Listbox:listbox clear +Listbox:listbox add +Listbox:listbox +Widgets:Dropbox +Dropbox:dropbox select +Dropbox:dropbox remove +Dropbox:dropbox get$ +Dropbox:dropbox count +Dropbox:dropbox clear +Dropbox:dropbox add +Dropbox:dropbox +Widgets:Columnbox +Columnbox:columnbox select +Columnbox:columnbox remove +Columnbox:columnbox get$ +Columnbox:columnbox get +Columnbox:columnbox count +Columnbox:columnbox column +Columnbox:columnbox color +Columnbox:columnbox clear +Columnbox:columnbox add +Columnbox:columnbox +Widgets:Colorcontrol +Colorcontrol:colorcontrol set +Colorcontrol:colorcontrol get +Colorcontrol:colorcontrol +Widgets:Checkbox +Checkbox:checkbox set +Checkbox:checkbox image +Checkbox:checkbox +Widgets:Calendar +Calendar:calendar set +Calendar:calendar get$ +Calendar:calendar +Widgets:Button +Button:button image +Button:button +Graphical User Interface:Views +Views:View +View :view remove +View :view get +View :view dropzone +View :view +Views:Tabview +Tabview:tabview set +Tabview:tabview get +Tabview:tabview add +Tabview:tabview +Views:Stackview +Stackview:stackview set +Stackview:stackview get +Stackview:stackview +Views:Splitview +Splitview:splitview set +Splitview:splitview get +Splitview:splitview +Views:Scrollbar +Scrollbar:scrollbar set +Scrollbar:scrollbar get +Scrollbar:scrollbar +Views:layout +Views:boxview +Graphical User Interface:Printing +Printing:printer setup +Printing:printer +Graphical User Interface:Menus +Menus:submenu set +Menus:submenu +Menus:popupmenu +Menus:menu set +Menus:menu +Graphical User Interface:Input and Messages +Input and Messages:shortcut +Input and Messages:mouse set +Input and Messages:mousemove$ +Input and Messages:mouse message$() +Input and Messages:message send +Input and Messages:message$ +Input and Messages:keyboard message$() +Input and Messages:ismousein() +Graphical User Interface:Drawing +Drawing:draw text +Drawing:draw set +Drawing:draw rect +Drawing:draw line +Drawing:draw image +Drawing:draw get$ +Drawing:draw get +Drawing:draw flush +Drawing:draw ellipse +Drawing:draw dot +Drawing:draw curve +Drawing:draw circle +Drawing:draw bitmap +Graphical User Interface:Bitmaps +Bitmaps:screenshot +Bitmaps:canvas +Bitmaps:bitmap save +Bitmaps:bitmap remove +Bitmaps:bitmap get +Bitmaps:bitmap +&Localization:translate$() +&Localization:localize +Sound:sound wait +Sound:sound stop +Sound:sound play +Sound:bell +Sound:beep +String Handling:val() +String Handling:upper$() +String Handling:trim$() +String Handling:token() +String Handling:str$() +String Handling:split() +String Handling:rtrim$() +String Handling:right$() +String Handling:mid$() +String Handling:ltrim$() +String Handling:lower$() +String Handling:len() +String Handling:left$() +String Handling:instr() +String Handling:hex$() +String Handling:glob() +String Handling:chr$() +String Handling:asc() +Subroutines:sub +Subroutines:static +Subroutines:return +Subroutines:numparams +Subroutines:local +Subroutines:import +Subroutines:export +Subroutines:end sub +System:: +System:# +System:// +System:wait +System:to +System:time$ +System:thread remove +System:thread get +System:system() +System:system$() +System:sleep +System:rem +System:poke +System:peek$ +System:peek +System:pause +System:iscomputeron +System:exit +System:execute() +System:execute$() +System:error +System:docu$ +System:doc +System:date$ +System:compile +System:clipboard copy +System:clipboard paste$ +System:bind() +& +& Information texts (info texts for short) are separated by +& comment lines. The file must end with a comment line! +& +& The info texts start here: +& infotext +&Arithmetic +& +abs() + +Name: +abs() -- returns the absolute value of its numeric argument + +Synopsis: +y=abs(x) + +Description: +If the argument of the abs-function is positive (e.g. 2) it is returned unchanged, if the argument is negative (e.g. -1) it is returned as a positive value (e.g. 1). + +Example: +print abs(-2),abs(2) +Explanation: + + This example will print 2 2 + + +Related: sig + +& +acos() + +Name: +acos() -- returns the arcus cosine of its numeric argument + +Synopsis: +x=acos(angle) + +Description: +The acos is the arcus cosine-function, i.e. the inverse of the cos-function. Or, more elaborate: It Returns the angle (in radian, not degree!), which, fed to the cosine-function will produce the argument passed to the acos-function. + +Example: +print acos(0.5),acos(cos(pi)) +Explanation: + + This example will print 1.0472 3.14159 which are pi/3 and pi respectively. + + +Related: cos, asin + +& +and() + +Name: +and() -- the bitwise arithmetic and + +Synopsis: + x=and(a,b) + +Description: +Used to compute the bitwise and of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resultingvalue will then be 1, if both arguments have a 1 at this position in their binary representation. +Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may leadto unexpected results when passed to and. + +Example: +print and(6,3) +Explanation: + + This will print 2. This result is clear, if you note, that the binary representation of 6 and 3 are 110 and 011 respectively; this will yield 010 in binary representaion or 2 as decimal. + + +Related: or, eor, xor, not + +& +asin() + +Name: +asin() -- returns the arcus sine of its numeric argument + +Synopsis: +angle=asin(x) + +Description: +The acos is the arcus sine-function, i.e. the inverse of the sin-function. Or, more elaborate: It Returns the angle (in radian, not degree!), which,fed to the sine -function will produce the argument passed to the asin-function. + +Example: +print asin(0.5),asin(sin(pi)) +Explanation: + + This will print 0.523599 -2.06823e-13 which is pi/6 and almost 0 respectively. + + +Related: sin, acos + +& +atan() + +Name: +atan() -- returns the arcus tangens of its numeric argument + +Synopsis: +angle=atan(a,b) +angle=atan(a) + +Description: +The atan is the arcus-tangens-function, i.e. the inverse of the tan-function. Or, more elaborate: It Returns the angle (in radian, not degree!), which, fed to the tan-function will produce the argument passed to the atan-function. +The atan-function has a second form, which accepts two arguments: atan(a,b) which is (mostly) equivilantly to atan(a/b) except for the fact, that the two-argument-form returns an angle in the range -pi to pi, whereas the one-argument-form returns an angle in the range -pi/2 to pi/2. To understand this you have to be good at math. + +Example: +print atan(1),atan(tan(pi)),atan(-0,-1),atan(-0,1) +Explanation: + + This will print 0.785398 2.06823e-13 -3.14159 3.14159 which is pi/4, almost 0, -pi and pi respectively. + + +Related: tan, sin + +& +bin$() + +Name: +bin$() -- converts a number into a sequence of binary digits + +Synopsis: +hexadecimal$=bin$(decimal) + +Description: +The bin$-function takes a single numeric argument an converts it into a stringof binary digits (i.e. zeroes and ones). If you pass a negative number to bin$, the resulting string will be preceeded by a '-'. +If you want to convert the other way around (i.e. from binary to decimal) you may use the dec-function. + +Example: +for a=1 to 100 + print bin$(a) +next a +Explanation: + + This example prints the binary representation of all digits between 1 and 100. + + +Related: hex$, dec + +& +cos() + +Name: +cos() -- return the cosine of its single argument + +Synopsis: +x=cos(angle) + +Description: +The cos-function expects an angle (in radian) and returns its cosine. + +Example: +print cos(pi) +Explanation: + + This example will print -1. + + +Related: acos, sin + +& +dec() + +Name: +dec() -- convert a base 2 or base 16 number into decimal form + +Synopsis: +a=dec(number$) +a=dec(number$,base) + +Description: +The dec-function takes the string-representation of a base-2 or base-16 (which is the default) number and converts it into a decimal number. The optional second argument (base) might be used to specify a base other than 16. However, currently only base 2 or base 16 are supported. + +Example: +input "Please enter a binary number: " a$ +print a$," is ",dec(a$) +Related: bin$, hex$ + +& +eor() + +Name: +eor() -- compute the bitwise exclusive or of its two arguments + +Synopsis: +print eor(a,b) + +Description: +The eor-function takes two arguments and computes their bitwise exclusive or. See your favorite introductory text on informatics for an explanation of this function. +The xor-function is the same as the eor function; both are synonymous; however they have each their own description, so you may check out the entry of xor for a slightly different view. + +Example: +for a=0 to 3 + for b=0 to 3 + print fill$(bin$(a))," eor ",fill$(bin$(b))," = ",fill$(bin$(eor(a,b))) + next b +next a + +sub fill$(a$) + return right$("0"+a$,2) +end sub +Explanation: + + This example prints a table, from which you may figure, how the eor-function is computed. + +Related: and, or + +& +euler + +Name: +euler -- another name for the constant 2.71828182864 + +Synopsis: +foo=euler + +Description: +euler is the well known constant named after Leonard Euler; its value is 2.71828182864. euler is not a function, so parens are not allowed (i.e. euler() will produce an error). Finally, you may not assign to euler; it wouldn't sense anyway, because it is a constant. + +Example: +print euler +Related: pi + +& +exp() + +Name: +exp() -- compute the exponential function of its single argument + +Synopsis: + foo=exp(bar) + +Description: +This function computes e to the power of its argument, where e is the well known euler constant 2.71828182864. The exp-function is the inverse of the log-function. + +Example: +window open 100,100 to 300,300, "Example", "Example" +for x=-100 to 100 + draw dot x,100-100*exp(x/100)/euler, "Example" +next x +sleep 5 +window close "Example" +Explanation: + +This program plots part of the exp-function, however the range is rather small, so that you may not recognize the function from this plot. + +Related: log + +& +frac() + +Name: +frac() -- return the fractional part of its numeric argument + +Synopsis: +x=frac(y) + +Description: +The frac-function takes its argument, removes all the digits to the left of the comma and just returns the digits right of the comma, i.e. the fractional part. Refer to the example to learn how to rewrite frac by employing the int-function. + +Example: +for a=1 to 10 + print frac(sqr(a)) + print sqr(a)-int(sqr(a)) +next a +Explanation: + + The example prints the fractional part of the square root of the numbers between 1 and 10. + Each result is computed (and printed) twice: Once by employing the frac-function and once by employing the int-function. + + +Related: int + +& +int() + +Name: +int() -- return the integer part of its single numeric argument + +Synopsis: + print int(a) + +Description: +The int-function returns only the digits before the comma; int(2.5) returns 2 and int(-2.3) returns -2. + +Example: +input "Please enter a whole number between 1 and 10: " a +if (a=int(a) and a>=1 and a<=10) then + print "Thanx!" +else + print "Never mind ..." +endif +Related: frac + +& +log() + +Name: +log() -- compute the natural logarithm + +Synopsis: +a=log(x) +a=log(x,base) + +Description: +The log-function computes the logarithm of its first argument. The optional second argument gives the base for the logarithm; if this second argument is omitted, the euler-constant 2.71828... will be taken as the base. + +Example: +window open 200,200 to 400,400, "Example", "Example" +draw set 0, "highsolidfill" +for x=10 to 190 step 10 + for y=10 to 190 step 10 + r=3*log(1+x,1+y) + if (r>10) r=10 + if (r<1) r=1 + draw circle x,y,r, "Example" + next y +next x +sleep 5 +window close "Example" +Explanation: + + This draws another nice plot. + + +Related: exp + +& +max() + +Name: +max() -- return the larger of its two arguments + +Synopsis: +print max(a,b) + +Description: +Return the maximum of its two arguments. + +Example: +dim m(10) +for a=1 to 1000 + m=0 + for b=1 to 10 + m=max(m,ran(10)) + next b + m(m)=m(m)+1 +next a + +for a=1 to 9 + print a,": ",m(a) +next a +Explanation: + + Within the inner for-loop (the one with the loop-variable b), the example computes the maximum of 10 random numbers. The outer loop (with the loop variable a) now repeats this process 1000 times and counts, how often each maximum appears. The last loop finally reports the result. + Now, the interesting question would be, which will be approached, when we increase the number of iterations from thousend to infinity. Well, maybe someone could just tell me :-) + +Related: min + +& +min() + +Name: +min() -- return the smaller of its two arguments + +Synopsis: +print min(a,b) + +Description: +Return the minimum of its two argument. + +Example: +dim m(10) +for a=1 to 1000 + m=min(ran(10),ran(10)) + m(m)=m(m)+1 +next a + +for a=1 to 9 + print a,": ",m(a) +next a +Explanation: + + For each iteration of the loop, the lower of two random number is recorded. The result is printed at the end. + + +Related: max + +& +mod() + +Name: +mod() -- compute the remainder of a division + +Synopsis: +print mod(a,b) + +Description: +The mod-function divides its two arguments and computes the remainder. Note, that a/b-int(a/b) and mod(a,b) are always equal. + +Example: +clear screen +print at(10,10) "Please wait " +p$="-\|/" +for a=1 to 100 + rem ... do something lengthy here, or simply sleep :-) + pause(1) + print at(22,10) mid$(p$,1+mod(a,4)) +next a +Explanation: + + This example executes some time consuming action within a loop (in fact, it simply sleeps) and gives the user some indication of progress by displaying a turning bar (thats where the mod()-function comes into play). +Start this program in a terminal. + + +Related: int, frac + +& +or() + +Name: +or() -- arithmetic or, used for bit-operations + +Synopsis: +x=or(a,b) + +Description: +Used to compute the bitwise or of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if any of its arguments has 1 at this position in theirbinary representation. +Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to or. + +Example: +print or(14,3) +Explanation: + + This will print 15. This result is clear, if you note, that the binary representation of 14 and 3 are 1110 and 0011 respectively; this will yield 1111 in binary representaion or 15 as decimal. + +Related: and, eor, xor, not + +& +pi + +Name: +pi -- a constant with the value 3.14159 + +Synopsis: +print pi + +Description: +pi is 3.14159265359 (well at least for yab); do not try to assign to pi (e.g. pi=22/7)this would not only be mathematically dubious, but would also result in a syntax error. + +Example: +for a=0 to 180 + print "The sine of ",a," degrees is ",sin(a*pi/180) +next a +Explanation: + + This program uses pi to transform an angle from degrees into radians. + + +Related: euler + +& +ran() + +Name: +ran() -- return a random number + +Synopsis: +print ran() +x=ran(y) + +Description: +The ran-function returns a random number. If no argument is given, the number returned is in the range from 0 to 1; where only 0 is a possible value; 1 will never be returned. If an argument is supplied, the number returned will be in the range from 0 up to this argument, whereas this argument itself is not a possible return value. + +Example: +clear screen +c=peek("screenwidth")-1 +l=peek("screenheight") + +dim col$(8) +for a=0 to 7 + read col$(a) +next a + +do + x=ran(c) + y=l-ran(l*exp(-32*((x/c-1/2)**2))) + i=i+1 + print color(col$(mod(i,8))) at(x,y) "*" +loop + +data "black","white","red","blue","green","yellow","cyan","magenta" +Explanation: + + This example will print a cloured bell-curve. Start this program in a terminal. + + +Related: int + +& +sig() + +Name: +sig() -- return the sign of its argument + +Synopsis: +a=sig(b) + +Description: +Return +1, -1 or 0, if the single argument is positive, negative or zero. + +Example: +clear screen +dim c$(3):c$(1)="red":c$(2)="white":c$(3)="green" +do + num=ran(100)-50 + print color(c$(2+sig(num))) num +loop +Explanation: + + This program prints an infinite sequence of random number; positive numbers are printed in green, negative numbers are printed red (an exact zero would be printed white). (With a little extra work, this program could be easily extended into a brogerage system). + + Start this program in a terminal. + + +Related: abs, int, frac + +& +sin() + +Name: +sin() -- return the sine of its single argument + +Synopsis: +y=sin(angle) + +Description: +The sin-function expects an angle (in radian, not degree) and returns its sine. + +Example: +window open 200,200 to 400,400, "Example", "Example" +for phi=0 to 2*pi step 0.1 + draw line 100+90*sin(phi-0.1),100+90*cos(phi-0.1) to 100+90*sin(phi),100+90*cos(phi), "Example" +next phi +sleep 5 +window close "Example" +Explanation: + + This program draws a circle (ignoring the existence of the circle-command). + + +Related: asin, cos + +& +sqr() + +Name: +sqr() -- compute the square of its argument + +Synopsis: +a=sqr(b) + +Description: +The sqr-function computes the square of its numerical argument (i.e. it multiplies its argument with itself). + +Example: +for a=1 to 10 + print a,sqr(a),a**2 +next a +Explanation: + + As you may see from the output, sqr can be written as **2 (or ^2) too. + + +Related: sqrt, **, ^ + +& +sqrt() + +Name: +sqrt() -- compute the square root of its argument + +Synopsis: +to be written + +Description: +The sqrt-function computes the square root of its numerical argument. + +Example: +for a=1 to 5 + print a,sqrt(a),a**(1/2) +next a +Explanation: + + As you may see from the output, sqrt can be written as **(1/2) (or ^(1/2)) too. + + +Related: sqr, **, ^ + +& +tan() + +Name: +tan() -- return the tangens of its argument + +Synopsis: +foo=tan(bar) + +Description: +The tan-function computes the tangens of its arguments (which should be specified in radian). + +Example: +for a=0 to 45 + print tan(a*pi/180) +next a +Explanation: + + This example simply prints the tangens of all angles between 0 and 45 degree. + + +Related: atan, sin + +& +xor() + +Name: +xor() -- compute the exclusive or + +Synopsis: +x=xor(a,b) + +Description: +The xor computes the bitwise exclusive or of its two numeric arguments. To understand the result, both arguments should be viewed as binary numbers(i.e. a series of 0 and 1); a bit of the result will then be 1, if exactly one argument has a 1 and the other has a 0 at this position in their binary representation. +Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead tounexpected results when passed to and. + +Example: +print xor(7,4) +Explanation: + + This will print 3. This result is obvious, if you note, that the binary representation of 7 and 4 are 111 and 100 respectively; this will yield 011 in binary representaion or 2 as decimal. The eor-function is the same as the xor function; both are synonymous; however they have each their own description, so you may check out the entry of eor for a slightly different view. + + +Related: and, or, eor, not + +& +** or ^ + +Name: +** or ^ -- raise its first argument to the power of its second + +Synopsis: +print 2**b +print 3^4 + +Description: +** (or ^, which is an exact synonym), is the arithmetic operator of exponentiation; it requires one number to its left and a second one to its right; ** then raises thefirst argument to the power of the second and returns the result. The result will only be computed if it yields a real number (as opposed to a complex number); this means, that the power can not be computed, if the first argument is negative and the second one is fractional. On the other hand, the second argument can be fractional, if the first one ist positive; this means, that ** may be used to compute arbitrary roots: e.g. x**0.5 computes the square root of x. + +Example: +print 2**0.5 +Related: sqrt + +&Conditions and Loops +& +and + +Name: +and -- logical and, used in conditions + +Synopsis: +if (a and b) +while (a and b) + +Description: +Used in conditions (e.g within if, while or until) to join two expressions. Returns true, if and only if its left and right argument are both true and false otherwise. +Note, that logical shortcuts may take place. + +Example: +input "Please enter a number" a +if (a>=1 and a<=9) print "your input is between 1 and 9" +Related: or, not, xor, eor + +& +break + +Name: +break -- breaks out of a switch statement or a loop + +Synopsis: +break + +Description: +break transfers control immediately outside the enclosing loop or switch statement. This is the preferred way of leaving a such a statement (rather than goto, which is still possible in most cases). + +Example: +for a=1 to 10 + break + print "Hi" +next a + +while(1) + break + print "Hi" +wend + +repeat + break + print "Hi" +until(0) + +switch 1 + case 1:break + case 2:case 3:print "Hi" +end switch +Explanation: + + This example prints nothing at all, because each of the loops (and the switch-statement) does an immediate break (before it could print any "Hi"). + + +Related: for, while, repeat, switch + +& +case + +Name: +case -- mark the different cases within a switch-statement + +Synopsis: +switch a + case 1 + case 2 + ... +end switch + +... + +switch a$ + case "a" + case "b" + ... +end switch + +Description: +Please see the switch-statement. + +Example: +input a +switch(a) + case 1:print "one":break + case 2:print "two":break + default:print "more" +end switch +Explanation: + + Depending on your input (a number is expected) this code will print one or two or otherwise more. + + +Related: switch + +& +continue + +Name: +continue -- start the next iteration of a for-, do-, repeat- or while-loop + +Synopsis: +continue + +Description: +You may use continue within any loop to start the next iteration immediately. Depending on the type of the loop, the loop-condition will or will not be checked. Especially: for- and while-loops will evaluate their respective conditions, do- and repeat-loops will not. +Remark: Another way to change the flow of execution within a loop, is the break-command. + +Example: +for a=1 to 100 + if mod(a,2)=0 continue + print a +next a +Explanation: + + This example will print all odd numbers between 1 and 100. + + +Related: for, do, repeat, while, break + +& +default + +Name: +default -- mark the default-branch within a switch-statement + +Synopsis: +switch a+3 +case 1 + ... +case 2 + ... +default + ... +end switch + +Description: +The default-clause is an optional part of the switch-statement (see there for more information). It introduces a series of statements, that should be executed, if none of the casese matches, that have been specified before (each with its own case-clause). So default specifies a default to be executed, if none of the explicitly named cases matches; hence its name. + +Example: +print "Please enter a number between 0 and 6," +print "specifying a day in the week." +input d +switch d + case 0:print "Monday":break + case 1:print "Tuesday":break + case 2:print "Wednesday":break + case 3:print "Thursday":break + case 4:print "Friday":break + case 5:print "Saturday":break + case 6:print "Sunday":break + default:print "Hey you entered something invalid!" +end switch +Explanation: + + This program translates a number between 0 and 6 into the name of a weekday; the default -case is used to detect (and complain about) invalid input. + + +Related: sub, case + +& +do + +Name: +do -- start a (conditionless) do-loop + +Synopsis: +do +... +loop + +Description: +Starts a loop, which is terminated by loop; everything between do and loop willbe repeated forever. This loop has no condition, so it is an infinite loop; note however, that a break- or goto-statement might be used to leave this loop anytime. + +Example: +do + a=a+1 + print a + if (a>100) break +loop +Explanation: + + This example prints the numbers between 1 and 101. The break-statement is used to leave the loop. + + +Related: loop, repeat, while, break + +& +else + +Name: +else -- mark an alternative within an if-statement + +Synopsis: +if (...) then + ... +else + ... +endif + +Description: +The else-statement introduces the alternate branch of an if-statement. I.e. it starts the sequence of statements, which is executed, if the condition of the if-statement is not true. + +Example: +input "Please enter a number: " a +if (mod(a,2)=1) then + print a," is odd." +else + print a," is even." +endif +Explanation: + + This program detects, if the number you have entered is even or odd. + + +Related: if + +& +elsif + +Name: +elsif -- starts an alternate condition within an if-statement + +Synopsis: +if (...) then + ... +elseif (...) + ... +elsif (...) then + ... +else + ... +endif + +Description: +The elsif-statement is used to select a single alternative among a seriesof choices. With each elsif-statement you may specify a condition, which is tested, if the main condition (specified with the if-statement) has failed. Note that elsif might be just as well written as elseif. +Within the example below, two variables a and b are tested against a rangeof values. The variable a is tested with the elsif-statement. The very same tests are performed for the variable b too; but here an involved series of if-else-statements is employed, making the tests much more obscure. + +Example: + +input "Please enter a number: " a +if (a<0) then + print "less than 0" +elseif (a<=10) then + print "between 0 and 10" +elsif (a<=20) + print "between 11 and 20" +else + print "over 20" +endif + +input "Please enter another number: " b +if (b<0) then + print "less than 0" +else + if (b<=10) then + print "between 0 and 10" + else + if (b<=20) then + print "between 11 and 20" + else + print "over 20" + endif + endif +endif +Explanation: + + Note, that the very same tests are performed for the variables a and b, but can be stated much more clearly with the elsif-statement. + Note, that elsif might be written as elseif too, and that the keyword then is optional. + + +Related: if, else + +& +end + +Name: +end -- terminate your program + +Synopsis: +end + +Description: +Terminate your program. Much (but not exactly) like the exit command. +Note, that end may not end your program immediately; if you have opened a window or called clear screen, yab assumes, that your user wants to study the output of your program after it has ended; therfore it issuesthe line ---Program done, press RETURN--- and waits for a key to be pressed. If you do not like this behaviour, consider using exit. + +Example: + + print "Do you want to continue ?" + input "Please answer y(es) or n(o): " a$ + if (lower$(left$(a$,1))="n") then + print "bye" + end + fi + + +Related: exit + +& +endif + +Name: +endif -- ends an if-statement + +Synopsis: +if (...) then + ... +endif + +Description: +The endif-statement closes (or ends) an if-statement. +Note, that endif may be written in a variety of other ways: end if, end-if or even fi. The endif-statement must be omitted, if the if-statement does not contain the keyword then (see the example below). Such an if-statement without endif extends only over a single line. + +Example: +input "A number please: " a +if (a<10) then + print "Your number is less than 10." +endif + +rem and now without endif + +input "A number please: " a +if (a<10) print "Your number is less than 10." +Related: if + +& +false + +Name: +false -- a constant with the value of 0 + +Synopsis: +okay=false + +Description: +The constant false can be assigned to variables which later appear in conditions (e.g. within an if-statement. +false may also be written as FALSE or even FaLsE. + +Example: +input "Please enter a number between 1 and 10: " a +if (check_input(a)) print "Okay" + +sub check_input(x) + if (x>10 or x<1) return false + return true +end sub +Explanation: + + The subroutine check_input checks its argument and returns true or false according to the outcome of the check. + + +Related: true + +& +fi + +Name: +fi -- another name for endif + +Synopsis: +if (...) +... +fi + +Description: +fi marks the end of an if-statement and is exactly equivilent to endif, please see there for further information. + +Example: +input "A number please: " a +if (a<10) then + print "Your number is less than 10." +fi +Related: endif + +& +for + +Name: +for -- starts a for-loop + +Synopsis: +for a=1 to 100 step 2 + ... +next a + +Description: +The for-loop lets its numerical variable (a in the synopsis) assume all valueswithin the given range. The optional step-clause may specify a value (default: 1) by which the variable will be incremented (or decremented, if step is negative). + +Any for-statement can be replaced by a set of ifs and gotos; as you may infer from the example below this is normally not feasable. However if you want to know in detail how the for-statement works, you should study this example, which presents a for-statement and an exactly equivilant series of ifs and gotos. + +Example: +for a=1 to 10 step 2 + print a +next a + +a=1 +label check +if (a>10) goto done +print a +a=a+2 +goto check +label done +Explanation: + +This example simply prints the numbers 1, 3, 5, 7 and 9. It does this twice: +First with a simple for-statment and then with ifs and gotos. + + +Related: step, next + +& +gosub + +Name: +gosub -- continue execution at another point within your program +(and return later) + +Synopsis: +gosub foo + +... + +label foo +... +return + +Description: +gosub remembers the current position within your program and then passes the flow of execution to another point (which is normally marked with a label). Later, when a return- statement is encountered, the execution is resumed at the previous location. +gosub is the traditional command for calling code, which needs to be executed from various places within your program. However, with subroutines yab offers a much more flexible way to achieve this (and more). Therefore gosub must to be considered obsolete. + +Example: +print "Do you want to exit ? " +gosub ask +if (r$="y") exit + +label ask +input "Please answer yes or no, by typing 'y' or 'n': ",r$ +return +Related: return, goto, sub, label, on gosub + +& +goto + +Name: +goto -- continue execution at another point within your program (and never come back) + +Synopsis: +goto foo + +... + +label foo + +Description: +The goto-statement passes the flow of execution to another point within your program (which is normally marked with a label). +goto is normally considered obsolete and harmful, however in yab it may be put to the good use of leaving loops (e.g. while or for) prematurely. Note however, that subroutines may not be left with the goto-statement. + +Example: +clear screen +print "Please press any key to continue." +print "(program will continue by itself within 10 seconds)" +for a=1 to 10 + if (inkey$(1)<>"") goto done +next a +label done +print "Hello World!" +Explanation: + +Here the goto-statment is used to leave the for-loop prematurely. Start this program in a terminal. + + +Related: gosub, on goto + +& +if + +Name: +if -- evaluate a condition and execute statements or not, depending on the result + +Synopsis: +if (...) then + ... +endif + +if (...) ... + +if (...) then + ... +else + ... +endif + +if (...) then + ... +elsif (...) + ... +elsif (...) then + ... +else + ... +endif + +Description: +The if-statement is used to evaluate a conditions and take actions accordingly. (As an aside, please note that there is no real difference between conditions and expressions.)There are two major forms of the if-statement:The one-line-form without the keyword then: if (...) ... +This form evaluates the condition and if the result is true executes all commands (seperated by colons) upt to the end of the line. There is neither an endif keyword nor an else-branch. +The multi-line-form with the keyword then: if (...) then ... elsif (...) ... else ... endif(where elsif and else are optional, whereas endif is not. +According to the requirements of your program, you may specify:elsif(...), which specifies a condition, that will be evaluated only if the condition(s) whithin if or any preceeding elsif did not match. +else, which introduces a sequence of commands, that will be executed, if none of the conditions above did match. endif is required and ends the if-statement. + +Example: +input "Please enter a number between 1 and 4: " a +if (a<=1 or a>=4) error "Wrong, wrong!" +if (a=1) then + print "one" +elsif (a=2) + print "two" +elsif (a=3) + print "three" +else + print "four" +endif +Explanation: + +The input-number between 1 and 4 is simply echoed as text (one, two, ...). The example demonstrates both forms (short and long) of the if-statement (Note however, that the same thing can be done, probably somewhat more elegant, with the switch-statement). + +Related: else, elsif, endif + +& +label + +Name: +label -- mark a specific location within your program for goto, gosub or restore + +Synopsis: +label foo + +... + +goto foo + +Description: +The label-command can be used to give a name to a specific location within your program. Such a position might be referred from one of three commands: goto, gosub and restore. +You may use labels safely within libraries, because a label (e.g. foo) does not collide with a label with the same name within the main program or within another library; yab will not mix them up. +As an aside, please note, that line numbers are a special (however deprecated) case of labels; see the second example below. + +Example: +for a=1 to 100 + if (rand(10)>5) goto done +next a +label done + +10 for a=1 to 100 +20 if (rand(10)>5) goto 40 +30 next a +40 +Explanation: + +Within this example, the for-loop will probably be left prematurely with a goto-statement. This task is done twice: First with labels and then again with line numbers. + +Related: gosub, goto + +& +loop + +Name: +loop -- marks the end of an infinite loop + +Synopsis: +do + ... +loop + +Description: +The loop-command marks the ends of a loop (which is started by do), wherein all statements within the loop are repeated forever. In this respect the do loop-loop is infinite, however, you may leave it anytime via break or goto. + +Example: +print "Hello, I will throw dice, until I get a 2 ..." +do + r=int(rand(6))+1 + print r + if (r=2) break +loop +Related: do, for, repeat, while, break + +& +next + +Name: +next -- mark the end of a for loop + +Synopsis: +for a=1 to 10 +next a + +Description: +The next-keyword marks the end of a for-loop. All statements up to the next-keyword will be repeated as specified with the for-clause. Note, that the name of the variable is optional; so instead of next a you may write next. + +Example: +for a=1 to 300000 + for b=1 to 21+20*sin(pi*a/20) + print "*" + next b + print + sleep 0.1 +next a +Explanation: + +This example simply plots a sine-curve until you fall asleep. Start this program in a terminal. + + +Related: for + +& +not + +Name: +not -- negate an expression; can be written as! + +Synopsis: +if (not a9 or a<1) print "a is not between 1 and 9" +Related: and, not, xor, eor + +& +pause + +Name: +pause -- pause, sleep, wait for the specified number of seconds + +Synopsis: +pause 5 + +Description: +The pause-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yab will not wait at all. The pause-command cannot be interrupted. However, sometimes you may want the wait to be interuptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument). + +Example: +deg=0 +do + maxx=44+40*sin(deg) + for x=1 to maxx + print "*" + next x + pause 0.1+(maxx*maxx/(4*84*84)) + print + deg=deg+0.1 +loop +Explanation: + +This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity. + +Related: sleep, wait + +& +repeat + +Name: +repeat -- start a repeat-loop + +Synopsis: +repeat + ... +until (...) + +Description: +The repeat-loop executes all the statements up to the final until-keyword over and over. The loop is executed as long as the condition, which is specified with the until-clause, becomes true. By construction, the statements within the loop are executed at least once. + +Example: +x=0 +clear screen +print "This program will print the numbers from 1 to 10" +repeat + x=x+1 + print x + print "Press any key for the next number, or 'q' to quit" + if (inkey$="q") break +until(x=10) +Explanation: + +This program is pretty much useless, but self-explanatory. + + +Related: until, break, while, do + +& +return + +Name: +return -- return from a subroutine or a gosub + +Synopsis: +gosub foo +... +label foo +... +return + +sub bar(baz) + ... + return quertz +end sub + +Description: +The return-statement serves two different (albeit somewhat related) purposes. The probably more important use of return is to return control from within a subroutine to the place in your program, where the subroutine has been called. If the subroutine is declared to return a value, the return-statement might be accompanied by a string or number, which constitutes the return value of the subroutine. +However, even if the subroutine should return a value, the return-statement need not carry a value; in that case the subroutine will return 0 or the empty string (depending on the type of the subroutine). Moreover, feel free to place multiple return-statements within your subroutine; it's a nice way of controlling the flow of execution. +The second (but historcially first) use of return is to return to the position, where a prior gosub has left off. In that case return may not carry a value. + +Example: +do + read a$ + if (a$="") then + print + end + endif + print mark$(a$)," " +loop + +data "The","quick","brown","fox","jumped" +data "over","the","lazy","dog","" + +sub mark$(a$) + if (instr(lower$(a$),"q")) return upper$(a$) + return a$ +end sub +Explanation: + +This example features a subroutine mark$, that returns its argument in upper case, if it contains the letter "q", or unchanged otherwise. In the test-text the word quick will end up beeing marked as QUICK. +The example above demonstrates return within subroutines; please see gosub for an example of how to use return in this context. + + +Related: sub, gosub + +& +sleep + +Name: +sleep -- pause, sleep, wait for the specified number of seconds + +Synopsis: +sleep 4 + +Description: +The sleep-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. +Therefore you should refer to the entry for the pause-function for further information. + +Related: pause, wait +& +step + +Name: +step -- specifies the increment step in a for-loop + +Synopsis: +for a=1 to 10 step 3 + ... +next a + +Description: +Specify, by which amount the loop-variable of a for-loop will be incremented at each step. +The step (as well as the lower and upper bound) are computed anew in each step; this is not common, but possible, as the example below demonstrates. + +Example: +for x=1 to 1000 step y + y=x+y + print x," ",y," " +next x +print +Explanation: + +This program computes the fibonacci numbers between 1 and 1000. + + +Related: for + +& +switch + +Name: +switch -- select one of many alternatives depending on a value + +Synopsis: +switch a + case 1 + case 2 + ... +end switch + +... + +switch a$ + case "a" + case "b" +end switch + +Description: +The switch-statment selects one of many codepaths depending on a numerical or string expression. I.e. it takes an expression (either numeric or string) and compares it with a series of values, each wrapped within a case-clause. If the expression equals the value given in a case-clause, the subsequent statements are executed. +The default-clause allows to specify commands, which should be executed, if none of case-clauses matches. +Note, that many case-clauses might be clustered (e.g. case "a":case "b":case "c"). Or put another way: You need a break-statement at the end of a case-branch, if you do not want to run into the next case. + +Example: +input "Please enter a single digit: " n +switch n + case 0:print "zero":break + case 1:print "one":break + case 2:print "two":break + case 3:print "three":break + case 4:print "four":break + case 5:case 6: case 7:case 8:case 9 + print "Much!":break + default:print "Hey! That was more than a single digit!" +end switch +Explanation: + +This example translates a single digit into a string; note, how the cases 5 to 7 are clustered. + + +Related: switch, case, break + +& +then + +Name: +then -- tell the long from the short form of the if-statement + +Synopsis: +if (a2 or arraydim(m2())<>2 or arraydim(r())<>2) then + error "Need two dimensional arrays as input" + endif + + y=arraysize(m1(),1):x=arraysize(m1(),2) + if (arraysize(m2(),1)<>y or arraysize(m2(),2)<>x) then + error "The two matrices cannot be added elementwise" + endif + + if (arraysize(r(),1)<>y or arraysize(r(),2)<>x) then + error "The result cannot be stored in the third argument" + endif + + local xx:local yy + for xx=1 to x + for yy=1 to y + r(yy,xx)=m1(yy,xx)+m2(yy,xx) + next yy + next xx +end sub +Related: arraydim, dim + +& +data + +Name: +data -- introduces a list of data-items + +Synopsis: +data 9,"world" +... +read b,a$ + +Description: +The data-keyword introduces a list of comma-seperated list of strings or numbers, which may be retrieved with the read-command. +The data-command itself does nothing; it just stores data. A single data-command may precede an arbitrarily long list of values, in which strings or numbers may be mixed at will. + +yab internally uses a data-pointer to keep track of the current location within the data-list; this pointer may be reset with the restore-command. + +Example: +do + restore + for a=1 to 4 + read num$,num + print num$,"=",num + next a +loop +data "eleven",11,"twelve",12,"thirteen",13,"fourteen",14 +Explanation: + +This example just prints a series of lines eleven=11 up to fourteen=14 and so on without end. +The restore-command ensures that the list of data-items is read from the start with every iteration. + + +Related: read, restore + +& +dim + +Name: +dim -- create an array prior to its first use + +Synopsis: +dim array(x,y) +dim array$(x,y) + +Description: +The dim-command prepares one or more arrays (of either strings or numbers) for later use. This command can also be used to enlarges an existing array. + +When an array is created with the dim-statement, memory is allocated and all elements are initialized with either 0 (for numerical arrays) or "" (for string arrays). +If the array already existed, and the dim-statement specifies a larger size than the current size, the array is enlarged and any old content is preserved. + +Note, that dim cannot be used to shrink an array: If you specify a size, that is smaller than the current size, the dim-command does nothing. + +Finally: To create an array, that is only known within a single subroutine, you should use the command local, which creates local variables as well as local arrays. + +Example: +dim a(5,5) +for x=1 to 5 + for y=1 to 5 + a(x,y)=int(ran(100)) + y +next x +printmatrix(a()) +dim a(7,7) +printmatrix(a()) + +sub printmatrix(ar()) + local x,y,p,q + x=arraysize(ar(),1) + y=arraysize(ar(),2) + for q=1 to y + for p=1 to y + print ar(p,q),"\t" + next p + print + next q +end sub +Explanation: + +This example creates a 2-dimenional array (i.e. a matrix) with the dim-statement and fills it with random numbers. The second dim-statement enlarges the array, all new elements are filled with 0. + +The subroutine printmatrix just does, what its name says. + + +Related: arraysize, arraydim, local + +& +read + +Name: +read -- read data from data-statements + +Synopsis: +read a$,a +... +data "Hello!",7 + +Description: +The read-statement retrieves literal data, which is stored within data-statements elsewhere in your program. + +Example: +read num +dim col$(num) +for a=1 to num:read col$(a):next a +clear screen +print "These are the colours known to yab:\n" +for a=1 to num + print colour(col$(a)) col$(a) +next a + +data 8,"black","white","red","blue" +data "green","yellow","cyan","magenta" +Explanation: + +This program prints the names of the colors known to yab in those very colors. + +Start this program in a terminal. + + +Related: data, restore + +& +redim + +Name: +redim -- create an array prior to its first use. A synonym for dim + +Synopsis: +See the dim-command. + +Description: +The redim-command does exactly the same as the dim-command; it is just a synonym. redim has been around in older versions of basic (not even yab) for many years; therefore it is supported in yab for compatibility reasons. +Please refer to the entry for the dim-command for further information. + +Related: dim +& +restore + +Name: +restore -- reposition the data-pointer + +Synopsis: +read a,b,c,d,e,f +restore +read g,h,i +restore foo +data 1,2,3 +label foo +data 4,5,6 + +Description: +The restore-command may be used to reset the reading of data-statements, so that the next read-statement will read data from the first data-statement. +You may specify a label with the restore-command; in that case, the next read-statement will read data starting at the given label. If the label is omitted, reading data will begin with the first data-statement within your program. + +Example: +input "Which language (German/English) ? " l$ +if (instr("German",l$)>0) then + restore German +else + restore English +endif + +for a=1 to 3 + read x,x$ + print x,"=",x$ +next a + +label English +data 1,"one",2,"two",3,"three" +label German +data 1,"eins",2,"zwei",3,"drei" +Explanation: + +This program asks to select one of those languages known to me (i.e. English or German) and then prints the numbers 1,2 and 3 and their textual equivalents in the chosen language. + + +Related: read, data, label + +&String Handling +& +asc() + +Name: +asc() -- accepts a string and returns the position of its first character +within the ascii charset + +Synopsis: +a=asc(char$) + +Description: +The asc-function accepts a string, takes its first character and looks it up within the ascii-charset; this position will be returned. The asc-function is the opposite of the chr$-function. There are valid uses for asc, however, comparing strings (i.e. to bring them into alphabetical sequence) is not among them; in such many cases you might consider to compare strings directly with <, = and > (rather than converting a string to a number and comparing this number). + +Example: +input "Please enter a letter between 'a' and 'y': " a$ +if (a$<"a" or a$>"y") print a$," is not in the proper range":end +print "The letter after ",a$," is ",chr$(asc(a$)+1) +Related: chr$ + +& +chr$() + +Name: +chr$() -- accepts a number and returns the character at this position within the ascii charset + +Synopsis: +character$=chr$(ascii) + +Description: +The chr$-function is the opposite of the asc-function. It looks up and returns the character at the given position within the ascii-charset. It's typical use is to construct nonprintable characters which do not occur on your keyboard. +Nevertheless you won't use chr$ as often as you might think, because the most important nonprintable characters can be constructed using escape-sequences using the \-character (e.g. you might use \n instead of chr$(10) wherever you want to use the newline-character). + +Example: +print "a",chr$(10),"b" +Explanation: + +This will print the letters 'a' and 'b' in different lines because of the intervening newline-character, which is returned by chr$(10). + + +Related: asc + +& +glob() + +Name: +glob() -- check if a string matches a simple pattern + +Synopsis: +if (glob(string$,pattern$)) ... + +Description: +The glob-function takes two arguments, a string and a (glob-) pattern, and checks if the string matches the pattern. However glob does not employ the powerful rules of regular expressions; rather it has only two special characters: * (which matches any number (even zero) of characters) and ? (which matches exactly a single character). + +Example: +for a=1 to 10 + read string$,pattern$ + if (glob(string$,pattern$)) then + print string$," matches ",pattern$ + else + print string$," does not match ",pattern$ + endif +next a + +data "abc","a*" +data "abc","a?" +data "abc","a??" +data "abc","*b*" +data "abc","*" +data "abc","???" +data "abc","?" +data "abc","*c" +data "abc","A*" +data "abc","????" +Explanation: + +This program checks the string abc against various patterns and prints the result. The output is: + +&exverbatim +abc matches a* +abc does not match a? +abc matches a?? +abc matches *b* +abc matches * +abc matches ??? +abc does not match ? +abc matches *c +abc does not match A* +abc does not match ???? +&exverbatim + +& +hex$() + +Name: +hex$() -- convert a number into hexadecimal + +Synopsis: +print hex$(foo) + +Description: +The hex$-function converts a number into a string with its hexadecimal representation. hex$ is the inverse of the dec-function. + +Example: +open 1,"foo" +while(!eof(1)) + print right$("0"+hex$(peek(1)),2)," " + i=i+1 + if (mod(i,10)=0) print +end while +print +Explanation: + +This program reads the file foo and prints its output as a hex-dump using the hex-function. + + +Related: dec, bin$ + +& +instr() + +Name: +instr() -- searches its second argument within the first; returns its position if found + +Synopsis: +print instr(a$,b$) +if (instr(a$,b$)) ... +pos=instr(a$,b$,x) + +Description: +The instr-functions requires two string arguments and searches the second argument within the first. If the second argument can be found within the first, the position is returned (counting from one). If it can not be found, the instr-function returns 0; this makes this function usable within the condition of an if-statement (see the example below). + +If you supply a third, numeric argument to the instr-function, it will be used as a starting point for the search. Therefore instr("abcdeabcdeabcde","e",8) will return 10, because the search for an "e" starts at position 8 and finds the "e" at position 10 (and not the one at position 5). + +Example: +input "Please enter a text containing the string 'bumf': " a$ +if (instr(a$,"bumf")) then + print "Well done!" +else + print "not so well ..." +endif +Related: rinstr + +& +left$() + +Name: +left$() -- return (or change) left end of a string + +Synopsis: +print left$(a$,2) +left$(b$,3)="foobar" + +Description: +The left$-function accepts two arguments (a string and a number) and returns the part from the left end of the string, whose length is specified by its second argument. Loosely spoken, it simply returns the requested number of chars from the left end of the given string. + +Note, that the left$-function can be assigned to, i.e. it may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the left$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below. + +Example: +input "Please answer yes or no: " a$ +l=len(a$):a$=lower$(a$):print "Your answer is " +if (left$("yes",l)=a$ and l>=1) then + print "yes" +elsif (left$("no",l)=a$ and l>=1) then + print "no" +else + print "?" +endif + +a$="Heiho World!" +print a$ +left$(a$,5)="Hello" +print a$ +Explanation: + +This example asks a simple yes/no question and goes some way to accept even incomplete input, while still beeing able to reject invalid input. This second example demonstrates the capability to assign to the left$-function. + + +Related: right$, mid$ + +& +len() + +Name: +len() -- return the length of a string + +Synopsis: +x=len(a$) + +Description: +The len-function returns the length of its single string argument. + +Example: +input "Please enter a password: " a$ +if (len(a$)<6) error "Password too short!" +Explanation: + +This example checks the length of the password, that the user has entered. + +Related: left$, right$, mid$ + +& +lower$() + +Name: +lower$() -- convert a string to lower case + +Synopsis: +l$=lower$(a$) + +Description: +The lower$-function accepts a single string-argument and converts it to all lower case. + +Example: +input "Please enter a password: " a$ +if (a$=lower$(a$)) error "Your password is NOT mixed case!" +Explanation: + +This example prompts for a password and checks, if it is really lower case. + + +Related: upper$ + +& +ltrim$() + +Name: +ltrim$() -- trim spaces at the left end of a string + +Synopsis: +a$=ltrim$(b$) + +Description: +The ltrim$-function removes all whitespace from the left end of a string and returns the result. + +Example: +input "Please answer 'yes' or 'no' : " a$ +a$=lower$(ltrim$(rtrim$(a$))) +if (len(a$)>0 and a$=left$("yes",len(a$))) then + print "Yes ..." +else + print "No ..." +endif +Explanation: + +This example prompts for an answer and removes any spaces, which might precede the input; therefore it is even prepared for the (albeit somewhat patological case), that the user first hits space before entering his answer. + + +Related: rtrim$, trim$ + +& +rtrim$() + +Name: +rtrim$() -- trim spaces at the right end of a string + +Synopsis: +a$=rtrim$(b$) + +Description: +The rtrim$-function removes all whitespace from the right end of a string and returns the result. + +Example: +input "Please answer 'yes' or 'no' : " a$ +a$=lower$(ltrim$(rtrim$(a$))) +if (len(a$)>0 and a$=left$("yes",len(a$))) then + "Yes ..." +else + print "No ..." +endif +Explanation: + +This example prompts for an answer and removes any spaces, which might precede the input; therefore it is even prepared for the (albeit somewhat patological case), that the user first hits space before entering his answer. + + +Related: ltrim$, trim$ + +& +mid$() + +Name: +mid$() -- return (or change) characters from within a string + +Synopsis: +print mid$(a$,2,1) +print mid$(a$,2) +mid$(a$,5,3)="foo" +mid$(a$,5)="foo" + +Description: +The mid$-function requires three arguments: a string and two numbers, where the first number specifies a position within the string and the second one gives the number of characters to be returned; if you omit the second argument, the mid$-function returns all characters up to the end of the string. +Note, that you may assign to the mid$-function, i.e. mid$ may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the mid$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below. + +Example: +input "Please enter a string: " a$ +for a=1 to len(a$) + if (instr("aeiou",lower$(mid$(a$,a,1)))) mid$(a$,a,1)="e" +next a +print "When you turn everything to lower case and" +print "replace every vowel with 'e', your input reads:" +print +print a$ +Explanation: + +This example transforms the input string a bit, using the mid$-function to retrieve a character from within the string as well as to change it. + + +Related: left$, right$ + +& +right$() + +Name: +right$() -- return (or change) the right end of a string + +Synopsis: +print right$(a$,2) +right$(b$,2)="baz" + +Description: +The right$-function requires two arguments (a string and a number) and returns the part from the right end of the string, whose length is specified by its second argument. So, right$ simply returns the requested number of chars from the right end of the given string. +Note, that the right$-function can be assigned to, i.e. it may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the right$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below. + +Example: +print "Please enter a length either in inch or centimeter" +print "please add 'in' or 'cm' to mark the unit." +input "Length: " a$ +if (right$(a$,2)="in") then + length=val(a$)*2.56 +elsif (right$(a$,2)="cm") then + length=val(a$) +else + error "Invalid input: "+a$ +endif + +a$="Heiho World!" +print a$ +right$(a$,7)="dwarfs." +print a$ +Explanation: + +This program allows the user to enter a length qulified with a unit (either inch or centimeter). +The second example demonstrates the capability to assign to the right$-function. + + +Related: right$, mid$ + +& +split() + +Name: +split() -- split a string into many strings + +Synopsis: +dim w$(10) +... +num=split(a$,w$()) +num=split(a$,w$(),s$) + +Description: +The split-function requires a string (containing the text to be split), a reference to a string-array (which will receive the resulting strings, i.e. the tokens) and an optional string (with a set of characters, at which to split, i.e. the delimiters). + +The split-function regards its first argument (a string) as a list of tokens separated by delimiters and it will store the list of tokens within the array-reference you have supplied. Note, that the array, which is passed as a reference (w$() in the synopsis), will be resized accordingly, so that you don't have to figure out the number of tokens in advance. The element at position zero (i.e. w$(0)) will not be used. + +Normally (i.e. if you omit the third, which is the delimiter-argument) the function will regard space or tab as delimiters for tokens; however by supplying a third argument, you may split at any single of the characters within this string. E.g. if you supply ":;" as the third argument, then colon (:) or semicolon (;) will delimit tokens. +Note, that a sequence of separator-characters will produce a sequence of empty tokens; that way, the number of tokens returned will always be one plus the number of separator characters contained within the string. Refer to the closely related token-function, if you do not like this behaviour. In some way, the split-function focuses on the separators (other than the token-function, which focuses on the tokens), hence its name. + +The second argument is a reference on a string-array, where the tokens will be stored; this array will be expanded (or shrinked) to have room for all tokens, if necessary. +The first argument finally contains the text, that will be split into tokens. The split-function returns the number of tokens that have been found. + +Please see the examples below for some hints on the exact behaviour of the split-function and how it differs from the token-function: + +Example: +print "This program will help you to understand, how the" +print "split()-function exactly works and how it behaves" +print "in certain special cases." +print +print "Please enter a line containing tokens separated" +print "by either '=' or '-'" +dim t$(10) +do + print + input "Please enter a line: " l$ + num=split(l$,t$(),"=-") + print num," Tokens: " + for a=1 to num + if (t$(a)="") then + print "(EMPTY)" + else + print t$(a); + endif + if (a0 and a$=left$("no",len(a$)) exit +loop +Explanation: + +This example asks for an answer (yes or no) and removes spaces with trim$ to make the comparison with the string "no" more bulletproof. + + +Related: ltrim$, rtrim$ + +& +upper$() + +Name: +upper$() -- convert a string to upper case + +Synopsis: +u$=upper$(a$) + +Description: +The upper$-function accepts a single string argument and converts it to all upper case. + +Example: +line input "Please enter a sentence without the letter 'e': " l$ +p=instr(upper$(l$),"E") +if (p) then + l$=lower$(l$) + mid$(l$,p,1)="E" + print "Hey, you are wrong, see here!" + print l$ +else + print "Thanks." +endif +Explanation: + +This program asks for a sentence and marks the first (if any) occurence of the letter 'e' by coverting it to upper case (in contrast to the rest of the sentence, which is converted to lower case). + + +Related: lower$ + +& +val() + +Name: +val() -- converts a string to a number + +Synopsis: +x=val(x$) + +Description: +The val-function checks, if the start of its string argument forms a floating point number and then returns this number. The string therefore has to start with digits (only whitespace infront is allowed), otherwise the val-function returns zero. + +Example: +input "Please enter a length, either in inches (in) or centimeters (cm) " l$ +if (right$(l$,2)="in") then + l=val(l$)*2.51 +else + l=val(l$) +endif +print "You have entered ",l,"cm." +Explanation: + +This example queries for a length and checks, if it has been specified in inches or centimeters. The length is then converted to centimeters. + + +Related: str$ + +&Input and Output +& +at() + +Name: +at() -- can be used in the print-command to place the output at a specified position + +Synopsis: +clear screen +... +print at(a,b) +print @(a,b) + +Description: +The at-clause takes two numeric arguments (e.g. at(2,3)) and can be inserted after the print-keyword. at() can be used only if clear screen has been executed at least once within the program (otherwise you will get an error). + +The two numeric arguments of the at-function may range from 0 to the width of your terminal minus 1, and from 0 to the height of your terminal minus 1; if any argument exceeds these values, it will be truncated accordingly. However, yab has no influence on the size of your terminal (80x25 is a common, but not mandatory), the size of your terminal and the maximum values acceptable within the at-clause may vary. To get the size of your terminal you may use the peek-function: peek("screenwidth") returns the width of your terminal and peek("screenheight") its height. + +Example: +clear screen +maxx=peek("screenwidth")-1:maxy=peek("screenheight")-1 +for x=0 to maxx + print at(x,maxy*(0.5+sin(2*pi*x/maxx)/2)) "*" +next x +Explanation: + +This example plots a full period of the sine-function across the screen. Start this program in a terminal. + + +Related: print, clear screen, color + +& +clear screen + +Name: +clear screen -- erases the text window + +Synopsis: +clear screen + +Description: +clear screen erases the text window (the window where the output of print appears). +It must be issued at least once, before some advanced screen-commands (e.g. print at or inkey$) may be called; this requirement is due to some limititations of the curses-library, which is used by yab for some commands. + +Example: +clear screen +print "Please press a key : " +a$=inkey$ +print a$ +Explanation: + +The clear screen command is essential here; if it would be omitted, yab would issue an error ("need to call 'clear screen' first") while trying to execute the inkey$-function. + +Start this program in a terminal. + + +Related: inkey$ + +& +close + +Name: +close -- close a file, which has been opened before + +Synopsis: +close filenum +close # filenum + +Description: +The close-command closes an open file. You should issue this command as soon as you are done with reading from or writing to a file. + +Example: +open "my.data" for reading as 1 +input #1 a +print a +close 1 +Explanation: + +This program opens the file "my.data", reads a number from it, prints this number and closes the file again. + + +Related: open + +& +color + +Name: +color -- print with color + +Synopsis: +print color(fore$) text$ +print color(fore$,back$) text$ + +Description: +Not a seperate command, but part of the print-command; may be included just after print and can only be issued after clear screen has been executed. + +color() takes one or two string-arguments, specifying the color of the text and (optionally) the background. +The one or two strings passed to color() can be one of these: "black", "white", "red", "blue", "green", "yellow", "cyan" and "magenta" (which can be abbreviated as "bla", "whi", "red", "blu", "gre", "yel", "cya" and "mag" respectively). color() can only be used, if clear scren has been issued at least once. + +Note, that color() can be written as colour() too. + +Example: +clear screen +dim col$(7):for a=0 to 7:read col$(a):next a +do + print color(col$(ran(7)),col$(ran(7))) " Hallo " + pause 0.01 +loop +data "black","white","red","blue" +data "green","yellow","cyan","magenta" +Explanation: + +This prints the word " Hallo " in all colors accross your screen. +Start this program in a terminal. + +Related: print, clear screen, at + +& +colour + +Name: +colour -- see color + +Synopsis: +print colour(fore$) text$ +print colour(fore$,back$) text$ + +Description: +See color. + +Related: color + +& +eof + +Name: +eof -- check, if an open file contains data + +Synopsis: +open 1,"foo.bar" +if (eof(1)) then + ... +end if + +Description: +The eof-function checks, if there is still data left within an open file. As an argument it expects the file-number as returned by (or used within) the open-function (or statement). + +Example: +a=open("foo.bar") +while(not eof(a)) + input #a,a$ + print a$ +end while +Explanation: + +This example will print the contents of the file "foo.bar". The eof-function will terminate the loop, if there is no more data left within the file. + + +Related: open + +& +getscreen$() + +Name: +getscreen$() -- returns a string representing a rectangular section of the text terminal + +Synopsis: +a$=getscreen$(2,2,20,20) + +Description: +The getscreen$ function returns a string representing the area of the screen as specified by its four arguments (which specify two corners). I.e. everything you have printed within this rectangle will be encoded in the string returned (including any colour-information). +Like most other commands dealing with advanced text output, getscreen$ requires, that you have called clear screen before. + +Example: +clear screen + +for a=1 to 1000: + print color("red") "1" + print color("green") "2" + print color("blue") "3" +next a +screen$=getscreen$(10,10,40,10) +print at(10,10) " Please Press 'y' or 'n'! " +a$=inkey$ +putscreen screen$,10,10 +Explanation: + +This program fills the screen with coloured digits and afterwards asks the user for a choice ( Please press 'y' or 'n'! ). Afterwards the area of the screen, which has been overwritten by the question will be restored with its previous contents, whhch had been saved via getscreen$. + +Start this program in a terminal. + +Related: putscreen$ + +& +inkey$ + +Name: +inkey$ -- wait, until a key is pressed + +Synopsis: +clear screen +foo$=inkey$ +inkey$ +foo$=inkey$(bar) +inkey$(bar) + +Description: +The inkeys$-function waits, until the user presses a key on the keyboard or a button of his mouse, and returns this very key. An optional argument specifies the number of seconds to wait; if omitted, inkey$ will wait indefinitely. inkey$ may only be used, if clear screen has been called at least once. + +For normal keys, yab simply returns the key, e.g. a, 1 or !. For function keys you will get f1, f2 and so on. Other special keys will return these strings respectively: enter, backspace, del, esc, scrnup (for screen up), scrndown and tab. Modifier keys (e.g. ctrl, alt or shift) by themself can not be detected (however, if you press shift and e.g. a simultaniously, inkey$ will return the letter A instead of a of course). + +Example: +clear screen +print "Press any key or press 'q' to stop." +repeat + a$=inkey$ + print a$ +until(a$="q") +Explanation: + +This program simply returns the key pressed. You may use it, to learn, which strings are returned for the special keys on your keyboard (e.g. function-keys). + +Start this program in a terminal. + +Related: clear screen + +& +input + +Name: +input -- read input from the user (or from a file) and assign it to a variable + +Synopsis: +input a +input a,b,c +input a$ +input "Hello" a +input #1 a$ + +Description: +input reads the new contents of one or many (numeric- or string-) variables, either from the keyboard (i.e. from you) or from a file. An optional first string-argument specifies a prompt, which will be issued before reading any contents. + +If you want to read from an open file, you need to specify a hash ('#'), followed by the number, under which the file has been opened. + +Note, that the input is split at spaces, i.e. if you enter a whole line consisting of many space-seperated word, the first input-statement will only return the first word; the other words will only be returned on subsequent calls to input; the same applies, if a single input reads multiple variables: The first variable gets only the first word, the second one the second word, and so on. If you don't like this behaviour, you may use line input, which returns a whole line (including embedded spaces) at once. + +Example: +input "Please enter the name of a file to read: " a$ +open 1,a$ +while(!eof(1)) + input #1 b$ + print b$ +wend +Explanation: + +If this program is stored within a file test.yab and you enter this name when prompted for a file to read, you will see this output: + +&exverbatim +Please enter the name of a file to read: test.yab +input +"Please +enter +the +name +of +a +file +to +read: +" +a$ +open +1,a$ +while(!eof(1)) +input +#1 +b$ +print +b$ +wend +&exverbatim + + +Related: line input + +& +line input + +Name: +line input -- read in a whole line of text and assign it to a variable + +Synopsis: +line input a +line input a$ +line input "Hello" a +line input #1 a$ + +Description: +In most respects line input is like the input-command: It reads the new contents of a variable, either from keyboard or from a file. However, line input always reads a complete line and assigns it to its variable. line input does not stop reading at spaces and is therefore the best way to read in a string which might contain whitespace. Note, that the final newline is stripped of. + +Example: +line input "Please enter your name (e.g. Frodo Beutelin): " a$ +print "Hello ",a$ +Explanation: + +Note that the usage of line input is essential in this example; a simple input-statement would only return the string up to the first space, e.g. Frodo. + + +Related: input + +& +open + +Name: +open -- open a file + +Synopsis: +open a,"file","r" +open #a,"file","w" +open "file" for reading as a +open "file" for writing as #a +a=open("file") +a=open("file","r") +if (open(a,"file")) ... +if (open(a,"file","w")) ... + +Description: +The open-command opens a file for reading or writing for printing text. open comes in a wide variety of ways; it requires these arguments:filenumber In the synopsis this is a or #a. In yab each file is associated with a number between 1 and a maximum value, which depends on the operating system. + +For historical reasons the filenumber can be preceded by a hash ('#'). Note, that specifying a filenumber is optional; if it is omitted, the open-function will return a filenumber, which should then be stored in a variable for later reference. This filenumber can be a simple number or an arbitrary complex arithmetic expression, in which case braces might be necessary to save yab from getting confused. + +filename -- In the synopsis above this is "file". This string specifies the name of the file to open (note the important caveat on specifying these filenames). +accessmode -- In the synopsis this is "r", "w", for reading or for writing. This string or clause specifies the mode in which the file is opened; it may be one of: "r"Open the file for reading (may also be written as for reading). If the file does not exist, the command will fail. This mode is the default, i.e. if no mode is specified with the open-command, the file will be opened with this mode. + +"w" -- Open the file for writing (may also be written as for writing). If the file does not exist, it will be created. + +"a" -- Open the file for appending, i.e. what you write to the file will be appended after its initial contents. If the file does not exist, it will be created. + +"b" -- This letter may not appear alone, but may be combined with the other letters (e.g. "rb") to open a file in binary mode (as opposed to text mode). + +As you may see from the synopsis, the open-command may either be called as a command (without braces) or as a function (with braces). If called as a function, it will return the filenumber or zero if the operation fails. Therefore the open-function may be used within the condition of an if-statement. + +If the open-command fails, you may use peek("error") to retrieve the exact nature of the error. +Finally you may read the description for peek("error") to learn which errors may have happened during an open-call. + +Example: +open "foo.bar" for writing as #1 +print #1 "Hallo!" +close #1 +if (not open(1,"foo.bar")) error "Could not open 'foo.bar' for reading" +while(not eof(1)) + line input #1 a$ + print a$ +wend +Explanation: + +This example simply opens the file foo.bar, writes a single line, reopens it and reads its contents again. + + +Related: close, print, peek + +& +print + +Name: +print -- Write to terminal or file + +Synopsis: +print "foo",a$,b +print "foo","a$,b; +print #a "foo",a$ +print #a "foo",a$; +print foo using "##.###" +print reverse "foo" +print at(10,10) a$,b +print @(10,10) a$,b +print color("red","blue") a$,b +print color("magenta") a$,b +print color("green","yellow") at(5,5) a$,b + +Description: +The print-statement outputs strings or characters, either to your terminal (also known as console) or to an open file. + +To understand all those uses of the print-statement, let's go throught the various lines in the synopsis above:print "foo",a$,bPrint the string foo as well as the contents of the variables a$ and b onto the screen, silently adding a newline. + +print "foo",a$,b; +(Note the trailing semicolon!) This statement does the same as the one above; only the implicit newline is skipped, which means that the next print-statement will append seamlessly. + +print #a "foo",a$ +This is the way to write to files. The file with the number a must be open already, an implicit newline is added. Note the file-number #a, which starts with a hash ('#') amd is separated from the rest of the statement by a space only. The file-number (contained in the variable a) must have been returned by a previous open-statement (e.g. a=open("bar")). + +print #a "foo",a$; +The same as above, but without the implicit newline. + +print foo using "##.###" +Print the number foo with as many digits before and after the decimal dot as given by the number of '#'-signs. See the entries for using and str$ for a detailed description of this format. + +print reverse "foo" +As all the print-variants to follow, this form of the print-statement can only be issued after clear screen has been called. The strings and numbers after the reverse-clause are simply printed inverse (compared to the normal print-statement). + +print at(10,10) a$,b +Print at the specified (x,y)-position. This is only allowed after clear screen has been called. You may want to query peek$("screenwidth") or peek$("screenheight") to learn the actual size of your screen. You may add a semicolon to suppress the implicit newline. + +print @(10,10) a$,b +This is exactly the same as above, however, at may be written as @. + +print color("red","blue") at(5,5) a$,b +Print with the specified fore- ("red") and background ("blue") color (or colour). The possible values are "black", "white", "red", "blue", "green", "yellow", "cyan" or "magenta". Again, you need to call clear screen first and add a semicolon if you want to suppress the implicit newline. + +print color("magenta") a$,b +You may specify the foreground color only. + +print color("green","yellow") a$,b +A color and a position (in this sequence, not the other way around) may be specified at once. + +Example: +clear screen +columns=peek("screenwidth") +lines=peek("screenheight") +dim col$(7) +for a=0 to 7:read col$(a):next a +data "black","white","red","blue","green","yellow","cyan","magenta" + +for a=0 to 2*pi step 0.1 + print colour(col$(mod(i,8))) at(columns*(0.8*sin(a)+0.9)/2,lines*(0.8*cos(a)+0.9)/2) "*" + i=i+1 +next a +Explanation: + +This example draws a cloured ellipse within the text window. +Start this program in a terminal. + +Related: at, color, input, clear screen, using, ; + +& +putscreen + +Name: +putscreen -- draw a rectangle of characters into the text terminal + +Synopsis +clear screen +... +a$=getscreen$(5,5,10,10) +... +putscreen a$,7,7 + +Description: +The putscreen-command is the counterpart of the getscreen$-function. putscreen requires a string as returned by the getscreen-function. Such a string contains a rectangular detail from the terminal; the putscreen-function puts such a region back into the terminal-window. +Note, that clear screen must have been called before. + +Example: +clear screen +for a=1 to 200 + print color("red") "Hallo!" + print color("blue") "Welt!" +next a +r$=getscreen$(0,0,20,20) +for x=0 to 60 + putscreen r$,x,0 + sleep 0.1 +next x +Explanation: + +This example prints the string "Hallo!Welt!" all over the screen and then moves a rectangle from one side to the other. +Start this program in a terminal. + +Related: getscreen$, clear screen + +& +reverse + +Name: +reverse -- print reverse (background and foreground colors exchanged) + +Synopsis: +clear screen +... +print reverse "foo" + +Description: +reverse may be used to print text in reverse. reverse is not a seperate command, but part of the print-command; it may be included just after the print and can only be issued once that clear screen has been issued. + +Example: +clear screen + +print "1 " +c=3 +do + prim=true + for a=2 to sqrt(c) + if (frac(c/a)=0) then + prim=false + break + endif + next a + if (prim) then + print + print reverse c; + else + print c; + endif + print " " + c=c+1 +loop +Explanation: + +This program prints numbers from 1 on and marks each prime number in reverse. +Start this program in a terminal. + +Related: at, color, print, clear screen + +& +screen + +Name: +screen -- as clear screen clears the text window + +Synopsis: +clear screen + +Description: +The keyword screen appears only within the sequence clear screen; please see there for a description. + +Related: clear screen + +& +seek() + +Name: +seek() -- change the position within an open file + +Synopsis: +open 1,"foo" +seek #1,q +seek #1,x,"begin" +seek #1,y,"end" +seek #1,z,"here" + +Description: +The seek-command changes the position, where the next input (or peek) statement will read from an open file. Usually files are read from the beginning to the end sequentially; however sometimes you may want to depart from this simple scheme. This can be done with the seek-command, allowing you to change the position, where the next piece of data will be read from the file. + +seek accepts two or three arguments: The first one is the number of an already open file. The second one is the position where the next read from the file will start. The third argument is optional and specifies the the point from where the position (the second argument) will count. It can be one of: + +begin -- Count from the beginning of the file. + +end -- Count from the end of the file. + +here -- Count from the current position within the file. + + +Example: +open #1,"count.dat","w" +for a=1 to 10 + print #1,"00000000" + if (a<10) print #1,"" +next a + +dim count(10) +do + x=int(ran(10)) + i=i+1 + if (mod(i,1000)=0) print "." + count(x)=count(x)+1 + curr$=right$("00000000"+str$(count(x)),8) + seek #1,9*x,"begin" + print #1,curr$; +loop +Explanation: + +This example increments randomly one of ten counters (in the array count()); however, the result is always kept and updated within the file count.dat, so even in case of an unexpected interrupt, the result will not be lost. + + +Related: tell, open, print, peek + +& +tell + +Name: +tell -- get the current position within an open file + +Synopsis: +open #1,"foo" + ... +position=tell(#1) + +Description: +The tell-function requires the number of an open file as an argument. It returns the position (counted in bytes, starting from the beginning of the file) where the next read will start. + +Example: +open #1,"foo","w" +print #1 "Hello World!" +close #1 + +open #1,"foo" +seek #1,0,"end" +print tell(#1) +close 1 +Explanation: + +This example (mis)uses tell to get the size of the file. The seek positions the file pointer at the end of the file, therefor the call to tell returns the total length of the file. + + +Related: tell, open + +& +using + +Name: +using -- Specify the format for printing a number + +Synopsis: +print a using "##.###" +print a using("##.###",",.") + +Description: +The using-keyword may appear as part of the print-statement and specifies the format (e.g. the number of digits before and after the decimal dot), which should be used to print the number. + +The possible values for the format argument ("##.###" in the synopsis above) are described within the entry for the str$-function; especially the second line in the synopsis (print a using("##.###",",.")) will become clear after referring to str$. In fact the using clause is closely related to the str$-function; the former can always be rewritten using the latter; i.e. print foo using bar$ is always equivalent to print str$(foo,bar$). Therefore you should check out str$ to learn more. + +Example: +for a=1 to 10 + print sqrt(ran(10000*a)) using "#########.#####" +next a +Explanation: + +This example prints a column of square roots of random number, nicely aligned at the decimal dot. + + +Related: print, str$ + +& +# + +Name: +# -- either a comment or a marker for a file-number + +Synopsis: +# This is a comment, but the line below not! +open #1,"foo" + +Description: +The hash ('#') has two totally unrelated uses:A hash might appear in commands related with file-io. yab uses simple numbers to refer to open files (within input, print, peek or eof). In those commands the hash may precede the number, which species the file. Please see those commands for further information and examples; the rest of this entry is about the second use (as a comment). + +As the very first character within a line, a hash introduces comments (similar to rem). +'#' as a comment is common in most scripting languages and has a special use under BeOS: If the very first line of any BeOS-program begins with the character sequence '#!' ("she-bang", no spaces allowed), the rest of the line is taken as the program that should be used to execute the script. I.e. if your yab-program starts with '#!/boot/home/config/bin/yab', the program /boot/home/config/bin/yab will be invoked to execute the rest of the program. + +Example: +# This line is a valid comment +print "Hello " : # But this is a syntax error, because +print "World!" : # the hash is not the first character! +Explanation: + +Note, that this example will produce a syntax error and is not a valid program! + + +Related: input, print, peek, eof, //, rem + +& +at() + +Name: +at() -- can be used in the print-command to place the output at a specified position + +Synopsis: +clear screen +... +print at(a,b) +print @(a,b) + +Description: +The at-clause takes two numeric arguments (e.g. at(2,3)) and can be inserted after the print-keyword. at() can be used only if clear screen has been executed at least once within the program (otherwise you will get an error). + +The two numeric arguments of the at-function may range from 0 to the width of your terminal minus 1, and from 0 to the height of your terminal minus 1; if any argument exceeds these values, it will be truncated accordingly. However, yab has no influence on the size of your terminal (80x25 is a common, but not mandatory), the size of your terminal and the maximum values acceptable within the at-clause may vary. To get the size of your terminal you may use the peek-function: peek("screenwidth") returns the width of your terminal and peek("screenheight") its height. + +Example: +clear screen +maxx=peek("screenwidth")-1:maxy=peek("screenheight")-1 +for x=0 to maxx + print at(x,maxy*(0.5+sin(2*pi*x/maxx)/2)) "*" +next x +Explanation: + +This example plots a full period of the sine-function across the screen. +Start this program in a terminal. + +Related: print, clear screen, color + +& +; + +Name: +; -- suppress the implicit newline after a print-statement + +Synopsis: +print "foo",bar; + +Description: +The semicolon (';') may only appear at the last position within a print-statement. It supresses the implicit newline, which yab normally adds after each print-statement. + +Put another way: Normally the output of each print-statement appears on a line by itself. If you rather want the output of many print-statements to appear on a single line, you should end the print-statement with a semicolon. + +Example: +print "Hello ":print "World!" +Explanation: + +This example prints Hello World! in a single line. + + +Related: print + +&Subroutines +& +end sub + +Name: +end sub -- ends a subroutine definition + +Synopsis: +sub foo(...) + ... +end sub + +Description: +Marks the end of a subroutine-definition (which starts with the sub-keyword). The whole concept of subroutines is explained within the entry for sub. +Example: +print foo(3) + +sub foo(a) + return a*2 +end sub +Explanation: + +This program prints out 6. The subroutine foo simply returns twice its argument. + + +Related: sub + +& +export + +Name: +export -- mark a function as globally visible + +Synopsis: +export sub foo(bar) +... +end sub + +Description: +The export-statement is used within libraries to mark a user defined subroutine as visible outside the library wherein it is defined. Subroutines, which are not exported, must be qualified with the name of the library, e.g. foo.baz (where foo is the name of the library and baz the name of the subroutine); exported subroutines may be used without specifying the name of the library, e.g. bar. + +Therefore export may only be useful within libraries. + +Example: +export sub bar() + print "Hello" +end sub + +sub baz() + print "World" +end sub +Explanation: + +The library foo.bar (which is listed above) defines two functions bar and baz, however only the function bar is exported and therefore visible even outside the library; baz is not exported and may only be used within the library foo.yab. + +Now within your main program cux.yab (which imports the library foo.yab); note that this program produces an error: +&exverbatim +import foo + +print "Calling subroutine foo.bar (okay) ..." +foo.bar() +print "done." + +print "Calling subroutine bar (okay) ..." +bar() +print "done." + +print "Calling subroutine foo.baz (okay) ..." +foo.baz() +print "done." + +print "Calling subroutine baz (NOT okay) ..." +baz() +print "done." +&exverbatim + +The output when executing yab foo.yab is this: + +&exverbatim +Calling subroutine foo.bar (okay) ... +Hello +done. +Calling subroutine bar (okay) ... +Hello +done. +Calling subroutine foo.baz (okay) ... +World +done. +Calling subroutine baz (NOT okay) ... +---Error in main.yab, line 16: can't find subroutine 'baz' +---Dump: sub baz() called in main.yab,16 +---Error: Program stopped due to an error +&exverbatim + +As the error message above shows, the subroutine baz must be qualified with the name of the library, if used outside the library, wherein it is defined (e.g. foo.baz. I.e. outside the library foo.yab you need to write foo.baz. baz alone would be an error. + +The subroutine bar (without adding the name of the library) however may (and probably should) be used in any program, which imports the library foo.yab. +Note: In some sense the set of exported subroutines constitutes the interface of a library. + + +Related: sub, import + +& +import + +Name: +import -- import a library + +Synopsis: +import foo + +Description: +The import-statment imports a library. It expects a single argument, which must be the name of a library (without the trailing .yab). This library will then be read and parsed and its subroutines (and variables) will be made available within the main program. + +Libraries will first be searched within the current directory (i.e. the directory within which you have invoked yab), then within the special directory /boot/home/config/lib/yab. The location of this second directory may be changed with the option -library. + +Example: +import lib + +rem This works ... +lib.x(0) + +rem This works too .. +x(1) + +rem And this. +lib.y(2) + +rem But this not! +y(3) +Explanation: + +Lets say you have a yab-program foo.yab, which imports a library lib.yab. + +Now the library lib.yab reads: + +&exverbatim +rem Make the subroutine x easily available outside this library +export sub x(a) + print a + return +end sub + +rem sub y must be referenced by its full name +rem outside this library +sub y(a) + print a + return +end sub +&exverbatim + +This program produces an error: + +&exverbatim +0 +1 +2 +---Error in foo.yab, line 13: can't find subroutine 'y' +---Dump: sub y() called in foo.yab,13 +---Error: Program stopped due to an error +&exverbatim + +As you may see from the error message, yab is unable to find the subroutine y without specifying the name of the library (i.e. lib.y). The reason for this is, that y, other than x, is not exported from the library lib.yab (using the export-statement). + + +Related: export, sub + +& +local + +Name: +local -- mark a variable as local to a subroutine + +Synopsis: +sub foo() + + local a,b,c$,d(10),e$(5,5) + + ... + +end sub + +Description: +The local-command can (and should be) used to mark a variable (or array) as local to the containing subroutine. This means, that a local variable in your subroutine is totally different from a variable with the same name within your main program. Variables which are known everywhere within your program are called global in contrast. +Declaring variables within the subroutine as local helps to avoid hard to find bugs; therefore local variables should be used whenever possible. + +Note, that the parameters of your subroutines are always local. + +As you may see from the example, local arrays may be created without using the keyword dim (which is required only for global arrays). + +Example: +a=1 +b=1 +print a,b +foo() +print a,b + +sub foo() + local a + a=2 + b=2 +end sub +Explanation: + +This example demonstrates the difference between local and global variables; it produces this output: +1 1 +1 2 +As you may see, the content of the global variable a is unchanged after the subroutine foo; this is because the assignment a=2 within the subroutine affects the local variable a only and not the global one. However, the variable b is never declared local and therefore the subroutine changes the global variable, which is reflected in the output of the second print-statement. + + +Related: sub, static, dim + +& +numparams + +Name: +numparams -- return the number of parameters, that have been passed to a subroutine + +Synopsis: +sub foo(a,b,c) + if (numparams=1) ... + ... +end sub + +Description: +Within a subroutine the local variable numparam or numparams contains the number of parameters, that have been passed to the subroutine. This information can be useful, because the subroutine may have been called with fewer parameters than actually declared. The number of values that actually have been passed while calling the subroutine, can be found in numparams. + +Note, that arguments which are used in the definition of a subroutine but are left out during a call to it (thereby reducing the value of numparams) receive a value of 0 or "" (empty string) respectively. + +Example: +a$="123456789" +print part$(a$,4) +print part$(a$,3,7) + +sub part$(a$,f,t) + if (numparams=2) then + return mid$(a$,f) + else + return mid$(a$,f,t-f+1) + end if +end sub +Explanation: + +When you run this example, it will print 456789 and 34567. Take a look at the subroutine part$, which returns part of the string which has been passed as an argument. If (besides the string) two numbers are passed, they define the starting and end position of the substring, that will be returned. However, if only one number is passed, the rest of the string, starting from this position will be returned. Each of these cases is recognized with the help of the numparams variable. + + +Related: sub + +& +return + +Name: +return -- return from a subroutine or a gosub + +Synopsis: +gosub foo +... +label foo +... +return + +sub bar(baz) + ... + return quertz +end sub + +Description: +The return-statement serves two different (albeit somewhat related) purposes. The probably more important use of return is to return control from within a subroutine to the place in your program, where the subroutine has been called. If the subroutine is declared to return a value, the return-statement might be accompanied by a string or number, which constitutes the return value of the subroutine. + +However, even if the subroutine should return a value, the return-statement need not carry a value; in that case the subroutine will return 0 or the empty string (depending on the type of the subroutine). Moreover, feel free to place multiple return-statements within your subroutine; it's a nice way of controlling the flow of execution. +The second (but historcially first) use of return is to return to the position, where a prior gosub has left off. In that case return may not carry a value. + +Example: +do + read a$ + if (a$="") then + print + end + endif + print mark$(a$)," " +loop + +data "The","quick","brown","fox","jumped" +data "over","the","lazy","dog","" + +sub mark$(a$) + if (instr(lower$(a$),"q")) return upper$(a$) + return a$ +end sub +Explanation: + +This example features a subroutine mark$, that returns its argument in upper case, if it contains the letter "q", or unchanged otherwise. In the test-text the word quick will end up beeing marked as QUICK. +The example above demonstrates return within subroutines; please see gosub for an example of how to use return in this context. + + +Related: sub, gosub + +& +static + +Name: +static -- preserves the value of a variable between calls to a subroutine + +Synopsis: +sub foo() + + static a + + ... + +end sub + +Description: +The static keyword can be used within subroutines to mark variables as static. This has two effects: First, the variable is local to the subroutine, i.e. its value is not know outside the subroutine (this is the effect of the local keyword). Second, the static-keyword arranges things, so that the variable keeps its value between invocations of the subroutine (this is different from the local-keyword). + +Example: +foo() +foo() +foo() + +sub foo() + static a + local b + a=a+1 + b=b+1 + print a,b +end sub +Explanation: + +This program shows the difference between static and local variables within a subroutine; it produces this output: + +&exverbatim +1 1 +2 1 +3 1 +&exverbatim + +The output shows, that the static variable a keeps its value between subroutine calls, whereas b is initialized with the value 0 at every call to the subroutine foo. + + +Related: sub, local + +& +sub + +Name: +sub -- declare a user defined subroutine + +Synopsis: +foo(2,"hello") + +... + +sub foo(bar,baz$) + ... + return qux + ... +end sub + +Description: +The sub-keyword starts the definition of a user defined subroutine. With user defined subroutines you are able to somewhat extend yab with your own commands or functions. A subroutine accepts arguments (numbers or strings) and returns a number or a string (however, you are not required to assign the value returned to a variable). The name of the subroutine follows after the keyword sub. If the name (in the synopsis: foo) ends on a '$', the subroutine should return a string (with the return-statement), otherwise a number. + +After the name of the subroutine yab requires a pair of braces; within those braces you may specify a list of parameters, for which values can (but need not) be included when calling the subroutine. If you omit one of those parameters when calling such a subroutine, it assumes the value zero (for numeric parameters) or the empty string (for string parameters). However with peek("argument") you may find out, how many arguments have really been passed while calling the subroutine. + +Parameters of a subroutine are always local variables (see the keyword local for more explanation). +From within the subroutine you may return any time with the keyword return; along with the return-keyword you may specify the return value. Note that more than one return is allowed within a single subroutine. + +Finally, the keyword end sub ends the subroutine definition. Note, that the definition of a subroutine need not appear within the program before the first call to this sub. + +Note: As braces have two uses in yab (i.e. for supplying arguments to a subroutine as well as to list the indices of an array). yab can not tell apart an array from a subroutine with the same name. Therefore you cannot define a subroutine with the same name as an array! + +Example: +p=2 +do + if (is_prime(p)) print p + p=p+1 +loop + +sub is_prime(a) + local b + for b=2 to sqrt(a) + if (frac(a/b)=0) return false + next b + return true +end sub +Explanation: + +This example is not the recommended way to compute prime numbers. However it gives a nice demonstration of using a subroutine. + + +Related: local, static, peek + +&System +& +bind() + +Name: +bind() -- Binds a yab-program and the yab-interpreter together into a standalone program. + +Synopsis: +bind("foo.exe") + +Description: +The bind-command combines your own yab-program (plus all the libraries it does import) and the interpreter by copying them into a new file, whose name is passed as an argument. This new program may then be executed on any computer, even if it does not have yab installed. + +Note: With the current version of yab, bind should not be used anymore, use the Build Factory instead. + +Example: +if (!peek("isbound")) then + bind "foo" + print "Successfully created the standalone executable 'foo'!" + exit +endif + +print "Hello World!" +Explanation: + +This example creates a standalone program foo from itself. + + +Related: peek +& +clipboard copy + +Name: +clipboard copy -- copy a string to the clipboard + +Synopsis: +CLIPBOARD COPY Text$ + +Description: +Clipboard copy simply copies the string Text$ to the system clipboard. Note: This will overwrite all text currently stored in the clipboard. + +Example: +print "This is the content of the clipboard: "+clipboard paste$ +print "Now we copy \"Foo Bar\" to the clipboard" +clipboard copy "Foo Bar" +print "This is the content of the clipboard: "+clipboard paste$ +Explanation: + +The example will first display whatever is written in the clipboard (might be empty too), and then copies the string "Foo Bar" to the clipboard. Another output shows, it actually worked. + +Related: clipboard paste$ +& +clipboard paste$ + +Name: +clipboard paste$ -- read out the clipboard + +Synopsis: +Text$ = CLIPBOARD PASTE$ + +Description: +This command will read out ("paste") the content of the system clipboard. + +Example: +print "This is the content of the clipboard: "+clipboard paste$ +print "Now we copy \"Foo Bar\" to the clipboard" +clipboard copy "Foo Bar" +print "This is the content of the clipboard: "+clipboard paste$ +Explanation: + +The example will first display whatever is written in the clipboard (might be empty too), and then copies the string "Foo Bar" to the clipboard. Another output shows, it actually worked. + +Related: clipboard copy +& +compile + +Name: +compile -- compile a string with yab-code on the fly + +Synopsis: +compile(code$) + +Description: +This is an advanced command (closely related with the execute-command). It allows you to compile a string of yab-code (which is the only argument). Afterwards the compiled code is a normal part of your program. +Note, that there is no way to remove the compiled code. + +Example: +compile("sub mysub(a):print a:end sub") +mysub(2) +Explanation: + +This example creates a function named mysub, which simply prints its single argument. + + +Related: execute + +& +date$ + +Name: +date$ -- returns a string with various components of the current date + +Synopsis: +a$=date$ + +Description: +The date$-function (which must be called without parantheses; i.e. date$() would be an error) returns a string containing various components of a date; an example would be 4-05-27-2004-Thu-May. This string consists of various fields seperated by hyphens ("-"):The day within the week as a number in the range 0 (=sunday) to 6 (=saturday) (in the example above: 4, i.e. thursday). + +The month as a number in the range 1 (=january) to 12 (=december) (in the example: 5 which stands for may). +The day within the month as a number in the range 1 to 31 (in the example: 27). +The full, 4-digit year (in the example: 2004, which reminds me that I should adjust the clock within my computer ...). +The abbreviated name of the day within the week (Mon to Sun). +The abbreviated name of the month (Jan to Dec). + +Therefore the whole example above (4-05-27-2004-Thu-May) would read: day 4 in the week (counting from 0), May 27 in the year 2004, which is a thursday in May. +Note, that all fields within the string returned by date$ have a fixed with (numbers are padded with zeroes); therefore it is easy to extract the various fields of a date format with mid$. + +Example: +rem Two ways to print the same ... + +print mid$(date$,3,10) + +dim fields$(6) +a=split(date$,fields$(),"-") +print fields$(2),"-",fields$(3),"-",fields$(4) +Explanation: + +This example shows two different techniques to extract components from the value returned by date$. The mid$-function is the preferred way, but you could just as well split the return-value of date$ at every "-" and store the result within an array of strings. + + +Related: time$ + +& +doc + +Name: +doc -- special comment, which might be retrieved by the program itself + +Synopsis: +doc This is a comment +docu This is another comment + +Description: +Introduces a comment, which spans up to the end of the line. But other than the rem-comment, any docu-comment is collected within the special docu$-array and might be retrieved later on. Moreover you might invoke yab -docu foo.yab on the commandline to retrieve the embedded documentation within the program foo.yab. +Instead of doc you may just as well write docu or even documentation. + +Example: +rem Hi, this has been written by me +rem +doc This program asks for a number and +doc prints this number multiplied with 2 +rem +rem Print out rhe above message +for a=1 to arraysize(docu$()):print docu$(a):next a + +rem Read and print the number +input "Please input a number: " x +print x*2 +Explanation: + +This program uses the comments within its code to print out a help message for the user. +The contents of the doc-lines are retrieved from the docu$-array; if you do not want a comment to be collected within this array, use the rem-statement instead. + + +Related: docu$, rem + +& +docu$ + +Name: +docu$ -- special array, containing the contents of all docu-statement within the program + +Synopsis: +a$=docu$(1) + +Description: +Before your program is executed, yab collects the content of all the doc-statements within your program within this 1-dimensional array (well only those within the main-program, libraries are skipped). +You may use the arraysize function to find out, how many lines it contains. + +Example: +docu +docu This program reads two numbers +docu and adds them. +docu + +rem retrieve and print the embedded documentation +for a=1 to arraysize(docu$(),1) + print docu$(a) +next a + +input "First number: " b +input "Second number: " c + +print "The sum of ",b," and ",c," is ",b+c +Explanation: + +This program uses the embedded documentation to issue a usage-message. + + +Related: arraydim, rem + +& +error + +Name: +error -- raise an error and terminate your program + +Synopsis: +error "Wrong, wrong, wrong!!" + +Description: +Produces the same kind or error messages, that yab itself produces (e.g. in case of a syntax-error). The single argument is issued along with the current line-number. + +Example: +input "Please enter a number between 1 and 10: " a +if (a<1 or a>10) error "Oh no ..." +Explanation: + +This program is very harsh in checking the users input; instead of just asking again, the program terminates with an error, if the user enters something wrong. +The error message would look like this: + +&exverbatim +---Error in t.yab, line 2: Oh no ... +---Error: Program stopped due to an error +&exverbatim + + +& +execute$() + +Name: +execute$() -- execute a user defined subroutine, which must return a string + +Synopsis: +print execute$("foo$","arg1","arg2") + +Description: +execute$ can be used to execute a user defined subroutine, whose name may be specified as a string expression. +This feature is the only way to execute a subroutine, whose name is not known by the time you write your program. This might happen, if you want to execute a subroutine, which is compiled (using the compile command) during the course of execution of your program. +Note however, that the execute$-function is not the preferred method to execute a user defined subroutine; almost all cases you should just execute a subroutine by writing down its name within your yab program (see the example). + +Example: +print execute$("foo$","Hello","world!") +sub foo$(a$,b$) + return a$+" "+b$ +end sub +Explanation: + +The example simply prints Hello world!, which is the return value of the user defined subroutine foo$. The same could be achieved by executing: + +&exverbatim +print foo$(a$,b$) +&exverbatim + + +Related: compile, execute + +& +execute() + +Name: +execute() -- execute a user defined subroutine, which must return a number + +Synopsis: +print execute("bar","arg1","arg2") + +Description: +The execute-function is the counterpart of the execute$-function (please see there for some caveats). execute executes subroutines, which returns a number. + +Example: +print execute("bar",2,3) +sub bar(a,b) + return a+b +end sub +Related: compile, execute$ + +& +exit + +Name: +exit -- terminate your program + +Synopsis: +exit +exit 1 + +Description: +Terminate your program and return any given value to the operating system. exit is similar to end, but it will terminate your program immediately, no matter what. + +Example: +print "Do you want to continue ?" +input "Please answer y(es) or n(o): " a$ +if (lower$(left$(a$,1))="n") exit 1 +Related: end + +& +iscomputeron + +Name: +iscomputeron -- tells you whether the computer is on + +Synopsis: +IsItTurnedOn = ISCOMPUTERON + +Description: +Returns 1 if the computer is on. If the computer isn't on, the value returned by this function is undefined. + +Example: +print "This program will run until the computer is shut down :)" +while(iscomputeron) +wend +Explanation: + +Iscomputeron looks nice for endless loops. + +& +pause + +Name: +pause -- pause, sleep, wait for the specified number of seconds + +Synopsis: +pause 5 + +Description: +The pause-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. + +The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yab will not wait at all. +The pause-command cannot be interrupted. However, sometimes you may want the wait to be interuptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument). + +Example: +deg=0 +do + maxx=44+40*sin(deg) + for x=1 to maxx + print "*" + next x + pause 0.1+(maxx*maxx/(4*84*84)) + print + deg=deg+0.1 +loop +Explanation: + +This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity. + + +Related: sleep, wait + +& +peek + +Name: +peek -- retrieve various internal informations + +Synopsis: +print peek("foo") +a=peek(#1) + +Description: +The peek-function has many different and mostly unrelated uses. It is a kind of grabbag for retrieving all kinds of numerical information, internal to yab. The meaning of the numbers returned be the peek-function depends on the string or number passed as an argument. + +peek always returns a number, however the closely related peek$-function exists, which may be used to retrieve string information from among the internals of yab. Finally note, that some of the values which are retrieved with peek may even be changed, using the poke-function. + +There are two variants of the peek-function: One expects an integer, positive number and is described within the first entry of the list below. The other variant expects one of a well defined set of strings as described in the second and all the following entries of the list below. + +peek(a), peek(#a) +Read a single character from the file a (which must be open of course). + +peek("screenheight") +Return the height in characters of the window, wherein yab runs. If you have not called clear screen yet, this peekwill return 0, regardless of the size of your terminal. + +peek("screenwidth") +Return the width in characters of the window, wherein yab runs. If you have not called clear screen yet, this peekwill return 0, regardless of the size of your terminal. + +peek("argument") +Return the number of arguments, that have been passed to yab at invocation time. E.g. if yab has been called like this: + yab foo.yab bar baz +then peek("argument") will return 2. This is because foo.yab is treated as the name of the program to run, whereas bar and baz are considered arguments to the program, which are passed on the commandline. The function peek("argument") can be written as peek("arguments") too. +You will want to check out the corresponding function peek$("argument") to actually retrieve the arguments. Note, that each call to peek$("argument") reduces the number returned by peek("argument"). + +peek("isbound") +Return true, if the executing yab-program is part of a standalone program; see the section about creating a standalone-program for details. + +peek("version") +Return the version number of yab (e.g. 1). + +peek("error") +Return a number specifying the nature of the last error in an open- or seek-statement. Normally an error within an open-statement immediately terminates your program with an appropriate error-message, so there is no chance and no need to learn more about the nature of the error. However, if you use open as a condition (e.g. if (open(#1,"foo")) ...) the outcome (success or failure) of the open-operation will determine, if the condition evaluates to true or false. If now such an operation fails, your program will not be terminated and you might want to learn the reason for failure. This reason will be returned by peek("error") (as a number) or by peek$("error") (as a string)The table below shows the various error codes; the value returned by peek$("error") explains the nature of the error. Note, that the codes 10,11 and 12 refer to the seek-command. + +Error codes + +peek("error")| peek$("error") | Explanation +2 Stream already in use Do not try to open one and the same + filenumber twice; rather close it first. + +3 'x' is not a valid filemode The optional filemode argument, which may + be passed to the open-function, has an + invalid value + +4 could not open 'foo' The open-call did not work, no further + explanation is available. + +5 reached maximum number + of open files You have opened more files than your + operating system permits. + +9 invalid stream number An attempt to use an invalid + (e.g. negative) stream number; + example: open(-1,"foo") + +10 could not position stream x + to byte y seek did not work. + +11 stream x not open You have tried to seek within a stream, + that has not been opened yet. + +12 seek mode 'x' is none of + begin,end,here The argument, which has been passed to + seek is invalid. + +Example: +open "foo" for reading as #1 +open "bar" for writing as #2 +while(not eof(#1)) + poke #2,chr$(peek(#1)); +wend +Explanation: + +This program will copy the file foo byte by byte to bar. +Note, that each peek does something entirely different, and only one has been demonstratedabove. Therefore you need to make up examples yourself for all the other peeks. + + +Related: peek$, poke, open + +& +peek$ + +Name: +peek$ -- retrieve various internal string-informations + +Synopsis: +print peek$("foo") + +Description: +The peek$-function has many different and unrelated uses. It is a kind of grabbag for retrieving all kinds of string information, internal to yab; the exact nature of the strings returned be the peek$-function depends on the string passed as an argument. + +peek$ always returns a string, however the closely related peek-function exists, which may be used to retrieve numerical information from among the internals of yab. Finally note, that some of the values which are retrieved with peek$ may even be changed, using the poke-function. + +The following list shows all possible arguments to peek$:peek$("infolevel")Returns either "debug", "note", "warning", "error" or "fatal", depending on the current infolevel. This value can be specified with an option on the commandline or changed during the execution of the program with the corresponding poke; however, normally only the author of yab would want to change this from its default value "warning". + +peek$("error") +Return a string describing the nature of the last error in an open- or seek-statement. See the corresponding peek("error") for a detailed description. + +peek$("library") +Return the name of the library, this statement is contained in. See the import-command for a detailed description or for more about libraries. + +peek$("os") +This peek returns the name of the operating system, where your yab version was compiled on. This can be either "BeOS" or "ZETA". On BeOS R5 it will always be "BeOS" while on ZETA it can be both. To check whether the system is really running ZETA do: RealOS$ = upper$(system$("uname -o")) + +peek$("env","NAME") +Return the environment variable specified by NAME (which may be any string expression). Which kind of environment variables are available on your system depends, as well as their meaning, on your system; however typing env on the commandline will produce a list. Note, that peek$("env",...) can be written as peek$("environment",...) too. + +peek$("argument") +Return one of the arguments, that have been passed to yab at invocation time (the next call will return the the second argument, and so on). E.g. if yab has been called like this: yab foo.yab bar baz, then the first call to peek$("argument") will return bar. This is because foo.yab is treated as the name of the program to run, whereas bar and baz are considered arguments to this program, which are passed on the commandline. The second call to peek$("argument") will return baz. Note, that peek$("argument") can be written as peek$("arguments"). +Finally you will want to check out the corresponding function peek("argument"). + +Example: +print "You have supplied these arguments: " +while(peek("argument")) + print peek("argument"),peek$("argument") +wend +Explanation: + +If you save this program in a file foo.yab and execute it via yab t.yab a b c, your will get this output: + +&exverbatim +3a +2b +1c +&exverbatim + + +Related: peek, poke, open + +& +poke + +Name: +poke -- change selected internals of yab + +Synopsis: +poke "foo","bar" +poke "foo",baz +poke #a,"bar" +poke #a,baz + +Description: +The poke-command may be used to change details of yabs behaviour. Like the related function peek, poke does many different things, depending on the arguments supplied. + +Here are the different things you can do with poke:poke "infolevel","debug"Change the amount of internal information, that yab outputs during execution. +The second argument can be either "debug", "note", "warning", "error" or "fatal". However, normally you will not want to change this from its default value "warning". See also the related peek$("infolevel"). + +poke #1,a +Write the given byte (a in the example above) to the specified stream (#a in the example). + +See also the related function peek(#1). + +Example: +print "Hello, now you will see, how much work" +print "a simple for-loop involves ..." +input "Please press return " a$ +poke "infolevel","debug" +for a=1 to 10:next a +Explanation: + +This example only demonstrates one of the many pokes, which are described above: The program switches the infolevel to debug, which makes yab produce a lot of debug-messages during the subsequent for-loop. + + +Related: peek, peek$ + +& +rem + +Name: +rem -- start a comment + +Synopsis: +rem Hey, this is a comment + # this is a comment too +// even this +print "Not a comment" # This is an error!! +print "Not a comment":// But this is again a valid comment +print "Not a comment" // even this. +print "Not a comment" rem and this! + +Description: +rem introduces a comment (like # or //), that extends up to the end of the line. +Those comments do not even need a colon (':' infront of them); they (rem, # and //) all behave alike except for #, which may only appear at the very beginning of a line; therefore the fourth example in the synopsis above (print "Not a comment" # This is an error!!) is indeed an error. +Note, that rem is an abbreviation for remark. remark however is not a valid command in yab. +Finally note, that a comment intoduced with '#' may have a special meaning under BeOS; see the entry for # for details. + +Example: +# +rem comments on data structures +# are more useful than +// comments on algorithms. +rem +Explanation: + +This program does nothing, but in a splendid and well commented way. + + +Related: #, // + +& +sleep + +Name: +sleep -- pause, sleep, wait for the specified number of seconds + +Synopsis: +sleep 4 + +Description: +The sleep-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. +Therefore you should refer to the entry for the pause-function for further information. + +& +system$() + +Name: +system$() -- hand a statement over to your operating system and return its output + +Synopsis: +print system$("dir") + +Description: +The system$-command accepts a single string argument, specifying a command, that can be found and executed by your operating system. It returns the output of this command as one big string. + +Example: +input "Please enter the name of a directory: " d$ +print +print "This is the contents of the '"+d$+"':" +print system$("ls -l "+d$) +Explanation: + +This example lists the contents of a directory, employing the ls-command. + + +Related: system + +& +system() + +Name: +system() -- hand a statement over to your operating system and return its exitcode + +Synopsis: +ret=system("foo") +system("bar") + +Description: +The system-command accepts a single string argument, which specifies a command to be executed. The function will return the exitcode of the command; its output (if any) will be lost. + +Example: +print "Please enter the name of the file, that should be deleted." +input f$ +if (system("rm "+f$+" >/dev/null 2>&1")) then + print "Error!" +else + print "okay." +endif +Explanation: + +This program uses the commandline command rm to remove a file. + +Related: system$ + +& +thread get + +Name: +thread get -- get the thread identification for a team or program + +Synopsis: +Id = THREAD GET Option$, Program$ + +Description: +For more advanced control of the running threads, this command provides you with ID a given program named Program$. Option$ can be set as follows: + +Option$ = "TeamID" -- returns the team ID for the program named Program$. Specify the whole path with parameters (only the first 64 characters are important) for the team, the ID of the first team with this path and parameters will be returned. + +Option$ = "ThreadID" -- returns the thread ID for the program named Program$. Specify the program name, the ID of the first thread with this name will be returned. + +Thread get will return -1 when the program was not found. This helps you to find out whether a program e.g. started with the system command is still running or not. + +Note: Using thread get is much better than trying to parse "ps" from the command line. + +Example: +print thread get "teamid", "/boot/home/config/bin/yab" +print thread get "threadid", "yab" +Explanation: + +The first statement prints the team ID number of the first yab program running. The second statement prints the first thread ID of the first yab program running. Note: The team ID takes the whole path while the thread ID only takes the program name. + +Related: thread remove +& +thread remove + +Name: +thread remove -- kill a running thread or team + +Synopsis: +Success = THREAD REMOVE Option$, ID + +Description: +For a given ID this command kills either the team or the thread. Thus Option$ is either "TeamID" or "ThreadID". If the team or thread was killed successfully Success is set to true, otherwise it is set to false. + +Note: You can crash your system with this command! If you do not know what this command is meant for, then do not use it! + +Example: +id = thread get "teamid", "/boot/home/config/bin/yab kamikaze.yab" +print "Commiting suicide..." +success = thread remove "teamid", id +print "This line is never reached." +Explanation: + +Save this example in the file kamikaze.yab and start it from the command line (not from the IDE). It first gets the ID from itself and then kills its own team. Thus the last print command is not executed anymore. This is a very unelegant way to exit. + +Related: thread get +& +time$ + +Name: +time$ -- return a string containing the current time + +Synopsis: +print time$ +print time$() + +Description: +The time$ function returns the current time in four fields separated by hyphens '-'. The fields are:The current hour in the range from 0 to 23, padded with zeroes (e.g. 00 or 04) to a length of two characters. + +The number of minutes, padded with zeroes. +The number of seconds, padded with zeroes. +The number of seconds, that have elapsed since the program has been started. This value encreases as long as your program runs and is therefore unbound and not padded with zeroes. + +At the time of writing this documentation, time$ returns 22-58-53-0. Note, that the first three of the four fields returned by time$ have a fixed width; therefore it is easy to extract some fields with the usual string-functions mid$ (and others). + +Example: +print "Hello it is ",time$ +print "An empty for-loop with ten million iterations takes " +s=val(mid$(time$,10)) +for a=1 to 10000000:next a +e=val(mid$(time$,10)) +print e-s," seconds" +Explanation: + +This program benchmarks the for-loop and uses the fourth field of the string returned by time$. + + +Related: date$ + +& +to + +Name: +to -- this keyword appears as part of other statements + +Synopsis +for a=1 to 100 step 2 + ... +next a +draw line x,y to a,b, View$ + +Description: +The to-keyword serves two purposes (which are not related at all):within for-statements, to specify the upper bound of the loop. +Within any graphical command (e.g. line), that requires two points (i.e. four numbers) as arguments, a comma ',' might be replaced with the keyword to. I.e. instead of 100,100,200,200 you may write 100,100 to 200,200 in such commands. + +Related: for, draw line, view + +& +// + +Name: +// -- starts a comment + +Synopsis: +// This is a comment! + +Description: +The double-slash ('//') is (besides REM and '#') the third way to start a comment. '//' is the latest and greatest in the field of commenting and allows yab to catch up with such cool languages like C++ and Java. + +Example: +// Another comment. +print "Hello world!" // Another comment +Explanation: + +Unlike the example given for '#' this example is syntactically correct and will not produce an error. + + +Related: #, rem + +& +: + +Name: +: -- separate commands from each other + +Synopsis: +print "Hello ":print "World" + +Description: +The colon (':') separates multiple commands on a single line. +The colon and the newline-character have mostly the same effect, only that the latter, well, starts a new line too. The only other difference is their effect within the (so-called) short if, which is an if-statement without the keyword then. Please see the entry for if for more details. + +Example: +if (a<10) print "Hello ":print "World!" +Explanation: + +This example demonstrates the difference between colon and newline as described above. + + +Related: if + +&GUI +&Drawing +& +draw circle + +Name: +draw circle -- draw a circle + +Synopsis: +DRAW CIRCLE x,y, Radius, Target$ + +Description: +This command will draw a circle on Target$. Target$ has to be either a valid view, bitmap or canvas. The center of the circle is (x,y) and the circle has a radius of Radius. + +At default it will draw a filled circle in the current highcolor. With the draw set command you can change the filling settings. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw circle 150,150, 75, "Example" +sleep 7 +window close "Example" +Related: draw curve, draw dot, draw ellipse, draw flush, draw line, draw rect, draw set +& +draw curve + +Name: +draw curve -- draw a Bezier curve with four reference points + +Synopsis: +DRAW CURVE x1,y1, x2,y2, x3,y3, x4,y4, Target$ + +Description: +Bezier curves are defined by a number of points. They will always start in the first point and end in the last one. The curve will always be within the four sides if you connect the points directly. For our command, the curve is defined by four points (x1,y1) ... (x4,y4) and it is drawn on Target$. Target$ has to be either a valid view, bitmap or canvas. + +At default it will draw a filled curve in the current highcolor. With the draw set command you can change the filling settings. Note: A filled curve might have refresh problems due to a bug in the app-server. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw curve 10,150, 75,60, 150,20, 250,140, "Example" +sleep 7 +window close "Example" +Related: draw circle, draw dot, draw ellipse, draw flush, draw line, draw rect, draw set +& +draw dot + +Name: +draw dot -- draw a single dot + +Synopsis: +DRAW DOT x,y, View$ + +Description: +Draw a single dot at (x,y) on Target$. Target$ has to be either a valid view, bitmap or canvas. + +At default the dot is drawn in the current highcolor. + +Example: +window open 100,100 to 400,400, "Example", "Example" +for i = 0 to 300 step 0.5 + draw dot i, sin(i*50)*50+150, "Example" +next i +sleep 7 +window close "Example" +Explanation: + +This program draws a sinus curve with single dots. + +Related: draw circle, draw curve, draw ellipse, draw flush, draw line, draw rect, draw set +& +draw ellipse + +Name: +draw ellipse -- draw an ellipse + +Synopsis: +DRAW ELLIPSE x,y, RadiusX, RadiusY, View$ + +Description: +This command will draw an ellipse on Target$. Target$ has to be either a valid view, bitmap or canvas. The center of the ellipse is (x,y) and the ellipse has a horizontal radius of RadiusX and a vertical radius of RadiusY. + +At default it will draw a filled ellipse in the current highcolor. With the draw set command you can change the filling settings. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw ellipse 150,150, 75, 30, "Example" +sleep 7 +window close "Example" +Explanation: + +Related: draw circle, draw curve, draw dot, draw flush, draw line, draw rect, draw set +& +draw flush + +Name: +draw flush -- clear all prior draw commands + +Synopsis: +DRAW FLUSH View$ + +Description: +Draw flush clears the view named View$ from all drawings. + +In yab, all draw commands are stored in a list for every view. If the window is updated, e.g. when resized, all prior drawing is repeated. If you do a lot of drawing in a view, you might notice the redrawing due to flickering. if you want to clear your view, it is much better to clear it with draw flush than e.g. drawing a big rectangle over the other drawings. For flickerfree drawing consider to draw on a canvas instead of a view. + +Note: This does not work for canvas and bitmaps. + +Note: Widgets are not affected by draw flush. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw line 0,0 to 300,300, "Example" +draw circle 100,50, 20, "Example" +draw rect 10,200 to 200,250, "Example" +sleep 1 +draw flush "Example" +sleep 3 +window close "Example" +Explanation: + +In this example, some things are drawn on the window and then cleared by the draw flush command. + +Related: draw circle, draw curve, draw dot, draw ellipse, draw line, draw rect, draw set +& +draw get + +Name: +draw get -- retrieve font properties + +Synopsis: +Width = DRAW GET FontProperty$, Text$, Target$ +Height = DRAW GET FontProperty$, Target$ + +Description: +The draw get command provides you with some information about the width or height of a string with the current font settings that are used for the draw text command. + +If FontProperty$ is set to "Text-Width", you have to provide a string Text$ too. The resulting Width is the width of Text$ in the current font setting. The width of a string e.g. helps you to align text. Note: Text$ will not be localized automatically, you have to translate it yourself with translate$(Text$). Target$ has to be either a valid view, bitmap or canvas. + +If FontProperty$ is set to "Max-Text-Height" you get the maximum height of the font as return value. The normal font size is the size starting at the baseline. The maximum height gives you the size plus how far the characters can descend below the baseline. + +Example: +window open 100,100 to 400,400, "Example", "Example" +// set font +draw set "Zurich, Roman, 25", "Example" +draw text 50,150, "yab Example", "Example" +// the string length +width = draw get "text-width", "yab Example", "Example" +// baseline +draw set "highcolor", 0,0,255, "Example" +draw line 40,150 to width+60,150, "Example" +// font size +draw set "highcolor", 255,0,255, "Example" +draw line 40,150-25 to width+60,150-25, "Example" +// descend below baseline +maxheight = draw get "max-text-height", "Example" +draw set "highcolor", 255,0,0, "Example" +draw line 40,150-25+maxheight to width+60,150-25+maxheight, "Example" +sleep 7 +window close "Example" +Explanation: + +The example shows the baseline (blue line), the font size (pink line) and the lower boundary (red line) for the given string. The lower boundary is calculated by: baseline - font size + maximum text height. If you respect these distances, you can align text pretty well. + +Related: draw get$, draw set, draw text +& +draw get$ + +Name: +draw get$ -- retrieve information about the installed fonts + +Synopsis: +FontFamilies$ = DRAW GET$ "FontFamily" +FontStyles$ = DRAW GET$ FontFamily$ + +Description: +The draw get$ command reads out the information about all installed fonts and their styles. + +Use the parameter "FontFamily" first to get all font families. For a given font family, get the possible styles with the family name as parameter. + +Use draw set or textedit set to set the font for a draw text or textedit. + +Example: +dim fonts$(1) +dim styles$(1) +window open 100,100 to 400,400, "Example", "Example" +menu "File", "Quit", "Q", "Example" +fontfamilies$ = draw get$ "fontfamily" +numFonts = token(fontfamilies$, fonts$(), "|") +for i = 1 to numFonts + menu "Fonts", fonts$(i), "", "Example" + fontstyles$ = draw get$ fonts$(i) + numStyles = token(fontstyles$, styles$(), "|") + for j = 1 to numStyles + submenu "Fonts", fonts$(i), styles$(j), "", "Example" + next j + submenu set "Fonts", fonts$(i), true, "Example" +next i +while(not instr(message$, "Quit")) +wend +window close "Example" +Explanation: + +This example sets up a whole menu with all fonts installed and their styles. Note: It is up to you to deselect old submenu items in this example whenever a new item is selected. In other words, this simple example allows several font selections, which is probably not what you want. + +Related: draw get, draw set, draw text, textedit set +& +draw image + +Name: +draw image -- load and display an image file + +Synopsis: +LoadError = DRAW IMAGE x,y, ImageFile$, Target$ +LoadError = DRAW IMAGE x1,y1 TO x2,y2, ImageFile$, Target$ + +Description: +The image with the filename ImageFile$ is loaded and put on Target$. Target$ has to be either a valid view, bitmap or canvas. Any image files that are understood by the system can be used. Transparent images are supported, however they might cause problems when printed with the printer command. + +If only one coordinate pair is given, the image will be displayed in its full size where (x,y) is the upper left corner. If the second coordinates are given too, the image will be resized from (x1,y1) to (x2,y2). +If x2 is set to -1, the width is scaled according to the height; +if y2 is set to -1, the height is scaled according to the width; +if x2 and y2 are set to -1, the image is not scaled at all. + +Draw image returns information about the success of the loading procedure: +LoadError = 0, image successfully loaded +LoadError = 1, the file was not found +LoadError = 2, the translator roster was not found, i.e. the system does not understand the image type +LoadError = 3, translation failed, maybe the file is corrupted? +LoadError = 4, detaching the bitmap failed, maybe out of memory? + +Example: +window open 100,100 to 400,400, "Example", "Example" +err = draw image 10,10, "mypicture.png", "Example" +switch(err) + case 1: alert "File not found!", "Ok", "stop" + exit(1) + case 2: alert "Translator not found!", "Ok", "stop" + exit(1) + case 3: alert "Translation failed!", "Ok", "stop" + exit(1) + case 4: alert "Detaching failed!", "Ok", "stop" + exit(1) + default: + break +end switch +sleep 7 +window close "Example" +Explanation: + +The example program will try to load and display the file "mypicture.png" from the current directory. If the load process failed, an error message is produced. + +Related: draw flush +& +draw line + +Name: +draw line -- draw a line + +Synopsis: +DRAW LINE x1,y1 TO x2,y2, Target$ + +Description: +This command draws a line from (x1,y1) to (x2,y2) on Target$ in the current highcolor. Target$ has to be either a valid view, bitmap or canvas. + +Example: +window open 100,100 to 400,400, "Example", "Example" +for i = 0 to 300 step 10 + draw line 0,i to i,300, "Example" + draw line 300,i to i,0, "Example" +next i +sleep 7 +window close "Example" +Explanation: + +Draws some nice lines. + +Related: draw circle, draw curve, draw dot, draw ellipse, draw flush, draw rect, draw set +& +draw rect + +Name: +draw rect -- draw a rectangle + +Synopsis: +DRAW RECT x1,y1 TO x2,y2, Target$ + +Description: +This command will draw a rectangle from (x1,y1) to (x2,y2) on Target$. Target$ has to be either a valid view, bitmap or canvas. + +At default it will draw a filled rectangle in the current highcolor. With the draw set command you can change the filling settings. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw rect 10,10, 290, 290, "Example" +sleep 7 +window close "Example" +Explanation: + +Display a rectangle. + +Related: draw circle, draw curve, draw dot, draw ellipse, draw flush, draw line, draw set +& +draw set + +Name: +draw set -- set various drawing parameters + +Synopsis: +DRAW SET Color$, r,g,b, Target$ +DRAW SET "Alpha", Alpha-Value +DRAW SET IsStroke, Pattern$ +DRAW SET Font$, Target$ + +Description: +Draw set allows you to set various parameters for the other draw commands. + +Draw set with a Color$ allows you to set three different colors: the background color of Target$, the so-called lowcolor and the highcolor. At default, everything is drawn with the current highcolor, the lowcolor is useful for patterns which can have two colors. The background color can only be set for views, otherwise Target$ has to be either a valid view, bitmap or canvas. +If Color$ = "BGColor", the background color of the view Target$ is set, default is grey (216,216,216), +if Color$ = "LowColor", the lowcolor of Target$ is set, default is grey (216,216,216), +if Color$ = "HighColor", the highcolor of Target$ is set, default is black (0,0,0). + +A short note about colors: On BeOS and ZETA, colors are notated with their three component colors red (r), green (g) and blue (b). These component colors are values between 0 (dark) and 255 (light) and mixed together (additive mixture) they represent a 32bit color space. Have a look at the colorcontrol widget to learn more about colors. + +Draw set with "Alpha" as option sets the alpha channel value. At default it is set to 255 which is completly opaque. The smaller the alpha value gets, the more translucent following drawings will become. Note: This only affects the graphic primitives as dot, line, rect, text etc. but not draw image. +Note: When Alpha-Value is below 255, use only HighSolidFill to draw, patterns are ignored! +Note: Transparent drawing (that is Alpha-Value below 255) is not printed (see printer) correctly! + +Draw set can also set the stroke or fill parameter and a pattern. If IsStroke is true, only the outline of circle, ellipse, rectangle and curve are drawn, otherwise they are filled up (which is the default setting). The Pattern$ specifies a pattern that is used for drawing and filling. The following patterns are predefined: +If Pattern$ = "HighSolidFill" solid fill is used with the current high color (default), +if Pattern$ = "LowSolidFill" solid fill is used with the current low color, +if Pattern$ = "CheckeredFill" checkered fill is used as a combination of low- and highcolor, +otherwise Pattern$ is a 8x8 1bit map where one line is one character which is written out as its ASCII code. +Use the pattern editor to draw and calculate patterns for your convenience. + +Draw set with a parameter Font$ sets the font for Target$. The Font$ consists of the font family, the font style and the font size separated with commas. E.g. the following is a valid font string: +Font$ = "Zurich, Roman, 25" +Note: Use the correct spelling of the font families and styles keeping existing spaces; they are case sensitive too. +Three special Font$ are available, namely the system fonts: +If Font$ = "system-plain", the plain system font is used (default), +if Font$ = "system-fixed", the fixed-sized system font is used, +if Font$ = "system-bold", the bold system font is used. +See the command draw get$ for more information about font families and styles. + +Example: +"127191223239215187109214" +Explanation: + +Related: draw circle, draw curve, draw dot, draw ellipse, draw get, draw get$, draw line, draw rect, draw text, view +& +draw text + +Name: +draw text -- draw a text string in the current font + +Synopsis: +DRAW TEXT x,y, Text$, Target$ + +Description: +Draw the string Text$ in the current font and highcolor on Target$. Target$ has to be either a valid view, bitmap or canvas. The left baseline (!) starts at (x,y). Please refer to the example of the command draw get to learn more about the font height and its baseline. + +Note: The text will be anti-aliased (smoothed) with the current lowcolor. If your text looks strange and blocky, you probably should set the lowcolor to the background color. + +Example: +window open 100,100 to 400,400, "Example", "Example" +// set the colors, ajust lowcolor to background color +draw set "bgcolor", 0,0,125, "Example" +draw set "lowcolor", 0,0,125, "Example" +draw set "highcolor", 255,255,0, "Example" +// set the font +draw set "Zurich, Roman, 25", "Example" +// draw the text +draw text 80,150, "yab Example", "Example" +sleep 7 +window close "Example" +Explanation: + +This program sets the colors to a blue background and a yellow textcolor. It sets the font and then displays the string "yab Example". + +Related: draw flush, draw get, draw get$, draw set + +&Input and Messages +& +ismousein() + +Name: +ismousein() -- reports whether the mouse is currently in a view + +Synopsis: +State = ISMOUSEIN(View$) + +Description: +Ismousein reports true whenever it is called and the mouse pointer is currently over the view named View$. This is independend of whether the window containing the view is active or not. + +Example: +window open 100,100 to 300,300, "Example", "Example" +while(not instr(message$, "Quit")) + if(ismousein("Example")) print "Mouse is in window" +wend +window close "Example" +Explanation: +After opening the window named "Example", this program checks if the mouse is currently over the window. Then a message is printed on the console. + + +Related: mouse message$(), mousemove$, mouse set + +& +keyboard message$() + +Name: +keyboard message$() -- check the keyboard for pressed buttons + +Synopsis: +Msg$ = KEYBOARD MESSAGE$(View$) + +Description: +With keyboard message$(), you can receive key strokes. These key strokes are always sent to the view that currently has focus, so you should make sure, that you set the focus for the view named View$. This avoids trouble with textedit or textcontrol widgets that rely on user input too. + +For normal keys, yab simply returns the key, e.g. a, 1 or !. For function keys you will get f1, f2 and so on. Other special keys will return these strings respectively: enter, backspace, del, esc, pageup, pagedown and tab. Modifier keys (e.g. ctrl, alt or shift) by themself can not be detected (however, if you press shift and e.g. a simultaniously, keyboard message$ will return the letter A instead of a of course). + +If you are interested in getting the key strokes in a terminal, have a look at the inkey$ command. Note, other than inkey$, keyboard message$() does not wait for a key to be pressed. It will simply return an empty string ("") when no key is pressed. + +Design: +It is quite hard to use keyboard message$() for a input method that behaves like e.g. a textcontrol because you have to control the key repeat rate yourself. So rather use a textcontrol, spincontrol or a textedit widget for more complex editing. + +Example: +window open 100,100 to 300,300, "Example", "Example" +option set "Example", "Focus", true +while(not instr(message$, "Quit")) + k$ = keyboard message$("Example") + if(k$<>"" and k$<>old_k$) then + print "You pressed "+k$ + old_k$ = k$ + endif +wend +window close "Example" +Explanation: +This simple example first sets the focus on the view that should get the keyboard messages. Whenever a key is pressed, and it is not similar to the pressed key before, we show a text message. + +Related: inkey$, mouse message$(), option set, shortcut +& +message$ + +Name: +message$ -- receive a system message + +Synopsis: +msg$ = MESSAGE$ + +Description: +Message$ is one of the most important commands for graphical user interfaces. It checks the message queue for new messages that might have arrived from open windows or graphical widgets. + +Most of the time the message queue is empty and message$ will return an empty string "". However, when some window or widget is selected or clicked on you probably will receive a message. + +Note, once message$ is called, the queue is emptied. So you receive a message only once! It is therefore a good idea to store the message in a string (e.g. msg$) or in an array (see example below) so you can evaluate it further. + +Messages are separated by the pipe symbol "|". Normally, you only receive one message. However, when there is some time passing between two message calls (e.g. because of a long calculation or a sleep command), several messages might have been coming in. Therefore you should always split the whole message into its message parts with the token() command (split() will do too). Use a loop to go through all messages then. + +The kind of message is related to the window or widget sending the messgae. Check the different widget entries for more information on the type of message they send. + +Currently, there is one general system message that you always should process: +"_QuitRequested" -- this means that your program was asked to quit by another program (e.g. by ProcessController or the system shutdown) + +Example: +// set DEBUG to true to have the messages printed on the console +// set it to false to disable this feature +DEBUG = true + +window open 100,100 to 300,300, "Example", "Example" + +dim msg$(1) +while(not quitting) + // get all messages and split them immediatly + numMessages = token(message$, msg$(), "|") + + // go through all messages + for i = 1 to numMessages + // if DEBUG is set, print the current message + if(DEBUG) print msg$(i) + switch(msg$(i)) + case "_QuitRequested" + case "Example:_QuitRequested" + quitting = true + break + end switch + next i +wend +window close "Example" +Explanation: +This example shows a message loop as it is recommended for most programs. The message$ is split into parts by the token command. Using a switch(), the different messages can be examined. + +Related: message send +& +message send + +Name: +message send -- send a system message + +Synopsis: +Arrived = MESSAGE SEND Application$, Message$ + +Description: +This is an rather advanced command for sending messages to other yab programs. + +The target program should have the signature Application$. The default signature is: "application/x-vnd.yab-app". + +You can change the signature for yab scripts when you add a comment in the first or second line of your program like this: +// mimetype "application/x-vnd.myapp" + +For binaries, change the signature using the external QuickRes program. + +The command returns one of the following error codes: + 0: Message was delivered + 1: The destination program was not found + 2: The target's message queue is full + 3: Time out, the message never made it to the target + 4: An other error occurred + +Message: +The destination yab application will produce a message$ stating: + +&exverbatim +_Scripting:...| +&exverbatim + +(The ... is the Message$.) + +See the files Ping.yab and Pong.yab for a nice example of message send. As you have to start both, use the tracker or the terminal to run them, but not the IDE. + +Related: message$ +& +mouse message$() + +Name: +mouse message$() -- check the mouse for its position and the state of the buttons + +Synopsis: +Mouse$ = MOUSE MESSAGE$(View$) + +Description: +Mouse message$() returns a string containing information of the mouse coordinates (relative to View$) and the state of the mouse buttons. + +The mouse string has the format "X:Y:LMB:MMB:RMB" where MB is the corresponding left, middle, right mousebutton and X and Y are the coordinates relative to the view named View$. Use the token() command to split the string into an array and use val() to get the actual numerical values (see the example below). + +Design: +Using the mouse message$() is not recommended for beginners. Also the advanced programmer should use it not too intensivly, but rather rely on the existing widgets. However, controlling the mouse gives you some means to create some own sort of widgets or some cool mouse-over effects. + +Example: +window open 100,100 to 500,500, "Example", "Example" +x = 100 +y = 100 +draw rect x,y to x+50,y+50, "Example" +text 10,10, "mytext", "Drag the square with the mouse", "Example" +dim mouse$(1) +while(not instr(message$, "Quit")) + GetMouse() + + // the button is pressed and the mouse is over the rectangle, start drag + if(mlmb and mx>=x and mx<=x+50 and my>=y and my<=y+50) then + while(mlmb) + GetMouse() + x = mx-25 + y = my-25 + draw flush "Example" + draw rect x,y to x+50,y+50, "Example" + wend + endif +wend +window close "Example" + +sub GetMouse() + n = token(mouse message$("Example"), mouse$(), ":") + mx = val(mouse$(1)) + my = val(mouse$(2)) + mlmb = val(mouse$(3)) +end sub +Explanation: +This example lets you drag a rectangle with the mouse. It gets the current position and button state in the sub GetMouse(). Now when the left mouse button is pressed and the mouse is over the rectangle, the rectangle will be moved as long as the button is pressed. The redrawing of the rectangle can be improved by checking whether the mouse actually moved. + + +Related: ismousein(), keyboard message$(), mousemove$, mouse set +& +mousemove$ + +Name: +mousemove$ -- returns more detailed mouse messages + +Synopsis: +Mouse$ = MOUSEMOVE$ + +Description: +This command is somewhat a duplicate to mouse message$(). However, it does not require a view to be given, but reports the name of the view back as part of the message Mouse$. The following messages can occur: + +Control$+":_InsideView" +Control$+":_EnteredView" +Control$+":_ExitedView" +Control$+":_MouseDown" +Control$+":_MouseUp" +Control$+":_LeftMouseButton" +Control$+":_RightMouseButton" +Control$+":_MiddleMouseButton" +where Control$ is the ID of the widget or view where the event occured. + +Related: ismousein(), mouse message$(), mouse set +& +MOUSE SET Option$ + +Name: +mouse set -- show or hide the mouse cursor + +Synopsis: +MOUSE SET Option$ + +Description: +Sometimes (e.g. games) the mouse cursor is just in the way. To get rid of it for your application windows, this command allows you to hide it (or later show it again). Use Option$ as described: + +Option$ = "Hide" -- hide the mouse cursor +Option$ = "Show" -- show the mouse cursor +Option$ = "Obscure" -- hide the mouse cursor until the mouse is moved + +Related: ismousein(), mouse message$(), mousemove$ +& +shortcut + +Name: +shortcut -- sends a message when a specified shortcut key is pressed + +Synopsis: + +SHORTCUT View$, Shortcut$, MyMessage$ + +Description: +For adding keyboard shortcuts to your program that are not related to menu entries, use the shortcut command. It sends the message MyMessage$ whenever the key combination Shortcut$ is pressed and the view named View$ has focus. + +The first letter of Shortcut$ specifys the shortcut key for this menu item. It is always combined with the command key which is ALT normally (or CTRL when CTRL and ALT are switched in the preferences). E.g. consider a Shortcut$ of "O" then ALT-O will send MyMessage$ to the message queue. Additionaly to the command key you can specify further modifiers which are set before the shortcut letter: + +&exverbatim +"S" for the shift key +"C" for the control key (CTRL, or ALT if CTRL and ALT are switched) +"O" for the option key (on most keyboards probably the Windows button) +&exverbatim + +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" + +Some Shortcut examples: + +&exverbatim +"O" for ALT-O +"SO" for Shift-ALT-O +"COO" for Control-Option-ALT-O +&exverbatim + +Message: +Shortcut sends MyMessage$. + +Design: +To use shortcuts is good but to use shortcuts in menus is much better. In menus the user can see the shortcut and does not have to memorize it. Furthermore he can select the according action by mouse too. + +Use the default shortcuts as described for the menu command. Note: Other than with menu, the following shortcuts are reserved and cannot be overwritten: + +&exverbatim +ALT-X +ALT-C +ALT-V +ALT-A +ALT-W +ALT-Q +&exverbatim + +Example: +window open 100,100 to 300,200, "Example", "Example" + +draw text 10,20, "Press Alt-B for an about window", "Example" +draw text 10,40, "Press Alt-Shift-Q to quit", "Example" + +shortcut "Example", "B", "About" +shortcut "Example", "SQ", "MyQuit" + +option set "Example", "focus", true + +while(not quitting) + m$ = message$ + if(instr(m$, "About")) alert "An easy shortcut example", "Dooh", "info" + if(instr(m$, "MyQuit")) then + quitting = true + elsif(instr(m$,"Quit")) then + alert "Use the shortcut to quit!", "Ok", "info" + endif +wend + +window close "Example" +Explanation: + +Here two shortcuts are setup, ALT-B (or CTRL-B if ALT and CTRL are switched in your preferences) sends the message "About" and Shift-ALT-Q to send the message "MyQuit". Additionally other quit messages are rejected telling the user to only use the shortcut. + +Related: keyboard message$, menu, message$ +& +&Printing +& +printer + +Name: +printer -- send a view to the printer + +Synopsis: +PrintingError = PRINTER JobName$, SetupFile$, View$ + +Description: +Printer is a powerful but yet simple command to print a view named View$. The view is send to the currently active printer and put into the spooling queue. There, it is visible under the name JobName$. + +SetupFile$ gives a files as saved by the printer setup command. If the setup file is not valid or empty (""), the printing setup is called first automatically. Otherwise the saved setup is used for the printing. + +Printer returns one of the following numbers: +0 = No Problems +1 = Page setup failed (probably communication problems with the print server) +2 = The configuration file was loaded but page setup failed +3 = The view View$ was not found +4 = The number of pages is 0 or less +5 = The printing was canceled or something went wrong with printing + +Note: PrintingError = 4 can happen because of a bug in the PDF printing driver; although a page size is shown, none is selected. If this happens, you may want to call a PRINTER SETUP for the user and try to print again. + +Note: When an error with code 1,2,3 or 4 occurs, you can be shure that nothing was sent to the printer yet. + +Note: Alpha transparency is not printed correctly! + +Note: Due to a bug in BeOS and ZETA, there are probably problems printing CHECKBOX IMAGE and BUTTON IMAGE images, use DRAW IMAGE instead! + +Example: +window open 100,100 to 300,300, "Example", "Example" + +view 10,10 to 190,160, "PrintMe", "Example" +draw set "bgcolor", 255,255,255, "PrintMe" +draw text 50,50, "Print Me!", "PrintMe" + +button 50,170 to 150,190, "PrintButton", "Print...", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "PrintButton")) then + errcode = printer "Example Printjob", "", "PrintMe" + if(errcode>1) alert "Printing Problem: "+str$(errcode), "Ok", "Warning" + endif + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: + +First a window is opened and then a white view named "PrintMe" is put upon it. Of course it makes perfect sence to have a white background for your view that is to be printed. When the "Print..." button is pressed, the PrintMe view is send to the printer with the job name "Example Printjob". In case of an error, the user is informed. + +Related: printer setup +& +printer setup + +Name: +printer setup -- setup the current printer + +Synopsis: +PRINTER SETUP SetupFile$ + +Description: +Printer setup call the setup window of the currently active printer. Here, the user can specify printing parameters like paper size or a border width. The setup is saved in the file called SetupFile$. No file is created when the user cancels the setup. + +Note: At least one window has to be open before printer setup can be called. + +Example: +window open 100,100 to 300,300, "Example", "Example" +menu "File", "Printer Setup...", "", "Example" +menu "File", "--", "", "Example" +menu "File", "Quit", "Q", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "Printer Setup...")) printer setup "ExamplePrinterConfig" + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: +The example shows a window with a menu. When printer setup is selected from this menu, the setup is called. If the user saves the config, it will be stored in the file named "ExamplePrinterConfig". + +Related: printer +&Menus +& +menu + +Name: +menu -- create a menu item for the menubar + +Synopsis: +MENU Head$, Menu$, Shortcut$, View$ + +Description: +To add a menubar with menus to a window or a view named View$ is very easy. Simply call menu with the menu entry Head$ and a menu item called Menu$. If there is no menubar yet, a new one will be created. If the entry Head$ already exists, the item Menu$ will be added to the existing items at the end. + +If Menu$ is set as follows: +&exverbatim +Menu$ = "--" +&exverbatim +then the menu item will be a separator line. + +The first letter of Shortcut$ specifys the shortcut key for this menu item. It is always combined with the command key which is ALT normally (or CTRL when CTRL and ALT are switched in the preferences). E.g. consider a Shortcut$ of "O" then ALT-O will appear in the menu and the user has to press ALT-O to activate this menu item. Additionaly to the command key you can specify further modifiers which are set before the shortcut letter: + +&exverbatim +"S" for the shift key +"C" for the control key (CTRL, or ALT if CTRL and ALT are switched) +"O" for the option key (on most keyboards probably the Windows button) +&exverbatim +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" + +Some Shortcut examples: +&exverbatim +"O" for ALT-O +"SO" for Shift-ALT-O +"COO" for Control-Option-ALT-O +&exverbatim + +The height of the menubar (which depends on the size of the system menu font) can be checked with the peek command. + +Message: +The menu when selected or called by the shortcut key will return a message of the format: + +View$+":"+Head$+":"+Menu$ + +Note, when you have switched on localization, you get the translated message. Have a look at the example below, how to handle such translations. + +Design: +Although views can have a menubar too, you should only give windows a menu. Use capitalized words for English menu entries (like for headings). A menu item should have three dots (...) always when the user can expect a further dialog and not an immediate action. Use the default menu head entries: File, Edit, View, Help + +Use the following default shortcuts: +&exverbatim +For the menu Head$ "File": +"N" -- New +"O" -- Open +"S" -- Save +"W" -- Close +"Q" -- Quit + +For the menu Head$ "Edit": +"Z" -- Undo +"X" -- Cut +"C" -- Copy +"V" -- Paste +"A" -- Select All + +Further default shortcuts: +"F" -- Find +"G" -- Find Again +"H" -- Help +"P" -- Print +&exverbatim + +Example: +localize +window open 100,100 to 400,300, "Example", "Example" +menu "File", "About...", "", "Example" +menu "File", "--", "", "Example" +menu "File", "Quit", "Q", "Example" + +menu "Action", "My Action Menu", "COA", "Example" + +dim msg$(1) +while(not quitting) + n = token(message$, msg$(), "|") + for i = 1 to n + switch(msg$(i)) + case "_QuitRequested" + case "Example:_QuitRequested" + case translate$("Example:File:Quit") + quitting = true + break + case translate$("Example:File:About...") + alert "Menu example", "Ok", "info" + break + case translate$("Example:Action:My Action Menu") + press = press + 1 + draw flush "Example" + draw text 50,100, translate$("Menu call: ")+str$(press), "Example" + break + end switch + next i +wend + +window close "Example" +Explanation: +We open a window and allow localization. This should explain the usage of translating the messages in the loop. After initializing the menus, we check the messages. When a message arrives, we compare it to the translated (!) counterpart. + +Related: menu set, peek, submenu, submenu set +& +menu set + +Name: +menu set -- set options for the menu + +Synopsis: +MENU SET MenuHead$, SetRadioMode, View$ +MENU SET MenuHead$, MenuItem$, Option$, View$ + +Description: +This lets you set some options for the first level menu. + +Given a MenuHead$ you can put the entire menu in radio mode, i.e. only one item can be selected at a time. Set SetRadioMode to true to allow radio mode, set it to false to return to a normal behavior again. Note, you have to select the first item yourself after switching to radio mode. Use the following option to do so. + +Given a MenuHead$ and a MeniItem$ you can disable or enable the item or you can select it by putting a mark to it or remove the mark again. Thus the following options are valid: + +&exverbatim +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +Option$ = "Enable" -- enable a formerly disabled item again +Option$ = "Mark" -- mark this item +Option$ = "Plain" -- remove a mark again +&exverbatim + +Example: +window open 100,100 to 400,300, "Example", "Example" +menu "Test", "Foo", "", "Example" +menu "Test", "Bar", "", "Example" +menu set "Test", "Foo", "mark", "Example" +menu set "Test", "Bar", "disable", "Example" +fooMarked = true + +menu "Radio", "1", "", "Example" +menu "Radio", "2", "", "Example" +menu "Radio", "3", "", "Example" +menu set "Radio", true, "Example" +menu set "Radio", "2", "mark", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "Quit")) quitting = true + if(instr(m$, "Foo")) then + fooMarked = not fooMarked + if(fooMarked) then + menu set "Test", "Foo", "mark", "Example" + else + menu set "Test", "Foo", "plain", "Example" + endif + endif +wend +window close "Example" +Explanation: +The first menu has two items, the first item is selectable. As you see in the message loop you are responsable yourself to apply or remove the mark from this item. The second item is disabled. + +The second menu is in radio mode, so only one item can be selected. The user will do that for you, however you have to select an item for the first time. + +Related: menu, submenu, submenu set +& +popupmenu + +Name: +popupmenu -- open a popup menu + +Synopsis: +Selected$ = POPUPMENU x,y, MenuItems$, View$ + +Description: +This function pops up a menu at the position (x,y) as upper left corner on View$. The menu contains several menu items which are given as MenuItems$. The items are separated by a pipe "|". If a menu item is a double minus, it will be used as a separator. + +Your program will wait until an item is selected from the menu or the user clicks somewhere else. The command will then return either the selected item name or an empty string "" when nothing was selected. + +Note, you cannot add submenus, have a radio mode or select items which is possible for menus in a menubar. + +Similar to the menu, the Selected$ will contain the translation of the selected item when localization is used. Use translate$ where necessary, as explained for the menu command. + +Design: +Remember to give the user a hint so he can expect a popup menu. E.g. add a small down-arrow to a button image, if this button opens a popup menu. + +Example: +window open 100,100 to 300,300, "Example", "Example" +button 10,10 to 100,30, "MyButton", "Popup", "Example" +while(not quitting) + m$ = message$ + if(instr(m$, "Quit")) quitting = true + if(instr(m$, "MyButton")) then + selected$ = popupmenu 10,31, "About...|--|Quit", "Example" + if(selected$ = "About...") alert "Popupmenu example.", "Ok", "Info" + if(selected$ = "Quit") quitting = true + endif +wend +window close "Example" +Explanation: +The example opens a window with a button. Whenever the button is clicked on, a popup menu appears. The selection of the popup menu is then processed immediately. + +Related: dropbox +& +submenu + +Name: +submenu -- create a submenu item for an existing menu + +Synopsis: +SUBMENU MenuHead$, MenuItem$, SubMenuItem$, Shortcut$, View$ + +Description: +To have a submenu to an existing menu, you have to specify the menu title MenuHead$, the menu item that will contain the submenu MenuItem$ and the new name for the submenu entry SubMenuItem$. If MenuHead$ or MenuItem$ do not exist, they are created. Similar to the menu command the submenu item can be called by a shortcut key Shortcut$. This again explained below in detail. + +If SubMenuItem$ is set as follows: +&exverbatim +Menu$ = "--" +&exverbatim +then the submenu item will be a separator line. + +The first letter of Shortcut$ specifys the shortcut key for this submenu item. It is always combined with the command key which is ALT normally (or CTRL when CTRL and ALT are switched in the preferences). E.g. consider a Shortcut$ of "O" then ALT-O will appear in the menu and the user has to press ALT-O to activate this menu item. Additionaly to the command key you can specify further modifiers which are set before the shortcut letter: + +&exverbatim +"S" for the shift key +"C" for the control key (CTRL, or ALT if CTRL and ALT are switched) +"O" for the option key (on most keyboards probably the Windows button) +&exverbatim +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" + +Some Shortcut examples: +&exverbatim +"O" for ALT-O +"SO" for Shift-ALT-O +"COO" for Control-Option-ALT-O +&exverbatim + +Message: +The submenu when selected or called by the shortcut key will return a message of the format: + +View$+":"+Head$+":"+MenuItem$+":"+SubMenuItem$ + +Note, when you have switched on localization, you get the translated message. Have a look at the example below, how to handle such translations. + +Design: +Use submenus sparsely. Even a complex program like the yab IDE contains only one submenu (for the online resources). Most often submenus should only be used for a list of similar items. Use capitalized words for English menu entries (like for headings). A menu item should have three dots (...) always when the user can expect a further dialog and not an immediate action. + +Example: +localize +window open 100,100 to 400,300, "Example", "Example" + +submenu "File", "Alert Types", "Empty Alert...", "", "Example" +submenu "File", "Alert Types", "Info Alert...", "", "Example" +submenu "File", "Alert Types", "Idea Alert...", "", "Example" +submenu "File", "Alert Types", "Warning Alert...", "", "Example" +submenu "File", "Alert Types", "Stop Alert...", "", "Example" + +menu "File", "--", "", "Example" +menu "File", "Quit", "Q", "Example" + +dim msg$(1) +while(not quitting) + n = token(message$, msg$(), "|") + for i = 1 to n + switch(msg$(i)) + case "_QuitRequested" + case "Example:_QuitRequested" + case translate$("Example:File:Quit") + quitting = true + break + case translate$("Example:File:Alert Types:Empty Alert...") + alert "Empty alert.", "Ok", "empty" + break + case translate$("Example:File:Alert Types:Info Alert...") + alert "Info alert.", "Ok", "info" + break + case translate$("Example:File:Alert Types:Idea Alert...") + alert "Idea alert.", "Ok", "idea" + break + case translate$("Example:File:Alert Types:Warning Alert...") + alert "Warning alert.", "Ok", "warning" + break + case translate$("Example:File:Alert Types:Stop Alert...") + alert "Stop alert.", "Ok", "stop" + break + end switch + next i +wend + +window close "Example" +Explanation: +Here the important part is the declaration of the submenu. With the first submenu command the menubar, the menu head named "File" and the menu item named "Alert Types" are created. Because of localization we have to check the submenu message with the translate$() otherwise we would miss them. + +Related: menu, menu set, submenu set +& +submenu set + +Name: +submenu set -- set options for the submenu + +Synopsis: +SUBMENU SET MenuHead$, MenuItem$, SetRadioMode, View$ +SUBMENU SET MenuHead$, MenuItem$, SubMenuItem$, Option$, View$ + +Description: +This lets you set some options for the second level menu. + +Given a MenuHead$ and a MenuItem$ you can put the entire submenu in radio mode, i.e. only one item can be selected at a time. Set SetRadioMode to true to allow radio mode, set it to false to return to a normal behavior again. Note, you have to select the first item yourself after switching to radio mode. Use the following option to do so. + +Given a MenuHead$, a MeniItem$ and a SubMenuItem$ you can disable or enable the item or you can select it by putting a mark to it or remove the mark again. Thus the following options are valid: + +&exverbatim +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +Option$ = "Enable" -- enable a formerly disabled item again +Option$ = "Mark" -- mark this item +Option$ = "Plain" -- remove a mark again +&exverbatim + +Example: +window open 100,100 to 400,300, "Example", "Example" + +submenu "Test", "My Favorite OS", "BeOS", "", "Example" +submenu "Test", "My Favorite OS", "Haiku", "", "Example" +submenu "Test", "My Favorite OS", "ZETA", "", "Example" + +submenu set "Test", "My Favorite OS", true, "Example" +submenu set "Test", "My Favorite OS", "BeOS", "mark", "Example" +submenu set "Test", "My Favorite OS", "ZETA", "disable", "Example" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: +The submenu is in radio mode, so only one item can be selected. The user will do that for you, however you have to select an item for the first time. The last item cannot be selected because it is disabled. + +Related: menu, menu set, submenu +&Views +& +boxview + +Name: +boxview -- a boxview is view with a labeled border + +Synopsis: +BOXVIEW x1,y1 TO x2,y2, ID$, Label$, LineType, View$ + +Description: +This command sets up a view named ID$ with a border and a label. While the boxview is constructed at the coordinates (x1,y1) to (x2,y2) on the view named View$, the own coordinates of a boxview start at (x1+3,y1+12) to (x2-3,y2-3) so that the border can not be overwritten. This is independent of the line type. + +If Label$ is not "", it will be displayed on the upper left corner of the boxview. Otherwise no label is shown. + +There are three possible line types for the border style: + For LineType = 0 the boxview has no border. + For LineType = 1 the boxview has a simple line border. + For LineType = 2 the boxview has a fancy line border. + +Other than commands like stackview, tabview or splitview, you can simply remove a boxview just as a normal view with the view remove command. + +Layout: +The boxview will follow all sides as in standard layout. + +Design: +Use boxviews to group similar entries. Do not use too much boxviews in a window, as this looks too cluttered. + +Example: +window open 100,100 to 300,300, "Example", "Example" +boxview 10,10 to 190,190, "MyBox", "Hello Box", 2, "Example" +sleep 7 +window close "Example" +Explanation: + +The example opens a window and sets up a boxview with the label "Hello Box" and a fancy border style (2). + +Related: view, view remove +& +stackview + +Name: +stackview -- create views above each other + +Synopsis: +STACKVIEW x1,y1 TO x2,y2, ID$, NumberOfViews, View$ + +Description: +Stackview creates several views on top of each other. All views have the same coordinates (x1,y1)-(x2,y2) on the view named View$. NumberOfViews specifies how many views should be created. Obviously it should be greater or equal to 2 to be useful. + +All stacked views get a own ID which is ID$ and the number of the view. E.g. if ID$ = "MyStack" and NumberOfViews = 3, then the stacked views have the IDs "MyStack1", MyStack2" and "MyStack3". Use the command stackview set to switch between these views. + +Layout: +The stackview and all views it contains will follow all sides as in standard layout. + +Design: +You can think of a stackview as a tabview without tabs. Therefore it is up to the programmer to provide a method to switch between the stacked views. + +Stackviews are useful in typical BeOS style option windows (e.g. in the yab IDE). Have a look at the code below for an example. + +Example: +window open 100,100 to 400,300, "Example", "Option Example" + +listbox 10,10 to 100,190, "List", 1, "Example" +listbox add "List", "First Option" +listbox add "List", "Second Option" +listbox add "List", "Third Option" + +stackview 110,10 to 290,190, "Stack", 3, "Example" +draw set "bgcolor", 255,200,200, "Stack1" +draw text 10,10, "This is view \"Stack1\"", "Stack1" +draw set "bgcolor", 200,255,200, "Stack2" +draw text 10,10, "This is view \"Stack2\"", "Stack2" +draw set "bgcolor", 200,200,255, "Stack3" +draw text 10,10, "This is view \"Stack3\"", "Stack3" + +while(not quitting) + msg$ = message$ + if(instr(msg$, "List")) then + n = listbox get "List" + stackview set "Stack", n + elsif(instr(msg$, "Quit")) then + quitting = true + endif +wend + +window close "Example" +Explanation: + +This window has a listbox on the left-hand side and a stackview with three views on the right. Each view has a own background color and text. When an item is selected in the list, we get its number and then switch the stackview to the corresponding view. + +Related: stackview get, stackview set, tabview +& +stackview get + +Name: +stackview get -- get the number of the shown view in a stackview + +Synopsis: +ViewNumber = STACKVIEW GET StackView$ + +Description: +Stackview get will return you the number of the currently shown view. Remember: Numbering starts with 1. + +Related: stackview, stackview set +& +stackview set + +Name: +stackview set -- set the shown view in a stackview + +Synopsis: +STACKVIEW SET StackView$, ViewNumber + +Description: +To switch the views of a stackview, yoy have to use this command. Simply provide it with the ID of the stackview (here: StackView$) and the number of the view you want it to show. Remember: The first view on the stack has the number 1. If you provide an invalid number, nothing will happen. + +Related: stackview, stackview get +&Widgets +& +button + +Name: +button -- create a new button + +Synopsis: +BUTTON x1,y1 TO x2,y2, ID$, Label$, View$ + +Description: +The button command creates a button from the coordinates (x1,y1) to (x2,y2) on the window or view named View$. It has a text label Label$ and the identifier ID$. + +With the option set command you can modify the button, as setting the background color, the focus, enabling or diabling it or resizing it to its preferred size. + +Message: +The button when pressed will send a message string with ID$. + +Layout: +In standard layout, the button will follow the lower, right corner of the view or window. + +Design: +Always use meaningful labels for buttons. If you care for localization (on ZETA you should!), remember that labels can be much longer in other languages. So either provide enough space or use the option set command to auto-resize the button. + +Example: +window open 100,100 to 300,200, "Example", "Example" +button 20,40 to 180,60, "MyButton", "Hello World", "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyButton|") alert "You pressed the button", "Ok", "info" + if(instr(m$, "_QuitRequested")) quitting = true +wend +window close "Example" +Explanation: + +In this example, a button is set on the window. If the button is pressed, an alert window pops up. + +Related: button image, option set +& +button image + +Name: +button image -- create a new button with images + +Synopsis: +BUTTON IMAGE x,y, ID$, EnabledPressed$, EnabledNormal$, Disabled$, View$ + +Description: +This command lets you create a button with images named ID$ on the view View$. The position (x,y) is the upper left corner of the images and the size of the first image (EnabledPressed$) is taken. + +You have to provide at least two image files: +EnabledPressed$ -- the image file name of the pressed button +EnabledNormal$ -- the image file name of the released button +The images can be of any format that BeOS or ZETA can translate. + +If you want to disable the button, you should provide the additional image file: +Disabled$ -- the image file name of the disabled button +You can put in an empty string "" if you don't need a disabled button. + +Just be aware that image files with relative path might be not found when you start your program as a script from tracker. + +Message: +The button when pressed will send a message string with ID$. + +Layout: +In standard layout, the button will follow the lower, right corner of the view or window. + +Design: +Be creative but do not use offensive images. For icons, try to use BeOS-like icons always. Ask in the community if you need assistence in creating new icons. + +Example: +window open 100,100 to 300,200, "Example", "Example" +button image 10,10, "MyIconButton", "icon_pressed.png", "icon_released", "icon_disabled", "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyIconButton|") alert "You pressed the button", "Ok", "info" + if(instr(m$, "_QuitRequested")) quitting = true +wend +window close "Example" +Explanation: + +The button is only shown correctly, when the images "icon_pressed.png" and "icon_released" exist. + +Related: button +& +calendar + +Name: +calendar -- create a new calendar + +Synopsis: +CALENDAR x,y, ID$, Format$, SetDate$, View$ + +Description: +Calendar is a nifty widget that gives you a date textcontrol with a dropdown calendar window. It is created at (x,y) as upper left corner on the view View$. With the default font size, it always has a width of 80 pixels and a height of 20 pixels. + +You have to provide a date format Format$ which must be either "DDMMYYYY" for day, month, year or "MMDDYYYY" for month, day, year. Futhermore, you have to add a divider to the Format$ which can be either ".", "/" or "-". Thus, the default Format$ looks like this: "DDMMYYYY." + +The SetDate$ should give the starting date in the format you have chosen. Default is the current day, when SetDate$ = "". Note: this SetDate$ has a different format than the yab command date$. However, it is not too difficult to convert these formats. + +The calendar can be disabled or enabled with the option set command. + +Layout: +In standard layout, the calendar will follow the lower, right corner of the view or window. + +Example: +window open 100,100 to 300,200, "Example", "Example" +calendar 10,10, "MyCalendar", "MMDDYYYY/", "04.06.1975", "Example" +while(not quitting) + if(instr(message$, "_QuitRequested")) then + alert "You selected: "+calendar get$ "MyCalendar", "Duh", "info" + quitting = true + endif +wend +window close "Example" +Explanation: + +In this example, a calendar is set on the window with an American date format, month, day, year and the / as separator. When the window is closed, an alert window shows the selected date with calendar get$. + +Related: calendar get$, calendar set, date$, option set +& +calendar get$ + +Name: +calendar get$ -- returns the selected date of a calendar + +Synopsis: +GetDate$ = CALENDAR GET$ Calendar$ + +Description: +The command will return the currently selected date of the calendar widget named Calendar$. Note: the calendar does not send any messages, so use this command to read out a calendar. + +Note: This GetDate$ has a different format than the yab command date$. However, it is not too difficult to convert these formats. + +Related: calendar, calendar set, date$ +& +calendar set + +Name: +calendar set -- sets the date for a calendar + +Synopsis: +CALENDAR SET Calendar$, SetDate$ + +Description: +This lets you set the date of the calendar named Calendar$. Note: SetDate$ has to use the format, that is defined for the calendar. + +Note: this SetDate$ has a different format than the yab command date$. However, it is not too difficult to convert these formats. + +Related: calendar, calendar get$, date$ +& +checkbox + +Name: +checkbox -- create a new checkbox + +Synopsis: +CHECKBOX x,y, ID$, Label$, IsSelected, View$ + +Description: +Set up a checkbox named ID$ at the position (x,y). It will display the label Label$ next to the box. If IsSelected is set to true, the checkbox will be selected. + +You can use option set to disable the checkbox or to change the label. + +Message: +The checkbox when selected will send a message string with ID$+":ON", and when deselected with the message string ID$+":OFF". + +Layout: +In standard layout, the checkbox will follow the lower, right corner of the view or window. + +Design: +Try to align checkboxes below each other. Also put them in groups (e.g. in a boxview) when you have many checkboxes. + +Example: +window open 100,100 to 400,200, "Example", "Example" +checkbox 10,10, "MyCheckBox", "Select this checkbox", false, "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyCheckBox:OFF|") alert "The checkbox is deselected", "Ok", "info" + if(m$ = "MyCheckBox:ON|") alert "The checkbox is selected", "Ok", "info" + if(instr(m$, "Quit")) quitting = true +wend +window close "Example" +Explanation: + +Whenever the checkbox is selected or deselected, an alert window will tell you. + +Related: checkbox image, checkbox set, option set +& +checkbox image + +Name: +checkbox image -- create a new checkbox with images + +Synopsis: +CHECKBOX IMAGE x,y, ID$, EnabledOn$, EnabledOff$, DisabledOn$, DisabledOff$, IsSelected, View$ + +Description: +This command lets you create a checkbox with images named ID$ on the view View$. The position (x,y) is the upper left corner of the images and the size of the first image (EnabledOn$) is taken. If IsSelected is set to true, the checkbox will be selected. + +You have to provide at least two image files: +EnabledOn$ -- the image file name of the selected checkbox +EnabledOff$ -- the image file name of the deselected checkbox +The images can be of any format that BeOS or ZETA can translate. + +If you want to disable the checkbox, you should provide the additional image files: +DisabledOn$ -- the image file name of the disabled selected checkbox +DisabledOff$ -- the image file name of the disabled deselected checkbox +You can put in an empty string "" if you don't need a disabled checkbox. + +Just be aware that image files with relative path might be not found when you start your program as a script from tracker. + +You can use option set to disable the checkbox. + +Message: +The checkbox when selected will send a message string with ID$+":ON", and when deselected with the message string ID$+":OFF". + +Layout: +In standard layout, the checkbox will follow the lower, right corner of the view or window. + +Design: +Be creative but do not use offensive images. For icons, try to use BeOS-like icons always. Ask in the community if you need assistence in creating new icons. + +Example: +window open 100,100 to 400,200, "Example", "Example" +checkbox 10,10, "MyCheckBox", "enabled_icon_on.png", "enabled_icon_off.png", + "disabled_icon_on.png", "disabled_icon_off.png", false, "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyCheckBox:OFF|") alert "The checkbox is deselected", "Ok", "info" + if(m$ = "MyCheckBox:ON|") alert "The checkbox is selected", "Ok", "info" + if(instr(m$, "Quit")) quitting = true +wend +window close "Example" +Explanation: + +Whenever the checkbox is selected or deselected, an alert window will tell you. The checknox is only shown correctly, when the images exist. + +Related: checkbox, checkbox set, option set +& +checkbox set + +Name: +checkbox set -- (de-)select the checkbox + +Synopsis: +CHECKBOX SET CheckBox$, IsSelected + +Description: +If IsSelected is set to true, the checkbox named CheckBox$ will be selected. If IsSelected is set to false, the checkbox will be deselected. + +Related: checkbox, checkbox image +& +colorcontrol + +Name: +colorcontrol -- create a new control for choosing a color + +Synopsis: +COLORCONTROL x,y, ID$, View$ + +Description: +Colorcontrol gives you a basic color selection tool in only one command. The colorcontrol named ID$ has its upper left corner at the position (x,y) of the view View$. It always has a width of 276 pixels and a height of 54 pixels. + +Note: The colorcontrol will look differently on 8 bit displays than on displays with 16 or more bit. However, this should not concern you, the system will take care of that. On BeOS, the colorcontrol will have an additional deactivated selection for alpha channel selection. This is not functional, so again, do not care. + +The colorcontrol does not send any message, you have to check with colorcontrol get what the user selected. + +You can use option set to disable the colorcontrol. Use colorcontrol set, to set a color. + +Layout: +In standard layout, the colorcontrol will follow the lower, right corner of the view or window. + +Design: +Always give feedback to the user, how the color looks like, he is currently selecting. The example below shows how to do that. + +Example: +window open 100,100 to 426,176, "Example", "Example" +view 10,10 to 40,66, "Color", "Example" +colorcontrol 50,10, "MyColorControl", "Example" + +// set color to white +colorcontrol set "MyColorControl", 255,255,255 + +while(not quitting) + if(instr(message$, "Quit")) quitting = true + r = colorcontrol get "MyColorControl", "red" + g = colorcontrol get "MyColorControl", "green" + b = colorcontrol get "MyColorControl", "blue" + + // check if the color was changed + if(r<>old_r or g<>old_g or b<>old_b) then + old_r = r: old_g = g: old_b = b + draw set "bgcolor", r,g,b, "Color" + endif +wend +window close "Example" +Explanation: + +The example shows a colorcontrol and view. The view always takes the color that is selected by the user. Note: The color is only set, when the selection changed. This avoids flickering on slow machines. + +Related: colorcontrol get, colorcontrol set, option set +& +colorcontrol get + +Name: +colorcontrol get -- return a color component of the currently selected color in a colorcontrol + +Synopsis: +Value = COLORCONTROL GET ColorControl$, ColorComponent$ + +Description: +Returns the current selected color component of the colorcontrol ColorControl$. Value is always between 0 and 255, where lower values represent darker colors and higher values represent lighter colors. + +ColorComponent$ has to be one of the following: +"Red" -- the value of the red color +"Green" -- the value of the green color +"Blue" -- the value of the blue color + +Related: colorcontrol, colorcontrol set +& +colorcontrol set + +Name: +colorcontrol set -- set the color in a colorcontrol + +Synopsis: +COLORCONTROL SET ColorControl$, r,g,b + +Description: +Sets the color in the colorcontrol ColorControl$ to its RGB values r, g and b. Read the part on the draw set command to learn more about RGB color space in yab. + +Related: colorcontrol, colorcontrol get +& +columnbox + +Name: +columnbox -- create a list widget with columns + +Synopsis: +COLUMNBOX x1,y1 TO x2,y2, ID$, HasHScrollbar, Option$, View$ + +Description: +The columnbox ist created at (x1,y1) to (x2,y2) on the target view named View$. It gets an own ID i.e. ID$. If it should have a horizontal scrollbar, set HasHScrollbar to true otherwise set it to false. Note: a columnbox always has a vertical scrollbar. + +There are several options regarding the behaviour of the columns. These options affect all columns: +"movable" -- the columns can be dragged +"resizable" -- the columns can be resized +"popup" -- clicking on the columns with the right mouse button brings up a popup menu with all column names +"removable" -- the columns can be removed + +An addtional options is "no-border" which draws the columnbox without a borderline. + +Several options can be combined, e.g. "movable, resizable, no-border". Note: If "removable" is allowed, you should allow "popup" too, so that removed columns can be brought back again. + +After setting up a columnbox you have to add columns with the columnbox column command before adding items. + +Note: A columnbox cannot be sorted. + +Message: +The columnbox provides two messages. The first kicks in when a row is selected by clicking once on it or by the up and down keys. This then has the format ID$+":_Select:"+SelectedRow$ where SelectedRow$ contains the number of the row selected. The second message is send, when a row is invoked, i.e. by double-clicking at a row or pressing the Enter key. It has the format ID$+":_Invoke:"+SelectedRow$. + +Layout: +The columbox will follow all sides as in standard layout. + +Design: +To use a columnbox is almost always a good idea. It helps to present a lot of data in an organized way. Additionally it allows bitmaps and icons as list entries and it is the most customizable list widget in yab. + +Example: +window open 100,100 to 400,500, "Example", "Example" + +columnbox 10,10 to 290,390, "MyColumnbox", true, "movable, resizable, popup, removable", "Example" + +columnbox column "MyColumnbox", " ", 1, 20, 20, 20, "align-center" +columnbox column "MyColumnbox", "Name", 2, 140, 60, 80, "align-right" +columnbox column "MyColumnbox", "Address", 3, 250, 60, 180, "align-left" +columnbox column "MyColumnbox", "Age", 4, 250, 60, 50, "align-center" + +columnbox add "MyColumnbox", 1, 1, 18, "__Mime__=application/x-person" +columnbox add "MyColumnbox", 2, 1, 18, "John" +columnbox add "MyColumnbox", 3, 1, 18, "Cape Town" +columnbox add "MyColumnbox", 4, 1, 18, "30" + +columnbox add "MyColumnbox", 1, 2, 18, "__Mime__=application/x-person" +columnbox add "MyColumnbox", 2, 2, 18, "Mary" +columnbox add "MyColumnbox", 3, 2, 18, "Omaruru" +columnbox add "MyColumnbox", 4, 2, 18, "27" + +columnbox color "MyColumnbox", "text", 0,0,200 +columnbox color "MyColumnbox", "selection", 200,200,255 +columnbox color "MyColumnbox", "row-divider", 255,255,255 + +columnbox select "MyColumnbox", 2 + +while(not quitting) + m$ = message$ + if(instr(m$, "_Select")) then + currentRow = columnbox get "MyColumnbox" + print columnbox get$ "MyColumnbox", 2, currentRow + endif + if(instr(m$, "_Invoke")) then + currentRow = columnbox get "MyColumnbox" + currentItem$ = columnbox get$ "MyColumnbox", 2, currentRow + alert "You selected "+currentItem$, "Ok", "info" + endif + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: + +In this example, first a columnbox is created. It has a horizontal scrollbar. Due to the options, the columns can be moved by clicking and dragging on the column title, they can be removed by dragging a title out of the columnbox, the columns can be resized by dragging the mouse at the border of the column titles and by right clicking on the column title a popup window appears. + +Next the column are defined with columnbox column. All four columns have a title and a column number. Ideally this number starts at one and it increases with every column. Furthermore we specify the width of the column and its maximum and minimum width. This is important when the columnbox allows the "resizable" option. + +Several items are inserted into the columnbox with the columnbox add command. Here the column number has to be given and the row number too. The row height is set by the first columnbox add command for a row and here it is set to 18 because we use icons with a 16 pixel height. We obtain the icon from the mimetype of the type "application/x-person" which is given by the system. + +Several colors are set to personalize our columnbox a bit and the second row is selected with the columnbox select command. + +In the message loop we check for the "_Select" and the "_Invoke" messages of the columnbox. When a row is selected, e.g. by clicking on it once, we first obtain the row where the click happened with columnbox get (this can also be obtain from the message itself using the right$ and val commands). Then the item string itself is retrieved with the columnbox get$ command. + +Related: columnbox add, columnbox clear, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox add + +Name: +columnbox add -- add an item to a columnbox + +Synopsis: +COLUMNBOX ADD ColumnBox$, Column, Row, Height, Item$ + +Description: +To add an item named Item$ to a columnbox named ColumnBox$, you have to specify the column and the row where the item should be located in the columnbox table. An existing item will be overwritten. If Row is larger than the number of rows in the columnbox, a new row is created. Furthermore, you have to specify the height of the row in pixels, a normal value should be Height = 14 or Height = 16 for text items. + +To have images or icons as items, you have to specify that with special identifiers in Item$: +If Item$ = "__Icon__="+FileName$ then the image file FileName$ will be shown, +if Item$ = "__Path__="+FileName$ then the large Trackericon of the file FileName$ will be shown +if Item$ = "__Mime__="+Signature$ then the small icon of the mime type Signature$ will be shown. + +Note: These identifiers are case sensitive! + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox clear + +Name: +columnbox clear -- deletes everything in a columnbox + +Synopsis: +COLUMNBOX CLEAR ColumnBox$ + +Description: +Use columnbox clear to remove all rows and items in the columnbox named ColumnBox$. + +Related: columnbox, columnbox add, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox color + +Name: +columnbox color -- change the colors of a columnbox + +Synopsis: +COLUMNBOX COLOR ColumnBox$, Option$, r,g,b + +Description: +The colors in a columnbox can be changed easily. This distinguishes the columnbox from other list widgets like listbox, dropbox or treebox. Given an option string Option$ the colors can be set to the RGB value (r,g,b). Read the part on the draw set command to learn more about RGB color space in yab. + +The following values for Option$ are valid: +"selection-text" -- set the color of the text in the selected row +"non-focus-selection" -- set the color of the selection when the columnbox is not focussed +"selection" -- set the color for the selected row +"text" -- set the general text color +"row-divider" -- set the color of the line between the rows +"background" -- set the background color + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox column + +Name: +columnbox column -- add a new column to a columnbox + +Synopsis: +COLUMNBOX COLUMN ColumnBox$, Name$, ColumnNumber, MaxWidth, MinWidth, Width, Option$ + +Description: +This command takes quite a number of parameters. Here ColumnBox$ is the columnbox where the column should be added. Name$ is the string that shows up in the title of the column. + +ColumnNumber gives the position relative to the other columns. Ideally ColumnNumber starts at 1 for the first column and with every new column it is incremented by 1. The column gets the width Width (thus the next column will start at Position+Width). MaxWidth and MinWidth declare the boundaries for the column when resizing was specified in the construction of the columnbox. + +Finally the alignment of all items in the column has to be defined in Option$. Possible values are "align-left" for left alignment, "align-center" for center alignment and "align-right" for right alignment. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox count + +Name: +columnbox count -- returns the number of rows in a columnbox + +Synopsis: +NumberOfRows = COLUMNBOX COUNT ColumnBox$ + +Description: +For a existing columnbox named ColumnBox$, this command simply returns the number of rows it contains and stores it in NumberOfRows. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox get + +Name: +columnbox get -- returns the number of the currently selected row in a columnbox + +Synopsis: +ItemNumber = COLUMNBOX GET ColumnBox$ + +Description: +To obtain the row that is currently selected in the columnbox named ColumnBox$, simply use this command. If no row is selected, ItemNumber will be set to 0. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get$, columnbox remove, columnbox select +& +columnbox get$ + +Name: +columnbox get$ -- get a specific item in a columnbox + +Synopsis: +Item$ = COLUMNBOX GET$ ColumnBox$, Column, Row + +Description: +In the given columnbox named ColumnBox$, the item text at the position (Column, Row) will be stored in Item$. For icons and images, this will return the identifier and the file path. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox remove, columnbox select +& +columnbox remove + +Name: +columnbox remove -- delete a line in a columnbox + +Synopsis: +COLUMNBOX REMOVE ColumnBox$, Row + +Description: +In the given columnbox named ColumnBox$, the specified row is deleted. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox select +& +columnbox select + +Name: +columnbox select -- select a row in a columnbox + +Synopsis: +COLUMNBOX SELECT ColumnBox$, Row + +Description: +In the given columnbox named ColumnBox$, the specified row is selected. If Row is set to 0, any former selection is revoked. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove +& +listbox + +Name: +listbox -- create a list widget + +Synopsis: +LISTBOX x1,y1 TO x2,y2, ID$, ScrollbarType, View$ + +Description: +The listbox provides a list widget that can be filled with text items. It is set up at the position (x1,y1) to (x2,y2) on the view named View$. It gets an own identifier ID$. Additionally you have to specify whether the listbox should get scrollbars. This is given by ScrollbarType as follows: + +ScrollbarType = 0 -- no scrollbar +ScrollbarType = 1 -- the listbox has a vertical scrollbar +ScrollbarType = 2 -- the listbox has a horizontal scrollbar +ScrollbarType = 3 -- the listbox has a vertical and a horizontal scrollbar + +Message: +The listbox provides two messages. The first kicks in when an item is selected by clicking once on it or by the up and down keys. This then has the format ID$+":_Select:"+SelectedItem$ where SelectedItem$ contains the number of the item selected. The second message is send, when a item is invoked, i.e. by double-clicking at a item or pressing the Enter key. It has the format ID$+":_Invoke:"+SelectedItem$. + +Layout: +The listbox will follow all sides as in standard layout. + +Design: +The listbox is an easy method to present a lot of data well-structured in a list. Use it instead of a dropbox when you have enough space or the list of data gets too long. For having icons or images in a list, use the columnbox instead. + +Example: +window open 100,100 to 400,400, "Example", "Example" + +listbox 10,10 to 290,260, "MyList", 1, "Example" +button 10,270 to 290,290, "MyButton", "Sort List", "Example" + +listbox add "MyList", "Apple" +listbox add "MyList", "8088" +listbox add "MyList", "80286" +listbox add "MyList", "ZX81" +listbox add "MyList", 1, "BeOS" + +listbox select "MyList", 2 + +while(not quitting) + m$ = message$ + if(instr(m$, "MyButton")) then + listbox sort "MyList" + endif + if(instr(m$, "_Select")) then + currentItem = listbox get "MyList" + print listbox get$ "MyList", currentItem + endif + if(instr(m$, "_Invoke")) then + currentItem = listbox get "MyList" + item$ = listbox get$ "MyList", currentItem + alert "You selected "+item$, "Ok", "info" + endif + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: + +This program opens a window with a listbox named "MyList" and a button named "MyButton". Several items are added, note the order of the items. The last item is put into the first position of the list. Then the second item is selected, this will generate a message which will be processed immendiatly. You can see the name of the selected item on the console output. When the sort button is pressed, the list is sorted. When double clicking on an item, an alert window pops up showing the selected item. + +Related: listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox add + +Name: +listbox add -- add an item to a listbox + +Synopsis: +LISTBOX ADD ListBox$, Item$ +LISTBOX ADD ListBox$, Position, Item$ + +Description: +This command adds a string here named Item$ to the listbox with the ID ListBox$. If Position is given too, the item will be inserted at that position. + +Have a look at the listbox command for an example. + +Related: listbox, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox clear + +Name: +listbox clear -- remove all items of a listbox + +Synopsis: +LISTBOX CLEAR ListBox$ + +Description: +Listbox clear deletes and removes all items in a listbox. + +Related: listbox, listbox add, listbox count, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox count + +Name: +listbox count -- returns the number of items in a listbox + +Synopsis: +NumberOfItems = LISTBOX COUNT ListBox$ + +Description: +For an existing listbox named ListBox$, this command simply returns the number of items it contains and stores it in NumberOfItems. + +Related: listbox, listbox add, listbox clear, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox get + +Name: +listbox get -- returns the number of the currently selected item in a listbox + +Synopsis: +ItemNumber = LISTBOX GET ListBox$ + +Description: +To obtain the item that is currently selected in the listbox named ListBox$, simply use this command. If no item is selected, ItemNumber will be set to 0. + +Have a look at the listbox command for an example. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get$, listbox remove, listbox select, listbox sort +& +listbox get$ + +Name: +listbox get$ -- get a specific item string in a listbox + +Synopsis: +Item$ = LISTBOX GET$ ListBox$, Position + +Description: +In the given listbox named ListBox$, the item text at the position Position will be stored in Item$. + +Have a look at the listbox command for an example. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox remove, listbox select, listbox sort +& +listbox remove + +Name: +listbox remove -- delete a line in a listbox + +Synopsis: +LISTBOX REMOVE ListBox$, Position + +Description: +In the given listbox named ListBox$, the specified item at the position Position is deleted. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox select, listbox sort +& +listbox select + +Name: +listbox select -- select an item in a listbox + +Synopsis: +LISTBOX SELECT ListBox$, Position + +Description: +In the given listbox named ListBox$, the specified item at the position Position is selected. If Position is set to 0, any former selection is revoked. + +Have a look at the listbox command for an example. + +Message: +Using the listbox select command will generate a selection message. This then has the format ID$+":_Select:"+SelectedItem$ where SelectedItem$ contains the number of the item selected. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox sort +& +listbox sort + +Name: +listbox sort -- sort all items in a listbox + +Synopsis: +LISTBOX SORT ListBox$ + +Description: +This command sorts the given listbox named ListBox$ alphabetically. Items starting with a number will be set before items starting with a letter. However, please note that items containing numbers will NOT be sorted as numbers. E.g. The items "1", "2", "10" will be sorted according to the ASCII codes and the length of the strings, thus they are sorted to: "1", "10", "2" + +Note: After sorting, any former selection is removed. + +Have a look at the listbox command for an example. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox select +& +radiobutton + +Name: +radiobutton -- create a new radiobutton + +Synopsis: +RADIOBUTTON x,y, ID$, Label$, IsActivated, View$ + +Description: +Set up a radiobutton named ID$ at the position (x,y). It will display the label Label$ next to the button. If IsActivated is set to true, the radiobutton will be selected. All radiobuttons on one view will act as a group. Thus on a view only one radiobutton will be active. + +Note: On setup it is up to you to preselect a radiobutton. You can even make more than one radiobutton active but this is hardly useful. When the user selects a radiobutton, all others will be deselected automatically. + +You can use option set to disable the radiobutton or to change the label. + +Message: +The radiobutton when selected will send a message string with its ID$. + +Layout: +In standard layout, the radiobutton will follow the lower, right corner of the view or window. + +Design: +Try to align radiobuttons below each other. + +Example: +window open 100,100 to 200,200, "Example", "Music" +radiobutton 10,10, "Radio1", "Classic", true, "Example" +radiobutton 10,30, "Radio2", "Jazz", false, "Example" +radiobutton 10,50, "Radio3", "Pop", false, "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "_QuitRequested")) then + quitting = true + elsif(instr(m$, "Radio")) then + n$ = mid$(m$,instr(m$, "Radio")+5,1) + alert "You selected the "+n$+". radiobutton", "Ok", "info" + endif +wend + +window close "Example" +Explanation: + +Here we have a window with three radiobuttons. Because they are all on one view (the window view) they act as a group. When selected, the number of the radiobutton ID will be extracted with mid$ and stored in n$. It is then shown in an alert window. + +Related: radiobutton set, option set +& +radiobutton set + +Name: +radiobutton set -- (de-)activate the radiobutton + +Synopsis: +RADIOBUTTON SET RadioButton$, IsActivated + +Description: +If IsActivated is set to true, the radiobutton named RadioButton$ will be selected. If IsActivated is set to false, the radiobutton will be deselected. Note: This allows you to activate more than one radiobutton in a group which is not recommended. + +Related: radiobutton +& +statusbar + +Name: +statusbar -- create a progress or status bar + +Synopsis: +STATUSBAR x1, y1 TO x2, y2, ID$, LeftLabel$, RightLabel$, View$ + +Description: +Use the statusbar to visualize the progress of a long computation process, e.g. installation or search. The statusbar is simply set up with the identifier ID$ at (x1,y1) to (x2,y2) on the view named View$. It takes two labels, LeftLabel$ is shown on the left side above of the statusbar and RightLabel$ is shown on the right side above of the statusbar. + +Layout: +The statusbar will follow the lower right corner of a window in standard layout. + +Design: +The statusbar should give the user an idea how long a specific process takes. This of course is only useful for processes that take some time. Also having a statusbar that stays for one minute at 5% and then immediatly jumps to 100% should be avoided although this sometimes is not in control of the programmer. + +Example: +window open 100,100 to 300,150, "Example", "Example" +statusbar 10,10 to 190,40, "MyStatus", "Start", "End", "Example" + +while(not instr(message$, "Quit") and i<100) + i = i + 2 + statusbar set "MyStatus", "Start", "End", i + sleep 0.05 +wend + +window close "Example" +Explanation: + +The statusbar is put on top of the example window with the two labels "Start" and "End". Using the statusbar set command, the statusbar is updated regularly to the new calculated value i which is between 0 and 100. + +Related: statusbar set +& +statusbar set + +Name: +statusbar -- set the value for a status bar + +Synopsis: +STATUSBAR SET Statusbar$, LeftLabel$, RightLabel$, State + +Description: +Use statusbar set to actually set the bar to a specific value. This value named State here is a number between 0 and 100. Thus, 0 is the empty statusbar while 100 is the full statusbar. During your update, you can change the labels at the left and right (LeftLabel$ and RightLabel$). + +Have a look at the statusbar command for an example. + +Related: statusbar +& +text + +Name: +text -- create a text label + +Synopsis: +TEXT x,y, ID$, Text$, View$ +TEXT x1,y1 TO x2,y2, ID$, Text$, View$ + +Description: +The text command sets up a text label Text$ at the position (x,y) or (x1,y1) of the view named View$. Providing second coordinates (x2,y2) is useful for the alignment of the text, see text set for details. The text label has an ID$ which is needed for text set or for changing the text itself with option set. + +So how does this compare to the draw text command? +A text cannot be flushed and it will never flicker. +A text can be aligned. +The label of a text can change. +On a canvas only draw text can be used. +The font and color can only be changed for draw text. + +Note: (x,y) is the upper left corner, this is different to draw text, where y is the baseline of the text. + +Design: +Text should be used for labels on a view. Use the alignment to make clean interfaces. + +Example: +window open 100,100 to 200,150, "Example", "Example" +text 10,10, "Text", "Hello World", "Example" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +A simple yab program, just a window and a text label. + +Related: draw text, option set, text set +& +text set + +Name: +text set -- set the alignment of a text widget + +Synopsis: +TEXT SET Text$, Alignment$ + +Description: +For a text label named Text$ you can change the alignment so that it is aligned to the left, center or right. This only works when you have used the text command with the (x2,y2) parameters because the alignment refers to x1 for left alignment und x2 for right alignment. + +The alignment is given as: +Alignment$ = "Align-Left" -- align to the left +Alignment$ = "Align-Center" -- align to the center +Alignment$ = "Align-Right" -- align to the right + +Example: +window open 100,100 to 300,200, "Example", "Example" +text 10,40 to 190,60, "Text", "Hello", "Example" +align = 1 + +while(not instr(message$, "Quit")) + switch align + case 1: + text set "Text", "Align-Left" + break + case 2: + text set "Text", "Align-Center" + break + case 3: + text set "Text", "Align-Right" + break + end switch + if align = 3 dir = -1 + if align = 1 dir = 1 + align = align + dir + sleep 0.5 +wend + +window close "Example" +Explanation: + +This fun program changes the alignment of the text every half second. + +Related: text +& +textedit + +Name: +textedit -- create a multiline text editor + +Synopsis: +TEXTEDIT x1,y1 TO x2,y2, ID$, ScrollbarType, View$ + +Description: + +Layout: + +Design: + +Example: +Explanation: + +Related: textcontrol, textedit add, textedit clear, textedit color, textedit get, textedit get$, textedit set +& +textedit add + +Name: +textedit add -- add text to a textedit + +Synopsis: +TEXTEDIT ADD TextEdit$, Text$ + +Description: + +Related: textedit, textedit clear, textedit color, textedit get, textedit get$, textedit set +& +textedit clear + +Name: +textedit clear -- delete all text of a textedit + +Synopsis: +TEXTEDIT CLEAR TextEdit$ + +Description: +This command removes all text within a textedit named TextEdit$. This also works when the textedit is not editable by the user. + +Related: textedit, textedit add, textedit color, textedit get, textedit get$, textedit set +& +textedit color + +Name: +textedit color -- set the colors of a textedit or provide syntax highlighting + +Synopsis: +TEXTEDIT COLOR TextEdit$, Option$, r,g,b +TEXTEDIT COLOR TextEdit$, Option$, Command$ + +Description: + +Related: textedit, textedit add, textedit clear, textedit get, textedit get$, textedit set +& +textedit get + +Name: +textedit get -- retrieve various information from a textedit + +Synopsis: +LineNumber = TEXTEDIT GET TextEdit$, Option$ +LineNumber = TEXTEDIT GET TextEdit$, Option$, Search$ +Result = TEXTEDIT GET TextEdit$, Option$, LineNumber + +Description: + +Related: textedit, textedit add, textedit clear, textedit color, textedit get$, textedit set +& +textedit get$ + +Name: +textedit get$ -- retrieve text from a textedit + +Synopsis: +EnteredText$ = TEXTEDIT GET$ TextEdit$ +TextLine$ = TEXTEDIT GET$ TextEdit$, LineNumber + +Description: + +Related: textedit, textedit add, textedit clear, textedit color, textedit get, textedit set +& +textedit set + +Name: +textedit set -- set various options for a textedit + +Synopsis: +TEXTEDIT SET TextEdit$, Option$ +TEXTEDIT SET TextEdit$, Option$, Value +TEXTEDIT SET TextEdit$, Option$, Value$ + +Description: +Textedit set allows you to apply standard editing operations, cut, copy, paste, clear, select-all, undo. It allows you set various options for the textedit, e.g. wordwrap, editable, autoindent. And it handles the autocompletion. Let us have a look in detail: + +Given only two parameters, the following options are valid for the textedit named TextEdit$: +Option$ = "cut" -- cut out the selected text and put it into the clipboard +Option$ = "clear" -- cut out the selected text but do not put it into the clipboard +Option$ = "copy" -- copy the selected text to the clipboard +Option$ = "paste" -- paste the content of the clipboard at the cursors position +Option$ = "select-all" -- select the whole text +Option$ = "undo" -- undo the last operation, note: undo remembers only one operation + +Given three parameters, the following options are valid for the textedit named TextEdit$ when the third parameter Value is either true or false: +Option$ = "autoindent" -- turn auto indent on or off, default is off (false) +Option$ = "changed" -- mark the textedit as changed or unchanged, default is false +Option$ = "color-case-sensitive" -- should the syntax highlighting be case-sensitive? default is false +Option$ = "editable" -- allow the user to edit the textedit, default is true +Option$ = "has-autocompletion" -- turn auto-completion on or off, default is on (true) +Option$ = "wordwrap" -- turn on/off word wrap at the end of a line, default is on (true) + +Some remarks: +Making a textedit not editable is useful when you want to show long text (or scrollable text). +The textedit will notice when text was changed since the last time the option "changed" was set to false. So when you saved the content of the textedit, remember to set back the "changed" option to false again. Then you know when the text should be saved again. + +Given three parameters, the following options are valid for the textedit named TextEdit$ when the third parameter Value is a number: +Option$ = "autocomplete-start" -- set the number of characters when auto-completion should kick in (default is 4) +Option$ = "gotoline" -- put the cursor to the line with number Value +Option$ = "select" -- select the line with number Value +Option$ = "tabwidth" -- set the tab width to Value (in pixel!), default is 28 +Option$ = "textwidth" -- set the maximum width of the text in pixel + +Given three parameters, the following options are valid for the textedit named TextEdit$ when the third parameter Value$ is a string: +Option$ = "font" -- set the font to Value$ (see draw set for details), default is "system-plain" +Option$ = "autocomplete" -- add the word Value$ to the auto-completion list + +Related: textedit, textedit add, textedit clear, textedit color, textedit get, textedit get$ +& +tooltip + +Name: +tooltip -- add a tooltip to a view or widget + +Synopsis: +TOOLTIP View$, Text$ + +Description: +A tooltip is a small popup that appears when the mouse moves over a widget to give some more information. + +To have a tooltip to any sort of view or widget named View$, simply add the tooltip string Text$. Text$ should be only one line without linebreaks. If Text$ is set to the empty string "", the tooltip is removed again from View$. + +Note: The tooltips look and behave slightly different on BeOS and ZETA. + +Design: +Tooltips can be of great help for the user to understand icons or buttons and the like. However, it does not make sence to add a tooltip "New" to a button that already has the label "New". Rather be more descriptive and provide additional information, e.g. "Open a new image file". For tooltips only the first word should be written with a capital letter. + +And remember, too many tooltips can be annoying too. + +Example: +window open 100,100 to 300,300, "Example", "Example" + +button 10,10 to 190,30, "Button", "We all...", "Example" +listbox 10,40 to 95,190, "List", 1, "Example" +listbox add "List", "...have own..." +slider 120,40 to 190,190, "Slider", "...tooltips.", 1,10, "triangle, vertical", "Example" + +tooltip "Example", "A tooltip for the whole window" +tooltip "Button", "A tooltip for the button" +tooltip "List", "A tooltip for the listbox" +tooltip "Slider", "A tooltip for the slider" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +The example shows how easily a tooltip can be applied to any kind of widget. Here, to the button, the listbox, the slider and the window view itself too. + +Related: tooltip color +& +tooltip color + +Name: +tooltip color -- set the color for all tooltips + +Synopsis: +TOOLTIP COLOR Option$, r,g,b + +Description: +To change the textcolor or the background color of all your tooltips, use this command. Given the option "bgcolor" or "textcolor" either the background color or the text color of the tooltips will be changed to the RGB color (r,g,b). Read the part on the draw set command to learn more about RGB color space in yab. + +Note: This command only works with the BeOS yab. The colors for the ZETA tooltips are set generally in the ZETA preferences and thus cannot be changed for a single app. So on ZETA with the ZETA yab interpreter this command simply does nothing. + +Example: +window open 100,100 to 300,140, "Example", "Example" + +button 10,10 to 190,30, "Button", "I have a tooltip", "Example" + +tooltip color "bgcolor", 0,0,0 +tooltip color "textcolor", 255,255,255 + +tooltip "Button", "A black and white tooltip for the button on BeOS" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +Here, the color of the tooltips are changed from the default yellow background and black text color to a black background (RGB color values: 0,0,0) and from the default black text color to a white text (RGB color values: 255,255,255). + +Related: tooltip +& +&Localization +& +localize + +Name: +localize -- enable the automatic localization of ZETA + +Synopsis: +LOCALIZE +LOCALIZE Filename$ + +Description: +Not everyone speaks English thus having multiple language support improves the usability of your program. yab provides a very simple language interface with the localize command. Use it once to turn automatic localization on. Now all strings in GUI widgets will be translated automatically if there is a dictionary entry for them. All you have to do, is to make a dictionary for your program. + +Dictionaries for stand-alone programs are normally put into the subdirectory Language/Dictionaries of your program. But if a filename Filename$ is given, the (absolute) path of this filename is used as dictionary directory. Note: As long as the yab program is not compiled with the build factory, you should specify the path. + +In the dictionary directory there should be files named like the programs name or like file name in Filename$. The files have a language code as ending. The language code consists of a two letter code for the language and a capitalized two letter code of the country. For a sample program named foobar.yab, some example dictionaries: foobar.deDE (language German (de) and country Germany (DE)), foorbar.enUS (language English (en) and country United States (US)), foobar.nlBE (language Dutch (nl) and country Belgium (BE)). + +The dictionary contains the English term in paranthesis ("") some spaces as separator and the translated text in the target language in paranthesis too. Example: +&exverbatim +# A comment starts with a # +# English German +"File" "Datei" +"Quit" "Beenden" +"This is a sentence." "Dies ist ein Satz." +&exverbatim + +This all looks complicated, but the reader is encouraged to have a look at the localization of the yab IDE and other tools to understand localization completly. + +Note: Menus and dropboxes return messages that contain a string that might be translated. Use the translate$() function to handle these. + +Note: The strings are case sensitive! + +Note: Currently localization is only supported on ZETA. However, supporting the localization of your program is a good idea for BeOS users too because localization support might be added soon to BeOS yab. + +Design: +It is good design to support localization. + +Example: +// this examples works with the example localization file above +// name it "foobar.deDE" in your home directory +localize "/boot/home/foobar" +window open 100,100 to 200,200, "Win", "Foobar" +menu "File", "Quit", "Q", "Win" +draw text 10,50, "This is a sentence.", "Win" + +while(not quitting) + msg$ = message$ + if(instr(msg$, "Quit") or instr(msg$, translate$("Quit"))) quitting = true +wend + +window close "Win" +Explanation: +This shows automatic translation of the menu strings "File" and "Quit" and the draw text string. Change the language settings to German in your ZETA preferences. Note: The menu strings are also translated when you do not provide the translation file because ZETA comes with some translations for typical strings used in applications. + +Further, we have to check the translation of the message$ too with translate$ because the menu now reports the message string "Datei:Beenden|" when selected in German. + +Related: translate$() +& +translate$() + +Name: +translate$() -- translate a string on ZETA + +Synopsis: +Translation$ = TRANSLATE$(Source$) + +Description: +The counterpart to the localize command is translate$(). It translates the string Source$ according to known dictionaries (see localize for more information about dictionaries) into the language currently set as default in ZETA. + +Note: Currently localization is only supported on ZETA. However, supporting the localization of your program is a good idea for BeOS users too because localization support might be added soon to BeOS yab. + +Example: +print translate$("File") +Explanation: +Using only the system dictionaries, we can obtain the translation of "File" according to the language set in the ZETA preferences. + +Related: localize +& +&Sound +& +beep + +Name: +beep -- ring the bell within your computer; a synonym for bell + +Synopsis: +beep + +Description: +The beep-command rings the bell once. beep is a synonym for bell. + +Example: +beep:print "This is a problem ..." +Related: bell +& +bell + +Name: +bell -- ring the bell within your computer (just as beep) + +Synopsis: +bell + +Description: +The bell-command rings the bell within your computer once. This command is not a sound-interface, so you can neither vary the length or the height of the sound. bell is exactly the same as beep. + +Example: +print "This is a problem ...":bell +Related: beep +& +sound play + +Name: +sound play -- play a sound file + +Synopsis: +Id = SOUND PLAY Filename$ + +Description: +To play a sound file named Filename$ which can be of any supported format (e.g. WAV, MP3, etc.) sound play will return a number Id. Use Id to have basic control with the two other sound commands: sound wait and sound stop. + +If the file could not load, Id will be set to -1. + +Design: +In a GUI context use sound wisely. Remember that not everyone can hear the sound, e.g. because sound is turned off, not supported or the user is deaf or hard-of-hearing. Thus, do not put important information for your application in speech files only. Additionally, remember that bells and whistles on each mouse click can become very annoying. + +Example: +id = sound play "bach.mp3" +while(1) +wend +Explanation: + +This loads the file "bach.mp3" and then waits forever (use Ctrl-C or Break to end the program). + +Related: sound stop, sound wait +& +sound stop + +Name: +sound stop -- stop playing a sound file + +Synopsis: +SOUND STOP Id +SOUND STOP(Id) + +Description: +Stop a sound that is playing with the valid identification number Id. + +Example: +id = sound play "bach.mp3" +sleep 3 +sound stop id +Explanation: + +This first loads the file "bach.mp3", plays it for three seconds and then stops it. + +Related: sound play, sound wait +& +sound wait + +Name: +sound wait -- waits until a sound file is finished playing + +Synopsis: +SOUND WAIT Id +SOUND WAIT(Id) + +Description: +After the a sound file named Id started playing, use this command to wait until the file finished playing. + +Example: +id = sound play "bach.mp3" +sound wait id +Explanation: + +This first loads the file "bach.mp3" and then plays it until it ends. + +Related: sound play, sound stop +& +&Window +& +alert + +Name: +alert -- show an alert window + +Synopsis: +ALERT Text$, ButtonLabel$, Type$ +Selected = ALERT Text$, Button1$, Button2$, Button3$, Type$ + +Description: +By simply calling alert, you can always display an alert window. + +It always has a message Text$ and it can either have one, two or three buttons. + +For the second syntax, the alert window will return the number of pressed button, where Button1$ is the label of the most left button and Button3$ is the label or the most right one. If you specify Button2$ or Button3$ as empty string (""), the according button is not shown. + +Type$ specifies the icon displayed on the left side of the alert window. It has to be one of the following strings: +"None" for no icon +"Info" for the information icon +"Idea" for the light bulb icon +"Warning" for the yellow exclamation mark +"Stop" for the red exclamation mark + +Design: +Use a warning icon to warn the user that something might go wrong (e.g. ask whether to save before quitting) and the stop icon to inform the user that something already went wrong (e.g. saving failed). + +For the dialog box, always use complete sentences, while for the buttons use understandable labels. Capitalize the buttons in English. + +Note: the right button always has the focus in the multi-button alert. Do not put a dangerous action on this button. E.g. for a dialog "Your data will be lost!", do not put the "Proceed" button on the right position, but rather the "Cancel" button. + +Example: +alert "Warning! All your base are belong to us.", "Ok", "warning" +selected = alert "Choose a button", "Left", "Middle", "Right", "info" +print "You selected button number: ", selected +Explanation: + +In the last line, the number of the selected button will be printed on screen. + +Related: window open +& +filepanel + +Name: +filepanel -- open a file or directory selection window + +Synopsis: +Filename$ = FILEPANEL Mode$, Title$, Directory$ +Filename$ = FILEPANEL Mode$, Title$, Directory$, DefaultFile$ + +Description: +In BeOS there is a default window for selecting files or directories to load or save. This so-called filepanel is easily accessable with the filepanel command in yab. The filepanel will open the selection window for you, it lets the user browse, select etc. in the directory tree and returns the selected or newly entered filename. Note: The filepanel just gives you the filename, it does not open, save or process this filename in any way; you have to do that on your own of course. + +First have a look at the parameters. Filename$ will contain the resulting path and name of the selected or newly created directory or filename. If the filepanel is canceled, the Filename$ will be empty (""). + +There are different modes Mode$ for a filepanel. Depending on the mode it will act differently: + +Mode$ = "Load-File" -- the user is able to select any file +Mode$ = "Load-Directory" -- the user is able to select any directory +Mode$ = "Load-File-and-Directory" -- the user is able to select any file or directory +Mode$ = "Save-File" -- the user is able to select either an existing file or enter a name for a new file; when selecting an existing file a popup window will ask whether the file should really be overwritten + +Furthermore, the title for the window tab has to specified in Title$. Ideally this should be something like "Open" or "Save" according to the mode. + +The starting directory for browsing is set with Directory$. If this is an invalid directory, "/boot/home" will be used instead. + +Only for the "Save-File" mode, you additionally can provide a default filename that is put into the textcontrol field of the filepanel in this mode. If you call the filepanel without DefaultFile$, the textcontrol field will be empty. + +Design: +Having filepanels for the file selection is always a good idea. They are much easier to handle than self constructed columnboxes for browsing directories. To use them is just the BeOS way of doing things. + +Example: +window open 100,100 to 300,200, "Example", "Example" +button 10,10 to 190,30, "OpenFile", "Open a file...", "Example" +button 10,40 to 190,60, "OpenDir", "Open a directory...", "Example" +button 10,70 to 190,90, "Save", "Save a file...", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "OpenFile")) filename$ = filepanel "load-file", "Open File", "" + if(instr(m$, "OpenDir")) filename$ = filepanel "load-directory", "Open Directory", "" + if(instr(m$, "Save")) filename$ = filepanel "save-file", "Save File", "", "SuggestedFile" + + if(instr(m$, "Quit")) quitting = true + + if(filename$ <> "") then + alert "You haven chosen "+filename$, "Ok", "info" + filename$ = "" + endif +wend + +window close "Example" +Explanation: + +The example above opens a window with three buttons. According to the button the filepanel is started in a different mode. Try to understand the difference in the behaviour of the three modes above. Finally, when a valid file or directory is chosen, an alert popup window opens to display the full path of that selected entry. + +& +window open + +Name: +window open -- open a window + +Synopsis: +WINDOW OPEN x1,y1 TO x2,y2, ID$, Title$ + +Description: +The window open command is a very basic and very important command for most yab programs. As it name says, a window is opened on the current desktop. The coordinates (x1,y1) to (x2,y2) of the window are related to the screen coordinates of the current desktop; thus (0,0) is the upper left corner of the screen. The window gets a title named Title$ which is displayed in the tab of the window. Title$ is allowed to be empty ("") aswell. Additionally, the window gets an own ID named ID$. You can use it like any other view and draw on it or put widgets on it. However, you cannot delete it with the view remove command, use window close instead. + +Message: +A window will send several messages to the message queue: +ID$+":_QuitRequested" -- the close button was pressed or the window received any other message to close itself +ID$+":_Activated" -- the window was activated +ID$+":_Deactivated" -- the window was deactivated + +If your application gets the general message "_QuitRequested" it is asked to close down completly. This is more general than the window "_QuitRequested" above which only should shut down the window itself. + +Design: +Use capitalized words for the title tab in English as in headings (but not in German!). Your window should always act as expected when the close button is pressed. Have a look at the window set command to learn about different look and feel parameters for your window. + +When your window has quite a lot of widgets and drawings on startup to do, it might look quite ugly with lots of flickering. To avoid this, simply construct the window with negative coordinates (e.g. window open -400,-400 to -100,-100, "Example", "Example"). Then move it to its real position on the workspace with the "MoveTo" option of the window set command when the setup is done. + +Example: +window open 100,100 to 300,300, "Example", "Example" +button 10,90 to 190,110, "Button", "My First Window", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "Example:_QuitRequested")) then + alert "You pressed the window close button", "Ok", "info" + quitting = true + elsif(instr(m$, "_QuitRequested")) then + alert "The application should now shut down", "Ok", "info" + quitting = true + elsif(instr(m$, "Button")) then + alert "The button was pressed", "Ok", "info" + endif +wend + +window close "Example" +Explanation: +A simple window with a button. Try to close it with the close button and then try to shut it down with the Alt-Q shortcut key. This shows how the different "_QuitRequested" messages should be handled. + +Related: +alert, window close, window count, window get, window set +& +window close + +Name: +window close -- close a window + +Synopsis: +WINDOW CLOSE WindowID$ + +Description: +Window close of course closes the window named WindowID$. All widgets and views in the window will be deleted. Their IDs and the window ID will no longer be valid, if you call them, yab will exit with an error message. + +Design: +It is good style to close all windows before exiting. Always keep track of the windows currently open. + +Related: +window open, window count, window get, window set +& +window count + +Name: +window count -- return the number of open windows + +Synopsis: +n = WINDOW COUNT + +Description: +To get the number n of currently open windows of your application, simply invoke window count. + +Example: +for i=1 to 10 + window open 10+i*10, 10+i*10 to 200+i*10, 200+i*10, "Win"+str$(i), "Win" + sleep 0.5 +next i + +n = window count + +while(n>0) + window close "Win"+str$(n) + n = window count + sleep 0.5 +wend +Explanation: + +This funky program first opens ten windows and then closes them using the window count to obtain the number ID of the last opened window. + +Related: +window open, window close, window get, window set +& +window get + +Name: +window get -- request information about a window + +Synopsis: +Result = WINDOW GET WindowID$, Option$ + +Description: +To obtain some properties of the window with the ID WindowID$, the following options are allowed: + +Option$ = "Position-X" -- Result will contain the horizontal position of the upper left corner of the window relative to the screen +Option$ = "Position-Y" -- Result will contain the vertical position of the upper left corner of the window relative to the screen +Option$ = "Width" -- Result will contain the width of the window +Option$ = "Height" -- Result will contain the height of the window +Option$ = "Minimum-Width" -- Result will contain the minimum width of the window that is allowed when resizing +Option$ = "Minimum-Height" -- Result will contain the minimum height of the window that is allowed when resizing +Option$ = "Maximum-Width" -- Result will contain the maximum width of the window that is allowed when resizing +Option$ = "Maximum-Height" -- Result will contain the maximum height of the window that is allowed when resizing +Option$ = "Exists" -- Result will be true if a window with this WindowID$ exits and false otherwise + +Example: +window open 100,100 to 300,300, "Example", "Example" + +w = 200 +h = 200 + +while(not instr(message$, "Quit")) + if(window get "Example", "Width" <> w) then + w = window get "Example", "Width" + print "New Width: ", w + endif + if(window get "Example", "Height" <> h) then + h = window get "Example", "Height" + print "New Height: ", h + endif +wend + +window close "Example" +Explanation: + +When the window is resized, the new width and the new height are printed on the standard output. + +Related: +window open, window close, window count, window set +& +window set + +Name: +window set -- set the properties of a window + +Synopsis: +WINDOW SET WindowID$, Option$ +WINDOW SET WindowID$, Option$, x,y +WINDOW SET WindowID$, Option$, Value$ + +Description: +This command allows the flexible ajustment of the look and feel of a window. We first inspect the options that require no further parameter other than Option$: + +Option$ = "Activate" -- activate the window, so it is in the foreground. +Option$ = "Deactivate" -- deactivate the window, so it is in the background. +Option$ = "Minimize" -- minimize the window, or restore the window if it is already minimized. +Option$ = "Maximize" -- maximize (zoom) the window. +Option$ = "Enable-Updates" -- updates the window again after a "Disable-Updates". +Option$ = "Disable-Updates" -- disables the automatic window updates. + +To disable updates is normally not needed, this just means that after this command no drawing even from widgets will be shown. + +Given two additional parameters x and y, the following options are valid: + +Option$ = "ResizeTo" -- resize the window to (x,y) relative screen coordinates +Option$ = "MoveTo" -- move the window to (x,y) relative screen coordinates +Option$ = "MinimumTo" -- when resizing, the minimum width and height is given by (x,y) +Option$ = "MaximumTo" -- when resizing, the maximum width and height is given by (x,y) + +Given an additional parameter Value$, the following options are valid: + +Option$ = "Look" -- this changes the appearance of the window accroding to the following values: +Value$ = "Document" -- large title bar, thick border, draggable resize box +Value$ = "Titled" -- same as the document window, but with a less substantial resize corner, default +Value$ = "Floating" -- small title bar, thin border, resize corner +Value$ = "Modal" -- no title bar, thick border, no resize control +Value$ = "Bordered" -- no title bar, line border, no resize control +Value$ = "No-Border" -- a borderless white rectangle + +Option$ = "Feel" -- this sets the behaviour of the window in relation to other windows +Value$ = "Normal" -- behaves like a normal window (non-modal, non-floating), default +Value$ = "Modal-App" -- the window blocks all other windows of this application +Value$ = "Modal-All" -- the window blocks all other windows on the system, the window is visible on all workspaces +Value$ = "Floating-App" -- the window floats on top of all other windows of this application +Value$ = "Floating-All" -- the window floats on top of all other windows on the system, the window is visible on all workspaces + +Option$ = "Flags" -- this sets special properties of a window, flags can be used accumulative, simply write all wanted flags in the Value$ +Value$ = "Not-Closable" -- the window does not have the close button in the tab +Value$ = "Not-Zoomable" -- the window does not have the zoom button in the tab +Value$ = "Not-Minimizable" -- the window cannot be minimized +Value$ = "Not-H-Resizable" -- the window cannot be resized horizontally +Value$ = "Not-V-Resizable" -- the window cannot be resized vertically +Value$ = "Not-Resizable" -- the window cannot be resized +Value$ = "Accept-First-Click" -- when the window is inactive it still accepts the first click +Value$ = "Reset" -- reset all flags back to none + +Option$ = "Workspace" -- sets where the window is shown: +Value$ = "All" -- the window is shown on all workspaces +Value$ = "Current" -- the window is shown on the current workspace, default + +Option$ = "Title" -- set the window title to Value$ + +Design: +Look: +For most application the default "Titled" look will be sufficient. However, heavy apps with big windows, e.g. the IDE, should have the "Document" look. Use "Floating" for toolboxes and other options that stay around, as done e.g. in Refraction. "Modal" is meant to be used for alert windows that block the main application. "Bordered" and "No-Border" are for more creative applications like games and eye candy stuff. + +Feel: +Always try to avoid windows with a "Modal-All" feel because they block the whole system. + +Resizable: +Try to set appropriate minimum and maximum width and height parameters so your application always looks good. + +Example: +window open 100,100 to 300,300, "Example", "Example" +window set "Example", "MinimumTo", 150,150 +window set "Example", "Look", "Floating" +window set "Example", "Feel", "Floating-All" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +A small demo window is opened with the floating look and feel. It can only be resized to a width and height of (150,150). + +Related: +window open, window close, window count, window get +& diff --git a/yab-IDE/data/Help_En_Index.dat b/yab-IDE/data/Help_En_Index.dat new file mode 100644 index 0000000..01989f5 --- /dev/null +++ b/yab-IDE/data/Help_En_Index.dat @@ -0,0 +1,620 @@ +&Arithmetic +7337 +& +7339 +abs() +7345 +acos() +7712 +and() +8211 +asin() +9001 +atan() +9510 +bin$() +10409 +cos() +11015 +dec() +11280 +eor() +11799 +euler +12576 +exp() +12982 +frac() +13604 +int() +14285 +log() +14685 +max() +15344 +min() +16136 +mod() +16551 +or() +17264 +pi +18057 +ran() +18513 +sig() +19356 +sin() +20000 +sqr() +20525 +sqrt() +20896 +tan() +21248 +xor() +21611 +** or ^ +22644 +& +23461 +and +23465 +break +23915 +case +24610 +continue +25107 +default +25776 +do +26896 +else +27440 +elsif +27979 +end +29449 +endif +30141 +false +30787 +fi +31354 +for +31668 +gosub +32630 +goto +33500 +if +34350 +label +36136 +loop +37125 +next +37612 +not +38171 +on gosub +38823 +on goto +40158 +on interrupt +41582 +logical or +42868 +pause +43271 +repeat +44499 +return +45186 +sleep +46885 +step +47260 +switch +47800 +then +49116 +true +49924 +until +50360 +wait +50967 +wend +51341 +while +51839 +: +52495 +& +53132 +arraydim() +53143 +arraysize() +54033 +data +56606 +dim +57558 +read +59075 +redim +59718 +restore +60157 +& +61226 +asc() +61232 +chr$() +62055 +glob() +62917 +abc matches a* +63878 + +64066 +hex$() +64075 +instr() +64565 +left$() +65579 +len() +66880 +lower$() +67254 +ltrim$() +67662 +rtrim$() +68314 +mid$() +68962 +right$() +70230 +split() +71549 +Please enter a line: a +74186 + +74680 +str$() +74706 +string | Result for converting 1000*pi | Description +76112 + +79509 +token() +79811 +Please enter a line: a +82334 + +82732 +trim$() +82759 +upper$() +83372 +val() +84020 +& +84734 +at() +84739 +clear screen +86030 +close +86746 +color +87217 +colour +88331 +eof +88478 +getscreen$() +89069 +inkey$ +90217 +input +91436 +Please enter the name of a file to read: test.yab +92830 + +92967 +line input +93002 +open +93844 +print +96665 +putscreen +99902 +reverse +100797 +screen +101576 +seek() +101806 +tell +103368 +using +104029 +# +105070 +at() +106443 +; +107722 +& +108368 +end sub +108376 +export +108808 +import foo +109855 + +110153 +Calling subroutine foo.bar (okay) ... +110254 + +110568 +import +111103 +rem Make the subroutine x easily available outside this library +112034 + +112210 +0 +112259 + +112417 +local +112702 +numparams +114162 +return +115613 +static +117315 +1 1 +118117 + +118140 +sub +118335 +& +120614 +bind() +120621 +clipboard copy +121393 +clipboard paste$ +122095 +compile +122717 +date$ +123273 +doc +124998 +docu$ +126153 +error +126975 +---Error in t.yab, line 2: Oh no ... +127618 + +127674 +execute$() +127688 +print foo$(a$,b$) +128723 + +128736 +execute() +128776 +exit +129181 +iscomputeron +129575 +pause +129963 +peek +131190 +peek$ +136253 +3a +139214 + +139235 +poke +139270 +rem +140508 +sleep +141622 +system$() +141981 +system() +142570 +thread get +143193 +thread remove +144542 +time$ +145465 +to +146634 +// +147188 +: +147692 +&Drawing +148325 +& +148327 +draw circle +148339 +draw curve +148998 +draw dot +149983 +draw ellipse +150564 +draw flush +151303 +draw get +152433 +draw get$ +154379 +draw image +155792 +draw line +157698 +draw rect +158270 +draw set +158926 +draw text +162295 +& +163465 +ismousein() +163477 +keyboard message$() +164199 +message$ +166088 +message send +168421 +_Scripting:...| +169326 + +169339 +mouse message$() +169566 +mousemove$ +171590 +MOUSE SET Option$ +172254 +shortcut +172760 +"S" for the shift key +173560 + +173712 +"O" for ALT-O +173862 + +173927 +ALT-X +174351 + +174394 +&Printing +175345 +& +175347 +printer +175355 +printer setup +177728 +& +178752 +menu +178757 +Menu$ = "--" +179225 +then the menu item will be a separator line. +179282 +"S" for the shift key +179755 +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" +180004 +"O" for ALT-O +180055 + +180120 +For the menu Head$ "File": +180918 + +181168 +menu set +182260 +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +183063 + +183212 +popupmenu +184323 +submenu +185971 +Menu$ = "--" +186555 +then the submenu item will be a separator line. +186615 +"S" for the shift key +187091 +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" +187340 +"O" for ALT-O +187391 + +187456 +submenu set +190342 +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +191218 + +191367 +& +192114 +boxview +192122 +stackview +193545 +stackview get +195659 +stackview set +195950 +& +196407 +button +196414 +button image +197729 +calendar +199470 +calendar get$ +201137 +calendar set +201630 +checkbox +202055 +checkbox image +203312 +checkbox set +205539 +colorcontrol +205838 +colorcontrol get +207860 +colorcontrol set +208468 +columnbox +208804 +columnbox add +214014 +columnbox clear +215195 +columnbox color +215563 +columnbox column +216608 +columnbox count +217767 +columnbox get +218205 +columnbox get$ +218740 +columnbox remove +219283 +columnbox select +219640 +listbox +220095 +listbox add +223060 +listbox clear +223538 +listbox count +223833 +listbox get +224229 +listbox get$ +224716 +listbox remove +225134 +listbox select +225473 +listbox sort +226118 +radiobutton +226830 +radiobutton set +228564 +statusbar +228970 +statusbar set +230439 +text +230937 +text set +232125 +textedit +233243 +textedit add +233536 +textedit clear +233748 +textedit color +234090 +textedit get +234392 +textedit get$ +234747 +textedit set +235021 +tooltip +237966 +tooltip color +239646 +&Localization +240934 +& +240936 +localize +240945 +# A comment starts with a # +242509 + +242633 +translate$() +244199 +&Sound +244952 +& +244954 +beep +244959 +bell +245193 +sound play +245556 +sound stop +246481 +sound wait +246855 +&Window +247260 +& +247262 +alert +247268 +filepanel +249046 +window open +252336 +window close +255051 +window count +255543 +window get +256170 +window set +257891 diff --git a/yab-IDE/data/SyntaxTree.dat b/yab-IDE/data/SyntaxTree.dat new file mode 100644 index 0000000..5a6d031 --- /dev/null +++ b/yab-IDE/data/SyntaxTree.dat @@ -0,0 +1,7889 @@ +& This is the data file for the help syntax of the yab-IDE 2.0 +& DO NOT CHANGE ANYTHING IN THIS FILE (unless you do a reindexing!) +& +& Comments start at the beginning of the line with a & +& +& Here the top level starts with the keyword: +& toplevel +Arithmetic +Conditions and Loops +Data Processing +Input and Output +Graphical User Interface +&Localization +Sound +String Handling +Subroutines +System +& Here the sub levels start (they are added as TREEBOX ADD adds). +& sublevel +Arithmetic:** or ^ +Arithmetic:xor() +Arithmetic:tan() +Arithmetic:sqrt() +Arithmetic:sqr() +Arithmetic:sin() +Arithmetic:sig() +Arithmetic:ran() +Arithmetic:pi +Arithmetic:or() +Arithmetic:mod() +Arithmetic:min() +Arithmetic:max() +Arithmetic:log() +Arithmetic:int() +Arithmetic:frac() +Arithmetic:exp() +Arithmetic:euler +Arithmetic:eor() +Arithmetic:dec() +Arithmetic:cos() +Arithmetic:bin$() +Arithmetic:atan() +Arithmetic:asin() +Arithmetic:and() +Arithmetic:acos() +Arithmetic:abs() +Conditions and Loops:while +Conditions and Loops:wend +Conditions and Loops:until +Conditions and Loops:true +Conditions and Loops:then +Conditions and Loops:switch +Conditions and Loops:step +Conditions and Loops:return +Conditions and Loops:repeat +Conditions and Loops:logical or +Conditions and Loops:on interrupt +Conditions and Loops:on goto +Conditions and Loops:on gosub +Conditions and Loops:not +Conditions and Loops:next +Conditions and Loops:loop +Conditions and Loops:label +Conditions and Loops:if +Conditions and Loops:goto +Conditions and Loops:gosub +Conditions and Loops:for +Conditions and Loops:fi +Conditions and Loops:false +Conditions and Loops:endif +Conditions and Loops:end +Conditions and Loops:elsif +Conditions and Loops:else +Conditions and Loops:do +Conditions and Loops:default +Conditions and Loops:continue +Conditions and Loops:case +Conditions and Loops:break +Conditions and Loops:and +Data Processing:restore +Data Processing:redim +Data Processing:read +Data Processing:dim +Data Processing:data +Data Processing:arraysize() +Data Processing:arraydim() +Input and Output:; +Input and Output:using +Input and Output:tell +Input and Output:seek() +Input and Output:screen +Input and Output:reverse +Input and Output:putscreen +Input and Output:print +Input and Output:open +Input and Output:line input +Input and Output:input +Input and Output:inkey$ +Input and Output:getscreen$() +Input and Output:eof +Input and Output:colour +Input and Output:color +Input and Output:close +Input and Output:clear screen +Input and Output:at() +Graphical User Interface:Window +Window :window set +Window :window open +Window :window get +Window :window count +Window :window close +Window :filepanel +Window :alert +Graphical User Interface:Widgets +Widgets:Treebox +Treebox:treebox sort +Treebox:treebox select +Treebox:treebox remove +Treebox:treebox get$ +Treebox:treebox expand +Treebox:treebox count +Treebox:treebox collapse +Treebox:treebox clear +Treebox:treebox add +Treebox:treebox +Widgets:Tooltip +Tooltip:tooltip color +Tooltip:tooltip +Widgets:TextURL +TextURL:texturl color +TextURL:texturl +Widgets:Textedit +Textedit:textedit set +Textedit:textedit get$ +Textedit:textedit get +Textedit:textedit color +Textedit:textedit clear +Textedit:textedit add +Textedit:textedit +Widgets:Textcontrol +Textcontrol:textcontrol set +Textcontrol:textcontrol get$ +Textcontrol:textcontrol clear +Textcontrol:textcontrol +Widgets:Text +Text:text set +Text:text +Widgets:Statusbar +Statusbar:statusbar set +Statusbar:statusbar +Widgets:Spincontrol +Spincontrol:spincontrol set +Spincontrol:spincontrol get +Spincontrol:spincontrol +Widgets:Slider +Slider:slider set +Slider:slider label +Slider:slider get +Slider:slider hashmarks +Slider:slider color +Slider:slider +Widgets:Radiobutton +Radiobutton:radiobutton set +Radiobutton:radiobutton +Widgets:Options +Options:option set +Options:option color +Widgets:Listbox +Listbox:listbox sort +Listbox:listbox select +Listbox:listbox remove +Listbox:listbox get$ +Listbox:listbox get +Listbox:listbox count +Listbox:listbox clear +Listbox:listbox add +Listbox:listbox +Widgets:Dropbox +Dropbox:dropbox select +Dropbox:dropbox remove +Dropbox:dropbox get$ +Dropbox:dropbox count +Dropbox:dropbox clear +Dropbox:dropbox add +Dropbox:dropbox +Widgets:Columnbox +Columnbox:columnbox select +Columnbox:columnbox remove +Columnbox:columnbox get$ +Columnbox:columnbox get +Columnbox:columnbox count +Columnbox:columnbox column +Columnbox:columnbox color +Columnbox:columnbox clear +Columnbox:columnbox add +Columnbox:columnbox +Widgets:Colorcontrol +Colorcontrol:colorcontrol set +Colorcontrol:colorcontrol get +Colorcontrol:colorcontrol +Widgets:Checkbox +Checkbox:checkbox set +Checkbox:checkbox image +Checkbox:checkbox +Widgets:Calendar +Calendar:calendar set +Calendar:calendar get$ +Calendar:calendar +Widgets:Button +Button:button image +Button:button +Graphical User Interface:Views +Views:View +View :view remove +View :view get +View :view dropzone +View :view +Views:Tabview +Tabview:tabview set +Tabview:tabview get +Tabview:tabview add +Tabview:tabview +Views:Stackview +Stackview:stackview set +Stackview:stackview get +Stackview:stackview +Views:Splitview +Splitview:splitview set +Splitview:splitview get +Splitview:splitview +Views:Scrollbar +Scrollbar:scrollbar set +Scrollbar:scrollbar get +Scrollbar:scrollbar +Views:layout +Views:boxview +boxview:boxview set +Graphical User Interface:Printing +Printing:printer setup +Printing:printer +Graphical User Interface:Menus +Menus:submenu set +Menus:submenu +Menus:popupmenu +Menus:menu set +Menus:menu +Graphical User Interface:Input and Messages +Input and Messages:shortcut +Input and Messages:mouse set +Input and Messages:mousemove$ +Input and Messages:mouse message$() +Input and Messages:message send +Input and Messages:message$ +Input and Messages:keyboard message$() +Input and Messages:ismousein() +Graphical User Interface:Drawing +Drawing:draw text +Drawing:draw set +Drawing:draw rect +Drawing:draw line +Drawing:draw image +Drawing:draw get$ +Drawing:draw get +Drawing:draw flush +Drawing:draw ellipse +Drawing:draw dot +Drawing:draw curve +Drawing:draw circle +Drawing:draw bitmap +Graphical User Interface:Bitmaps +Bitmaps:screenshot +Bitmaps:canvas +Bitmaps:bitmap save +Bitmaps:bitmap remove +Bitmaps:bitmap get +Bitmaps:bitmap +Localization:translate$() +Localization:localize +Sound:sound wait +Sound:sound stop +Sound:sound play +Sound:bell +Sound:beep +String Handling:val() +String Handling:upper$() +String Handling:trim$() +String Handling:token() +String Handling:str$() +String Handling:split() +String Handling:rtrim$() +String Handling:right$() +String Handling:mid$() +String Handling:ltrim$() +String Handling:lower$() +String Handling:len() +String Handling:left$() +String Handling:instr() +String Handling:hex$() +String Handling:glob() +String Handling:chr$() +String Handling:asc() +Subroutines:sub +Subroutines:static +Subroutines:return +Subroutines:numparams +Subroutines:local +Subroutines:import +Subroutines:export +Subroutines:end sub +System:: +System:# +System:// +System:wait +System:to +System:time$ +System:thread remove +System:thread get +System:system() +System:system$() +System:sleep +System:rem +System:poke +System:peek$ +System:peek +System:pause +System:iscomputeron +System:exit +System:execute() +System:execute$() +System:error +System:docu$ +System:doc +System:date$ +System:compile +System:clipboard copy +System:clipboard paste$ +System:bind() +& +& Information texts (info texts for short) are separated by +& comment lines. The file must end with a comment line! +& +& The info texts start here: +& infotext +&Arithmetic +& +abs() + +Name: +abs() -- returns the absolute value of its numeric argument + +Synopsis: +y=abs(x) + +Description: +If the argument of the abs-function is positive (e.g. 2) it is returned unchanged, if the argument is negative (e.g. -1) it is returned as a positive value (e.g. 1). + +Example: +print abs(-2),abs(2) +Explanation: + + This example will print 2 2 + + +Related: sig + +& +acos() + +Name: +acos() -- returns the arcus cosine of its numeric argument + +Synopsis: +x=acos(angle) + +Description: +The acos is the arcus cosine-function, i.e. the inverse of the cos-function. Or, more elaborate: It Returns the angle (in radian, not degree!), which, fed to the cosine-function will produce the argument passed to the acos-function. + +Example: +print acos(0.5),acos(cos(pi)) +Explanation: + + This example will print 1.0472 3.14159 which are pi/3 and pi respectively. + + +Related: cos, asin + +& +and() + +Name: +and() -- the bitwise arithmetic and + +Synopsis: + x=and(a,b) + +Description: +Used to compute the bitwise and of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resultingvalue will then be 1, if both arguments have a 1 at this position in their binary representation. +Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may leadto unexpected results when passed to and. + +Example: +print and(6,3) +Explanation: + + This will print 2. This result is clear, if you note, that the binary representation of 6 and 3 are 110 and 011 respectively; this will yield 010 in binary representaion or 2 as decimal. + + +Related: or, eor, xor, not + +& +asin() + +Name: +asin() -- returns the arcus sine of its numeric argument + +Synopsis: +angle=asin(x) + +Description: +The acos is the arcus sine-function, i.e. the inverse of the sin-function. Or, more elaborate: It Returns the angle (in radian, not degree!), which,fed to the sine -function will produce the argument passed to the asin-function. + +Example: +print asin(0.5),asin(sin(pi)) +Explanation: + + This will print 0.523599 -2.06823e-13 which is pi/6 and almost 0 respectively. + + +Related: sin, acos + +& +atan() + +Name: +atan() -- returns the arcus tangens of its numeric argument + +Synopsis: +angle=atan(a,b) +angle=atan(a) + +Description: +The atan is the arcus-tangens-function, i.e. the inverse of the tan-function. Or, more elaborate: It Returns the angle (in radian, not degree!), which, fed to the tan-function will produce the argument passed to the atan-function. +The atan-function has a second form, which accepts two arguments: atan(a,b) which is (mostly) equivilantly to atan(a/b) except for the fact, that the two-argument-form returns an angle in the range -pi to pi, whereas the one-argument-form returns an angle in the range -pi/2 to pi/2. To understand this you have to be good at math. + +Example: +print atan(1),atan(tan(pi)),atan(-0,-1),atan(-0,1) +Explanation: + + This will print 0.785398 2.06823e-13 -3.14159 3.14159 which is pi/4, almost 0, -pi and pi respectively. + + +Related: tan, sin + +& +bin$() + +Name: +bin$() -- converts a number into a sequence of binary digits + +Synopsis: +hexadecimal$=bin$(decimal) + +Description: +The bin$-function takes a single numeric argument an converts it into a stringof binary digits (i.e. zeroes and ones). If you pass a negative number to bin$, the resulting string will be preceeded by a '-'. +If you want to convert the other way around (i.e. from binary to decimal) you may use the dec-function. + +Example: +for a=1 to 100 + print bin$(a) +next a +Explanation: + + This example prints the binary representation of all digits between 1 and 100. + + +Related: hex$, dec + +& +cos() + +Name: +cos() -- return the cosine of its single argument + +Synopsis: +x=cos(angle) + +Description: +The cos-function expects an angle (in radian) and returns its cosine. + +Example: +print cos(pi) +Explanation: + + This example will print -1. + + +Related: acos, sin + +& +dec() + +Name: +dec() -- convert a base 2 or base 16 number into decimal form + +Synopsis: +a=dec(number$) +a=dec(number$,base) + +Description: +The dec-function takes the string-representation of a base-2 or base-16 (which is the default) number and converts it into a decimal number. The optional second argument (base) might be used to specify a base other than 16. However, currently only base 2 or base 16 are supported. + +Example: +input "Please enter a binary number: " a$ +print a$," is ",dec(a$) +Related: bin$, hex$ + +& +eor() + +Name: +eor() -- compute the bitwise exclusive or of its two arguments + +Synopsis: +print eor(a,b) + +Description: +The eor-function takes two arguments and computes their bitwise exclusive or. See your favorite introductory text on informatics for an explanation of this function. +The xor-function is the same as the eor function; both are synonymous; however they have each their own description, so you may check out the entry of xor for a slightly different view. + +Example: +for a=0 to 3 + for b=0 to 3 + print fill$(bin$(a))," eor ",fill$(bin$(b))," = ",fill$(bin$(eor(a,b))) + next b +next a + +sub fill$(a$) + return right$("0"+a$,2) +end sub +Explanation: + + This example prints a table, from which you may figure, how the eor-function is computed. + +Related: and, or + +& +euler + +Name: +euler -- another name for the constant 2.71828182864 + +Synopsis: +foo=euler + +Description: +euler is the well known constant named after Leonard Euler; its value is 2.71828182864. euler is not a function, so parens are not allowed (i.e. euler() will produce an error). Finally, you may not assign to euler; it wouldn't sense anyway, because it is a constant. + +Example: +print euler +Related: pi + +& +exp() + +Name: +exp() -- compute the exponential function of its single argument + +Synopsis: + foo=exp(bar) + +Description: +This function computes e to the power of its argument, where e is the well known euler constant 2.71828182864. The exp-function is the inverse of the log-function. + +Example: +window open 100,100 to 300,300, "Example", "Example" +for x=-100 to 100 + draw dot x,100-100*exp(x/100)/euler, "Example" +next x +sleep 5 +window close "Example" +Explanation: + +This program plots part of the exp-function, however the range is rather small, so that you may not recognize the function from this plot. + +Related: log + +& +frac() + +Name: +frac() -- return the fractional part of its numeric argument + +Synopsis: +x=frac(y) + +Description: +The frac-function takes its argument, removes all the digits to the left of the comma and just returns the digits right of the comma, i.e. the fractional part. Refer to the example to learn how to rewrite frac by employing the int-function. + +Example: +for a=1 to 10 + print frac(sqr(a)) + print sqr(a)-int(sqr(a)) +next a +Explanation: + + The example prints the fractional part of the square root of the numbers between 1 and 10. + Each result is computed (and printed) twice: Once by employing the frac-function and once by employing the int-function. + + +Related: int + +& +int() + +Name: +int() -- return the integer part of its single numeric argument + +Synopsis: + print int(a) + +Description: +The int-function returns only the digits before the comma; int(2.5) returns 2 and int(-2.3) returns -2. + +Example: +input "Please enter a whole number between 1 and 10: " a +if (a=int(a) and a>=1 and a<=10) then + print "Thanx!" +else + print "Never mind ..." +endif +Related: frac + +& +log() + +Name: +log() -- compute the natural logarithm + +Synopsis: +a=log(x) +a=log(x,base) + +Description: +The log-function computes the logarithm of its first argument. The optional second argument gives the base for the logarithm; if this second argument is omitted, the euler-constant 2.71828... will be taken as the base. + +Example: +window open 200,200 to 400,400, "Example", "Example" +draw set 0, "highsolidfill" +for x=10 to 190 step 10 + for y=10 to 190 step 10 + r=3*log(1+x,1+y) + if (r>10) r=10 + if (r<1) r=1 + draw circle x,y,r, "Example" + next y +next x +sleep 5 +window close "Example" +Explanation: + + This draws another nice plot. + + +Related: exp + +& +max() + +Name: +max() -- return the larger of its two arguments + +Synopsis: +print max(a,b) + +Description: +Return the maximum of its two arguments. + +Example: +dim m(10) +for a=1 to 1000 + m=0 + for b=1 to 10 + m=max(m,ran(10)) + next b + m(m)=m(m)+1 +next a + +for a=1 to 9 + print a,": ",m(a) +next a +Explanation: + + Within the inner for-loop (the one with the loop-variable b), the example computes the maximum of 10 random numbers. The outer loop (with the loop variable a) now repeats this process 1000 times and counts, how often each maximum appears. The last loop finally reports the result. + Now, the interesting question would be, which will be approached, when we increase the number of iterations from thousend to infinity. Well, maybe someone could just tell me :-) + +Related: min + +& +min() + +Name: +min() -- return the smaller of its two arguments + +Synopsis: +print min(a,b) + +Description: +Return the minimum of its two argument. + +Example: +dim m(10) +for a=1 to 1000 + m=min(ran(10),ran(10)) + m(m)=m(m)+1 +next a + +for a=1 to 9 + print a,": ",m(a) +next a +Explanation: + + For each iteration of the loop, the lower of two random number is recorded. The result is printed at the end. + + +Related: max + +& +mod() + +Name: +mod() -- compute the remainder of a division + +Synopsis: +print mod(a,b) + +Description: +The mod-function divides its two arguments and computes the remainder. Note, that a/b-int(a/b) and mod(a,b) are always equal. + +Example: +clear screen +print at(10,10) "Please wait " +p$="-\|/" +for a=1 to 100 + rem ... do something lengthy here, or simply sleep :-) + pause(1) + print at(22,10) mid$(p$,1+mod(a,4)) +next a +Explanation: + + This example executes some time consuming action within a loop (in fact, it simply sleeps) and gives the user some indication of progress by displaying a turning bar (thats where the mod()-function comes into play). +Start this program in a terminal. + + +Related: int, frac + +& +or() + +Name: +or() -- arithmetic or, used for bit-operations + +Synopsis: +x=or(a,b) + +Description: +Used to compute the bitwise or of both its argument. Both arguments are treated as binary numbers (i.e. a series of 0 and 1); a bit of the resulting value will then be 1, if any of its arguments has 1 at this position in theirbinary representation. +Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead to unexpected results when passed to or. + +Example: +print or(14,3) +Explanation: + + This will print 15. This result is clear, if you note, that the binary representation of 14 and 3 are 1110 and 0011 respectively; this will yield 1111 in binary representaion or 15 as decimal. + +Related: and, eor, xor, not + +& +pi + +Name: +pi -- a constant with the value 3.14159 + +Synopsis: +print pi + +Description: +pi is 3.14159265359 (well at least for yab); do not try to assign to pi (e.g. pi=22/7)this would not only be mathematically dubious, but would also result in a syntax error. + +Example: +for a=0 to 180 + print "The sine of ",a," degrees is ",sin(a*pi/180) +next a +Explanation: + + This program uses pi to transform an angle from degrees into radians. + + +Related: euler + +& +ran() + +Name: +ran() -- return a random number + +Synopsis: +print ran() +x=ran(y) + +Description: +The ran-function returns a random number. If no argument is given, the number returned is in the range from 0 to 1; where only 0 is a possible value; 1 will never be returned. If an argument is supplied, the number returned will be in the range from 0 up to this argument, whereas this argument itself is not a possible return value. + +Example: +clear screen +c=peek("screenwidth")-1 +l=peek("screenheight") + +dim col$(8) +for a=0 to 7 + read col$(a) +next a + +do + x=ran(c) + y=l-ran(l*exp(-32*((x/c-1/2)**2))) + i=i+1 + print color(col$(mod(i,8))) at(x,y) "*" +loop + +data "black","white","red","blue","green","yellow","cyan","magenta" +Explanation: + + This example will print a cloured bell-curve. Start this program in a terminal. + + +Related: int + +& +sig() + +Name: +sig() -- return the sign of its argument + +Synopsis: +a=sig(b) + +Description: +Return +1, -1 or 0, if the single argument is positive, negative or zero. + +Example: +clear screen +dim c$(3):c$(1)="red":c$(2)="white":c$(3)="green" +do + num=ran(100)-50 + print color(c$(2+sig(num))) num +loop +Explanation: + + This program prints an infinite sequence of random number; positive numbers are printed in green, negative numbers are printed red (an exact zero would be printed white). (With a little extra work, this program could be easily extended into a brogerage system). + + Start this program in a terminal. + + +Related: abs, int, frac + +& +sin() + +Name: +sin() -- return the sine of its single argument + +Synopsis: +y=sin(angle) + +Description: +The sin-function expects an angle (in radian, not degree) and returns its sine. + +Example: +window open 200,200 to 400,400, "Example", "Example" +for phi=0 to 2*pi step 0.1 + draw line 100+90*sin(phi-0.1),100+90*cos(phi-0.1) to 100+90*sin(phi),100+90*cos(phi), "Example" +next phi +sleep 5 +window close "Example" +Explanation: + + This program draws a circle (ignoring the existence of the circle-command). + + +Related: asin, cos + +& +sqr() + +Name: +sqr() -- compute the square of its argument + +Synopsis: +a=sqr(b) + +Description: +The sqr-function computes the square of its numerical argument (i.e. it multiplies its argument with itself). + +Example: +for a=1 to 10 + print a,sqr(a),a**2 +next a +Explanation: + + As you may see from the output, sqr can be written as **2 (or ^2) too. + + +Related: sqrt, **, ^ + +& +sqrt() + +Name: +sqrt() -- compute the square root of its argument + +Synopsis: +to be written + +Description: +The sqrt-function computes the square root of its numerical argument. + +Example: +for a=1 to 5 + print a,sqrt(a),a**(1/2) +next a +Explanation: + + As you may see from the output, sqrt can be written as **(1/2) (or ^(1/2)) too. + + +Related: sqr, **, ^ + +& +tan() + +Name: +tan() -- return the tangens of its argument + +Synopsis: +foo=tan(bar) + +Description: +The tan-function computes the tangens of its arguments (which should be specified in radian). + +Example: +for a=0 to 45 + print tan(a*pi/180) +next a +Explanation: + + This example simply prints the tangens of all angles between 0 and 45 degree. + + +Related: atan, sin + +& +xor() + +Name: +xor() -- compute the exclusive or + +Synopsis: +x=xor(a,b) + +Description: +The xor computes the bitwise exclusive or of its two numeric arguments. To understand the result, both arguments should be viewed as binary numbers(i.e. a series of 0 and 1); a bit of the result will then be 1, if exactly one argument has a 1 and the other has a 0 at this position in their binary representation. +Note, that both arguments are silently converted to integer values and that negative numbers have their own binary representation and may lead tounexpected results when passed to and. + +Example: +print xor(7,4) +Explanation: + + This will print 3. This result is obvious, if you note, that the binary representation of 7 and 4 are 111 and 100 respectively; this will yield 011 in binary representaion or 2 as decimal. The eor-function is the same as the xor function; both are synonymous; however they have each their own description, so you may check out the entry of eor for a slightly different view. + + +Related: and, or, eor, not + +& +** or ^ + +Name: +** or ^ -- raise its first argument to the power of its second + +Synopsis: +print 2**b +print 3^4 + +Description: +** (or ^, which is an exact synonym), is the arithmetic operator of exponentiation; it requires one number to its left and a second one to its right; ** then raises thefirst argument to the power of the second and returns the result. The result will only be computed if it yields a real number (as opposed to a complex number); this means, that the power can not be computed, if the first argument is negative and the second one is fractional. On the other hand, the second argument can be fractional, if the first one ist positive; this means, that ** may be used to compute arbitrary roots: e.g. x**0.5 computes the square root of x. + +Example: +print 2**0.5 +Related: sqrt + +&Conditions and Loops +& +and + +Name: +and -- logical and, used in conditions + +Synopsis: +if (a and b) +while (a and b) + +Description: +Used in conditions (e.g within if, while or until) to join two expressions. Returns true, if and only if its left and right argument are both true and false otherwise. +Note, that logical shortcuts may take place. + +Example: +input "Please enter a number" a +if (a>=1 and a<=9) print "your input is between 1 and 9" +Related: or, not, xor, eor + +& +break + +Name: +break -- breaks out of a switch statement or a loop + +Synopsis: +break + +Description: +break transfers control immediately outside the enclosing loop or switch statement. This is the preferred way of leaving a such a statement (rather than goto, which is still possible in most cases). + +Example: +for a=1 to 10 + break + print "Hi" +next a + +while(1) + break + print "Hi" +wend + +repeat + break + print "Hi" +until(0) + +switch 1 + case 1:break + case 2:case 3:print "Hi" +end switch +Explanation: + + This example prints nothing at all, because each of the loops (and the switch-statement) does an immediate break (before it could print any "Hi"). + + +Related: for, while, repeat, switch + +& +case + +Name: +case -- mark the different cases within a switch-statement + +Synopsis: +switch a + case 1 + case 2 + ... +end switch + +... + +switch a$ + case "a" + case "b" + ... +end switch + +Description: +Please see the switch-statement. + +Example: +input a +switch(a) + case 1:print "one":break + case 2:print "two":break + default:print "more" +end switch +Explanation: + + Depending on your input (a number is expected) this code will print one or two or otherwise more. + + +Related: switch + +& +continue + +Name: +continue -- start the next iteration of a for-, do-, repeat- or while-loop + +Synopsis: +continue + +Description: +You may use continue within any loop to start the next iteration immediately. Depending on the type of the loop, the loop-condition will or will not be checked. Especially: for- and while-loops will evaluate their respective conditions, do- and repeat-loops will not. +Remark: Another way to change the flow of execution within a loop, is the break-command. + +Example: +for a=1 to 100 + if mod(a,2)=0 continue + print a +next a +Explanation: + + This example will print all odd numbers between 1 and 100. + + +Related: for, do, repeat, while, break + +& +default + +Name: +default -- mark the default-branch within a switch-statement + +Synopsis: +switch a+3 +case 1 + ... +case 2 + ... +default + ... +end switch + +Description: +The default-clause is an optional part of the switch-statement (see there for more information). It introduces a series of statements, that should be executed, if none of the casese matches, that have been specified before (each with its own case-clause). So default specifies a default to be executed, if none of the explicitly named cases matches; hence its name. + +Example: +print "Please enter a number between 0 and 6," +print "specifying a day in the week." +input d +switch d + case 0:print "Monday":break + case 1:print "Tuesday":break + case 2:print "Wednesday":break + case 3:print "Thursday":break + case 4:print "Friday":break + case 5:print "Saturday":break + case 6:print "Sunday":break + default:print "Hey you entered something invalid!" +end switch +Explanation: + + This program translates a number between 0 and 6 into the name of a weekday; the default -case is used to detect (and complain about) invalid input. + + +Related: sub, case + +& +do + +Name: +do -- start a (conditionless) do-loop + +Synopsis: +do +... +loop + +Description: +Starts a loop, which is terminated by loop; everything between do and loop willbe repeated forever. This loop has no condition, so it is an infinite loop; note however, that a break- or goto-statement might be used to leave this loop anytime. + +Example: +do + a=a+1 + print a + if (a>100) break +loop +Explanation: + + This example prints the numbers between 1 and 101. The break-statement is used to leave the loop. + + +Related: loop, repeat, while, break + +& +else + +Name: +else -- mark an alternative within an if-statement + +Synopsis: +if (...) then + ... +else + ... +endif + +Description: +The else-statement introduces the alternate branch of an if-statement. I.e. it starts the sequence of statements, which is executed, if the condition of the if-statement is not true. + +Example: +input "Please enter a number: " a +if (mod(a,2)=1) then + print a," is odd." +else + print a," is even." +endif +Explanation: + + This program detects, if the number you have entered is even or odd. + + +Related: if + +& +elsif + +Name: +elsif -- starts an alternate condition within an if-statement + +Synopsis: +if (...) then + ... +elseif (...) + ... +elsif (...) then + ... +else + ... +endif + +Description: +The elsif-statement is used to select a single alternative among a seriesof choices. With each elsif-statement you may specify a condition, which is tested, if the main condition (specified with the if-statement) has failed. Note that elsif might be just as well written as elseif. +Within the example below, two variables a and b are tested against a rangeof values. The variable a is tested with the elsif-statement. The very same tests are performed for the variable b too; but here an involved series of if-else-statements is employed, making the tests much more obscure. + +Example: + +input "Please enter a number: " a +if (a<0) then + print "less than 0" +elseif (a<=10) then + print "between 0 and 10" +elsif (a<=20) + print "between 11 and 20" +else + print "over 20" +endif + +input "Please enter another number: " b +if (b<0) then + print "less than 0" +else + if (b<=10) then + print "between 0 and 10" + else + if (b<=20) then + print "between 11 and 20" + else + print "over 20" + endif + endif +endif +Explanation: + + Note, that the very same tests are performed for the variables a and b, but can be stated much more clearly with the elsif-statement. + Note, that elsif might be written as elseif too, and that the keyword then is optional. + + +Related: if, else + +& +end + +Name: +end -- terminate your program + +Synopsis: +end + +Description: +Terminate your program. Much (but not exactly) like the exit command. +Note, that end may not end your program immediately; if you have opened a window or called clear screen, yab assumes, that your user wants to study the output of your program after it has ended; therfore it issuesthe line ---Program done, press RETURN--- and waits for a key to be pressed. If you do not like this behaviour, consider using exit. + +Example: + + print "Do you want to continue ?" + input "Please answer y(es) or n(o): " a$ + if (lower$(left$(a$,1))="n") then + print "bye" + end + fi + + +Related: exit + +& +endif + +Name: +endif -- ends an if-statement + +Synopsis: +if (...) then + ... +endif + +Description: +The endif-statement closes (or ends) an if-statement. +Note, that endif may be written in a variety of other ways: end if, end-if or even fi. The endif-statement must be omitted, if the if-statement does not contain the keyword then (see the example below). Such an if-statement without endif extends only over a single line. + +Example: +input "A number please: " a +if (a<10) then + print "Your number is less than 10." +endif + +rem and now without endif + +input "A number please: " a +if (a<10) print "Your number is less than 10." +Related: if + +& +false + +Name: +false -- a constant with the value of 0 + +Synopsis: +okay=false + +Description: +The constant false can be assigned to variables which later appear in conditions (e.g. within an if-statement. +false may also be written as FALSE or even FaLsE. + +Example: +input "Please enter a number between 1 and 10: " a +if (check_input(a)) print "Okay" + +sub check_input(x) + if (x>10 or x<1) return false + return true +end sub +Explanation: + + The subroutine check_input checks its argument and returns true or false according to the outcome of the check. + + +Related: true + +& +fi + +Name: +fi -- another name for endif + +Synopsis: +if (...) +... +fi + +Description: +fi marks the end of an if-statement and is exactly equivilent to endif, please see there for further information. + +Example: +input "A number please: " a +if (a<10) then + print "Your number is less than 10." +fi +Related: endif + +& +for + +Name: +for -- starts a for-loop + +Synopsis: +for a=1 to 100 step 2 + ... +next a + +Description: +The for-loop lets its numerical variable (a in the synopsis) assume all valueswithin the given range. The optional step-clause may specify a value (default: 1) by which the variable will be incremented (or decremented, if step is negative). + +Any for-statement can be replaced by a set of ifs and gotos; as you may infer from the example below this is normally not feasable. However if you want to know in detail how the for-statement works, you should study this example, which presents a for-statement and an exactly equivilant series of ifs and gotos. + +Example: +for a=1 to 10 step 2 + print a +next a + +a=1 +label check +if (a>10) goto done +print a +a=a+2 +goto check +label done +Explanation: + +This example simply prints the numbers 1, 3, 5, 7 and 9. It does this twice: +First with a simple for-statment and then with ifs and gotos. + + +Related: step, next + +& +gosub + +Name: +gosub -- continue execution at another point within your program +(and return later) + +Synopsis: +gosub foo + +... + +label foo +... +return + +Description: +gosub remembers the current position within your program and then passes the flow of execution to another point (which is normally marked with a label). Later, when a return- statement is encountered, the execution is resumed at the previous location. +gosub is the traditional command for calling code, which needs to be executed from various places within your program. However, with subroutines yab offers a much more flexible way to achieve this (and more). Therefore gosub must to be considered obsolete. + +Example: +print "Do you want to exit ? " +gosub ask +if (r$="y") exit + +label ask +input "Please answer yes or no, by typing 'y' or 'n': ",r$ +return +Related: return, goto, sub, label, on gosub + +& +goto + +Name: +goto -- continue execution at another point within your program (and never come back) + +Synopsis: +goto foo + +... + +label foo + +Description: +The goto-statement passes the flow of execution to another point within your program (which is normally marked with a label). +goto is normally considered obsolete and harmful, however in yab it may be put to the good use of leaving loops (e.g. while or for) prematurely. Note however, that subroutines may not be left with the goto-statement. + +Example: +clear screen +print "Please press any key to continue." +print "(program will continue by itself within 10 seconds)" +for a=1 to 10 + if (inkey$(1)<>"") goto done +next a +label done +print "Hello World!" +Explanation: + +Here the goto-statment is used to leave the for-loop prematurely. Start this program in a terminal. + + +Related: gosub, on goto + +& +if + +Name: +if -- evaluate a condition and execute statements or not, depending on the result + +Synopsis: +if (...) then + ... +endif + +if (...) ... + +if (...) then + ... +else + ... +endif + +if (...) then + ... +elsif (...) + ... +elsif (...) then + ... +else + ... +endif + +Description: +The if-statement is used to evaluate a conditions and take actions accordingly. (As an aside, please note that there is no real difference between conditions and expressions.)There are two major forms of the if-statement:The one-line-form without the keyword then: if (...) ... +This form evaluates the condition and if the result is true executes all commands (seperated by colons) upt to the end of the line. There is neither an endif keyword nor an else-branch. +The multi-line-form with the keyword then: if (...) then ... elsif (...) ... else ... endif(where elsif and else are optional, whereas endif is not. +According to the requirements of your program, you may specify:elsif(...), which specifies a condition, that will be evaluated only if the condition(s) whithin if or any preceeding elsif did not match. +else, which introduces a sequence of commands, that will be executed, if none of the conditions above did match. endif is required and ends the if-statement. + +Example: +input "Please enter a number between 1 and 4: " a +if (a<=1 or a>=4) error "Wrong, wrong!" +if (a=1) then + print "one" +elsif (a=2) + print "two" +elsif (a=3) + print "three" +else + print "four" +endif +Explanation: + +The input-number between 1 and 4 is simply echoed as text (one, two, ...). The example demonstrates both forms (short and long) of the if-statement (Note however, that the same thing can be done, probably somewhat more elegant, with the switch-statement). + +Related: else, elsif, endif + +& +label + +Name: +label -- mark a specific location within your program for goto, gosub or restore + +Synopsis: +label foo + +... + +goto foo + +Description: +The label-command can be used to give a name to a specific location within your program. Such a position might be referred from one of three commands: goto, gosub and restore. +You may use labels safely within libraries, because a label (e.g. foo) does not collide with a label with the same name within the main program or within another library; yab will not mix them up. +As an aside, please note, that line numbers are a special (however deprecated) case of labels; see the second example below. + +Example: +for a=1 to 100 + if (rand(10)>5) goto done +next a +label done + +10 for a=1 to 100 +20 if (rand(10)>5) goto 40 +30 next a +40 +Explanation: + +Within this example, the for-loop will probably be left prematurely with a goto-statement. This task is done twice: First with labels and then again with line numbers. + +Related: gosub, goto + +& +loop + +Name: +loop -- marks the end of an infinite loop + +Synopsis: +do + ... +loop + +Description: +The loop-command marks the ends of a loop (which is started by do), wherein all statements within the loop are repeated forever. In this respect the do loop-loop is infinite, however, you may leave it anytime via break or goto. + +Example: +print "Hello, I will throw dice, until I get a 2 ..." +do + r=int(rand(6))+1 + print r + if (r=2) break +loop +Related: do, for, repeat, while, break + +& +next + +Name: +next -- mark the end of a for loop + +Synopsis: +for a=1 to 10 +next a + +Description: +The next-keyword marks the end of a for-loop. All statements up to the next-keyword will be repeated as specified with the for-clause. Note, that the name of the variable is optional; so instead of next a you may write next. + +Example: +for a=1 to 300000 + for b=1 to 21+20*sin(pi*a/20) + print "*" + next b + print + sleep 0.1 +next a +Explanation: + +This example simply plots a sine-curve until you fall asleep. Start this program in a terminal. + + +Related: for + +& +not + +Name: +not -- negate an expression; can be written as! + +Synopsis: +if (not a9 or a<1) print "a is not between 1 and 9" +Related: and, not, xor, eor + +& +pause + +Name: +pause -- pause, sleep, wait for the specified number of seconds + +Synopsis: +pause 5 + +Description: +The pause-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yab will not wait at all. The pause-command cannot be interrupted. However, sometimes you may want the wait to be interuptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument). + +Example: +deg=0 +do + maxx=44+40*sin(deg) + for x=1 to maxx + print "*" + next x + pause 0.1+(maxx*maxx/(4*84*84)) + print + deg=deg+0.1 +loop +Explanation: + +This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity. + +Related: sleep, wait + +& +repeat + +Name: +repeat -- start a repeat-loop + +Synopsis: +repeat + ... +until (...) + +Description: +The repeat-loop executes all the statements up to the final until-keyword over and over. The loop is executed as long as the condition, which is specified with the until-clause, becomes true. By construction, the statements within the loop are executed at least once. + +Example: +x=0 +clear screen +print "This program will print the numbers from 1 to 10" +repeat + x=x+1 + print x + print "Press any key for the next number, or 'q' to quit" + if (inkey$="q") break +until(x=10) +Explanation: + +This program is pretty much useless, but self-explanatory. + + +Related: until, break, while, do + +& +return + +Name: +return -- return from a subroutine or a gosub + +Synopsis: +gosub foo +... +label foo +... +return + +sub bar(baz) + ... + return quertz +end sub + +Description: +The return-statement serves two different (albeit somewhat related) purposes. The probably more important use of return is to return control from within a subroutine to the place in your program, where the subroutine has been called. If the subroutine is declared to return a value, the return-statement might be accompanied by a string or number, which constitutes the return value of the subroutine. +However, even if the subroutine should return a value, the return-statement need not carry a value; in that case the subroutine will return 0 or the empty string (depending on the type of the subroutine). Moreover, feel free to place multiple return-statements within your subroutine; it's a nice way of controlling the flow of execution. +The second (but historcially first) use of return is to return to the position, where a prior gosub has left off. In that case return may not carry a value. + +Example: +do + read a$ + if (a$="") then + print + end + endif + print mark$(a$)," " +loop + +data "The","quick","brown","fox","jumped" +data "over","the","lazy","dog","" + +sub mark$(a$) + if (instr(lower$(a$),"q")) return upper$(a$) + return a$ +end sub +Explanation: + +This example features a subroutine mark$, that returns its argument in upper case, if it contains the letter "q", or unchanged otherwise. In the test-text the word quick will end up beeing marked as QUICK. +The example above demonstrates return within subroutines; please see gosub for an example of how to use return in this context. + + +Related: sub, gosub + +& +sleep + +Name: +sleep -- pause, sleep, wait for the specified number of seconds + +Synopsis: +sleep 4 + +Description: +The sleep-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. +Therefore you should refer to the entry for the pause-function for further information. + +Related: pause, wait +& +step + +Name: +step -- specifies the increment step in a for-loop + +Synopsis: +for a=1 to 10 step 3 + ... +next a + +Description: +Specify, by which amount the loop-variable of a for-loop will be incremented at each step. +The step (as well as the lower and upper bound) are computed anew in each step; this is not common, but possible, as the example below demonstrates. + +Example: +for x=1 to 1000 step y + y=x+y + print x," ",y," " +next x +print +Explanation: + +This program computes the fibonacci numbers between 1 and 1000. + + +Related: for + +& +switch + +Name: +switch -- select one of many alternatives depending on a value + +Synopsis: +switch a + case 1 + case 2 + ... +end switch + +... + +switch a$ + case "a" + case "b" +end switch + +Description: +The switch-statment selects one of many codepaths depending on a numerical or string expression. I.e. it takes an expression (either numeric or string) and compares it with a series of values, each wrapped within a case-clause. If the expression equals the value given in a case-clause, the subsequent statements are executed. +The default-clause allows to specify commands, which should be executed, if none of case-clauses matches. +Note, that many case-clauses might be clustered (e.g. case "a":case "b":case "c"). Or put another way: You need a break-statement at the end of a case-branch, if you do not want to run into the next case. + +Example: +input "Please enter a single digit: " n +switch n + case 0:print "zero":break + case 1:print "one":break + case 2:print "two":break + case 3:print "three":break + case 4:print "four":break + case 5:case 6: case 7:case 8:case 9 + print "Much!":break + default:print "Hey! That was more than a single digit!" +end switch +Explanation: + +This example translates a single digit into a string; note, how the cases 5 to 7 are clustered. + + +Related: switch, case, break + +& +then + +Name: +then -- tell the long from the short form of the if-statement + +Synopsis: +if (a2 or arraydim(m2())<>2 or arraydim(r())<>2) then + error "Need two dimensional arrays as input" + endif + + y=arraysize(m1(),1):x=arraysize(m1(),2) + if (arraysize(m2(),1)<>y or arraysize(m2(),2)<>x) then + error "The two matrices cannot be added elementwise" + endif + + if (arraysize(r(),1)<>y or arraysize(r(),2)<>x) then + error "The result cannot be stored in the third argument" + endif + + local xx:local yy + for xx=1 to x + for yy=1 to y + r(yy,xx)=m1(yy,xx)+m2(yy,xx) + next yy + next xx +end sub +Related: arraydim, dim + +& +data + +Name: +data -- introduces a list of data-items + +Synopsis: +data 9,"world" +... +read b,a$ + +Description: +The data-keyword introduces a list of comma-seperated list of strings or numbers, which may be retrieved with the read-command. +The data-command itself does nothing; it just stores data. A single data-command may precede an arbitrarily long list of values, in which strings or numbers may be mixed at will. + +yab internally uses a data-pointer to keep track of the current location within the data-list; this pointer may be reset with the restore-command. + +Example: +do + restore + for a=1 to 4 + read num$,num + print num$,"=",num + next a +loop +data "eleven",11,"twelve",12,"thirteen",13,"fourteen",14 +Explanation: + +This example just prints a series of lines eleven=11 up to fourteen=14 and so on without end. +The restore-command ensures that the list of data-items is read from the start with every iteration. + + +Related: read, restore + +& +dim + +Name: +dim -- create an array prior to its first use + +Synopsis: +dim array(x,y) +dim array$(x,y) + +Description: +The dim-command prepares one or more arrays (of either strings or numbers) for later use. This command can also be used to enlarges an existing array. + +When an array is created with the dim-statement, memory is allocated and all elements are initialized with either 0 (for numerical arrays) or "" (for string arrays). +If the array already existed, and the dim-statement specifies a larger size than the current size, the array is enlarged and any old content is preserved. + +Note, that dim cannot be used to shrink an array: If you specify a size, that is smaller than the current size, the dim-command does nothing. + +Finally: To create an array, that is only known within a single subroutine, you should use the command local, which creates local variables as well as local arrays. + +Example: +dim a(5,5) +for x=1 to 5 + for y=1 to 5 + a(x,y)=int(ran(100)) + y +next x +printmatrix(a()) +dim a(7,7) +printmatrix(a()) + +sub printmatrix(ar()) + local x,y,p,q + x=arraysize(ar(),1) + y=arraysize(ar(),2) + for q=1 to y + for p=1 to y + print ar(p,q),"\t" + next p + print + next q +end sub +Explanation: + +This example creates a 2-dimenional array (i.e. a matrix) with the dim-statement and fills it with random numbers. The second dim-statement enlarges the array, all new elements are filled with 0. + +The subroutine printmatrix just does, what its name says. + + +Related: arraysize, arraydim, local + +& +read + +Name: +read -- read data from data-statements + +Synopsis: +read a$,a +... +data "Hello!",7 + +Description: +The read-statement retrieves literal data, which is stored within data-statements elsewhere in your program. + +Example: +read num +dim col$(num) +for a=1 to num:read col$(a):next a +clear screen +print "These are the colours known to yab:\n" +for a=1 to num + print colour(col$(a)) col$(a) +next a + +data 8,"black","white","red","blue" +data "green","yellow","cyan","magenta" +Explanation: + +This program prints the names of the colors known to yab in those very colors. + +Start this program in a terminal. + + +Related: data, restore + +& +redim + +Name: +redim -- create an array prior to its first use. A synonym for dim + +Synopsis: +See the dim-command. + +Description: +The redim-command does exactly the same as the dim-command; it is just a synonym. redim has been around in older versions of basic (not even yab) for many years; therefore it is supported in yab for compatibility reasons. +Please refer to the entry for the dim-command for further information. + +Related: dim +& +restore + +Name: +restore -- reposition the data-pointer + +Synopsis: +read a,b,c,d,e,f +restore +read g,h,i +restore foo +data 1,2,3 +label foo +data 4,5,6 + +Description: +The restore-command may be used to reset the reading of data-statements, so that the next read-statement will read data from the first data-statement. +You may specify a label with the restore-command; in that case, the next read-statement will read data starting at the given label. If the label is omitted, reading data will begin with the first data-statement within your program. + +Example: +input "Which language (German/English) ? " l$ +if (instr("German",l$)>0) then + restore German +else + restore English +endif + +for a=1 to 3 + read x,x$ + print x,"=",x$ +next a + +label English +data 1,"one",2,"two",3,"three" +label German +data 1,"eins",2,"zwei",3,"drei" +Explanation: + +This program asks to select one of those languages known to me (i.e. English or German) and then prints the numbers 1,2 and 3 and their textual equivalents in the chosen language. + + +Related: read, data, label + +&String Handling +& +asc() + +Name: +asc() -- accepts a string and returns the position of its first character +within the ascii charset + +Synopsis: +a=asc(char$) + +Description: +The asc-function accepts a string, takes its first character and looks it up within the ascii-charset; this position will be returned. The asc-function is the opposite of the chr$-function. There are valid uses for asc, however, comparing strings (i.e. to bring them into alphabetical sequence) is not among them; in such many cases you might consider to compare strings directly with <, = and > (rather than converting a string to a number and comparing this number). + +Example: +input "Please enter a letter between 'a' and 'y': " a$ +if (a$<"a" or a$>"y") print a$," is not in the proper range":end +print "The letter after ",a$," is ",chr$(asc(a$)+1) +Related: chr$ + +& +chr$() + +Name: +chr$() -- accepts a number and returns the character at this position within the ascii charset + +Synopsis: +character$=chr$(ascii) + +Description: +The chr$-function is the opposite of the asc-function. It looks up and returns the character at the given position within the ascii-charset. It's typical use is to construct nonprintable characters which do not occur on your keyboard. +Nevertheless you won't use chr$ as often as you might think, because the most important nonprintable characters can be constructed using escape-sequences using the \-character (e.g. you might use \n instead of chr$(10) wherever you want to use the newline-character). + +Example: +print "a",chr$(10),"b" +Explanation: + +This will print the letters 'a' and 'b' in different lines because of the intervening newline-character, which is returned by chr$(10). + + +Related: asc + +& +glob() + +Name: +glob() -- check if a string matches a simple pattern + +Synopsis: +if (glob(string$,pattern$)) ... + +Description: +The glob-function takes two arguments, a string and a (glob-) pattern, and checks if the string matches the pattern. However glob does not employ the powerful rules of regular expressions; rather it has only two special characters: * (which matches any number (even zero) of characters) and ? (which matches exactly a single character). + +Example: +for a=1 to 10 + read string$,pattern$ + if (glob(string$,pattern$)) then + print string$," matches ",pattern$ + else + print string$," does not match ",pattern$ + endif +next a + +data "abc","a*" +data "abc","a?" +data "abc","a??" +data "abc","*b*" +data "abc","*" +data "abc","???" +data "abc","?" +data "abc","*c" +data "abc","A*" +data "abc","????" +Explanation: + +This program checks the string abc against various patterns and prints the result. The output is: + +&exverbatim +abc matches a* +abc does not match a? +abc matches a?? +abc matches *b* +abc matches * +abc matches ??? +abc does not match ? +abc matches *c +abc does not match A* +abc does not match ???? +&exverbatim + +& +hex$() + +Name: +hex$() -- convert a number into hexadecimal + +Synopsis: +print hex$(foo) + +Description: +The hex$-function converts a number into a string with its hexadecimal representation. hex$ is the inverse of the dec-function. + +Example: +open 1,"foo" +while(!eof(1)) + print right$("0"+hex$(peek(1)),2)," " + i=i+1 + if (mod(i,10)=0) print +end while +print +Explanation: + +This program reads the file foo and prints its output as a hex-dump using the hex-function. + + +Related: dec, bin$ + +& +instr() + +Name: +instr() -- searches its second argument within the first; returns its position if found + +Synopsis: +print instr(a$,b$) +if (instr(a$,b$)) ... +pos=instr(a$,b$,x) + +Description: +The instr-functions requires two string arguments and searches the second argument within the first. If the second argument can be found within the first, the position is returned (counting from one). If it can not be found, the instr-function returns 0; this makes this function usable within the condition of an if-statement (see the example below). + +If you supply a third, numeric argument to the instr-function, it will be used as a starting point for the search. Therefore instr("abcdeabcdeabcde","e",8) will return 10, because the search for an "e" starts at position 8 and finds the "e" at position 10 (and not the one at position 5). + +Example: +input "Please enter a text containing the string 'bumf': " a$ +if (instr(a$,"bumf")) then + print "Well done!" +else + print "not so well ..." +endif +Related: rinstr + +& +left$() + +Name: +left$() -- return (or change) left end of a string + +Synopsis: +print left$(a$,2) +left$(b$,3)="foobar" + +Description: +The left$-function accepts two arguments (a string and a number) and returns the part from the left end of the string, whose length is specified by its second argument. Loosely spoken, it simply returns the requested number of chars from the left end of the given string. + +Note, that the left$-function can be assigned to, i.e. it may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the left$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below. + +Example: +input "Please answer yes or no: " a$ +l=len(a$):a$=lower$(a$):print "Your answer is " +if (left$("yes",l)=a$ and l>=1) then + print "yes" +elsif (left$("no",l)=a$ and l>=1) then + print "no" +else + print "?" +endif + +a$="Heiho World!" +print a$ +left$(a$,5)="Hello" +print a$ +Explanation: + +This example asks a simple yes/no question and goes some way to accept even incomplete input, while still beeing able to reject invalid input. This second example demonstrates the capability to assign to the left$-function. + + +Related: right$, mid$ + +& +len() + +Name: +len() -- return the length of a string + +Synopsis: +x=len(a$) + +Description: +The len-function returns the length of its single string argument. + +Example: +input "Please enter a password: " a$ +if (len(a$)<6) error "Password too short!" +Explanation: + +This example checks the length of the password, that the user has entered. + +Related: left$, right$, mid$ + +& +lower$() + +Name: +lower$() -- convert a string to lower case + +Synopsis: +l$=lower$(a$) + +Description: +The lower$-function accepts a single string-argument and converts it to all lower case. + +Example: +input "Please enter a password: " a$ +if (a$=lower$(a$)) error "Your password is NOT mixed case!" +Explanation: + +This example prompts for a password and checks, if it is really lower case. + + +Related: upper$ + +& +ltrim$() + +Name: +ltrim$() -- trim spaces at the left end of a string + +Synopsis: +a$=ltrim$(b$) + +Description: +The ltrim$-function removes all whitespace from the left end of a string and returns the result. + +Example: +input "Please answer 'yes' or 'no' : " a$ +a$=lower$(ltrim$(rtrim$(a$))) +if (len(a$)>0 and a$=left$("yes",len(a$))) then + print "Yes ..." +else + print "No ..." +endif +Explanation: + +This example prompts for an answer and removes any spaces, which might precede the input; therefore it is even prepared for the (albeit somewhat patological case), that the user first hits space before entering his answer. + + +Related: rtrim$, trim$ + +& +rtrim$() + +Name: +rtrim$() -- trim spaces at the right end of a string + +Synopsis: +a$=rtrim$(b$) + +Description: +The rtrim$-function removes all whitespace from the right end of a string and returns the result. + +Example: +input "Please answer 'yes' or 'no' : " a$ +a$=lower$(ltrim$(rtrim$(a$))) +if (len(a$)>0 and a$=left$("yes",len(a$))) then + "Yes ..." +else + print "No ..." +endif +Explanation: + +This example prompts for an answer and removes any spaces, which might precede the input; therefore it is even prepared for the (albeit somewhat patological case), that the user first hits space before entering his answer. + + +Related: ltrim$, trim$ + +& +mid$() + +Name: +mid$() -- return (or change) characters from within a string + +Synopsis: +print mid$(a$,2,1) +print mid$(a$,2) +mid$(a$,5,3)="foo" +mid$(a$,5)="foo" + +Description: +The mid$-function requires three arguments: a string and two numbers, where the first number specifies a position within the string and the second one gives the number of characters to be returned; if you omit the second argument, the mid$-function returns all characters up to the end of the string. +Note, that you may assign to the mid$-function, i.e. mid$ may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the mid$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below. + +Example: +input "Please enter a string: " a$ +for a=1 to len(a$) + if (instr("aeiou",lower$(mid$(a$,a,1)))) mid$(a$,a,1)="e" +next a +print "When you turn everything to lower case and" +print "replace every vowel with 'e', your input reads:" +print +print a$ +Explanation: + +This example transforms the input string a bit, using the mid$-function to retrieve a character from within the string as well as to change it. + + +Related: left$, right$ + +& +right$() + +Name: +right$() -- return (or change) the right end of a string + +Synopsis: +print right$(a$,2) +right$(b$,2)="baz" + +Description: +The right$-function requires two arguments (a string and a number) and returns the part from the right end of the string, whose length is specified by its second argument. So, right$ simply returns the requested number of chars from the right end of the given string. +Note, that the right$-function can be assigned to, i.e. it may appear on the left hand side of an assignment. In this way it is possible to change a part of the variable used within the right$-function. Note, that that way the length of the string cannot be changed, i.e. characters might be overwritten, but not added. For an example see below. + +Example: +print "Please enter a length either in inch or centimeter" +print "please add 'in' or 'cm' to mark the unit." +input "Length: " a$ +if (right$(a$,2)="in") then + length=val(a$)*2.56 +elsif (right$(a$,2)="cm") then + length=val(a$) +else + error "Invalid input: "+a$ +endif + +a$="Heiho World!" +print a$ +right$(a$,7)="dwarfs." +print a$ +Explanation: + +This program allows the user to enter a length qulified with a unit (either inch or centimeter). +The second example demonstrates the capability to assign to the right$-function. + + +Related: right$, mid$ + +& +split() + +Name: +split() -- split a string into many strings + +Synopsis: +dim w$(10) +... +num=split(a$,w$()) +num=split(a$,w$(),s$) + +Description: +The split-function requires a string (containing the text to be split), a reference to a string-array (which will receive the resulting strings, i.e. the tokens) and an optional string (with a set of characters, at which to split, i.e. the delimiters). + +The split-function regards its first argument (a string) as a list of tokens separated by delimiters and it will store the list of tokens within the array-reference you have supplied. Note, that the array, which is passed as a reference (w$() in the synopsis), will be resized accordingly, so that you don't have to figure out the number of tokens in advance. The element at position zero (i.e. w$(0)) will not be used. + +Normally (i.e. if you omit the third, which is the delimiter-argument) the function will regard space or tab as delimiters for tokens; however by supplying a third argument, you may split at any single of the characters within this string. E.g. if you supply ":;" as the third argument, then colon (:) or semicolon (;) will delimit tokens. +Note, that a sequence of separator-characters will produce a sequence of empty tokens; that way, the number of tokens returned will always be one plus the number of separator characters contained within the string. Refer to the closely related token-function, if you do not like this behaviour. In some way, the split-function focuses on the separators (other than the token-function, which focuses on the tokens), hence its name. + +The second argument is a reference on a string-array, where the tokens will be stored; this array will be expanded (or shrinked) to have room for all tokens, if necessary. +The first argument finally contains the text, that will be split into tokens. The split-function returns the number of tokens that have been found. + +Please see the examples below for some hints on the exact behaviour of the split-function and how it differs from the token-function: + +Example: +print "This program will help you to understand, how the" +print "split()-function exactly works and how it behaves" +print "in certain special cases." +print +print "Please enter a line containing tokens separated" +print "by either '=' or '-'" +dim t$(10) +do + print + input "Please enter a line: " l$ + num=split(l$,t$(),"=-") + print num," Tokens: " + for a=1 to num + if (t$(a)="") then + print "(EMPTY)" + else + print t$(a); + endif + if (a0 and a$=left$("no",len(a$)) exit +loop +Explanation: + +This example asks for an answer (yes or no) and removes spaces with trim$ to make the comparison with the string "no" more bulletproof. + + +Related: ltrim$, rtrim$ + +& +upper$() + +Name: +upper$() -- convert a string to upper case + +Synopsis: +u$=upper$(a$) + +Description: +The upper$-function accepts a single string argument and converts it to all upper case. + +Example: +line input "Please enter a sentence without the letter 'e': " l$ +p=instr(upper$(l$),"E") +if (p) then + l$=lower$(l$) + mid$(l$,p,1)="E" + print "Hey, you are wrong, see here!" + print l$ +else + print "Thanks." +endif +Explanation: + +This program asks for a sentence and marks the first (if any) occurence of the letter 'e' by coverting it to upper case (in contrast to the rest of the sentence, which is converted to lower case). + + +Related: lower$ + +& +val() + +Name: +val() -- converts a string to a number + +Synopsis: +x=val(x$) + +Description: +The val-function checks, if the start of its string argument forms a floating point number and then returns this number. The string therefore has to start with digits (only whitespace infront is allowed), otherwise the val-function returns zero. + +Example: +input "Please enter a length, either in inches (in) or centimeters (cm) " l$ +if (right$(l$,2)="in") then + l=val(l$)*2.51 +else + l=val(l$) +endif +print "You have entered ",l,"cm." +Explanation: + +This example queries for a length and checks, if it has been specified in inches or centimeters. The length is then converted to centimeters. + + +Related: str$ + +&Input and Output +& +at() + +Name: +at() -- can be used in the print-command to place the output at a specified position + +Synopsis: +clear screen +... +print at(a,b) +print @(a,b) + +Description: +The at-clause takes two numeric arguments (e.g. at(2,3)) and can be inserted after the print-keyword. at() can be used only if clear screen has been executed at least once within the program (otherwise you will get an error). + +The two numeric arguments of the at-function may range from 0 to the width of your terminal minus 1, and from 0 to the height of your terminal minus 1; if any argument exceeds these values, it will be truncated accordingly. However, yab has no influence on the size of your terminal (80x25 is a common, but not mandatory), the size of your terminal and the maximum values acceptable within the at-clause may vary. To get the size of your terminal you may use the peek-function: peek("screenwidth") returns the width of your terminal and peek("screenheight") its height. + +Example: +clear screen +maxx=peek("screenwidth")-1:maxy=peek("screenheight")-1 +for x=0 to maxx + print at(x,maxy*(0.5+sin(2*pi*x/maxx)/2)) "*" +next x +Explanation: + +This example plots a full period of the sine-function across the screen. Start this program in a terminal. + + +Related: print, clear screen, color + +& +clear screen + +Name: +clear screen -- erases the text window + +Synopsis: +clear screen + +Description: +clear screen erases the text window (the window where the output of print appears). +It must be issued at least once, before some advanced screen-commands (e.g. print at or inkey$) may be called; this requirement is due to some limititations of the curses-library, which is used by yab for some commands. + +Example: +clear screen +print "Please press a key : " +a$=inkey$ +print a$ +Explanation: + +The clear screen command is essential here; if it would be omitted, yab would issue an error ("need to call 'clear screen' first") while trying to execute the inkey$-function. + +Start this program in a terminal. + + +Related: inkey$ + +& +close + +Name: +close -- close a file, which has been opened before + +Synopsis: +close filenum +close # filenum + +Description: +The close-command closes an open file. You should issue this command as soon as you are done with reading from or writing to a file. + +Example: +open "my.data" for reading as 1 +input #1 a +print a +close 1 +Explanation: + +This program opens the file "my.data", reads a number from it, prints this number and closes the file again. + + +Related: open + +& +color + +Name: +color -- print with color + +Synopsis: +print color(fore$) text$ +print color(fore$,back$) text$ + +Description: +Not a seperate command, but part of the print-command; may be included just after print and can only be issued after clear screen has been executed. + +color() takes one or two string-arguments, specifying the color of the text and (optionally) the background. +The one or two strings passed to color() can be one of these: "black", "white", "red", "blue", "green", "yellow", "cyan" and "magenta" (which can be abbreviated as "bla", "whi", "red", "blu", "gre", "yel", "cya" and "mag" respectively). color() can only be used, if clear scren has been issued at least once. + +Note, that color() can be written as colour() too. + +Example: +clear screen +dim col$(7):for a=0 to 7:read col$(a):next a +do + print color(col$(ran(7)),col$(ran(7))) " Hallo " + pause 0.01 +loop +data "black","white","red","blue" +data "green","yellow","cyan","magenta" +Explanation: + +This prints the word " Hallo " in all colors accross your screen. +Start this program in a terminal. + +Related: print, clear screen, at + +& +colour + +Name: +colour -- see color + +Synopsis: +print colour(fore$) text$ +print colour(fore$,back$) text$ + +Description: +See color. + +Related: color + +& +eof + +Name: +eof -- check, if an open file contains data + +Synopsis: +open 1,"foo.bar" +if (eof(1)) then + ... +end if + +Description: +The eof-function checks, if there is still data left within an open file. As an argument it expects the file-number as returned by (or used within) the open-function (or statement). + +Example: +a=open("foo.bar") +while(not eof(a)) + input #a,a$ + print a$ +end while +Explanation: + +This example will print the contents of the file "foo.bar". The eof-function will terminate the loop, if there is no more data left within the file. + + +Related: open + +& +getscreen$() + +Name: +getscreen$() -- returns a string representing a rectangular section of the text terminal + +Synopsis: +a$=getscreen$(2,2,20,20) + +Description: +The getscreen$ function returns a string representing the area of the screen as specified by its four arguments (which specify two corners). I.e. everything you have printed within this rectangle will be encoded in the string returned (including any colour-information). +Like most other commands dealing with advanced text output, getscreen$ requires, that you have called clear screen before. + +Example: +clear screen + +for a=1 to 1000: + print color("red") "1" + print color("green") "2" + print color("blue") "3" +next a +screen$=getscreen$(10,10,40,10) +print at(10,10) " Please Press 'y' or 'n'! " +a$=inkey$ +putscreen screen$,10,10 +Explanation: + +This program fills the screen with coloured digits and afterwards asks the user for a choice ( Please press 'y' or 'n'! ). Afterwards the area of the screen, which has been overwritten by the question will be restored with its previous contents, whhch had been saved via getscreen$. + +Start this program in a terminal. + +Related: putscreen$ + +& +inkey$ + +Name: +inkey$ -- wait, until a key is pressed + +Synopsis: +clear screen +foo$=inkey$ +inkey$ +foo$=inkey$(bar) +inkey$(bar) + +Description: +The inkeys$-function waits, until the user presses a key on the keyboard or a button of his mouse, and returns this very key. An optional argument specifies the number of seconds to wait; if omitted, inkey$ will wait indefinitely. inkey$ may only be used, if clear screen has been called at least once. + +For normal keys, yab simply returns the key, e.g. a, 1 or !. For function keys you will get f1, f2 and so on. Other special keys will return these strings respectively: enter, backspace, del, esc, scrnup (for screen up), scrndown and tab. Modifier keys (e.g. ctrl, alt or shift) by themself can not be detected (however, if you press shift and e.g. a simultaniously, inkey$ will return the letter A instead of a of course). + +Example: +clear screen +print "Press any key or press 'q' to stop." +repeat + a$=inkey$ + print a$ +until(a$="q") +Explanation: + +This program simply returns the key pressed. You may use it, to learn, which strings are returned for the special keys on your keyboard (e.g. function-keys). + +Start this program in a terminal. + +Related: clear screen + +& +input + +Name: +input -- read input from the user (or from a file) and assign it to a variable + +Synopsis: +input a +input a,b,c +input a$ +input "Hello" a +input #1 a$ + +Description: +input reads the new contents of one or many (numeric- or string-) variables, either from the keyboard (i.e. from you) or from a file. An optional first string-argument specifies a prompt, which will be issued before reading any contents. + +If you want to read from an open file, you need to specify a hash ('#'), followed by the number, under which the file has been opened. + +Note, that the input is split at spaces, i.e. if you enter a whole line consisting of many space-seperated word, the first input-statement will only return the first word; the other words will only be returned on subsequent calls to input; the same applies, if a single input reads multiple variables: The first variable gets only the first word, the second one the second word, and so on. If you don't like this behaviour, you may use line input, which returns a whole line (including embedded spaces) at once. + +Example: +input "Please enter the name of a file to read: " a$ +open 1,a$ +while(!eof(1)) + input #1 b$ + print b$ +wend +Explanation: + +If this program is stored within a file test.yab and you enter this name when prompted for a file to read, you will see this output: + +&exverbatim +Please enter the name of a file to read: test.yab +input +"Please +enter +the +name +of +a +file +to +read: +" +a$ +open +1,a$ +while(!eof(1)) +input +#1 +b$ +print +b$ +wend +&exverbatim + + +Related: line input + +& +line input + +Name: +line input -- read in a whole line of text and assign it to a variable + +Synopsis: +line input a +line input a$ +line input "Hello" a +line input #1 a$ + +Description: +In most respects line input is like the input-command: It reads the new contents of a variable, either from keyboard or from a file. However, line input always reads a complete line and assigns it to its variable. line input does not stop reading at spaces and is therefore the best way to read in a string which might contain whitespace. Note, that the final newline is stripped of. + +Example: +line input "Please enter your name (e.g. Frodo Beutelin): " a$ +print "Hello ",a$ +Explanation: + +Note that the usage of line input is essential in this example; a simple input-statement would only return the string up to the first space, e.g. Frodo. + + +Related: input + +& +open + +Name: +open -- open a file + +Synopsis: +open a,"file","r" +open #a,"file","w" +open "file" for reading as a +open "file" for writing as #a +a=open("file") +a=open("file","r") +if (open(a,"file")) ... +if (open(a,"file","w")) ... + +Description: +The open-command opens a file for reading or writing for printing text. open comes in a wide variety of ways; it requires these arguments:filenumber In the synopsis this is a or #a. In yab each file is associated with a number between 1 and a maximum value, which depends on the operating system. + +For historical reasons the filenumber can be preceded by a hash ('#'). Note, that specifying a filenumber is optional; if it is omitted, the open-function will return a filenumber, which should then be stored in a variable for later reference. This filenumber can be a simple number or an arbitrary complex arithmetic expression, in which case braces might be necessary to save yab from getting confused. + +filename -- In the synopsis above this is "file". This string specifies the name of the file to open (note the important caveat on specifying these filenames). +accessmode -- In the synopsis this is "r", "w", for reading or for writing. This string or clause specifies the mode in which the file is opened; it may be one of: "r"Open the file for reading (may also be written as for reading). If the file does not exist, the command will fail. This mode is the default, i.e. if no mode is specified with the open-command, the file will be opened with this mode. + +"w" -- Open the file for writing (may also be written as for writing). If the file does not exist, it will be created. + +"a" -- Open the file for appending, i.e. what you write to the file will be appended after its initial contents. If the file does not exist, it will be created. + +"b" -- This letter may not appear alone, but may be combined with the other letters (e.g. "rb") to open a file in binary mode (as opposed to text mode). + +As you may see from the synopsis, the open-command may either be called as a command (without braces) or as a function (with braces). If called as a function, it will return the filenumber or zero if the operation fails. Therefore the open-function may be used within the condition of an if-statement. + +If the open-command fails, you may use peek("error") to retrieve the exact nature of the error. +Finally you may read the description for peek("error") to learn which errors may have happened during an open-call. + +Example: +open "foo.bar" for writing as #1 +print #1 "Hallo!" +close #1 +if (not open(1,"foo.bar")) error "Could not open 'foo.bar' for reading" +while(not eof(1)) + line input #1 a$ + print a$ +wend +Explanation: + +This example simply opens the file foo.bar, writes a single line, reopens it and reads its contents again. + + +Related: close, print, peek + +& +print + +Name: +print -- Write to terminal or file + +Synopsis: +print "foo",a$,b +print "foo","a$,b; +print #a "foo",a$ +print #a "foo",a$; +print foo using "##.###" +print reverse "foo" +print at(10,10) a$,b +print @(10,10) a$,b +print color("red","blue") a$,b +print color("magenta") a$,b +print color("green","yellow") at(5,5) a$,b + +Description: +The print-statement outputs strings or characters, either to your terminal (also known as console) or to an open file. + +To understand all those uses of the print-statement, let's go throught the various lines in the synopsis above:print "foo",a$,bPrint the string foo as well as the contents of the variables a$ and b onto the screen, silently adding a newline. + +print "foo",a$,b; +(Note the trailing semicolon!) This statement does the same as the one above; only the implicit newline is skipped, which means that the next print-statement will append seamlessly. + +print #a "foo",a$ +This is the way to write to files. The file with the number a must be open already, an implicit newline is added. Note the file-number #a, which starts with a hash ('#') amd is separated from the rest of the statement by a space only. The file-number (contained in the variable a) must have been returned by a previous open-statement (e.g. a=open("bar")). + +print #a "foo",a$; +The same as above, but without the implicit newline. + +print foo using "##.###" +Print the number foo with as many digits before and after the decimal dot as given by the number of '#'-signs. See the entries for using and str$ for a detailed description of this format. + +print reverse "foo" +As all the print-variants to follow, this form of the print-statement can only be issued after clear screen has been called. The strings and numbers after the reverse-clause are simply printed inverse (compared to the normal print-statement). + +print at(10,10) a$,b +Print at the specified (x,y)-position. This is only allowed after clear screen has been called. You may want to query peek$("screenwidth") or peek$("screenheight") to learn the actual size of your screen. You may add a semicolon to suppress the implicit newline. + +print @(10,10) a$,b +This is exactly the same as above, however, at may be written as @. + +print color("red","blue") at(5,5) a$,b +Print with the specified fore- ("red") and background ("blue") color (or colour). The possible values are "black", "white", "red", "blue", "green", "yellow", "cyan" or "magenta". Again, you need to call clear screen first and add a semicolon if you want to suppress the implicit newline. + +print color("magenta") a$,b +You may specify the foreground color only. + +print color("green","yellow") a$,b +A color and a position (in this sequence, not the other way around) may be specified at once. + +Example: +clear screen +columns=peek("screenwidth") +lines=peek("screenheight") +dim col$(7) +for a=0 to 7:read col$(a):next a +data "black","white","red","blue","green","yellow","cyan","magenta" + +for a=0 to 2*pi step 0.1 + print colour(col$(mod(i,8))) at(columns*(0.8*sin(a)+0.9)/2,lines*(0.8*cos(a)+0.9)/2) "*" + i=i+1 +next a +Explanation: + +This example draws a cloured ellipse within the text window. +Start this program in a terminal. + +Related: at, color, input, clear screen, using, ; + +& +putscreen + +Name: +putscreen -- draw a rectangle of characters into the text terminal + +Synopsis +clear screen +... +a$=getscreen$(5,5,10,10) +... +putscreen a$,7,7 + +Description: +The putscreen-command is the counterpart of the getscreen$-function. putscreen requires a string as returned by the getscreen-function. Such a string contains a rectangular detail from the terminal; the putscreen-function puts such a region back into the terminal-window. +Note, that clear screen must have been called before. + +Example: +clear screen +for a=1 to 200 + print color("red") "Hallo!" + print color("blue") "Welt!" +next a +r$=getscreen$(0,0,20,20) +for x=0 to 60 + putscreen r$,x,0 + sleep 0.1 +next x +Explanation: + +This example prints the string "Hallo!Welt!" all over the screen and then moves a rectangle from one side to the other. +Start this program in a terminal. + +Related: getscreen$, clear screen + +& +reverse + +Name: +reverse -- print reverse (background and foreground colors exchanged) + +Synopsis: +clear screen +... +print reverse "foo" + +Description: +reverse may be used to print text in reverse. reverse is not a seperate command, but part of the print-command; it may be included just after the print and can only be issued once that clear screen has been issued. + +Example: +clear screen + +print "1 " +c=3 +do + prim=true + for a=2 to sqrt(c) + if (frac(c/a)=0) then + prim=false + break + endif + next a + if (prim) then + print + print reverse c; + else + print c; + endif + print " " + c=c+1 +loop +Explanation: + +This program prints numbers from 1 on and marks each prime number in reverse. +Start this program in a terminal. + +Related: at, color, print, clear screen + +& +screen + +Name: +screen -- as clear screen clears the text window + +Synopsis: +clear screen + +Description: +The keyword screen appears only within the sequence clear screen; please see there for a description. + +Related: clear screen + +& +seek() + +Name: +seek() -- change the position within an open file + +Synopsis: +open 1,"foo" +seek #1,q +seek #1,x,"begin" +seek #1,y,"end" +seek #1,z,"here" + +Description: +The seek-command changes the position, where the next input (or peek) statement will read from an open file. Usually files are read from the beginning to the end sequentially; however sometimes you may want to depart from this simple scheme. This can be done with the seek-command, allowing you to change the position, where the next piece of data will be read from the file. + +seek accepts two or three arguments: The first one is the number of an already open file. The second one is the position where the next read from the file will start. The third argument is optional and specifies the the point from where the position (the second argument) will count. It can be one of: + +begin -- Count from the beginning of the file. + +end -- Count from the end of the file. + +here -- Count from the current position within the file. + + +Example: +open #1,"count.dat","w" +for a=1 to 10 + print #1,"00000000" + if (a<10) print #1,"" +next a + +dim count(10) +do + x=int(ran(10)) + i=i+1 + if (mod(i,1000)=0) print "." + count(x)=count(x)+1 + curr$=right$("00000000"+str$(count(x)),8) + seek #1,9*x,"begin" + print #1,curr$; +loop +Explanation: + +This example increments randomly one of ten counters (in the array count()); however, the result is always kept and updated within the file count.dat, so even in case of an unexpected interrupt, the result will not be lost. + + +Related: tell, open, print, peek + +& +tell + +Name: +tell -- get the current position within an open file + +Synopsis: +open #1,"foo" + ... +position=tell(#1) + +Description: +The tell-function requires the number of an open file as an argument. It returns the position (counted in bytes, starting from the beginning of the file) where the next read will start. + +Example: +open #1,"foo","w" +print #1 "Hello World!" +close #1 + +open #1,"foo" +seek #1,0,"end" +print tell(#1) +close 1 +Explanation: + +This example (mis)uses tell to get the size of the file. The seek positions the file pointer at the end of the file, therefor the call to tell returns the total length of the file. + + +Related: tell, open + +& +using + +Name: +using -- Specify the format for printing a number + +Synopsis: +print a using "##.###" +print a using("##.###",",.") + +Description: +The using-keyword may appear as part of the print-statement and specifies the format (e.g. the number of digits before and after the decimal dot), which should be used to print the number. + +The possible values for the format argument ("##.###" in the synopsis above) are described within the entry for the str$-function; especially the second line in the synopsis (print a using("##.###",",.")) will become clear after referring to str$. In fact the using clause is closely related to the str$-function; the former can always be rewritten using the latter; i.e. print foo using bar$ is always equivalent to print str$(foo,bar$). Therefore you should check out str$ to learn more. + +Example: +for a=1 to 10 + print sqrt(ran(10000*a)) using "#########.#####" +next a +Explanation: + +This example prints a column of square roots of random number, nicely aligned at the decimal dot. + + +Related: print, str$ + +& +# + +Name: +# -- either a comment or a marker for a file-number + +Synopsis: +# This is a comment, but the line below not! +open #1,"foo" + +Description: +The hash ('#') has two totally unrelated uses:A hash might appear in commands related with file-io. yab uses simple numbers to refer to open files (within input, print, peek or eof). In those commands the hash may precede the number, which species the file. Please see those commands for further information and examples; the rest of this entry is about the second use (as a comment). + +As the very first character within a line, a hash introduces comments (similar to rem). +'#' as a comment is common in most scripting languages and has a special use under BeOS: If the very first line of any BeOS-program begins with the character sequence '#!' ("she-bang", no spaces allowed), the rest of the line is taken as the program that should be used to execute the script. I.e. if your yab-program starts with '#!/boot/home/config/bin/yab', the program /boot/home/config/bin/yab will be invoked to execute the rest of the program. + +Example: +# This line is a valid comment +print "Hello " : # But this is a syntax error, because +print "World!" : # the hash is not the first character! +Explanation: + +Note, that this example will produce a syntax error and is not a valid program! + + +Related: input, print, peek, eof, //, rem + +& +at() + +Name: +at() -- can be used in the print-command to place the output at a specified position + +Synopsis: +clear screen +... +print at(a,b) +print @(a,b) + +Description: +The at-clause takes two numeric arguments (e.g. at(2,3)) and can be inserted after the print-keyword. at() can be used only if clear screen has been executed at least once within the program (otherwise you will get an error). + +The two numeric arguments of the at-function may range from 0 to the width of your terminal minus 1, and from 0 to the height of your terminal minus 1; if any argument exceeds these values, it will be truncated accordingly. However, yab has no influence on the size of your terminal (80x25 is a common, but not mandatory), the size of your terminal and the maximum values acceptable within the at-clause may vary. To get the size of your terminal you may use the peek-function: peek("screenwidth") returns the width of your terminal and peek("screenheight") its height. + +Example: +clear screen +maxx=peek("screenwidth")-1:maxy=peek("screenheight")-1 +for x=0 to maxx + print at(x,maxy*(0.5+sin(2*pi*x/maxx)/2)) "*" +next x +Explanation: + +This example plots a full period of the sine-function across the screen. +Start this program in a terminal. + +Related: print, clear screen, color + +& +; + +Name: +; -- suppress the implicit newline after a print-statement + +Synopsis: +print "foo",bar; + +Description: +The semicolon (';') may only appear at the last position within a print-statement. It supresses the implicit newline, which yab normally adds after each print-statement. + +Put another way: Normally the output of each print-statement appears on a line by itself. If you rather want the output of many print-statements to appear on a single line, you should end the print-statement with a semicolon. + +Example: +print "Hello ":print "World!" +Explanation: + +This example prints Hello World! in a single line. + + +Related: print + +&Subroutines +& +end sub + +Name: +end sub -- ends a subroutine definition + +Synopsis: +sub foo(...) + ... +end sub + +Description: +Marks the end of a subroutine-definition (which starts with the sub-keyword). The whole concept of subroutines is explained within the entry for sub. +Example: +print foo(3) + +sub foo(a) + return a*2 +end sub +Explanation: + +This program prints out 6. The subroutine foo simply returns twice its argument. + + +Related: sub + +& +export + +Name: +export -- mark a function as globally visible + +Synopsis: +export sub foo(bar) +... +end sub + +Description: +The export-statement is used within libraries to mark a user defined subroutine as visible outside the library wherein it is defined. Subroutines, which are not exported, must be qualified with the name of the library, e.g. foo.baz (where foo is the name of the library and baz the name of the subroutine); exported subroutines may be used without specifying the name of the library, e.g. bar. + +Therefore export may only be useful within libraries. + +Example: +export sub bar() + print "Hello" +end sub + +sub baz() + print "World" +end sub +Explanation: + +The library foo.bar (which is listed above) defines two functions bar and baz, however only the function bar is exported and therefore visible even outside the library; baz is not exported and may only be used within the library foo.yab. + +Now within your main program cux.yab (which imports the library foo.yab); note that this program produces an error: +&exverbatim +import foo + +print "Calling subroutine foo.bar (okay) ..." +foo.bar() +print "done." + +print "Calling subroutine bar (okay) ..." +bar() +print "done." + +print "Calling subroutine foo.baz (okay) ..." +foo.baz() +print "done." + +print "Calling subroutine baz (NOT okay) ..." +baz() +print "done." +&exverbatim + +The output when executing yab foo.yab is this: + +&exverbatim +Calling subroutine foo.bar (okay) ... +Hello +done. +Calling subroutine bar (okay) ... +Hello +done. +Calling subroutine foo.baz (okay) ... +World +done. +Calling subroutine baz (NOT okay) ... +---Error in main.yab, line 16: can't find subroutine 'baz' +---Dump: sub baz() called in main.yab,16 +---Error: Program stopped due to an error +&exverbatim + +As the error message above shows, the subroutine baz must be qualified with the name of the library, if used outside the library, wherein it is defined (e.g. foo.baz. I.e. outside the library foo.yab you need to write foo.baz. baz alone would be an error. + +The subroutine bar (without adding the name of the library) however may (and probably should) be used in any program, which imports the library foo.yab. +Note: In some sense the set of exported subroutines constitutes the interface of a library. + + +Related: sub, import + +& +import + +Name: +import -- import a library + +Synopsis: +import foo + +Description: +The import-statment imports a library. It expects a single argument, which must be the name of a library (without the trailing .yab). This library will then be read and parsed and its subroutines (and variables) will be made available within the main program. + +Libraries will first be searched within the current directory (i.e. the directory within which you have invoked yab), then within the special directory /boot/home/config/lib/yab. The location of this second directory may be changed with the option -library. + +Example: +import lib + +rem This works ... +lib.x(0) + +rem This works too .. +x(1) + +rem And this. +lib.y(2) + +rem But this not! +y(3) +Explanation: + +Lets say you have a yab-program foo.yab, which imports a library lib.yab. + +Now the library lib.yab reads: + +&exverbatim +rem Make the subroutine x easily available outside this library +export sub x(a) + print a + return +end sub + +rem sub y must be referenced by its full name +rem outside this library +sub y(a) + print a + return +end sub +&exverbatim + +This program produces an error: + +&exverbatim +0 +1 +2 +---Error in foo.yab, line 13: can't find subroutine 'y' +---Dump: sub y() called in foo.yab,13 +---Error: Program stopped due to an error +&exverbatim + +As you may see from the error message, yab is unable to find the subroutine y without specifying the name of the library (i.e. lib.y). The reason for this is, that y, other than x, is not exported from the library lib.yab (using the export-statement). + + +Related: export, sub + +& +local + +Name: +local -- mark a variable as local to a subroutine + +Synopsis: +sub foo() + + local a,b,c$,d(10),e$(5,5) + + ... + +end sub + +Description: +The local-command can (and should be) used to mark a variable (or array) as local to the containing subroutine. This means, that a local variable in your subroutine is totally different from a variable with the same name within your main program. Variables which are known everywhere within your program are called global in contrast. +Declaring variables within the subroutine as local helps to avoid hard to find bugs; therefore local variables should be used whenever possible. + +Note, that the parameters of your subroutines are always local. + +As you may see from the example, local arrays may be created without using the keyword dim (which is required only for global arrays). + +Example: +a=1 +b=1 +print a,b +foo() +print a,b + +sub foo() + local a + a=2 + b=2 +end sub +Explanation: + +This example demonstrates the difference between local and global variables; it produces this output: +1 1 +1 2 +As you may see, the content of the global variable a is unchanged after the subroutine foo; this is because the assignment a=2 within the subroutine affects the local variable a only and not the global one. However, the variable b is never declared local and therefore the subroutine changes the global variable, which is reflected in the output of the second print-statement. + + +Related: sub, static, dim + +& +numparams + +Name: +numparams -- return the number of parameters, that have been passed to a subroutine + +Synopsis: +sub foo(a,b,c) + if (numparams=1) ... + ... +end sub + +Description: +Within a subroutine the local variable numparam or numparams contains the number of parameters, that have been passed to the subroutine. This information can be useful, because the subroutine may have been called with fewer parameters than actually declared. The number of values that actually have been passed while calling the subroutine, can be found in numparams. + +Note, that arguments which are used in the definition of a subroutine but are left out during a call to it (thereby reducing the value of numparams) receive a value of 0 or "" (empty string) respectively. + +Example: +a$="123456789" +print part$(a$,4) +print part$(a$,3,7) + +sub part$(a$,f,t) + if (numparams=2) then + return mid$(a$,f) + else + return mid$(a$,f,t-f+1) + end if +end sub +Explanation: + +When you run this example, it will print 456789 and 34567. Take a look at the subroutine part$, which returns part of the string which has been passed as an argument. If (besides the string) two numbers are passed, they define the starting and end position of the substring, that will be returned. However, if only one number is passed, the rest of the string, starting from this position will be returned. Each of these cases is recognized with the help of the numparams variable. + + +Related: sub + +& +return + +Name: +return -- return from a subroutine or a gosub + +Synopsis: +gosub foo +... +label foo +... +return + +sub bar(baz) + ... + return quertz +end sub + +Description: +The return-statement serves two different (albeit somewhat related) purposes. The probably more important use of return is to return control from within a subroutine to the place in your program, where the subroutine has been called. If the subroutine is declared to return a value, the return-statement might be accompanied by a string or number, which constitutes the return value of the subroutine. + +However, even if the subroutine should return a value, the return-statement need not carry a value; in that case the subroutine will return 0 or the empty string (depending on the type of the subroutine). Moreover, feel free to place multiple return-statements within your subroutine; it's a nice way of controlling the flow of execution. +The second (but historcially first) use of return is to return to the position, where a prior gosub has left off. In that case return may not carry a value. + +Example: +do + read a$ + if (a$="") then + print + end + endif + print mark$(a$)," " +loop + +data "The","quick","brown","fox","jumped" +data "over","the","lazy","dog","" + +sub mark$(a$) + if (instr(lower$(a$),"q")) return upper$(a$) + return a$ +end sub +Explanation: + +This example features a subroutine mark$, that returns its argument in upper case, if it contains the letter "q", or unchanged otherwise. In the test-text the word quick will end up beeing marked as QUICK. +The example above demonstrates return within subroutines; please see gosub for an example of how to use return in this context. + + +Related: sub, gosub + +& +static + +Name: +static -- preserves the value of a variable between calls to a subroutine + +Synopsis: +sub foo() + + static a + + ... + +end sub + +Description: +The static keyword can be used within subroutines to mark variables as static. This has two effects: First, the variable is local to the subroutine, i.e. its value is not know outside the subroutine (this is the effect of the local keyword). Second, the static-keyword arranges things, so that the variable keeps its value between invocations of the subroutine (this is different from the local-keyword). + +Example: +foo() +foo() +foo() + +sub foo() + static a + local b + a=a+1 + b=b+1 + print a,b +end sub +Explanation: + +This program shows the difference between static and local variables within a subroutine; it produces this output: + +&exverbatim +1 1 +2 1 +3 1 +&exverbatim + +The output shows, that the static variable a keeps its value between subroutine calls, whereas b is initialized with the value 0 at every call to the subroutine foo. + + +Related: sub, local + +& +sub + +Name: +sub -- declare a user defined subroutine + +Synopsis: +foo(2,"hello") + +... + +sub foo(bar,baz$) + ... + return qux + ... +end sub + +Description: +The sub-keyword starts the definition of a user defined subroutine. With user defined subroutines you are able to somewhat extend yab with your own commands or functions. A subroutine accepts arguments (numbers or strings) and returns a number or a string (however, you are not required to assign the value returned to a variable). The name of the subroutine follows after the keyword sub. If the name (in the synopsis: foo) ends on a '$', the subroutine should return a string (with the return-statement), otherwise a number. + +After the name of the subroutine yab requires a pair of braces; within those braces you may specify a list of parameters, for which values can (but need not) be included when calling the subroutine. If you omit one of those parameters when calling such a subroutine, it assumes the value zero (for numeric parameters) or the empty string (for string parameters). However with peek("argument") you may find out, how many arguments have really been passed while calling the subroutine. + +Parameters of a subroutine are always local variables (see the keyword local for more explanation). +From within the subroutine you may return any time with the keyword return; along with the return-keyword you may specify the return value. Note that more than one return is allowed within a single subroutine. + +Finally, the keyword end sub ends the subroutine definition. Note, that the definition of a subroutine need not appear within the program before the first call to this sub. + +Note: As braces have two uses in yab (i.e. for supplying arguments to a subroutine as well as to list the indices of an array). yab can not tell apart an array from a subroutine with the same name. Therefore you cannot define a subroutine with the same name as an array! + +Example: +p=2 +do + if (is_prime(p)) print p + p=p+1 +loop + +sub is_prime(a) + local b + for b=2 to sqrt(a) + if (frac(a/b)=0) return false + next b + return true +end sub +Explanation: + +This example is not the recommended way to compute prime numbers. However it gives a nice demonstration of using a subroutine. + + +Related: local, static, peek + +&System +& +bind() + +Name: +bind() -- Binds a yab-program and the yab-interpreter together into a standalone program. + +Synopsis: +bind("foo.exe") + +Description: +The bind-command combines your own yab-program (plus all the libraries it does import) and the interpreter by copying them into a new file, whose name is passed as an argument. This new program may then be executed on any computer, even if it does not have yab installed. + +Note: With the current version of yab, bind should not be used anymore, use the Build Factory instead. + +Example: +if (!peek("isbound")) then + bind "foo" + print "Successfully created the standalone executable 'foo'!" + exit +endif + +print "Hello World!" +Explanation: + +This example creates a standalone program foo from itself. + + +Related: peek +& +clipboard copy + +Name: +clipboard copy -- copy a string to the clipboard + +Synopsis: +CLIPBOARD COPY Text$ + +Description: +Clipboard copy simply copies the string Text$ to the system clipboard. Note: This will overwrite all text currently stored in the clipboard. + +Example: +print "This is the content of the clipboard: "+clipboard paste$ +print "Now we copy \"Foo Bar\" to the clipboard" +clipboard copy "Foo Bar" +print "This is the content of the clipboard: "+clipboard paste$ +Explanation: + +The example will first display whatever is written in the clipboard (might be empty too), and then copies the string "Foo Bar" to the clipboard. Another output shows, it actually worked. + +Related: clipboard paste$ +& +clipboard paste$ + +Name: +clipboard paste$ -- read out the clipboard + +Synopsis: +Text$ = CLIPBOARD PASTE$ + +Description: +This command will read out ("paste") the content of the system clipboard. + +Example: +print "This is the content of the clipboard: "+clipboard paste$ +print "Now we copy \"Foo Bar\" to the clipboard" +clipboard copy "Foo Bar" +print "This is the content of the clipboard: "+clipboard paste$ +Explanation: + +The example will first display whatever is written in the clipboard (might be empty too), and then copies the string "Foo Bar" to the clipboard. Another output shows, it actually worked. + +Related: clipboard copy +& +compile + +Name: +compile -- compile a string with yab-code on the fly + +Synopsis: +compile(code$) + +Description: +This is an advanced command (closely related with the execute-command). It allows you to compile a string of yab-code (which is the only argument). Afterwards the compiled code is a normal part of your program. +Note, that there is no way to remove the compiled code. + +Example: +compile("sub mysub(a):print a:end sub") +mysub(2) +Explanation: + +This example creates a function named mysub, which simply prints its single argument. + + +Related: execute + +& +date$ + +Name: +date$ -- returns a string with various components of the current date + +Synopsis: +a$=date$ + +Description: +The date$-function (which must be called without parantheses; i.e. date$() would be an error) returns a string containing various components of a date; an example would be 4-05-27-2004-Thu-May. This string consists of various fields seperated by hyphens ("-"):The day within the week as a number in the range 0 (=sunday) to 6 (=saturday) (in the example above: 4, i.e. thursday). + +The month as a number in the range 1 (=january) to 12 (=december) (in the example: 5 which stands for may). +The day within the month as a number in the range 1 to 31 (in the example: 27). +The full, 4-digit year (in the example: 2004, which reminds me that I should adjust the clock within my computer ...). +The abbreviated name of the day within the week (Mon to Sun). +The abbreviated name of the month (Jan to Dec). + +Therefore the whole example above (4-05-27-2004-Thu-May) would read: day 4 in the week (counting from 0), May 27 in the year 2004, which is a thursday in May. +Note, that all fields within the string returned by date$ have a fixed with (numbers are padded with zeroes); therefore it is easy to extract the various fields of a date format with mid$. + +Example: +rem Two ways to print the same ... + +print mid$(date$,3,10) + +dim fields$(6) +a=split(date$,fields$(),"-") +print fields$(2),"-",fields$(3),"-",fields$(4) +Explanation: + +This example shows two different techniques to extract components from the value returned by date$. The mid$-function is the preferred way, but you could just as well split the return-value of date$ at every "-" and store the result within an array of strings. + + +Related: time$ + +& +doc + +Name: +doc -- special comment, which might be retrieved by the program itself + +Synopsis: +doc This is a comment +docu This is another comment + +Description: +Introduces a comment, which spans up to the end of the line. But other than the rem-comment, any docu-comment is collected within the special docu$-array and might be retrieved later on. Moreover you might invoke yab -docu foo.yab on the commandline to retrieve the embedded documentation within the program foo.yab. +Instead of doc you may just as well write docu or even documentation. + +Example: +rem Hi, this has been written by me +rem +doc This program asks for a number and +doc prints this number multiplied with 2 +rem +rem Print out rhe above message +for a=1 to arraysize(docu$()):print docu$(a):next a + +rem Read and print the number +input "Please input a number: " x +print x*2 +Explanation: + +This program uses the comments within its code to print out a help message for the user. +The contents of the doc-lines are retrieved from the docu$-array; if you do not want a comment to be collected within this array, use the rem-statement instead. + + +Related: docu$, rem + +& +docu$ + +Name: +docu$ -- special array, containing the contents of all docu-statement within the program + +Synopsis: +a$=docu$(1) + +Description: +Before your program is executed, yab collects the content of all the doc-statements within your program within this 1-dimensional array (well only those within the main-program, libraries are skipped). +You may use the arraysize function to find out, how many lines it contains. + +Example: +docu +docu This program reads two numbers +docu and adds them. +docu + +rem retrieve and print the embedded documentation +for a=1 to arraysize(docu$(),1) + print docu$(a) +next a + +input "First number: " b +input "Second number: " c + +print "The sum of ",b," and ",c," is ",b+c +Explanation: + +This program uses the embedded documentation to issue a usage-message. + + +Related: arraydim, rem + +& +error + +Name: +error -- raise an error and terminate your program + +Synopsis: +error "Wrong, wrong, wrong!!" + +Description: +Produces the same kind or error messages, that yab itself produces (e.g. in case of a syntax-error). The single argument is issued along with the current line-number. + +Example: +input "Please enter a number between 1 and 10: " a +if (a<1 or a>10) error "Oh no ..." +Explanation: + +This program is very harsh in checking the users input; instead of just asking again, the program terminates with an error, if the user enters something wrong. +The error message would look like this: + +&exverbatim +---Error in t.yab, line 2: Oh no ... +---Error: Program stopped due to an error +&exverbatim + + +& +execute$() + +Name: +execute$() -- execute a user defined subroutine, which must return a string + +Synopsis: +print execute$("foo$","arg1","arg2") + +Description: +execute$ can be used to execute a user defined subroutine, whose name may be specified as a string expression. +This feature is the only way to execute a subroutine, whose name is not known by the time you write your program. This might happen, if you want to execute a subroutine, which is compiled (using the compile command) during the course of execution of your program. +Note however, that the execute$-function is not the preferred method to execute a user defined subroutine; almost all cases you should just execute a subroutine by writing down its name within your yab program (see the example). + +Example: +print execute$("foo$","Hello","world!") +sub foo$(a$,b$) + return a$+" "+b$ +end sub +Explanation: + +The example simply prints Hello world!, which is the return value of the user defined subroutine foo$. The same could be achieved by executing: + +&exverbatim +print foo$(a$,b$) +&exverbatim + + +Related: compile, execute + +& +execute() + +Name: +execute() -- execute a user defined subroutine, which must return a number + +Synopsis: +print execute("bar","arg1","arg2") + +Description: +The execute-function is the counterpart of the execute$-function (please see there for some caveats). execute executes subroutines, which returns a number. + +Example: +print execute("bar",2,3) +sub bar(a,b) + return a+b +end sub +Related: compile, execute$ + +& +exit + +Name: +exit -- terminate your program + +Synopsis: +exit +exit 1 + +Description: +Terminate your program and return any given value to the operating system. exit is similar to end, but it will terminate your program immediately, no matter what. + +Example: +print "Do you want to continue ?" +input "Please answer y(es) or n(o): " a$ +if (lower$(left$(a$,1))="n") exit 1 +Related: end + +& +iscomputeron + +Name: +iscomputeron -- tells you whether the computer is on + +Synopsis: +IsItTurnedOn = ISCOMPUTERON + +Description: +Returns 1 if the computer is on. If the computer isn't on, the value returned by this function is undefined. + +Example: +print "This program will run until the computer is shut down :)" +while(iscomputeron) +wend +Explanation: + +Iscomputeron looks nice for endless loops. + +& +pause + +Name: +pause -- pause, sleep, wait for the specified number of seconds + +Synopsis: +pause 5 + +Description: +The pause-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. + +The pause-command will simply wait for the specified number of seconds. This may be a fractional number, so you may well wait less than a second. However, if you try to pause for a smaller and smaller interval (e.g. 0.1 seconds, 0.01 seconds, 0.001 seconds and so on) you will find that at some point yab will not wait at all. +The pause-command cannot be interrupted. However, sometimes you may want the wait to be interuptible by simply pressing a key on the keyboard. In such cases you should consider using the inkey$-function, with a number of seconds as an argument). + +Example: +deg=0 +do + maxx=44+40*sin(deg) + for x=1 to maxx + print "*" + next x + pause 0.1+(maxx*maxx/(4*84*84)) + print + deg=deg+0.1 +loop +Explanation: + +This example draws a sine-curve; due to the pause-statement the speed of drawing varies in the same way as the speed of a ball might vary, if it would roll along this curve under the influence of gravity. + + +Related: sleep, wait + +& +peek + +Name: +peek -- retrieve various internal informations + +Synopsis: +print peek("foo") +a=peek(#1) + +Description: +The peek-function has many different and mostly unrelated uses. It is a kind of grabbag for retrieving all kinds of numerical information, internal to yab. The meaning of the numbers returned be the peek-function depends on the string or number passed as an argument. + +peek always returns a number, however the closely related peek$-function exists, which may be used to retrieve string information from among the internals of yab. Finally note, that some of the values which are retrieved with peek may even be changed, using the poke-function. + +There are two variants of the peek-function: One expects an integer, positive number and is described within the first entry of the list below. The other variant expects one of a well defined set of strings as described in the second and all the following entries of the list below. + +peek(a), peek(#a) +Read a single character from the file a (which must be open of course). + +peek("screenheight") +Return the height in characters of the window, wherein yab runs. If you have not called clear screen yet, this peekwill return 0, regardless of the size of your terminal. + +peek("screenwidth") +Return the width in characters of the window, wherein yab runs. If you have not called clear screen yet, this peekwill return 0, regardless of the size of your terminal. + +peek("argument") +Return the number of arguments, that have been passed to yab at invocation time. E.g. if yab has been called like this: + yab foo.yab bar baz +then peek("argument") will return 2. This is because foo.yab is treated as the name of the program to run, whereas bar and baz are considered arguments to the program, which are passed on the commandline. The function peek("argument") can be written as peek("arguments") too. +You will want to check out the corresponding function peek$("argument") to actually retrieve the arguments. Note, that each call to peek$("argument") reduces the number returned by peek("argument"). + +peek("isbound") +Return true, if the executing yab-program is part of a standalone program; see the section about creating a standalone-program for details. + +peek("version") +Return the version number of yab (e.g. 1). + +peek("error") +Return a number specifying the nature of the last error in an open- or seek-statement. Normally an error within an open-statement immediately terminates your program with an appropriate error-message, so there is no chance and no need to learn more about the nature of the error. However, if you use open as a condition (e.g. if (open(#1,"foo")) ...) the outcome (success or failure) of the open-operation will determine, if the condition evaluates to true or false. If now such an operation fails, your program will not be terminated and you might want to learn the reason for failure. This reason will be returned by peek("error") (as a number) or by peek$("error") (as a string)The table below shows the various error codes; the value returned by peek$("error") explains the nature of the error. Note, that the codes 10,11 and 12 refer to the seek-command. + +Error codes + +peek("error")| peek$("error") | Explanation +2 Stream already in use Do not try to open one and the same + filenumber twice; rather close it first. + +3 'x' is not a valid filemode The optional filemode argument, which may + be passed to the open-function, has an + invalid value + +4 could not open 'foo' The open-call did not work, no further + explanation is available. + +5 reached maximum number + of open files You have opened more files than your + operating system permits. + +9 invalid stream number An attempt to use an invalid + (e.g. negative) stream number; + example: open(-1,"foo") + +10 could not position stream x + to byte y seek did not work. + +11 stream x not open You have tried to seek within a stream, + that has not been opened yet. + +12 seek mode 'x' is none of + begin,end,here The argument, which has been passed to + seek is invalid. + +Example: +open "foo" for reading as #1 +open "bar" for writing as #2 +while(not eof(#1)) + poke #2,chr$(peek(#1)); +wend +Explanation: + +This program will copy the file foo byte by byte to bar. +Note, that each peek does something entirely different, and only one has been demonstratedabove. Therefore you need to make up examples yourself for all the other peeks. + + +Related: peek$, poke, open + +& +peek$ + +Name: +peek$ -- retrieve various internal string-informations + +Synopsis: +print peek$("foo") + +Description: +The peek$-function has many different and unrelated uses. It is a kind of grabbag for retrieving all kinds of string information, internal to yab; the exact nature of the strings returned be the peek$-function depends on the string passed as an argument. + +peek$ always returns a string, however the closely related peek-function exists, which may be used to retrieve numerical information from among the internals of yab. Finally note, that some of the values which are retrieved with peek$ may even be changed, using the poke-function. + +The following list shows all possible arguments to peek$:peek$("infolevel")Returns either "debug", "note", "warning", "error" or "fatal", depending on the current infolevel. This value can be specified with an option on the commandline or changed during the execution of the program with the corresponding poke; however, normally only the author of yab would want to change this from its default value "warning". + +peek$("error") +Return a string describing the nature of the last error in an open- or seek-statement. See the corresponding peek("error") for a detailed description. + +peek$("library") +Return the name of the library, this statement is contained in. See the import-command for a detailed description or for more about libraries. + +peek$("os") +This peek returns the name of the operating system, where your yab version was compiled on. This can be either "BeOS" or "ZETA". On BeOS R5 it will always be "BeOS" while on ZETA it can be both. To check whether the system is really running ZETA do: RealOS$ = upper$(system$("uname -o")) + +peek$("env","NAME") +Return the environment variable specified by NAME (which may be any string expression). Which kind of environment variables are available on your system depends, as well as their meaning, on your system; however typing env on the commandline will produce a list. Note, that peek$("env",...) can be written as peek$("environment",...) too. + +peek$("argument") +Return one of the arguments, that have been passed to yab at invocation time (the next call will return the the second argument, and so on). E.g. if yab has been called like this: yab foo.yab bar baz, then the first call to peek$("argument") will return bar. This is because foo.yab is treated as the name of the program to run, whereas bar and baz are considered arguments to this program, which are passed on the commandline. The second call to peek$("argument") will return baz. Note, that peek$("argument") can be written as peek$("arguments"). +Finally you will want to check out the corresponding function peek("argument"). + +Example: +print "You have supplied these arguments: " +while(peek("argument")) + print peek("argument"),peek$("argument") +wend +Explanation: + +If you save this program in a file foo.yab and execute it via yab t.yab a b c, your will get this output: + +&exverbatim +3a +2b +1c +&exverbatim + + +Related: peek, poke, open + +& +poke + +Name: +poke -- change selected internals of yab + +Synopsis: +poke "foo","bar" +poke "foo",baz +poke #a,"bar" +poke #a,baz + +Description: +The poke-command may be used to change details of yabs behaviour. Like the related function peek, poke does many different things, depending on the arguments supplied. + +Here are the different things you can do with poke:poke "infolevel","debug"Change the amount of internal information, that yab outputs during execution. +The second argument can be either "debug", "note", "warning", "error" or "fatal". However, normally you will not want to change this from its default value "warning". See also the related peek$("infolevel"). + +poke #1,a +Write the given byte (a in the example above) to the specified stream (#a in the example). + +See also the related function peek(#1). + +Example: +print "Hello, now you will see, how much work" +print "a simple for-loop involves ..." +input "Please press return " a$ +poke "infolevel","debug" +for a=1 to 10:next a +Explanation: + +This example only demonstrates one of the many pokes, which are described above: The program switches the infolevel to debug, which makes yab produce a lot of debug-messages during the subsequent for-loop. + + +Related: peek, peek$ + +& +rem + +Name: +rem -- start a comment + +Synopsis: +rem Hey, this is a comment + # this is a comment too +// even this +print "Not a comment" # This is an error!! +print "Not a comment":// But this is again a valid comment +print "Not a comment" // even this. +print "Not a comment" rem and this! + +Description: +rem introduces a comment (like # or //), that extends up to the end of the line. +Those comments do not even need a colon (':' infront of them); they (rem, # and //) all behave alike except for #, which may only appear at the very beginning of a line; therefore the fourth example in the synopsis above (print "Not a comment" # This is an error!!) is indeed an error. +Note, that rem is an abbreviation for remark. remark however is not a valid command in yab. +Finally note, that a comment intoduced with '#' may have a special meaning under BeOS; see the entry for # for details. + +Example: +# +rem comments on data structures +# are more useful than +// comments on algorithms. +rem +Explanation: + +This program does nothing, but in a splendid and well commented way. + + +Related: #, // + +& +sleep + +Name: +sleep -- pause, sleep, wait for the specified number of seconds + +Synopsis: +sleep 4 + +Description: +The sleep-command has many different names: You may write pause, sleep or wait interchangable; whatever you write, yab will always do exactly the same. +Therefore you should refer to the entry for the pause-function for further information. + +& +system$() + +Name: +system$() -- hand a statement over to your operating system and return its output + +Synopsis: +print system$("dir") + +Description: +The system$-command accepts a single string argument, specifying a command, that can be found and executed by your operating system. It returns the output of this command as one big string. + +Example: +input "Please enter the name of a directory: " d$ +print +print "This is the contents of the '"+d$+"':" +print system$("ls -l "+d$) +Explanation: + +This example lists the contents of a directory, employing the ls-command. + + +Related: system + +& +system() + +Name: +system() -- hand a statement over to your operating system and return its exitcode + +Synopsis: +ret=system("foo") +system("bar") + +Description: +The system-command accepts a single string argument, which specifies a command to be executed. The function will return the exitcode of the command; its output (if any) will be lost. + +Example: +print "Please enter the name of the file, that should be deleted." +input f$ +if (system("rm "+f$+" >/dev/null 2>&1")) then + print "Error!" +else + print "okay." +endif +Explanation: + +This program uses the commandline command rm to remove a file. + +Related: system$ + +& +thread get + +Name: +thread get -- get the thread identification for a team or program + +Synopsis: +Id = THREAD GET Option$, Program$ + +Description: +For more advanced control of the running threads, this command provides you with ID a given program named Program$. Option$ can be set as follows: + +Option$ = "TeamID" -- returns the team ID for the program named Program$. Specify the whole path with parameters (only the first 64 characters are important) for the team, the ID of the first team with this path and parameters will be returned. + +Option$ = "ThreadID" -- returns the thread ID for the program named Program$. Specify the program name, the ID of the first thread with this name will be returned. + +Thread get will return -1 when the program was not found. This helps you to find out whether a program e.g. started with the system command is still running or not. + +Note: Using thread get is much better than trying to parse "ps" from the command line. + +Example: +print thread get "teamid", "/boot/home/config/bin/yab" +print thread get "threadid", "yab" +Explanation: + +The first statement prints the team ID number of the first yab program running. The second statement prints the first thread ID of the first yab program running. Note: The team ID takes the whole path while the thread ID only takes the program name. + +Related: thread remove +& +thread remove + +Name: +thread remove -- kill a running thread or team + +Synopsis: +Success = THREAD REMOVE Option$, ID + +Description: +For a given ID this command kills either the team or the thread. Thus Option$ is either "TeamID" or "ThreadID". If the team or thread was killed successfully Success is set to true, otherwise it is set to false. + +Note: You can crash your system with this command! If you do not know what this command is meant for, then do not use it! + +Example: +id = thread get "teamid", "/boot/home/config/bin/yab kamikaze.yab" +print "Commiting suicide..." +success = thread remove "teamid", id +print "This line is never reached." +Explanation: + +Save this example in the file kamikaze.yab and start it from the command line (not from the IDE). It first gets the ID from itself and then kills its own team. Thus the last print command is not executed anymore. This is a very unelegant way to exit. + +Related: thread get +& +time$ + +Name: +time$ -- return a string containing the current time + +Synopsis: +print time$ +print time$() + +Description: +The time$ function returns the current time in four fields separated by hyphens '-'. The fields are:The current hour in the range from 0 to 23, padded with zeroes (e.g. 00 or 04) to a length of two characters. + +The number of minutes, padded with zeroes. +The number of seconds, padded with zeroes. +The number of seconds, that have elapsed since the program has been started. This value encreases as long as your program runs and is therefore unbound and not padded with zeroes. + +At the time of writing this documentation, time$ returns 22-58-53-0. Note, that the first three of the four fields returned by time$ have a fixed width; therefore it is easy to extract some fields with the usual string-functions mid$ (and others). + +Example: +print "Hello it is ",time$ +print "An empty for-loop with ten million iterations takes " +s=val(mid$(time$,10)) +for a=1 to 10000000:next a +e=val(mid$(time$,10)) +print e-s," seconds" +Explanation: + +This program benchmarks the for-loop and uses the fourth field of the string returned by time$. + + +Related: date$ + +& +to + +Name: +to -- this keyword appears as part of other statements + +Synopsis +for a=1 to 100 step 2 + ... +next a +draw line x,y to a,b, View$ + +Description: +The to-keyword serves two purposes (which are not related at all):within for-statements, to specify the upper bound of the loop. +Within any graphical command (e.g. line), that requires two points (i.e. four numbers) as arguments, a comma ',' might be replaced with the keyword to. I.e. instead of 100,100,200,200 you may write 100,100 to 200,200 in such commands. + +Related: for, draw line, view + +& +// + +Name: +// -- starts a comment + +Synopsis: +// This is a comment! + +Description: +The double-slash ('//') is (besides REM and '#') the third way to start a comment. '//' is the latest and greatest in the field of commenting and allows yab to catch up with such cool languages like C++ and Java. + +Example: +// Another comment. +print "Hello world!" // Another comment +Explanation: + +Unlike the example given for '#' this example is syntactically correct and will not produce an error. + + +Related: #, rem + +& +: + +Name: +: -- separate commands from each other + +Synopsis: +print "Hello ":print "World" + +Description: +The colon (':') separates multiple commands on a single line. +The colon and the newline-character have mostly the same effect, only that the latter, well, starts a new line too. The only other difference is their effect within the (so-called) short if, which is an if-statement without the keyword then. Please see the entry for if for more details. + +Example: +if (a<10) print "Hello ":print "World!" +Explanation: + +This example demonstrates the difference between colon and newline as described above. + + +Related: if + +&GUI +&Drawing +& +draw circle + +Name: +draw circle -- draw a circle + +Synopsis: +DRAW CIRCLE x,y, Radius, Target$ + +Description: +This command will draw a circle on Target$. Target$ has to be either a valid view, bitmap or canvas. The center of the circle is (x,y) and the circle has a radius of Radius. + +At default it will draw a filled circle in the current highcolor. With the draw set command you can change the filling settings. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw circle 150,150, 75, "Example" +sleep 7 +window close "Example" +Related: draw curve, draw dot, draw ellipse, draw flush, draw line, draw rect, draw set +& +draw curve + +Name: +draw curve -- draw a Bezier curve with four reference points + +Synopsis: +DRAW CURVE x1,y1, x2,y2, x3,y3, x4,y4, Target$ + +Description: +Bezier curves are defined by a number of points. They will always start in the first point and end in the last one. The curve will always be within the four sides if you connect the points directly. For our command, the curve is defined by four points (x1,y1) ... (x4,y4) and it is drawn on Target$. Target$ has to be either a valid view, bitmap or canvas. + +At default it will draw a filled curve in the current highcolor. With the draw set command you can change the filling settings. Note: A filled curve might have refresh problems due to a bug in the app-server. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw curve 10,150, 75,60, 150,20, 250,140, "Example" +sleep 7 +window close "Example" +Related: draw circle, draw dot, draw ellipse, draw flush, draw line, draw rect, draw set +& +draw dot + +Name: +draw dot -- draw a single dot + +Synopsis: +DRAW DOT x,y, View$ + +Description: +Draw a single dot at (x,y) on Target$. Target$ has to be either a valid view, bitmap or canvas. + +At default the dot is drawn in the current highcolor. + +Example: +window open 100,100 to 400,400, "Example", "Example" +for i = 0 to 300 step 0.5 + draw dot i, sin(i*50)*50+150, "Example" +next i +sleep 7 +window close "Example" +Explanation: + +This program draws a sinus curve with single dots. + +Related: draw circle, draw curve, draw ellipse, draw flush, draw line, draw rect, draw set +& +draw ellipse + +Name: +draw ellipse -- draw an ellipse + +Synopsis: +DRAW ELLIPSE x,y, RadiusX, RadiusY, View$ + +Description: +This command will draw an ellipse on Target$. Target$ has to be either a valid view, bitmap or canvas. The center of the ellipse is (x,y) and the ellipse has a horizontal radius of RadiusX and a vertical radius of RadiusY. + +At default it will draw a filled ellipse in the current highcolor. With the draw set command you can change the filling settings. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw ellipse 150,150, 75, 30, "Example" +sleep 7 +window close "Example" +Explanation: + +Related: draw circle, draw curve, draw dot, draw flush, draw line, draw rect, draw set +& +draw flush + +Name: +draw flush -- clear all prior draw commands + +Synopsis: +DRAW FLUSH View$ + +Description: +Draw flush clears the view named View$ from all drawings. + +In yab, all draw commands are stored in a list for every view. If the window is updated, e.g. when resized, all prior drawing is repeated. If you do a lot of drawing in a view, you might notice the redrawing due to flickering. if you want to clear your view, it is much better to clear it with draw flush than e.g. drawing a big rectangle over the other drawings. For flickerfree drawing consider to draw on a canvas instead of a view. + +Note: This does not work for canvas and bitmaps. + +Note: Widgets are not affected by draw flush. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw line 0,0 to 300,300, "Example" +draw circle 100,50, 20, "Example" +draw rect 10,200 to 200,250, "Example" +sleep 1 +draw flush "Example" +sleep 3 +window close "Example" +Explanation: + +In this example, some things are drawn on the window and then cleared by the draw flush command. + +Related: draw circle, draw curve, draw dot, draw ellipse, draw line, draw rect, draw set +& +draw get + +Name: +draw get -- retrieve font properties + +Synopsis: +Width = DRAW GET FontProperty$, Text$, Target$ +Height = DRAW GET FontProperty$, Target$ + +Description: +The draw get command provides you with some information about the width or height of a string with the current font settings that are used for the draw text command. + +If FontProperty$ is set to "Text-Width", you have to provide a string Text$ too. The resulting Width is the width of Text$ in the current font setting. The width of a string e.g. helps you to align text. Note: Text$ will not be localized automatically, you have to translate it yourself with translate$(Text$). Target$ has to be either a valid view, bitmap or canvas. + +If FontProperty$ is set to "Max-Text-Height" you get the maximum height of the font as return value. The normal font size is the size starting at the baseline. The maximum height gives you the size plus how far the characters can descend below the baseline. + +Example: +window open 100,100 to 400,400, "Example", "Example" +// set font +draw set "Zurich, Roman, 25", "Example" +draw text 50,150, "yab Example", "Example" +// the string length +width = draw get "text-width", "yab Example", "Example" +// baseline +draw set "highcolor", 0,0,255, "Example" +draw line 40,150 to width+60,150, "Example" +// font size +draw set "highcolor", 255,0,255, "Example" +draw line 40,150-25 to width+60,150-25, "Example" +// descend below baseline +maxheight = draw get "max-text-height", "Example" +draw set "highcolor", 255,0,0, "Example" +draw line 40,150-25+maxheight to width+60,150-25+maxheight, "Example" +sleep 7 +window close "Example" +Explanation: + +The example shows the baseline (blue line), the font size (pink line) and the lower boundary (red line) for the given string. The lower boundary is calculated by: baseline - font size + maximum text height. If you respect these distances, you can align text pretty well. + +Related: draw get$, draw set, draw text +& +draw get$ + +Name: +draw get$ -- retrieve information about the installed fonts + +Synopsis: +FontFamilies$ = DRAW GET$ "FontFamily" +FontStyles$ = DRAW GET$ FontFamily$ + +Description: +The draw get$ command reads out the information about all installed fonts and their styles. + +Use the parameter "FontFamily" first to get all font families. For a given font family, get the possible styles with the family name as parameter. + +Use draw set or textedit set to set the font for a draw text or textedit. + +Example: +dim fonts$(1) +dim styles$(1) +window open 100,100 to 400,400, "Example", "Example" +menu "File", "Quit", "Q", "Example" +fontfamilies$ = draw get$ "fontfamily" +numFonts = token(fontfamilies$, fonts$(), "|") +for i = 1 to numFonts + menu "Fonts", fonts$(i), "", "Example" + fontstyles$ = draw get$ fonts$(i) + numStyles = token(fontstyles$, styles$(), "|") + for j = 1 to numStyles + submenu "Fonts", fonts$(i), styles$(j), "", "Example" + next j + submenu set "Fonts", fonts$(i), true, "Example" +next i +while(not instr(message$, "Quit")) +wend +window close "Example" +Explanation: + +This example sets up a whole menu with all fonts installed and their styles. Note: It is up to you to deselect old submenu items in this example whenever a new item is selected. In other words, this simple example allows several font selections, which is probably not what you want. + +Related: draw get, draw set, draw text, textedit set +& +draw image + +Name: +draw image -- load and display an image file + +Synopsis: +LoadError = DRAW IMAGE x,y, ImageFile$, Target$ +LoadError = DRAW IMAGE x1,y1 TO x2,y2, ImageFile$, Target$ + +Description: +The image with the filename ImageFile$ is loaded and put on Target$. Target$ has to be either a valid view, bitmap or canvas. Any image files that are understood by the system can be used. Transparent images are supported, however they might cause problems when printed with the printer command. + +If only one coordinate pair is given, the image will be displayed in its full size where (x,y) is the upper left corner. If the second coordinates are given too, the image will be resized from (x1,y1) to (x2,y2). +If x2 is set to -1, the width is scaled according to the height; +if y2 is set to -1, the height is scaled according to the width; +if x2 and y2 are set to -1, the image is not scaled at all. + +Draw image returns information about the success of the loading procedure: +LoadError = 0, image successfully loaded +LoadError = 1, the file was not found +LoadError = 2, the translator roster was not found, i.e. the system does not understand the image type +LoadError = 3, translation failed, maybe the file is corrupted? +LoadError = 4, detaching the bitmap failed, maybe out of memory? + +Example: +window open 100,100 to 400,400, "Example", "Example" +err = draw image 10,10, "mypicture.png", "Example" +switch(err) + case 1: alert "File not found!", "Ok", "stop" + exit(1) + case 2: alert "Translator not found!", "Ok", "stop" + exit(1) + case 3: alert "Translation failed!", "Ok", "stop" + exit(1) + case 4: alert "Detaching failed!", "Ok", "stop" + exit(1) + default: + break +end switch +sleep 7 +window close "Example" +Explanation: + +The example program will try to load and display the file "mypicture.png" from the current directory. If the load process failed, an error message is produced. + +Related: draw flush +& +draw line + +Name: +draw line -- draw a line + +Synopsis: +DRAW LINE x1,y1 TO x2,y2, Target$ + +Description: +This command draws a line from (x1,y1) to (x2,y2) on Target$ in the current highcolor. Target$ has to be either a valid view, bitmap or canvas. + +Example: +window open 100,100 to 400,400, "Example", "Example" +for i = 0 to 300 step 10 + draw line 0,i to i,300, "Example" + draw line 300,i to i,0, "Example" +next i +sleep 7 +window close "Example" +Explanation: + +Draws some nice lines. + +Related: draw circle, draw curve, draw dot, draw ellipse, draw flush, draw rect, draw set +& +draw rect + +Name: +draw rect -- draw a rectangle + +Synopsis: +DRAW RECT x1,y1 TO x2,y2, Target$ + +Description: +This command will draw a rectangle from (x1,y1) to (x2,y2) on Target$. Target$ has to be either a valid view, bitmap or canvas. + +At default it will draw a filled rectangle in the current highcolor. With the draw set command you can change the filling settings. + +Example: +window open 100,100 to 400,400, "Example", "Example" +draw set true, "HighSolidFill" +draw rect 10,10, 290, 290, "Example" +sleep 7 +window close "Example" +Explanation: + +Display a rectangle. + +Related: draw circle, draw curve, draw dot, draw ellipse, draw flush, draw line, draw set +& +draw set + +Name: +draw set -- set various drawing parameters + +Synopsis: +DRAW SET Color$, r,g,b, Target$ +DRAW SET "Alpha", Alpha-Value +DRAW SET IsStroke, Pattern$ +DRAW SET Font$, Target$ + +Description: +Draw set allows you to set various parameters for the other draw commands. + +Draw set with a Color$ allows you to set three different colors: the background color of Target$, the so-called lowcolor and the highcolor. At default, everything is drawn with the current highcolor, the lowcolor is useful for patterns which can have two colors. The background color can only be set for views, otherwise Target$ has to be either a valid view, bitmap or canvas. +If Color$ = "BGColor", the background color of the view Target$ is set, default is grey (216,216,216), +if Color$ = "LowColor", the lowcolor of Target$ is set, default is grey (216,216,216), +if Color$ = "HighColor", the highcolor of Target$ is set, default is black (0,0,0). + +A short note about colors: On BeOS and ZETA, colors are notated with their three component colors red (r), green (g) and blue (b). These component colors are values between 0 (dark) and 255 (light) and mixed together (additive mixture) they represent a 32bit color space. Have a look at the colorcontrol widget to learn more about colors. + +Draw set with "Alpha" as option sets the alpha channel value. At default it is set to 255 which is completly opaque. The smaller the alpha value gets, the more translucent following drawings will become. Note: This only affects the graphic primitives as dot, line, rect, text etc. but not draw image. +Note: When Alpha-Value is below 255, use only HighSolidFill to draw, patterns are ignored! +Note: Transparent drawing (that is Alpha-Value below 255) is not printed (see printer) correctly! + +Draw set can also set the stroke or fill parameter and a pattern. If IsStroke is true, only the outline of circle, ellipse, rectangle and curve are drawn, otherwise they are filled up (which is the default setting). The Pattern$ specifies a pattern that is used for drawing and filling. The following patterns are predefined: +If Pattern$ = "HighSolidFill" solid fill is used with the current high color (default), +if Pattern$ = "LowSolidFill" solid fill is used with the current low color, +if Pattern$ = "CheckeredFill" checkered fill is used as a combination of low- and highcolor, +otherwise Pattern$ is a 8x8 1bit map where one line is one character which is written out as its ASCII code. +Use the pattern editor to draw and calculate patterns for your convenience. + +Draw set with a parameter Font$ sets the font for Target$. The Font$ consists of the font family, the font style and the font size separated with commas. E.g. the following is a valid font string: +Font$ = "Zurich, Roman, 25" +Note: Use the correct spelling of the font families and styles keeping existing spaces; they are case sensitive too. +Three special Font$ are available, namely the system fonts: +If Font$ = "system-plain", the plain system font is used (default), +if Font$ = "system-fixed", the fixed-sized system font is used, +if Font$ = "system-bold", the bold system font is used. +See the command draw get$ for more information about font families and styles. + +Example: +"127191223239215187109214" +Explanation: + +Related: draw circle, draw curve, draw dot, draw ellipse, draw get, draw get$, draw line, draw rect, draw text, view +& +draw text + +Name: +draw text -- draw a text string in the current font + +Synopsis: +DRAW TEXT x,y, Text$, Target$ + +Description: +Draw the string Text$ in the current font and highcolor on Target$. Target$ has to be either a valid view, bitmap or canvas. The left baseline (!) starts at (x,y). Please refer to the example of the command draw get to learn more about the font height and its baseline. + +Note: The text will be anti-aliased (smoothed) with the current lowcolor. If your text looks strange and blocky, you probably should set the lowcolor to the background color. + +Example: +window open 100,100 to 400,400, "Example", "Example" +// set the colors, ajust lowcolor to background color +draw set "bgcolor", 0,0,125, "Example" +draw set "lowcolor", 0,0,125, "Example" +draw set "highcolor", 255,255,0, "Example" +// set the font +draw set "Zurich, Roman, 25", "Example" +// draw the text +draw text 80,150, "yab Example", "Example" +sleep 7 +window close "Example" +Explanation: + +This program sets the colors to a blue background and a yellow textcolor. It sets the font and then displays the string "yab Example". + +Related: draw flush, draw get, draw get$, draw set + +&Input and Messages +& +ismousein() + +Name: +ismousein() -- reports whether the mouse is currently in a view + +Synopsis: +State = ISMOUSEIN(View$) + +Description: +Ismousein reports true whenever it is called and the mouse pointer is currently over the view named View$. This is independend of whether the window containing the view is active or not. + +Example: +window open 100,100 to 300,300, "Example", "Example" +while(not instr(message$, "Quit")) + if(ismousein("Example")) print "Mouse is in window" +wend +window close "Example" +Explanation: +After opening the window named "Example", this program checks if the mouse is currently over the window. Then a message is printed on the console. + + +Related: mouse message$(), mousemove$, mouse set + +& +keyboard message$() + +Name: +keyboard message$() -- check the keyboard for pressed buttons + +Synopsis: +Msg$ = KEYBOARD MESSAGE$(View$) + +Description: +With keyboard message$(), you can receive key strokes. These key strokes are always sent to the view that currently has focus, so you should make sure, that you set the focus for the view named View$. This avoids trouble with textedit or textcontrol widgets that rely on user input too. + +For normal keys, yab simply returns the key, e.g. a, 1 or !. For function keys you will get f1, f2 and so on. Other special keys will return these strings respectively: enter, backspace, del, esc, pageup, pagedown and tab. Modifier keys (e.g. ctrl, alt or shift) by themself can not be detected (however, if you press shift and e.g. a simultaniously, keyboard message$ will return the letter A instead of a of course). + +If you are interested in getting the key strokes in a terminal, have a look at the inkey$ command. Note, other than inkey$, keyboard message$() does not wait for a key to be pressed. It will simply return an empty string ("") when no key is pressed. + +Design: +It is quite hard to use keyboard message$() for a input method that behaves like e.g. a textcontrol because you have to control the key repeat rate yourself. So rather use a textcontrol, spincontrol or a textedit widget for more complex editing. + +Example: +window open 100,100 to 300,300, "Example", "Example" +option set "Example", "Focus", true +while(not instr(message$, "Quit")) + k$ = keyboard message$("Example") + if(k$<>"" and k$<>old_k$) then + print "You pressed "+k$ + old_k$ = k$ + endif +wend +window close "Example" +Explanation: +This simple example first sets the focus on the view that should get the keyboard messages. Whenever a key is pressed, and it is not similar to the pressed key before, we show a text message. + +Related: inkey$, mouse message$(), option set, shortcut +& +message$ + +Name: +message$ -- receive a system message + +Synopsis: +msg$ = MESSAGE$ + +Description: +Message$ is one of the most important commands for graphical user interfaces. It checks the message queue for new messages that might have arrived from open windows or graphical widgets. + +Most of the time the message queue is empty and message$ will return an empty string "". However, when some window or widget is selected or clicked on you probably will receive a message. + +Note, once message$ is called, the queue is emptied. So you receive a message only once! It is therefore a good idea to store the message in a string (e.g. msg$) or in an array (see example below) so you can evaluate it further. + +Messages are separated by the pipe symbol "|". Normally, you only receive one message. However, when there is some time passing between two message calls (e.g. because of a long calculation or a sleep command), several messages might have been coming in. Therefore you should always split the whole message into its message parts with the token() command (split() will do too). Use a loop to go through all messages then. + +The kind of message is related to the window or widget sending the messgae. Check the different widget entries for more information on the type of message they send. + +Currently, there is one general system message that you always should process: +"_QuitRequested" -- this means that your program was asked to quit by another program (e.g. by ProcessController or the system shutdown) + +Example: +// set DEBUG to true to have the messages printed on the console +// set it to false to disable this feature +DEBUG = true + +window open 100,100 to 300,300, "Example", "Example" + +dim msg$(1) +while(not quitting) + // get all messages and split them immediatly + numMessages = token(message$, msg$(), "|") + + // go through all messages + for i = 1 to numMessages + // if DEBUG is set, print the current message + if(DEBUG) print msg$(i) + switch(msg$(i)) + case "_QuitRequested" + case "Example:_QuitRequested" + quitting = true + break + end switch + next i +wend +window close "Example" +Explanation: +This example shows a message loop as it is recommended for most programs. The message$ is split into parts by the token command. Using a switch(), the different messages can be examined. + +Related: message send +& +message send + +Name: +message send -- send a system message + +Synopsis: +Arrived = MESSAGE SEND Application$, Message$ + +Description: +This is an rather advanced command for sending messages to other yab programs. + +The target program should have the signature Application$. The default signature is: "application/x-vnd.yab-app". + +You can change the signature for yab scripts when you add a comment in the first or second line of your program like this: +// mimetype "application/x-vnd.myapp" + +For binaries, change the signature using the external QuickRes program. + +The command returns one of the following error codes: + 0: Message was delivered + 1: The destination program was not found + 2: The target's message queue is full + 3: Time out, the message never made it to the target + 4: An other error occurred + +Message: +The destination yab application will produce a message$ stating: + +&exverbatim +_Scripting:...| +&exverbatim + +(The ... is the Message$.) + +See the files Ping.yab and Pong.yab for a nice example of message send. As you have to start both, use the tracker or the terminal to run them, but not the IDE. + +Related: message$ +& +mouse message$() + +Name: +mouse message$() -- check the mouse for its position and the state of the buttons + +Synopsis: +Mouse$ = MOUSE MESSAGE$(View$) + +Description: +Mouse message$() returns a string containing information of the mouse coordinates (relative to View$) and the state of the mouse buttons. + +The mouse string has the format "X:Y:LMB:MMB:RMB" where MB is the corresponding left, middle, right mousebutton and X and Y are the coordinates relative to the view named View$. Use the token() command to split the string into an array and use val() to get the actual numerical values (see the example below). + +Design: +Using the mouse message$() is not recommended for beginners. Also the advanced programmer should use it not too intensivly, but rather rely on the existing widgets. However, controlling the mouse gives you some means to create some own sort of widgets or some cool mouse-over effects. + +Example: +window open 100,100 to 500,500, "Example", "Example" +x = 100 +y = 100 +draw rect x,y to x+50,y+50, "Example" +text 10,10, "mytext", "Drag the square with the mouse", "Example" +dim mouse$(1) +while(not instr(message$, "Quit")) + GetMouse() + + // the button is pressed and the mouse is over the rectangle, start drag + if(mlmb and mx>=x and mx<=x+50 and my>=y and my<=y+50) then + while(mlmb) + GetMouse() + x = mx-25 + y = my-25 + draw flush "Example" + draw rect x,y to x+50,y+50, "Example" + wend + endif +wend +window close "Example" + +sub GetMouse() + n = token(mouse message$("Example"), mouse$(), ":") + mx = val(mouse$(1)) + my = val(mouse$(2)) + mlmb = val(mouse$(3)) +end sub +Explanation: +This example lets you drag a rectangle with the mouse. It gets the current position and button state in the sub GetMouse(). Now when the left mouse button is pressed and the mouse is over the rectangle, the rectangle will be moved as long as the button is pressed. The redrawing of the rectangle can be improved by checking whether the mouse actually moved. + + +Related: ismousein(), keyboard message$(), mousemove$, mouse set +& +mousemove$ + +Name: +mousemove$ -- returns more detailed mouse messages + +Synopsis: +Mouse$ = MOUSEMOVE$ + +Description: +This command is somewhat a duplicate to mouse message$(). However, it does not require a view to be given, but reports the name of the view back as part of the message Mouse$. The following messages can occur: + +Control$+":_InsideView" +Control$+":_EnteredView" +Control$+":_ExitedView" +Control$+":_MouseDown" +Control$+":_MouseUp" +Control$+":_LeftMouseButton" +Control$+":_RightMouseButton" +Control$+":_MiddleMouseButton" +where Control$ is the ID of the widget or view where the event occured. + +Related: ismousein(), mouse message$(), mouse set +& +MOUSE SET Option$ + +Name: +mouse set -- show or hide the mouse cursor + +Synopsis: +MOUSE SET Option$ + +Description: +Sometimes (e.g. games) the mouse cursor is just in the way. To get rid of it for your application windows, this command allows you to hide it (or later show it again). Use Option$ as described: + +Option$ = "Hide" -- hide the mouse cursor +Option$ = "Show" -- show the mouse cursor +Option$ = "Obscure" -- hide the mouse cursor until the mouse is moved + +Related: ismousein(), mouse message$(), mousemove$ +& +shortcut + +Name: +shortcut -- sends a message when a specified shortcut key is pressed + +Synopsis: + +SHORTCUT View$, Shortcut$, MyMessage$ + +Description: +For adding keyboard shortcuts to your program that are not related to menu entries, use the shortcut command. It sends the message MyMessage$ whenever the key combination Shortcut$ is pressed and the view named View$ has focus. + +The first letter of Shortcut$ specifys the shortcut key for this menu item. It is always combined with the command key which is ALT normally (or CTRL when CTRL and ALT are switched in the preferences). E.g. consider a Shortcut$ of "O" then ALT-O will send MyMessage$ to the message queue. Additionaly to the command key you can specify further modifiers which are set before the shortcut letter: + +&exverbatim +"S" for the shift key +"C" for the control key (CTRL, or ALT if CTRL and ALT are switched) +"O" for the option key (on most keyboards probably the Windows button) +&exverbatim + +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" + +Some Shortcut examples: + +&exverbatim +"O" for ALT-O +"SO" for Shift-ALT-O +"COO" for Control-Option-ALT-O +&exverbatim + +Message: +Shortcut sends MyMessage$. + +Design: +To use shortcuts is good but to use shortcuts in menus is much better. In menus the user can see the shortcut and does not have to memorize it. Furthermore he can select the according action by mouse too. + +Use the default shortcuts as described for the menu command. Note: Other than with menu, the following shortcuts are reserved and cannot be overwritten: + +&exverbatim +ALT-X +ALT-C +ALT-V +ALT-A +ALT-W +ALT-Q +&exverbatim + +Example: +window open 100,100 to 300,200, "Example", "Example" + +draw text 10,20, "Press Alt-B for an about window", "Example" +draw text 10,40, "Press Alt-Shift-Q to quit", "Example" + +shortcut "Example", "B", "About" +shortcut "Example", "SQ", "MyQuit" + +option set "Example", "focus", true + +while(not quitting) + m$ = message$ + if(instr(m$, "About")) alert "An easy shortcut example", "Dooh", "info" + if(instr(m$, "MyQuit")) then + quitting = true + elsif(instr(m$,"Quit")) then + alert "Use the shortcut to quit!", "Ok", "info" + endif +wend + +window close "Example" +Explanation: + +Here two shortcuts are setup, ALT-B (or CTRL-B if ALT and CTRL are switched in your preferences) sends the message "About" and Shift-ALT-Q to send the message "MyQuit". Additionally other quit messages are rejected telling the user to only use the shortcut. + +Related: keyboard message$, menu, message$ +& +&Printing +& +printer + +Name: +printer -- send a view to the printer + +Synopsis: +PrintingError = PRINTER JobName$, SetupFile$, View$ + +Description: +Printer is a powerful but yet simple command to print a view named View$. The view is send to the currently active printer and put into the spooling queue. There, it is visible under the name JobName$. + +SetupFile$ gives a files as saved by the printer setup command. If the setup file is not valid or empty (""), the printing setup is called first automatically. Otherwise the saved setup is used for the printing. + +Printer returns one of the following numbers: +0 = No Problems +1 = Page setup failed (probably communication problems with the print server) +2 = The configuration file was loaded but page setup failed +3 = The view View$ was not found +4 = The number of pages is 0 or less +5 = The printing was canceled or something went wrong with printing + +Note: PrintingError = 4 can happen because of a bug in the PDF printing driver; although a page size is shown, none is selected. If this happens, you may want to call a PRINTER SETUP for the user and try to print again. + +Note: When an error with code 1,2,3 or 4 occurs, you can be shure that nothing was sent to the printer yet. + +Note: Alpha transparency is not printed correctly! + +Note: Due to a bug in BeOS and ZETA, there are probably problems printing CHECKBOX IMAGE and BUTTON IMAGE images, use DRAW IMAGE instead! + +Example: +window open 100,100 to 300,300, "Example", "Example" + +view 10,10 to 190,160, "PrintMe", "Example" +draw set "bgcolor", 255,255,255, "PrintMe" +draw text 50,50, "Print Me!", "PrintMe" + +button 50,170 to 150,190, "PrintButton", "Print...", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "PrintButton")) then + errcode = printer "Example Printjob", "", "PrintMe" + if(errcode>1) alert "Printing Problem: "+str$(errcode), "Ok", "Warning" + endif + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: + +First a window is opened and then a white view named "PrintMe" is put upon it. Of course it makes perfect sence to have a white background for your view that is to be printed. When the "Print..." button is pressed, the PrintMe view is send to the printer with the job name "Example Printjob". In case of an error, the user is informed. + +Related: printer setup +& +printer setup + +Name: +printer setup -- setup the current printer + +Synopsis: +PRINTER SETUP SetupFile$ + +Description: +Printer setup call the setup window of the currently active printer. Here, the user can specify printing parameters like paper size or a border width. The setup is saved in the file called SetupFile$. No file is created when the user cancels the setup. + +Note: At least one window has to be open before printer setup can be called. + +Example: +window open 100,100 to 300,300, "Example", "Example" +menu "File", "Printer Setup...", "", "Example" +menu "File", "--", "", "Example" +menu "File", "Quit", "Q", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "Printer Setup...")) printer setup "ExamplePrinterConfig" + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: +The example shows a window with a menu. When printer setup is selected from this menu, the setup is called. If the user saves the config, it will be stored in the file named "ExamplePrinterConfig". + +Related: printer +&Menus +& +menu + +Name: +menu -- create a menu item for the menubar + +Synopsis: +MENU Head$, Menu$, Shortcut$, View$ + +Description: +To add a menubar with menus to a window or a view named View$ is very easy. Simply call menu with the menu entry Head$ and a menu item called Menu$. If there is no menubar yet, a new one will be created. If the entry Head$ already exists, the item Menu$ will be added to the existing items at the end. + +If Menu$ is set as follows: +&exverbatim +Menu$ = "--" +&exverbatim +then the menu item will be a separator line. + +The first letter of Shortcut$ specifys the shortcut key for this menu item. It is always combined with the command key which is ALT normally (or CTRL when CTRL and ALT are switched in the preferences). E.g. consider a Shortcut$ of "O" then ALT-O will appear in the menu and the user has to press ALT-O to activate this menu item. Additionaly to the command key you can specify further modifiers which are set before the shortcut letter: + +&exverbatim +"S" for the shift key +"C" for the control key (CTRL, or ALT if CTRL and ALT are switched) +"O" for the option key (on most keyboards probably the Windows button) +&exverbatim +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" + +Some Shortcut examples: +&exverbatim +"O" for ALT-O +"SO" for Shift-ALT-O +"COO" for Control-Option-ALT-O +&exverbatim + +The height of the menubar (which depends on the size of the system menu font) can be checked with the peek command. + +Message: +The menu when selected or called by the shortcut key will return a message of the format: + +View$+":"+Head$+":"+Menu$ + +Note, when you have switched on localization, you get the translated message. Have a look at the example below, how to handle such translations. + +Design: +Although views can have a menubar too, you should only give windows a menu. Use capitalized words for English menu entries (like for headings). A menu item should have three dots (...) always when the user can expect a further dialog and not an immediate action. Use the default menu head entries: File, Edit, View, Help + +Use the following default shortcuts: +&exverbatim +For the menu Head$ "File": +"N" -- New +"O" -- Open +"S" -- Save +"W" -- Close +"Q" -- Quit + +For the menu Head$ "Edit": +"Z" -- Undo +"X" -- Cut +"C" -- Copy +"V" -- Paste +"A" -- Select All + +Further default shortcuts: +"F" -- Find +"G" -- Find Again +"H" -- Help +"P" -- Print +&exverbatim + +Example: +localize +window open 100,100 to 400,300, "Example", "Example" +menu "File", "About...", "", "Example" +menu "File", "--", "", "Example" +menu "File", "Quit", "Q", "Example" + +menu "Action", "My Action Menu", "COA", "Example" + +dim msg$(1) +while(not quitting) + n = token(message$, msg$(), "|") + for i = 1 to n + switch(msg$(i)) + case "_QuitRequested" + case "Example:_QuitRequested" + case translate$("Example:File:Quit") + quitting = true + break + case translate$("Example:File:About...") + alert "Menu example", "Ok", "info" + break + case translate$("Example:Action:My Action Menu") + press = press + 1 + draw flush "Example" + draw text 50,100, translate$("Menu call: ")+str$(press), "Example" + break + end switch + next i +wend + +window close "Example" +Explanation: +We open a window and allow localization. This should explain the usage of translating the messages in the loop. After initializing the menus, we check the messages. When a message arrives, we compare it to the translated (!) counterpart. + +Related: menu set, peek, submenu, submenu set +& +menu set + +Name: +menu set -- set options for the menu + +Synopsis: +MENU SET MenuHead$, SetRadioMode, View$ +MENU SET MenuHead$, MenuItem$, Option$, View$ + +Description: +This lets you set some options for the first level menu. + +Given a MenuHead$ you can put the entire menu in radio mode, i.e. only one item can be selected at a time. Set SetRadioMode to true to allow radio mode, set it to false to return to a normal behavior again. Note, you have to select the first item yourself after switching to radio mode. Use the following option to do so. + +Given a MenuHead$ and a MeniItem$ you can disable or enable the item or you can select it by putting a mark to it or remove the mark again. Thus the following options are valid: + +&exverbatim +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +Option$ = "Enable" -- enable a formerly disabled item again +Option$ = "Mark" -- mark this item +Option$ = "Plain" -- remove a mark again +&exverbatim + +Example: +window open 100,100 to 400,300, "Example", "Example" +menu "Test", "Foo", "", "Example" +menu "Test", "Bar", "", "Example" +menu set "Test", "Foo", "mark", "Example" +menu set "Test", "Bar", "disable", "Example" +fooMarked = true + +menu "Radio", "1", "", "Example" +menu "Radio", "2", "", "Example" +menu "Radio", "3", "", "Example" +menu set "Radio", true, "Example" +menu set "Radio", "2", "mark", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "Quit")) quitting = true + if(instr(m$, "Foo")) then + fooMarked = not fooMarked + if(fooMarked) then + menu set "Test", "Foo", "mark", "Example" + else + menu set "Test", "Foo", "plain", "Example" + endif + endif +wend +window close "Example" +Explanation: +The first menu has two items, the first item is selectable. As you see in the message loop you are responsable yourself to apply or remove the mark from this item. The second item is disabled. + +The second menu is in radio mode, so only one item can be selected. The user will do that for you, however you have to select an item for the first time. + +Related: menu, submenu, submenu set +& +popupmenu + +Name: +popupmenu -- open a popup menu + +Synopsis: +Selected$ = POPUPMENU x,y, MenuItems$, View$ + +Description: +This function pops up a menu at the position (x,y) as upper left corner on View$. The menu contains several menu items which are given as MenuItems$. The items are separated by a pipe "|". If a menu item is a double minus, it will be used as a separator. + +Your program will wait until an item is selected from the menu or the user clicks somewhere else. The command will then return either the selected item name or an empty string "" when nothing was selected. + +Note, you cannot add submenus, have a radio mode or select items which is possible for menus in a menubar. + +Similar to the menu, the Selected$ will contain the translation of the selected item when localization is used. Use translate$ where necessary, as explained for the menu command. + +Design: +Remember to give the user a hint so he can expect a popup menu. E.g. add a small down-arrow to a button image, if this button opens a popup menu. + +Example: +window open 100,100 to 300,300, "Example", "Example" +button 10,10 to 100,30, "MyButton", "Popup", "Example" +while(not quitting) + m$ = message$ + if(instr(m$, "Quit")) quitting = true + if(instr(m$, "MyButton")) then + selected$ = popupmenu 10,31, "About...|--|Quit", "Example" + if(selected$ = "About...") alert "Popupmenu example.", "Ok", "Info" + if(selected$ = "Quit") quitting = true + endif +wend +window close "Example" +Explanation: +The example opens a window with a button. Whenever the button is clicked on, a popup menu appears. The selection of the popup menu is then processed immediately. + +Related: dropbox +& +submenu + +Name: +submenu -- create a submenu item for an existing menu + +Synopsis: +SUBMENU MenuHead$, MenuItem$, SubMenuItem$, Shortcut$, View$ + +Description: +To have a submenu to an existing menu, you have to specify the menu title MenuHead$, the menu item that will contain the submenu MenuItem$ and the new name for the submenu entry SubMenuItem$. If MenuHead$ or MenuItem$ do not exist, they are created. Similar to the menu command the submenu item can be called by a shortcut key Shortcut$. This again explained below in detail. + +If SubMenuItem$ is set as follows: +&exverbatim +Menu$ = "--" +&exverbatim +then the submenu item will be a separator line. + +The first letter of Shortcut$ specifys the shortcut key for this submenu item. It is always combined with the command key which is ALT normally (or CTRL when CTRL and ALT are switched in the preferences). E.g. consider a Shortcut$ of "O" then ALT-O will appear in the menu and the user has to press ALT-O to activate this menu item. Additionaly to the command key you can specify further modifiers which are set before the shortcut letter: + +&exverbatim +"S" for the shift key +"C" for the control key (CTRL, or ALT if CTRL and ALT are switched) +"O" for the option key (on most keyboards probably the Windows button) +&exverbatim +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" + +Some Shortcut examples: +&exverbatim +"O" for ALT-O +"SO" for Shift-ALT-O +"COO" for Control-Option-ALT-O +&exverbatim + +Message: +The submenu when selected or called by the shortcut key will return a message of the format: + +View$+":"+Head$+":"+MenuItem$+":"+SubMenuItem$ + +Note, when you have switched on localization, you get the translated message. Have a look at the example below, how to handle such translations. + +Design: +Use submenus sparsely. Even a complex program like the yab IDE contains only one submenu (for the online resources). Most often submenus should only be used for a list of similar items. Use capitalized words for English menu entries (like for headings). A menu item should have three dots (...) always when the user can expect a further dialog and not an immediate action. + +Example: +localize +window open 100,100 to 400,300, "Example", "Example" + +submenu "File", "Alert Types", "Empty Alert...", "", "Example" +submenu "File", "Alert Types", "Info Alert...", "", "Example" +submenu "File", "Alert Types", "Idea Alert...", "", "Example" +submenu "File", "Alert Types", "Warning Alert...", "", "Example" +submenu "File", "Alert Types", "Stop Alert...", "", "Example" + +menu "File", "--", "", "Example" +menu "File", "Quit", "Q", "Example" + +dim msg$(1) +while(not quitting) + n = token(message$, msg$(), "|") + for i = 1 to n + switch(msg$(i)) + case "_QuitRequested" + case "Example:_QuitRequested" + case translate$("Example:File:Quit") + quitting = true + break + case translate$("Example:File:Alert Types:Empty Alert...") + alert "Empty alert.", "Ok", "empty" + break + case translate$("Example:File:Alert Types:Info Alert...") + alert "Info alert.", "Ok", "info" + break + case translate$("Example:File:Alert Types:Idea Alert...") + alert "Idea alert.", "Ok", "idea" + break + case translate$("Example:File:Alert Types:Warning Alert...") + alert "Warning alert.", "Ok", "warning" + break + case translate$("Example:File:Alert Types:Stop Alert...") + alert "Stop alert.", "Ok", "stop" + break + end switch + next i +wend + +window close "Example" +Explanation: +Here the important part is the declaration of the submenu. With the first submenu command the menubar, the menu head named "File" and the menu item named "Alert Types" are created. Because of localization we have to check the submenu message with the translate$() otherwise we would miss them. + +Related: menu, menu set, submenu set +& +submenu set + +Name: +submenu set -- set options for the submenu + +Synopsis: +SUBMENU SET MenuHead$, MenuItem$, SetRadioMode, View$ +SUBMENU SET MenuHead$, MenuItem$, SubMenuItem$, Option$, View$ + +Description: +This lets you set some options for the second level menu. + +Given a MenuHead$ and a MenuItem$ you can put the entire submenu in radio mode, i.e. only one item can be selected at a time. Set SetRadioMode to true to allow radio mode, set it to false to return to a normal behavior again. Note, you have to select the first item yourself after switching to radio mode. Use the following option to do so. + +Given a MenuHead$, a MeniItem$ and a SubMenuItem$ you can disable or enable the item or you can select it by putting a mark to it or remove the mark again. Thus the following options are valid: + +&exverbatim +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +Option$ = "Enable" -- enable a formerly disabled item again +Option$ = "Mark" -- mark this item +Option$ = "Plain" -- remove a mark again +&exverbatim + +Example: +window open 100,100 to 400,300, "Example", "Example" + +submenu "Test", "My Favorite OS", "BeOS", "", "Example" +submenu "Test", "My Favorite OS", "Haiku", "", "Example" +submenu "Test", "My Favorite OS", "ZETA", "", "Example" + +submenu set "Test", "My Favorite OS", true, "Example" +submenu set "Test", "My Favorite OS", "BeOS", "mark", "Example" +submenu set "Test", "My Favorite OS", "ZETA", "disable", "Example" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: +The submenu is in radio mode, so only one item can be selected. The user will do that for you, however you have to select an item for the first time. The last item cannot be selected because it is disabled. + +Related: menu, menu set, submenu +&Views +& +boxview + +Name: +boxview -- a boxview is view with a labeled border + +Synopsis: +BOXVIEW x1,y1 TO x2,y2, ID$, Label$, LineType, View$ + +Description: +This command sets up a view named ID$ with a border and a label. While the boxview is constructed at the coordinates (x1,y1) to (x2,y2) on the view named View$, the own coordinates of a boxview start at (x1+3,y1+12) to (x2-3,y2-3) so that the border can not be overwritten. This is independent of the line type. + +If Label$ is not "", it will be displayed on the upper left corner of the boxview. Otherwise no label is shown. + +There are three possible line types for the border style: + For LineType = 0 the boxview has no border. + For LineType = 1 the boxview has a simple line border. + For LineType = 2 the boxview has a fancy line border. + +Other than commands like stackview, tabview or splitview, you can simply remove a boxview just as a normal view with the view remove command. + +Layout: +The boxview will follow all sides as in standard layout. + +Design: +Use boxviews to group similar entries. Do not use too much boxviews in a window, as this looks too cluttered. + +Example: +window open 100,100 to 300,300, "Example", "Example" +boxview 10,10 to 190,190, "MyBox", "Hello Box", 2, "Example" +sleep 7 +window close "Example" +Explanation: + +The example opens a window and sets up a boxview with the label "Hello Box" and a fancy border style (2). + +Related: view, view remove +& +stackview + +Name: +stackview -- create views above each other + +Synopsis: +STACKVIEW x1,y1 TO x2,y2, ID$, NumberOfViews, View$ + +Description: +Stackview creates several views on top of each other. All views have the same coordinates (x1,y1)-(x2,y2) on the view named View$. NumberOfViews specifies how many views should be created. Obviously it should be greater or equal to 2 to be useful. + +All stacked views get a own ID which is ID$ and the number of the view. E.g. if ID$ = "MyStack" and NumberOfViews = 3, then the stacked views have the IDs "MyStack1", MyStack2" and "MyStack3". Use the command stackview set to switch between these views. + +Layout: +The stackview and all views it contains will follow all sides as in standard layout. + +Design: +You can think of a stackview as a tabview without tabs. Therefore it is up to the programmer to provide a method to switch between the stacked views. + +Stackviews are useful in typical BeOS style option windows (e.g. in the yab IDE). Have a look at the code below for an example. + +Example: +window open 100,100 to 400,300, "Example", "Option Example" + +listbox 10,10 to 100,190, "List", 1, "Example" +listbox add "List", "First Option" +listbox add "List", "Second Option" +listbox add "List", "Third Option" + +stackview 110,10 to 290,190, "Stack", 3, "Example" +draw set "bgcolor", 255,200,200, "Stack1" +draw text 10,10, "This is view \"Stack1\"", "Stack1" +draw set "bgcolor", 200,255,200, "Stack2" +draw text 10,10, "This is view \"Stack2\"", "Stack2" +draw set "bgcolor", 200,200,255, "Stack3" +draw text 10,10, "This is view \"Stack3\"", "Stack3" + +while(not quitting) + msg$ = message$ + if(instr(msg$, "List")) then + n = listbox get "List" + stackview set "Stack", n + elsif(instr(msg$, "Quit")) then + quitting = true + endif +wend + +window close "Example" +Explanation: + +This window has a listbox on the left-hand side and a stackview with three views on the right. Each view has a own background color and text. When an item is selected in the list, we get its number and then switch the stackview to the corresponding view. + +Related: stackview get, stackview set, tabview +& +stackview get + +Name: +stackview get -- get the number of the shown view in a stackview + +Synopsis: +ViewNumber = STACKVIEW GET StackView$ + +Description: +Stackview get will return you the number of the currently shown view. Remember: Numbering starts with 1. + +Related: stackview, stackview set +& +stackview set + +Name: +stackview set -- set the shown view in a stackview + +Synopsis: +STACKVIEW SET StackView$, ViewNumber + +Description: +To switch the views of a stackview, yoy have to use this command. Simply provide it with the ID of the stackview (here: StackView$) and the number of the view you want it to show. Remember: The first view on the stack has the number 1. If you provide an invalid number, nothing will happen. + +Related: stackview, stackview get +&Widgets +& +button + +Name: +button -- create a new button + +Synopsis: +BUTTON x1,y1 TO x2,y2, ID$, Label$, View$ + +Description: +The button command creates a button from the coordinates (x1,y1) to (x2,y2) on the window or view named View$. It has a text label Label$ and the identifier ID$. + +With the option set command you can modify the button, as setting the background color, the focus, enabling or diabling it or resizing it to its preferred size. + +Message: +The button when pressed will send a message string with ID$. + +Layout: +In standard layout, the button will follow the lower, right corner of the view or window. + +Design: +Always use meaningful labels for buttons. If you care for localization (on ZETA you should!), remember that labels can be much longer in other languages. So either provide enough space or use the option set command to auto-resize the button. + +Example: +window open 100,100 to 300,200, "Example", "Example" +button 20,40 to 180,60, "MyButton", "Hello World", "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyButton|") alert "You pressed the button", "Ok", "info" + if(instr(m$, "_QuitRequested")) quitting = true +wend +window close "Example" +Explanation: + +In this example, a button is set on the window. If the button is pressed, an alert window pops up. + +Related: button image, option set +& +button image + +Name: +button image -- create a new button with images + +Synopsis: +BUTTON IMAGE x,y, ID$, EnabledPressed$, EnabledNormal$, Disabled$, View$ + +Description: +This command lets you create a button with images named ID$ on the view View$. The position (x,y) is the upper left corner of the images and the size of the first image (EnabledPressed$) is taken. + +You have to provide at least two image files: +EnabledPressed$ -- the image file name of the pressed button +EnabledNormal$ -- the image file name of the released button +The images can be of any format that BeOS or ZETA can translate. + +If you want to disable the button, you should provide the additional image file: +Disabled$ -- the image file name of the disabled button +You can put in an empty string "" if you don't need a disabled button. + +Just be aware that image files with relative path might be not found when you start your program as a script from tracker. + +Message: +The button when pressed will send a message string with ID$. + +Layout: +In standard layout, the button will follow the lower, right corner of the view or window. + +Design: +Be creative but do not use offensive images. For icons, try to use BeOS-like icons always. Ask in the community if you need assistence in creating new icons. + +Example: +window open 100,100 to 300,200, "Example", "Example" +button image 10,10, "MyIconButton", "icon_pressed.png", "icon_released", "icon_disabled", "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyIconButton|") alert "You pressed the button", "Ok", "info" + if(instr(m$, "_QuitRequested")) quitting = true +wend +window close "Example" +Explanation: + +The button is only shown correctly, when the images "icon_pressed.png" and "icon_released" exist. + +Related: button +& +calendar + +Name: +calendar -- create a new calendar + +Synopsis: +CALENDAR x,y, ID$, Format$, SetDate$, View$ + +Description: +Calendar is a nifty widget that gives you a date textcontrol with a dropdown calendar window. It is created at (x,y) as upper left corner on the view View$. With the default font size, it always has a width of 80 pixels and a height of 20 pixels. + +You have to provide a date format Format$ which must be either "DDMMYYYY" for day, month, year or "MMDDYYYY" for month, day, year. Futhermore, you have to add a divider to the Format$ which can be either ".", "/" or "-". Thus, the default Format$ looks like this: "DDMMYYYY." + +The SetDate$ should give the starting date in the format you have chosen. Default is the current day, when SetDate$ = "". Note: this SetDate$ has a different format than the yab command date$. However, it is not too difficult to convert these formats. + +The calendar can be disabled or enabled with the option set command. + +Layout: +In standard layout, the calendar will follow the lower, right corner of the view or window. + +Example: +window open 100,100 to 300,200, "Example", "Example" +calendar 10,10, "MyCalendar", "MMDDYYYY/", "04.06.1975", "Example" +while(not quitting) + if(instr(message$, "_QuitRequested")) then + alert "You selected: "+calendar get$ "MyCalendar", "Duh", "info" + quitting = true + endif +wend +window close "Example" +Explanation: + +In this example, a calendar is set on the window with an American date format, month, day, year and the / as separator. When the window is closed, an alert window shows the selected date with calendar get$. + +Related: calendar get$, calendar set, date$, option set +& +calendar get$ + +Name: +calendar get$ -- returns the selected date of a calendar + +Synopsis: +GetDate$ = CALENDAR GET$ Calendar$ + +Description: +The command will return the currently selected date of the calendar widget named Calendar$. Note: the calendar does not send any messages, so use this command to read out a calendar. + +Note: This GetDate$ has a different format than the yab command date$. However, it is not too difficult to convert these formats. + +Related: calendar, calendar set, date$ +& +calendar set + +Name: +calendar set -- sets the date for a calendar + +Synopsis: +CALENDAR SET Calendar$, SetDate$ + +Description: +This lets you set the date of the calendar named Calendar$. Note: SetDate$ has to use the format, that is defined for the calendar. + +Note: this SetDate$ has a different format than the yab command date$. However, it is not too difficult to convert these formats. + +Related: calendar, calendar get$, date$ +& +checkbox + +Name: +checkbox -- create a new checkbox + +Synopsis: +CHECKBOX x,y, ID$, Label$, IsSelected, View$ + +Description: +Set up a checkbox named ID$ at the position (x,y). It will display the label Label$ next to the box. If IsSelected is set to true, the checkbox will be selected. + +You can use option set to disable the checkbox or to change the label. + +Message: +The checkbox when selected will send a message string with ID$+":ON", and when deselected with the message string ID$+":OFF". + +Layout: +In standard layout, the checkbox will follow the lower, right corner of the view or window. + +Design: +Try to align checkboxes below each other. Also put them in groups (e.g. in a boxview) when you have many checkboxes. + +Example: +window open 100,100 to 400,200, "Example", "Example" +checkbox 10,10, "MyCheckBox", "Select this checkbox", false, "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyCheckBox:OFF|") alert "The checkbox is deselected", "Ok", "info" + if(m$ = "MyCheckBox:ON|") alert "The checkbox is selected", "Ok", "info" + if(instr(m$, "Quit")) quitting = true +wend +window close "Example" +Explanation: + +Whenever the checkbox is selected or deselected, an alert window will tell you. + +Related: checkbox image, checkbox set, option set +& +checkbox image + +Name: +checkbox image -- create a new checkbox with images + +Synopsis: +CHECKBOX IMAGE x,y, ID$, EnabledOn$, EnabledOff$, DisabledOn$, DisabledOff$, IsSelected, View$ + +Description: +This command lets you create a checkbox with images named ID$ on the view View$. The position (x,y) is the upper left corner of the images and the size of the first image (EnabledOn$) is taken. If IsSelected is set to true, the checkbox will be selected. + +You have to provide at least two image files: +EnabledOn$ -- the image file name of the selected checkbox +EnabledOff$ -- the image file name of the deselected checkbox +The images can be of any format that BeOS or ZETA can translate. + +If you want to disable the checkbox, you should provide the additional image files: +DisabledOn$ -- the image file name of the disabled selected checkbox +DisabledOff$ -- the image file name of the disabled deselected checkbox +You can put in an empty string "" if you don't need a disabled checkbox. + +Just be aware that image files with relative path might be not found when you start your program as a script from tracker. + +You can use option set to disable the checkbox. + +Message: +The checkbox when selected will send a message string with ID$+":ON", and when deselected with the message string ID$+":OFF". + +Layout: +In standard layout, the checkbox will follow the lower, right corner of the view or window. + +Design: +Be creative but do not use offensive images. For icons, try to use BeOS-like icons always. Ask in the community if you need assistence in creating new icons. + +Example: +window open 100,100 to 400,200, "Example", "Example" +checkbox 10,10, "MyCheckBox", "enabled_icon_on.png", "enabled_icon_off.png", + "disabled_icon_on.png", "disabled_icon_off.png", false, "Example" +while(not quitting) + m$ = message$ + if(m$ = "MyCheckBox:OFF|") alert "The checkbox is deselected", "Ok", "info" + if(m$ = "MyCheckBox:ON|") alert "The checkbox is selected", "Ok", "info" + if(instr(m$, "Quit")) quitting = true +wend +window close "Example" +Explanation: + +Whenever the checkbox is selected or deselected, an alert window will tell you. The checknox is only shown correctly, when the images exist. + +Related: checkbox, checkbox set, option set +& +checkbox set + +Name: +checkbox set -- (de-)select the checkbox + +Synopsis: +CHECKBOX SET CheckBox$, IsSelected + +Description: +If IsSelected is set to true, the checkbox named CheckBox$ will be selected. If IsSelected is set to false, the checkbox will be deselected. + +Related: checkbox, checkbox image +& +colorcontrol + +Name: +colorcontrol -- create a new control for choosing a color + +Synopsis: +COLORCONTROL x,y, ID$, View$ + +Description: +Colorcontrol gives you a basic color selection tool in only one command. The colorcontrol named ID$ has its upper left corner at the position (x,y) of the view View$. It always has a width of 276 pixels and a height of 54 pixels. + +Note: The colorcontrol will look differently on 8 bit displays than on displays with 16 or more bit. However, this should not concern you, the system will take care of that. On BeOS, the colorcontrol will have an additional deactivated selection for alpha channel selection. This is not functional, so again, do not care. + +The colorcontrol does not send any message, you have to check with colorcontrol get what the user selected. + +You can use option set to disable the colorcontrol. Use colorcontrol set, to set a color. + +Layout: +In standard layout, the colorcontrol will follow the lower, right corner of the view or window. + +Design: +Always give feedback to the user, how the color looks like, he is currently selecting. The example below shows how to do that. + +Example: +window open 100,100 to 426,176, "Example", "Example" +view 10,10 to 40,66, "Color", "Example" +colorcontrol 50,10, "MyColorControl", "Example" + +// set color to white +colorcontrol set "MyColorControl", 255,255,255 + +while(not quitting) + if(instr(message$, "Quit")) quitting = true + r = colorcontrol get "MyColorControl", "red" + g = colorcontrol get "MyColorControl", "green" + b = colorcontrol get "MyColorControl", "blue" + + // check if the color was changed + if(r<>old_r or g<>old_g or b<>old_b) then + old_r = r: old_g = g: old_b = b + draw set "bgcolor", r,g,b, "Color" + endif +wend +window close "Example" +Explanation: + +The example shows a colorcontrol and view. The view always takes the color that is selected by the user. Note: The color is only set, when the selection changed. This avoids flickering on slow machines. + +Related: colorcontrol get, colorcontrol set, option set +& +colorcontrol get + +Name: +colorcontrol get -- return a color component of the currently selected color in a colorcontrol + +Synopsis: +Value = COLORCONTROL GET ColorControl$, ColorComponent$ + +Description: +Returns the current selected color component of the colorcontrol ColorControl$. Value is always between 0 and 255, where lower values represent darker colors and higher values represent lighter colors. + +ColorComponent$ has to be one of the following: +"Red" -- the value of the red color +"Green" -- the value of the green color +"Blue" -- the value of the blue color + +Related: colorcontrol, colorcontrol set +& +colorcontrol set + +Name: +colorcontrol set -- set the color in a colorcontrol + +Synopsis: +COLORCONTROL SET ColorControl$, r,g,b + +Description: +Sets the color in the colorcontrol ColorControl$ to its RGB values r, g and b. Read the part on the draw set command to learn more about RGB color space in yab. + +Related: colorcontrol, colorcontrol get +& +columnbox + +Name: +columnbox -- create a list widget with columns + +Synopsis: +COLUMNBOX x1,y1 TO x2,y2, ID$, HasHScrollbar, Option$, View$ + +Description: +The columnbox ist created at (x1,y1) to (x2,y2) on the target view named View$. It gets an own ID i.e. ID$. If it should have a horizontal scrollbar, set HasHScrollbar to true otherwise set it to false. Note: a columnbox always has a vertical scrollbar. + +There are several options regarding the behaviour of the columns. These options affect all columns: +"movable" -- the columns can be dragged +"resizable" -- the columns can be resized +"popup" -- clicking on the columns with the right mouse button brings up a popup menu with all column names +"removable" -- the columns can be removed + +An addtional options is "no-border" which draws the columnbox without a borderline. + +Several options can be combined, e.g. "movable, resizable, no-border". Note: If "removable" is allowed, you should allow "popup" too, so that removed columns can be brought back again. + +After setting up a columnbox you have to add columns with the columnbox column command before adding items. + +Note: A columnbox cannot be sorted. + +Message: +The columnbox provides two messages. The first kicks in when a row is selected by clicking once on it or by the up and down keys. This then has the format ID$+":_Select:"+SelectedRow$ where SelectedRow$ contains the number of the row selected. The second message is send, when a row is invoked, i.e. by double-clicking at a row or pressing the Enter key. It has the format ID$+":_Invoke:"+SelectedRow$. + +Layout: +The columbox will follow all sides as in standard layout. + +Design: +To use a columnbox is almost always a good idea. It helps to present a lot of data in an organized way. Additionally it allows bitmaps and icons as list entries and it is the most customizable list widget in yab. + +Example: +window open 100,100 to 400,500, "Example", "Example" + +columnbox 10,10 to 290,390, "MyColumnbox", true, "movable, resizable, popup, removable", "Example" + +columnbox column "MyColumnbox", " ", 1, 20, 20, 20, "align-center" +columnbox column "MyColumnbox", "Name", 2, 140, 60, 80, "align-right" +columnbox column "MyColumnbox", "Address", 3, 250, 60, 180, "align-left" +columnbox column "MyColumnbox", "Age", 4, 250, 60, 50, "align-center" + +columnbox add "MyColumnbox", 1, 1, 18, "__Mime__=application/x-person" +columnbox add "MyColumnbox", 2, 1, 18, "John" +columnbox add "MyColumnbox", 3, 1, 18, "Cape Town" +columnbox add "MyColumnbox", 4, 1, 18, "30" + +columnbox add "MyColumnbox", 1, 2, 18, "__Mime__=application/x-person" +columnbox add "MyColumnbox", 2, 2, 18, "Mary" +columnbox add "MyColumnbox", 3, 2, 18, "Omaruru" +columnbox add "MyColumnbox", 4, 2, 18, "27" + +columnbox color "MyColumnbox", "text", 0,0,200 +columnbox color "MyColumnbox", "selection", 200,200,255 +columnbox color "MyColumnbox", "row-divider", 255,255,255 + +columnbox select "MyColumnbox", 2 + +while(not quitting) + m$ = message$ + if(instr(m$, "_Select")) then + currentRow = columnbox get "MyColumnbox" + print columnbox get$ "MyColumnbox", 2, currentRow + endif + if(instr(m$, "_Invoke")) then + currentRow = columnbox get "MyColumnbox" + currentItem$ = columnbox get$ "MyColumnbox", 2, currentRow + alert "You selected "+currentItem$, "Ok", "info" + endif + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: + +In this example, first a columnbox is created. It has a horizontal scrollbar. Due to the options, the columns can be moved by clicking and dragging on the column title, they can be removed by dragging a title out of the columnbox, the columns can be resized by dragging the mouse at the border of the column titles and by right clicking on the column title a popup window appears. + +Next the column are defined with columnbox column. All four columns have a title and a column number. Ideally this number starts at one and it increases with every column. Furthermore we specify the width of the column and its maximum and minimum width. This is important when the columnbox allows the "resizable" option. + +Several items are inserted into the columnbox with the columnbox add command. Here the column number has to be given and the row number too. The row height is set by the first columnbox add command for a row and here it is set to 18 because we use icons with a 16 pixel height. We obtain the icon from the mimetype of the type "application/x-person" which is given by the system. + +Several colors are set to personalize our columnbox a bit and the second row is selected with the columnbox select command. + +In the message loop we check for the "_Select" and the "_Invoke" messages of the columnbox. When a row is selected, e.g. by clicking on it once, we first obtain the row where the click happened with columnbox get (this can also be obtain from the message itself using the right$ and val commands). Then the item string itself is retrieved with the columnbox get$ command. + +Related: columnbox add, columnbox clear, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox add + +Name: +columnbox add -- add an item to a columnbox + +Synopsis: +COLUMNBOX ADD ColumnBox$, Column, Row, Height, Item$ + +Description: +To add an item named Item$ to a columnbox named ColumnBox$, you have to specify the column and the row where the item should be located in the columnbox table. An existing item will be overwritten. If Row is larger than the number of rows in the columnbox, a new row is created. Furthermore, you have to specify the height of the row in pixels, a normal value should be Height = 14 or Height = 16 for text items. + +To have images or icons as items, you have to specify that with special identifiers in Item$: +If Item$ = "__Icon__="+FileName$ then the image file FileName$ will be shown, +if Item$ = "__Path__="+FileName$ then the large Trackericon of the file FileName$ will be shown +if Item$ = "__Mime__="+Signature$ then the small icon of the mime type Signature$ will be shown. + +Note: These identifiers are case sensitive! + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox clear + +Name: +columnbox clear -- deletes everything in a columnbox + +Synopsis: +COLUMNBOX CLEAR ColumnBox$ + +Description: +Use columnbox clear to remove all rows and items in the columnbox named ColumnBox$. + +Related: columnbox, columnbox add, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox color + +Name: +columnbox color -- change the colors of a columnbox + +Synopsis: +COLUMNBOX COLOR ColumnBox$, Option$, r,g,b + +Description: +The colors in a columnbox can be changed easily. This distinguishes the columnbox from other list widgets like listbox, dropbox or treebox. Given an option string Option$ the colors can be set to the RGB value (r,g,b). Read the part on the draw set command to learn more about RGB color space in yab. + +The following values for Option$ are valid: +"selection-text" -- set the color of the text in the selected row +"non-focus-selection" -- set the color of the selection when the columnbox is not focussed +"selection" -- set the color for the selected row +"text" -- set the general text color +"row-divider" -- set the color of the line between the rows +"background" -- set the background color + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox column + +Name: +columnbox column -- add a new column to a columnbox + +Synopsis: +COLUMNBOX COLUMN ColumnBox$, Name$, ColumnNumber, MaxWidth, MinWidth, Width, Option$ + +Description: +This command takes quite a number of parameters. Here ColumnBox$ is the columnbox where the column should be added. Name$ is the string that shows up in the title of the column. + +ColumnNumber gives the position relative to the other columns. Ideally ColumnNumber starts at 1 for the first column and with every new column it is incremented by 1. The column gets the width Width (thus the next column will start at Position+Width). MaxWidth and MinWidth declare the boundaries for the column when resizing was specified in the construction of the columnbox. + +Finally the alignment of all items in the column has to be defined in Option$. Possible values are "align-left" for left alignment, "align-center" for center alignment and "align-right" for right alignment. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox count, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox count + +Name: +columnbox count -- returns the number of rows in a columnbox + +Synopsis: +NumberOfRows = COLUMNBOX COUNT ColumnBox$ + +Description: +For a existing columnbox named ColumnBox$, this command simply returns the number of rows it contains and stores it in NumberOfRows. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox get, columnbox get$, columnbox remove, columnbox select +& +columnbox get + +Name: +columnbox get -- returns the number of the currently selected row in a columnbox + +Synopsis: +ItemNumber = COLUMNBOX GET ColumnBox$ + +Description: +To obtain the row that is currently selected in the columnbox named ColumnBox$, simply use this command. If no row is selected, ItemNumber will be set to 0. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get$, columnbox remove, columnbox select +& +columnbox get$ + +Name: +columnbox get$ -- get a specific item in a columnbox + +Synopsis: +Item$ = COLUMNBOX GET$ ColumnBox$, Column, Row + +Description: +In the given columnbox named ColumnBox$, the item text at the position (Column, Row) will be stored in Item$. For icons and images, this will return the identifier and the file path. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox remove, columnbox select +& +columnbox remove + +Name: +columnbox remove -- delete a line in a columnbox + +Synopsis: +COLUMNBOX REMOVE ColumnBox$, Row + +Description: +In the given columnbox named ColumnBox$, the specified row is deleted. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox select +& +columnbox select + +Name: +columnbox select -- select a row in a columnbox + +Synopsis: +COLUMNBOX SELECT ColumnBox$, Row + +Description: +In the given columnbox named ColumnBox$, the specified row is selected. If Row is set to 0, any former selection is revoked. + +Have a look at the columnbox command for an example. + +Related: columnbox, columnbox add, columnbox clear, columnbox color, columnbox column, columnbox count, columnbox get, columnbox get$, columnbox remove +& +listbox + +Name: +listbox -- create a list widget + +Synopsis: +LISTBOX x1,y1 TO x2,y2, ID$, ScrollbarType, View$ + +Description: +The listbox provides a list widget that can be filled with text items. It is set up at the position (x1,y1) to (x2,y2) on the view named View$. It gets an own identifier ID$. Additionally you have to specify whether the listbox should get scrollbars. This is given by ScrollbarType as follows: + +ScrollbarType = 0 -- no scrollbar +ScrollbarType = 1 -- the listbox has a vertical scrollbar +ScrollbarType = 2 -- the listbox has a horizontal scrollbar +ScrollbarType = 3 -- the listbox has a vertical and a horizontal scrollbar + +Message: +The listbox provides two messages. The first kicks in when an item is selected by clicking once on it or by the up and down keys. This then has the format ID$+":_Select:"+SelectedItem$ where SelectedItem$ contains the number of the item selected. The second message is send, when a item is invoked, i.e. by double-clicking at a item or pressing the Enter key. It has the format ID$+":_Invoke:"+SelectedItem$. + +Layout: +The listbox will follow all sides as in standard layout. + +Design: +The listbox is an easy method to present a lot of data well-structured in a list. Use it instead of a dropbox when you have enough space or the list of data gets too long. For having icons or images in a list, use the columnbox instead. + +Example: +window open 100,100 to 400,400, "Example", "Example" + +listbox 10,10 to 290,260, "MyList", 1, "Example" +button 10,270 to 290,290, "MyButton", "Sort List", "Example" + +listbox add "MyList", "Apple" +listbox add "MyList", "8088" +listbox add "MyList", "80286" +listbox add "MyList", "ZX81" +listbox add "MyList", 1, "BeOS" + +listbox select "MyList", 2 + +while(not quitting) + m$ = message$ + if(instr(m$, "MyButton")) then + listbox sort "MyList" + endif + if(instr(m$, "_Select")) then + currentItem = listbox get "MyList" + print listbox get$ "MyList", currentItem + endif + if(instr(m$, "_Invoke")) then + currentItem = listbox get "MyList" + item$ = listbox get$ "MyList", currentItem + alert "You selected "+item$, "Ok", "info" + endif + if(instr(m$, "Quit")) quitting = true +wend + +window close "Example" +Explanation: + +This program opens a window with a listbox named "MyList" and a button named "MyButton". Several items are added, note the order of the items. The last item is put into the first position of the list. Then the second item is selected, this will generate a message which will be processed immendiatly. You can see the name of the selected item on the console output. When the sort button is pressed, the list is sorted. When double clicking on an item, an alert window pops up showing the selected item. + +Related: listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox add + +Name: +listbox add -- add an item to a listbox + +Synopsis: +LISTBOX ADD ListBox$, Item$ +LISTBOX ADD ListBox$, Position, Item$ + +Description: +This command adds a string here named Item$ to the listbox with the ID ListBox$. If Position is given too, the item will be inserted at that position. + +Have a look at the listbox command for an example. + +Related: listbox, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox clear + +Name: +listbox clear -- remove all items of a listbox + +Synopsis: +LISTBOX CLEAR ListBox$ + +Description: +Listbox clear deletes and removes all items in a listbox. + +Related: listbox, listbox add, listbox count, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox count + +Name: +listbox count -- returns the number of items in a listbox + +Synopsis: +NumberOfItems = LISTBOX COUNT ListBox$ + +Description: +For an existing listbox named ListBox$, this command simply returns the number of items it contains and stores it in NumberOfItems. + +Related: listbox, listbox add, listbox clear, listbox get, listbox get$, listbox remove, listbox select, listbox sort +& +listbox get + +Name: +listbox get -- returns the number of the currently selected item in a listbox + +Synopsis: +ItemNumber = LISTBOX GET ListBox$ + +Description: +To obtain the item that is currently selected in the listbox named ListBox$, simply use this command. If no item is selected, ItemNumber will be set to 0. + +Have a look at the listbox command for an example. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get$, listbox remove, listbox select, listbox sort +& +listbox get$ + +Name: +listbox get$ -- get a specific item string in a listbox + +Synopsis: +Item$ = LISTBOX GET$ ListBox$, Position + +Description: +In the given listbox named ListBox$, the item text at the position Position will be stored in Item$. + +Have a look at the listbox command for an example. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox remove, listbox select, listbox sort +& +listbox remove + +Name: +listbox remove -- delete a line in a listbox + +Synopsis: +LISTBOX REMOVE ListBox$, Position + +Description: +In the given listbox named ListBox$, the specified item at the position Position is deleted. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox select, listbox sort +& +listbox select + +Name: +listbox select -- select an item in a listbox + +Synopsis: +LISTBOX SELECT ListBox$, Position + +Description: +In the given listbox named ListBox$, the specified item at the position Position is selected. If Position is set to 0, any former selection is revoked. + +Have a look at the listbox command for an example. + +Message: +Using the listbox select command will generate a selection message. This then has the format ID$+":_Select:"+SelectedItem$ where SelectedItem$ contains the number of the item selected. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox sort +& +listbox sort + +Name: +listbox sort -- sort all items in a listbox + +Synopsis: +LISTBOX SORT ListBox$ + +Description: +This command sorts the given listbox named ListBox$ alphabetically. Items starting with a number will be set before items starting with a letter. However, please note that items containing numbers will NOT be sorted as numbers. E.g. The items "1", "2", "10" will be sorted according to the ASCII codes and the length of the strings, thus they are sorted to: "1", "10", "2" + +Note: After sorting, any former selection is removed. + +Have a look at the listbox command for an example. + +Related: listbox, listbox add, listbox clear, listbox count, listbox get, listbox get$, listbox remove, listbox select +& +radiobutton + +Name: +radiobutton -- create a new radiobutton + +Synopsis: +RADIOBUTTON x,y, ID$, Label$, IsActivated, View$ + +Description: +Set up a radiobutton named ID$ at the position (x,y). It will display the label Label$ next to the button. If IsActivated is set to true, the radiobutton will be selected. All radiobuttons on one view will act as a group. Thus on a view only one radiobutton will be active. + +Note: On setup it is up to you to preselect a radiobutton. You can even make more than one radiobutton active but this is hardly useful. When the user selects a radiobutton, all others will be deselected automatically. + +You can use option set to disable the radiobutton or to change the label. + +Message: +The radiobutton when selected will send a message string with its ID$. + +Layout: +In standard layout, the radiobutton will follow the lower, right corner of the view or window. + +Design: +Try to align radiobuttons below each other. + +Example: +window open 100,100 to 200,200, "Example", "Music" +radiobutton 10,10, "Radio1", "Classic", true, "Example" +radiobutton 10,30, "Radio2", "Jazz", false, "Example" +radiobutton 10,50, "Radio3", "Pop", false, "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "_QuitRequested")) then + quitting = true + elsif(instr(m$, "Radio")) then + n$ = mid$(m$,instr(m$, "Radio")+5,1) + alert "You selected the "+n$+". radiobutton", "Ok", "info" + endif +wend + +window close "Example" +Explanation: + +Here we have a window with three radiobuttons. Because they are all on one view (the window view) they act as a group. When selected, the number of the radiobutton ID will be extracted with mid$ and stored in n$. It is then shown in an alert window. + +Related: radiobutton set, option set +& +radiobutton set + +Name: +radiobutton set -- (de-)activate the radiobutton + +Synopsis: +RADIOBUTTON SET RadioButton$, IsActivated + +Description: +If IsActivated is set to true, the radiobutton named RadioButton$ will be selected. If IsActivated is set to false, the radiobutton will be deselected. Note: This allows you to activate more than one radiobutton in a group which is not recommended. + +Related: radiobutton +& +statusbar + +Name: +statusbar -- create a progress or status bar + +Synopsis: +STATUSBAR x1, y1 TO x2, y2, ID$, LeftLabel$, RightLabel$, View$ + +Description: +Use the statusbar to visualize the progress of a long computation process, e.g. installation or search. The statusbar is simply set up with the identifier ID$ at (x1,y1) to (x2,y2) on the view named View$. It takes two labels, LeftLabel$ is shown on the left side above of the statusbar and RightLabel$ is shown on the right side above of the statusbar. + +Layout: +The statusbar will follow the lower right corner of a window in standard layout. + +Design: +The statusbar should give the user an idea how long a specific process takes. This of course is only useful for processes that take some time. Also having a statusbar that stays for one minute at 5% and then immediatly jumps to 100% should be avoided although this sometimes is not in control of the programmer. + +Example: +window open 100,100 to 300,150, "Example", "Example" +statusbar 10,10 to 190,40, "MyStatus", "Start", "End", "Example" + +while(not instr(message$, "Quit") and i<100) + i = i + 2 + statusbar set "MyStatus", "Start", "End", i + sleep 0.05 +wend + +window close "Example" +Explanation: + +The statusbar is put on top of the example window with the two labels "Start" and "End". Using the statusbar set command, the statusbar is updated regularly to the new calculated value i which is between 0 and 100. + +Related: statusbar set +& +statusbar set + +Name: +statusbar -- set the value for a status bar + +Synopsis: +STATUSBAR SET Statusbar$, LeftLabel$, RightLabel$, State + +Description: +Use statusbar set to actually set the bar to a specific value. This value named State here is a number between 0 and 100. Thus, 0 is the empty statusbar while 100 is the full statusbar. During your update, you can change the labels at the left and right (LeftLabel$ and RightLabel$). + +Have a look at the statusbar command for an example. + +Related: statusbar +& +text + +Name: +text -- create a text label + +Synopsis: +TEXT x,y, ID$, Text$, View$ +TEXT x1,y1 TO x2,y2, ID$, Text$, View$ + +Description: +The text command sets up a text label Text$ at the position (x,y) or (x1,y1) of the view named View$. Providing second coordinates (x2,y2) is useful for the alignment of the text, see text set for details. The text label has an ID$ which is needed for text set or for changing the text itself with option set. + +So how does this compare to the draw text command? +A text cannot be flushed and it will never flicker. +A text can be aligned. +The label of a text can change. +On a canvas only draw text can be used. +The font and color can only be changed for draw text. + +Note: (x,y) is the upper left corner, this is different to draw text, where y is the baseline of the text. + +Design: +Text should be used for labels on a view. Use the alignment to make clean interfaces. + +Example: +window open 100,100 to 200,150, "Example", "Example" +text 10,10, "Text", "Hello World", "Example" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +A simple yab program, just a window and a text label. + +Related: draw text, option set, text set +& +text set + +Name: +text set -- set the alignment of a text widget + +Synopsis: +TEXT SET Text$, Alignment$ + +Description: +For a text label named Text$ you can change the alignment so that it is aligned to the left, center or right. This only works when you have used the text command with the (x2,y2) parameters because the alignment refers to x1 for left alignment und x2 for right alignment. + +The alignment is given as: +Alignment$ = "Align-Left" -- align to the left +Alignment$ = "Align-Center" -- align to the center +Alignment$ = "Align-Right" -- align to the right + +Example: +window open 100,100 to 300,200, "Example", "Example" +text 10,40 to 190,60, "Text", "Hello", "Example" +align = 1 + +while(not instr(message$, "Quit")) + switch align + case 1: + text set "Text", "Align-Left" + break + case 2: + text set "Text", "Align-Center" + break + case 3: + text set "Text", "Align-Right" + break + end switch + if align = 3 dir = -1 + if align = 1 dir = 1 + align = align + dir + sleep 0.5 +wend + +window close "Example" +Explanation: + +This fun program changes the alignment of the text every half second. + +Related: text +& +textedit + +Name: +textedit -- create a multiline text editor + +Synopsis: +TEXTEDIT x1,y1 TO x2,y2, ID$, ScrollbarType, View$ + +Description: + +Layout: + +Design: + +Example: +Explanation: + +Related: textcontrol, textedit add, textedit clear, textedit color, textedit get, textedit get$, textedit set +& +textedit add + +Name: +textedit add -- add text to a textedit + +Synopsis: +TEXTEDIT ADD TextEdit$, Text$ + +Description: + +Related: textedit, textedit clear, textedit color, textedit get, textedit get$, textedit set +& +textedit clear + +Name: +textedit clear -- delete all text of a textedit + +Synopsis: +TEXTEDIT CLEAR TextEdit$ + +Description: +This command removes all text within a textedit named TextEdit$. This also works when the textedit is not editable by the user. + +Related: textedit, textedit add, textedit color, textedit get, textedit get$, textedit set +& +textedit color + +Name: +textedit color -- set the colors of a textedit or provide syntax highlighting + +Synopsis: +TEXTEDIT COLOR TextEdit$, Option$, r,g,b +TEXTEDIT COLOR TextEdit$, Option$, Command$ + +Description: + +Related: textedit, textedit add, textedit clear, textedit get, textedit get$, textedit set +& +textedit get + +Name: +textedit get -- retrieve various information from a textedit + +Synopsis: +LineNumber = TEXTEDIT GET TextEdit$, Option$ +LineNumber = TEXTEDIT GET TextEdit$, Option$, Search$ +Result = TEXTEDIT GET TextEdit$, Option$, LineNumber + +Description: + +Related: textedit, textedit add, textedit clear, textedit color, textedit get$, textedit set +& +textedit get$ + +Name: +textedit get$ -- retrieve text from a textedit + +Synopsis: +EnteredText$ = TEXTEDIT GET$ TextEdit$ +TextLine$ = TEXTEDIT GET$ TextEdit$, LineNumber + +Description: + +Related: textedit, textedit add, textedit clear, textedit color, textedit get, textedit set +& +textedit set + +Name: +textedit set -- set various options for a textedit + +Synopsis: +TEXTEDIT SET TextEdit$, Option$ +TEXTEDIT SET TextEdit$, Option$, Value +TEXTEDIT SET TextEdit$, Option$, Value$ + +Description: +Textedit set allows you to apply standard editing operations, cut, copy, paste, clear, select-all, undo. It allows you set various options for the textedit, e.g. wordwrap, editable, autoindent. And it handles the autocompletion. Let us have a look in detail: + +Given only two parameters, the following options are valid for the textedit named TextEdit$: +Option$ = "cut" -- cut out the selected text and put it into the clipboard +Option$ = "clear" -- cut out the selected text but do not put it into the clipboard +Option$ = "copy" -- copy the selected text to the clipboard +Option$ = "paste" -- paste the content of the clipboard at the cursors position +Option$ = "select-all" -- select the whole text +Option$ = "undo" -- undo the last operation, note: undo remembers only one operation + +Given three parameters, the following options are valid for the textedit named TextEdit$ when the third parameter Value is either true or false: +Option$ = "autoindent" -- turn auto indent on or off, default is off (false) +Option$ = "changed" -- mark the textedit as changed or unchanged, default is false +Option$ = "color-case-sensitive" -- should the syntax highlighting be case-sensitive? default is false +Option$ = "editable" -- allow the user to edit the textedit, default is true +Option$ = "has-autocompletion" -- turn auto-completion on or off, default is on (true) +Option$ = "wordwrap" -- turn on/off word wrap at the end of a line, default is on (true) + +Some remarks: +Making a textedit not editable is useful when you want to show long text (or scrollable text). +The textedit will notice when text was changed since the last time the option "changed" was set to false. So when you saved the content of the textedit, remember to set back the "changed" option to false again. Then you know when the text should be saved again. + +Given three parameters, the following options are valid for the textedit named TextEdit$ when the third parameter Value is a number: +Option$ = "autocomplete-start" -- set the number of characters when auto-completion should kick in (default is 4) +Option$ = "gotoline" -- put the cursor to the line with number Value +Option$ = "select" -- select the line with number Value +Option$ = "tabwidth" -- set the tab width to Value (in pixel!), default is 28 +Option$ = "textwidth" -- set the maximum width of the text in pixel + +Given three parameters, the following options are valid for the textedit named TextEdit$ when the third parameter Value$ is a string: +Option$ = "font" -- set the font to Value$ (see draw set for details), default is "system-plain" +Option$ = "autocomplete" -- add the word Value$ to the auto-completion list + +Related: textedit, textedit add, textedit clear, textedit color, textedit get, textedit get$ +& +tooltip + +Name: +tooltip -- add a tooltip to a view or widget + +Synopsis: +TOOLTIP View$, Text$ + +Description: +A tooltip is a small popup that appears when the mouse moves over a widget to give some more information. + +To have a tooltip to any sort of view or widget named View$, simply add the tooltip string Text$. Text$ should be only one line without linebreaks. If Text$ is set to the empty string "", the tooltip is removed again from View$. + +Note: The tooltips look and behave slightly different on BeOS and ZETA. + +Design: +Tooltips can be of great help for the user to understand icons or buttons and the like. However, it does not make sence to add a tooltip "New" to a button that already has the label "New". Rather be more descriptive and provide additional information, e.g. "Open a new image file". For tooltips only the first word should be written with a capital letter. + +And remember, too many tooltips can be annoying too. + +Example: +window open 100,100 to 300,300, "Example", "Example" + +button 10,10 to 190,30, "Button", "We all...", "Example" +listbox 10,40 to 95,190, "List", 1, "Example" +listbox add "List", "...have own..." +slider 120,40 to 190,190, "Slider", "...tooltips.", 1,10, "triangle, vertical", "Example" + +tooltip "Example", "A tooltip for the whole window" +tooltip "Button", "A tooltip for the button" +tooltip "List", "A tooltip for the listbox" +tooltip "Slider", "A tooltip for the slider" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +The example shows how easily a tooltip can be applied to any kind of widget. Here, to the button, the listbox, the slider and the window view itself too. + +Related: tooltip color +& +tooltip color + +Name: +tooltip color -- set the color for all tooltips + +Synopsis: +TOOLTIP COLOR Option$, r,g,b + +Description: +To change the textcolor or the background color of all your tooltips, use this command. Given the option "bgcolor" or "textcolor" either the background color or the text color of the tooltips will be changed to the RGB color (r,g,b). Read the part on the draw set command to learn more about RGB color space in yab. + +Note: This command only works with the BeOS yab. The colors for the ZETA tooltips are set generally in the ZETA preferences and thus cannot be changed for a single app. So on ZETA with the ZETA yab interpreter this command simply does nothing. + +Example: +window open 100,100 to 300,140, "Example", "Example" + +button 10,10 to 190,30, "Button", "I have a tooltip", "Example" + +tooltip color "bgcolor", 0,0,0 +tooltip color "textcolor", 255,255,255 + +tooltip "Button", "A black and white tooltip for the button on BeOS" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +Here, the color of the tooltips are changed from the default yellow background and black text color to a black background (RGB color values: 0,0,0) and from the default black text color to a white text (RGB color values: 255,255,255). + +Related: tooltip +& +&Localization +& +localize + +Name: +localize -- enable the automatic localization of ZETA + +Synopsis: +LOCALIZE +LOCALIZE Filename$ + +Description: +Not everyone speaks English thus having multiple language support improves the usability of your program. yab provides a very simple language interface with the localize command. Use it once to turn automatic localization on. Now all strings in GUI widgets will be translated automatically if there is a dictionary entry for them. All you have to do, is to make a dictionary for your program. + +Dictionaries for stand-alone programs are normally put into the subdirectory Language/Dictionaries of your program. But if a filename Filename$ is given, the (absolute) path of this filename is used as dictionary directory. Note: As long as the yab program is not compiled with the build factory, you should specify the path. + +In the dictionary directory there should be files named like the programs name or like file name in Filename$. The files have a language code as ending. The language code consists of a two letter code for the language and a capitalized two letter code of the country. For a sample program named foobar.yab, some example dictionaries: foobar.deDE (language German (de) and country Germany (DE)), foorbar.enUS (language English (en) and country United States (US)), foobar.nlBE (language Dutch (nl) and country Belgium (BE)). + +The dictionary contains the English term in paranthesis ("") some spaces as separator and the translated text in the target language in paranthesis too. Example: +&exverbatim +# A comment starts with a # +# English German +"File" "Datei" +"Quit" "Beenden" +"This is a sentence." "Dies ist ein Satz." +&exverbatim + +This all looks complicated, but the reader is encouraged to have a look at the localization of the yab IDE and other tools to understand localization completly. + +Note: Menus and dropboxes return messages that contain a string that might be translated. Use the translate$() function to handle these. + +Note: The strings are case sensitive! + +Note: Currently localization is only supported on ZETA. However, supporting the localization of your program is a good idea for BeOS users too because localization support might be added soon to BeOS yab. + +Design: +It is good design to support localization. + +Example: +// this examples works with the example localization file above +// name it "foobar.deDE" in your home directory +localize "/boot/home/foobar" +window open 100,100 to 200,200, "Win", "Foobar" +menu "File", "Quit", "Q", "Win" +draw text 10,50, "This is a sentence.", "Win" + +while(not quitting) + msg$ = message$ + if(instr(msg$, "Quit") or instr(msg$, translate$("Quit"))) quitting = true +wend + +window close "Win" +Explanation: +This shows automatic translation of the menu strings "File" and "Quit" and the draw text string. Change the language settings to German in your ZETA preferences. Note: The menu strings are also translated when you do not provide the translation file because ZETA comes with some translations for typical strings used in applications. + +Further, we have to check the translation of the message$ too with translate$ because the menu now reports the message string "Datei:Beenden|" when selected in German. + +Related: translate$() +& +translate$() + +Name: +translate$() -- translate a string on ZETA + +Synopsis: +Translation$ = TRANSLATE$(Source$) + +Description: +The counterpart to the localize command is translate$(). It translates the string Source$ according to known dictionaries (see localize for more information about dictionaries) into the language currently set as default in ZETA. + +Note: Currently localization is only supported on ZETA. However, supporting the localization of your program is a good idea for BeOS users too because localization support might be added soon to BeOS yab. + +Example: +print translate$("File") +Explanation: +Using only the system dictionaries, we can obtain the translation of "File" according to the language set in the ZETA preferences. + +Related: localize +& +&Sound +& +beep + +Name: +beep -- ring the bell within your computer; a synonym for bell + +Synopsis: +beep + +Description: +The beep-command rings the bell once. beep is a synonym for bell. + +Example: +beep:print "This is a problem ..." +Related: bell +& +bell + +Name: +bell -- ring the bell within your computer (just as beep) + +Synopsis: +bell + +Description: +The bell-command rings the bell within your computer once. This command is not a sound-interface, so you can neither vary the length or the height of the sound. bell is exactly the same as beep. + +Example: +print "This is a problem ...":bell +Related: beep +& +sound play + +Name: +sound play -- play a sound file + +Synopsis: +Id = SOUND PLAY Filename$ + +Description: +To play a sound file named Filename$ which can be of any supported format (e.g. WAV, MP3, etc.) sound play will return a number Id. Use Id to have basic control with the two other sound commands: sound wait and sound stop. + +If the file could not load, Id will be set to -1. + +Design: +In a GUI context use sound wisely. Remember that not everyone can hear the sound, e.g. because sound is turned off, not supported or the user is deaf or hard-of-hearing. Thus, do not put important information for your application in speech files only. Additionally, remember that bells and whistles on each mouse click can become very annoying. + +Example: +id = sound play "bach.mp3" +while(1) +wend +Explanation: + +This loads the file "bach.mp3" and then waits forever (use Ctrl-C or Break to end the program). + +Related: sound stop, sound wait +& +sound stop + +Name: +sound stop -- stop playing a sound file + +Synopsis: +SOUND STOP Id +SOUND STOP(Id) + +Description: +Stop a sound that is playing with the valid identification number Id. + +Example: +id = sound play "bach.mp3" +sleep 3 +sound stop id +Explanation: + +This first loads the file "bach.mp3", plays it for three seconds and then stops it. + +Related: sound play, sound wait +& +sound wait + +Name: +sound wait -- waits until a sound file is finished playing + +Synopsis: +SOUND WAIT Id +SOUND WAIT(Id) + +Description: +After the a sound file named Id started playing, use this command to wait until the file finished playing. + +Example: +id = sound play "bach.mp3" +sound wait id +Explanation: + +This first loads the file "bach.mp3" and then plays it until it ends. + +Related: sound play, sound stop +& +&Window +& +alert + +Name: +alert -- show an alert window + +Synopsis: +ALERT Text$, ButtonLabel$, Type$ +Selected = ALERT Text$, Button1$, Button2$, Button3$, Type$ + +Description: +By simply calling alert, you can always display an alert window. + +It always has a message Text$ and it can either have one, two or three buttons. + +For the second syntax, the alert window will return the number of pressed button, where Button1$ is the label of the most left button and Button3$ is the label or the most right one. If you specify Button2$ or Button3$ as empty string (""), the according button is not shown. + +Type$ specifies the icon displayed on the left side of the alert window. It has to be one of the following strings: +"None" for no icon +"Info" for the information icon +"Idea" for the light bulb icon +"Warning" for the yellow exclamation mark +"Stop" for the red exclamation mark + +Design: +Use a warning icon to warn the user that something might go wrong (e.g. ask whether to save before quitting) and the stop icon to inform the user that something already went wrong (e.g. saving failed). + +For the dialog box, always use complete sentences, while for the buttons use understandable labels. Capitalize the buttons in English. + +Note: the right button always has the focus in the multi-button alert. Do not put a dangerous action on this button. E.g. for a dialog "Your data will be lost!", do not put the "Proceed" button on the right position, but rather the "Cancel" button. + +Example: +alert "Warning! All your base are belong to us.", "Ok", "warning" +selected = alert "Choose a button", "Left", "Middle", "Right", "info" +print "You selected button number: ", selected +Explanation: + +In the last line, the number of the selected button will be printed on screen. + +Related: window open +& +filepanel + +Name: +filepanel -- open a file or directory selection window + +Synopsis: +Filename$ = FILEPANEL Mode$, Title$, Directory$ +Filename$ = FILEPANEL Mode$, Title$, Directory$, DefaultFile$ + +Description: +In BeOS there is a default window for selecting files or directories to load or save. This so-called filepanel is easily accessable with the filepanel command in yab. The filepanel will open the selection window for you, it lets the user browse, select etc. in the directory tree and returns the selected or newly entered filename. Note: The filepanel just gives you the filename, it does not open, save or process this filename in any way; you have to do that on your own of course. + +First have a look at the parameters. Filename$ will contain the resulting path and name of the selected or newly created directory or filename. If the filepanel is canceled, the Filename$ will be empty (""). + +There are different modes Mode$ for a filepanel. Depending on the mode it will act differently: + +Mode$ = "Load-File" -- the user is able to select any file +Mode$ = "Load-Directory" -- the user is able to select any directory +Mode$ = "Load-File-and-Directory" -- the user is able to select any file or directory +Mode$ = "Save-File" -- the user is able to select either an existing file or enter a name for a new file; when selecting an existing file a popup window will ask whether the file should really be overwritten + +Furthermore, the title for the window tab has to specified in Title$. Ideally this should be something like "Open" or "Save" according to the mode. + +The starting directory for browsing is set with Directory$. If this is an invalid directory, "/boot/home" will be used instead. + +Only for the "Save-File" mode, you additionally can provide a default filename that is put into the textcontrol field of the filepanel in this mode. If you call the filepanel without DefaultFile$, the textcontrol field will be empty. + +Design: +Having filepanels for the file selection is always a good idea. They are much easier to handle than self constructed columnboxes for browsing directories. To use them is just the BeOS way of doing things. + +Example: +window open 100,100 to 300,200, "Example", "Example" +button 10,10 to 190,30, "OpenFile", "Open a file...", "Example" +button 10,40 to 190,60, "OpenDir", "Open a directory...", "Example" +button 10,70 to 190,90, "Save", "Save a file...", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "OpenFile")) filename$ = filepanel "load-file", "Open File", "" + if(instr(m$, "OpenDir")) filename$ = filepanel "load-directory", "Open Directory", "" + if(instr(m$, "Save")) filename$ = filepanel "save-file", "Save File", "", "SuggestedFile" + + if(instr(m$, "Quit")) quitting = true + + if(filename$ <> "") then + alert "You haven chosen "+filename$, "Ok", "info" + filename$ = "" + endif +wend + +window close "Example" +Explanation: + +The example above opens a window with three buttons. According to the button the filepanel is started in a different mode. Try to understand the difference in the behaviour of the three modes above. Finally, when a valid file or directory is chosen, an alert popup window opens to display the full path of that selected entry. + +& +window open + +Name: +window open -- open a window + +Synopsis: +WINDOW OPEN x1,y1 TO x2,y2, ID$, Title$ + +Description: +The window open command is a very basic and very important command for most yab programs. As it name says, a window is opened on the current desktop. The coordinates (x1,y1) to (x2,y2) of the window are related to the screen coordinates of the current desktop; thus (0,0) is the upper left corner of the screen. The window gets a title named Title$ which is displayed in the tab of the window. Title$ is allowed to be empty ("") aswell. Additionally, the window gets an own ID named ID$. You can use it like any other view and draw on it or put widgets on it. However, you cannot delete it with the view remove command, use window close instead. + +Message: +A window will send several messages to the message queue: +ID$+":_QuitRequested" -- the close button was pressed or the window received any other message to close itself +ID$+":_Activated" -- the window was activated +ID$+":_Deactivated" -- the window was deactivated + +If your application gets the general message "_QuitRequested" it is asked to close down completly. This is more general than the window "_QuitRequested" above which only should shut down the window itself. + +Design: +Use capitalized words for the title tab in English as in headings (but not in German!). Your window should always act as expected when the close button is pressed. Have a look at the window set command to learn about different look and feel parameters for your window. + +When your window has quite a lot of widgets and drawings on startup to do, it might look quite ugly with lots of flickering. To avoid this, simply construct the window with negative coordinates (e.g. window open -400,-400 to -100,-100, "Example", "Example"). Then move it to its real position on the workspace with the "MoveTo" option of the window set command when the setup is done. + +Example: +window open 100,100 to 300,300, "Example", "Example" +button 10,90 to 190,110, "Button", "My First Window", "Example" + +while(not quitting) + m$ = message$ + if(instr(m$, "Example:_QuitRequested")) then + alert "You pressed the window close button", "Ok", "info" + quitting = true + elsif(instr(m$, "_QuitRequested")) then + alert "The application should now shut down", "Ok", "info" + quitting = true + elsif(instr(m$, "Button")) then + alert "The button was pressed", "Ok", "info" + endif +wend + +window close "Example" +Explanation: +A simple window with a button. Try to close it with the close button and then try to shut it down with the Alt-Q shortcut key. This shows how the different "_QuitRequested" messages should be handled. + +Related: +alert, window close, window count, window get, window set +& +window close + +Name: +window close -- close a window + +Synopsis: +WINDOW CLOSE WindowID$ + +Description: +Window close of course closes the window named WindowID$. All widgets and views in the window will be deleted. Their IDs and the window ID will no longer be valid, if you call them, yab will exit with an error message. + +Design: +It is good style to close all windows before exiting. Always keep track of the windows currently open. + +Related: +window open, window count, window get, window set +& +window count + +Name: +window count -- return the number of open windows + +Synopsis: +n = WINDOW COUNT + +Description: +To get the number n of currently open windows of your application, simply invoke window count. + +Example: +for i=1 to 10 + window open 10+i*10, 10+i*10 to 200+i*10, 200+i*10, "Win"+str$(i), "Win" + sleep 0.5 +next i + +n = window count + +while(n>0) + window close "Win"+str$(n) + n = window count + sleep 0.5 +wend +Explanation: + +This funky program first opens ten windows and then closes them using the window count to obtain the number ID of the last opened window. + +Related: +window open, window close, window get, window set +& +window get + +Name: +window get -- request information about a window + +Synopsis: +Result = WINDOW GET WindowID$, Option$ + +Description: +To obtain some properties of the window with the ID WindowID$, the following options are allowed: + +Option$ = "Position-X" -- Result will contain the horizontal position of the upper left corner of the window relative to the screen +Option$ = "Position-Y" -- Result will contain the vertical position of the upper left corner of the window relative to the screen +Option$ = "Width" -- Result will contain the width of the window +Option$ = "Height" -- Result will contain the height of the window +Option$ = "Minimum-Width" -- Result will contain the minimum width of the window that is allowed when resizing +Option$ = "Minimum-Height" -- Result will contain the minimum height of the window that is allowed when resizing +Option$ = "Maximum-Width" -- Result will contain the maximum width of the window that is allowed when resizing +Option$ = "Maximum-Height" -- Result will contain the maximum height of the window that is allowed when resizing +Option$ = "Exists" -- Result will be true if a window with this WindowID$ exits and false otherwise + +Example: +window open 100,100 to 300,300, "Example", "Example" + +w = 200 +h = 200 + +while(not instr(message$, "Quit")) + if(window get "Example", "Width" <> w) then + w = window get "Example", "Width" + print "New Width: ", w + endif + if(window get "Example", "Height" <> h) then + h = window get "Example", "Height" + print "New Height: ", h + endif +wend + +window close "Example" +Explanation: + +When the window is resized, the new width and the new height are printed on the standard output. + +Related: +window open, window close, window count, window set +& +window set + +Name: +window set -- set the properties of a window + +Synopsis: +WINDOW SET WindowID$, Option$ +WINDOW SET WindowID$, Option$, x,y +WINDOW SET WindowID$, Option$, Value$ + +Description: +This command allows the flexible ajustment of the look and feel of a window. We first inspect the options that require no further parameter other than Option$: + +Option$ = "Activate" -- activate the window, so it is in the foreground. +Option$ = "Deactivate" -- deactivate the window, so it is in the background. +Option$ = "Minimize" -- minimize the window, or restore the window if it is already minimized. +Option$ = "Maximize" -- maximize (zoom) the window. +Option$ = "Enable-Updates" -- updates the window again after a "Disable-Updates". +Option$ = "Disable-Updates" -- disables the automatic window updates. + +To disable updates is normally not needed, this just means that after this command no drawing even from widgets will be shown. + +Given two additional parameters x and y, the following options are valid: + +Option$ = "ResizeTo" -- resize the window to (x,y) relative screen coordinates +Option$ = "MoveTo" -- move the window to (x,y) relative screen coordinates +Option$ = "MinimumTo" -- when resizing, the minimum width and height is given by (x,y) +Option$ = "MaximumTo" -- when resizing, the maximum width and height is given by (x,y) + +Given an additional parameter Value$, the following options are valid: + +Option$ = "Look" -- this changes the appearance of the window accroding to the following values: +Value$ = "Document" -- large title bar, thick border, draggable resize box +Value$ = "Titled" -- same as the document window, but with a less substantial resize corner, default +Value$ = "Floating" -- small title bar, thin border, resize corner +Value$ = "Modal" -- no title bar, thick border, no resize control +Value$ = "Bordered" -- no title bar, line border, no resize control +Value$ = "No-Border" -- a borderless white rectangle + +Option$ = "Feel" -- this sets the behaviour of the window in relation to other windows +Value$ = "Normal" -- behaves like a normal window (non-modal, non-floating), default +Value$ = "Modal-App" -- the window blocks all other windows of this application +Value$ = "Modal-All" -- the window blocks all other windows on the system, the window is visible on all workspaces +Value$ = "Floating-App" -- the window floats on top of all other windows of this application +Value$ = "Floating-All" -- the window floats on top of all other windows on the system, the window is visible on all workspaces + +Option$ = "Flags" -- this sets special properties of a window, flags can be used accumulative, simply write all wanted flags in the Value$ +Value$ = "Not-Closable" -- the window does not have the close button in the tab +Value$ = "Not-Zoomable" -- the window does not have the zoom button in the tab +Value$ = "Not-Minimizable" -- the window cannot be minimized +Value$ = "Not-H-Resizable" -- the window cannot be resized horizontally +Value$ = "Not-V-Resizable" -- the window cannot be resized vertically +Value$ = "Not-Resizable" -- the window cannot be resized +Value$ = "Accept-First-Click" -- when the window is inactive it still accepts the first click +Value$ = "Reset" -- reset all flags back to none + +Option$ = "Workspace" -- sets where the window is shown: +Value$ = "All" -- the window is shown on all workspaces +Value$ = "Current" -- the window is shown on the current workspace, default + +Option$ = "Title" -- set the window title to Value$ + +Design: +Look: +For most application the default "Titled" look will be sufficient. However, heavy apps with big windows, e.g. the IDE, should have the "Document" look. Use "Floating" for toolboxes and other options that stay around, as done e.g. in Refraction. "Modal" is meant to be used for alert windows that block the main application. "Bordered" and "No-Border" are for more creative applications like games and eye candy stuff. + +Feel: +Always try to avoid windows with a "Modal-All" feel because they block the whole system. + +Resizable: +Try to set appropriate minimum and maximum width and height parameters so your application always looks good. + +Example: +window open 100,100 to 300,300, "Example", "Example" +window set "Example", "MinimumTo", 150,150 +window set "Example", "Look", "Floating" +window set "Example", "Feel", "Floating-All" + +while(not instr(message$, "Quit")) +wend + +window close "Example" +Explanation: + +A small demo window is opened with the floating look and feel. It can only be resized to a width and height of (150,150). + +Related: +window open, window close, window count, window get +& diff --git a/yab-IDE/data/SyntaxTreeIndex.dat b/yab-IDE/data/SyntaxTreeIndex.dat new file mode 100644 index 0000000..01989f5 --- /dev/null +++ b/yab-IDE/data/SyntaxTreeIndex.dat @@ -0,0 +1,620 @@ +&Arithmetic +7337 +& +7339 +abs() +7345 +acos() +7712 +and() +8211 +asin() +9001 +atan() +9510 +bin$() +10409 +cos() +11015 +dec() +11280 +eor() +11799 +euler +12576 +exp() +12982 +frac() +13604 +int() +14285 +log() +14685 +max() +15344 +min() +16136 +mod() +16551 +or() +17264 +pi +18057 +ran() +18513 +sig() +19356 +sin() +20000 +sqr() +20525 +sqrt() +20896 +tan() +21248 +xor() +21611 +** or ^ +22644 +& +23461 +and +23465 +break +23915 +case +24610 +continue +25107 +default +25776 +do +26896 +else +27440 +elsif +27979 +end +29449 +endif +30141 +false +30787 +fi +31354 +for +31668 +gosub +32630 +goto +33500 +if +34350 +label +36136 +loop +37125 +next +37612 +not +38171 +on gosub +38823 +on goto +40158 +on interrupt +41582 +logical or +42868 +pause +43271 +repeat +44499 +return +45186 +sleep +46885 +step +47260 +switch +47800 +then +49116 +true +49924 +until +50360 +wait +50967 +wend +51341 +while +51839 +: +52495 +& +53132 +arraydim() +53143 +arraysize() +54033 +data +56606 +dim +57558 +read +59075 +redim +59718 +restore +60157 +& +61226 +asc() +61232 +chr$() +62055 +glob() +62917 +abc matches a* +63878 + +64066 +hex$() +64075 +instr() +64565 +left$() +65579 +len() +66880 +lower$() +67254 +ltrim$() +67662 +rtrim$() +68314 +mid$() +68962 +right$() +70230 +split() +71549 +Please enter a line: a +74186 + +74680 +str$() +74706 +string | Result for converting 1000*pi | Description +76112 + +79509 +token() +79811 +Please enter a line: a +82334 + +82732 +trim$() +82759 +upper$() +83372 +val() +84020 +& +84734 +at() +84739 +clear screen +86030 +close +86746 +color +87217 +colour +88331 +eof +88478 +getscreen$() +89069 +inkey$ +90217 +input +91436 +Please enter the name of a file to read: test.yab +92830 + +92967 +line input +93002 +open +93844 +print +96665 +putscreen +99902 +reverse +100797 +screen +101576 +seek() +101806 +tell +103368 +using +104029 +# +105070 +at() +106443 +; +107722 +& +108368 +end sub +108376 +export +108808 +import foo +109855 + +110153 +Calling subroutine foo.bar (okay) ... +110254 + +110568 +import +111103 +rem Make the subroutine x easily available outside this library +112034 + +112210 +0 +112259 + +112417 +local +112702 +numparams +114162 +return +115613 +static +117315 +1 1 +118117 + +118140 +sub +118335 +& +120614 +bind() +120621 +clipboard copy +121393 +clipboard paste$ +122095 +compile +122717 +date$ +123273 +doc +124998 +docu$ +126153 +error +126975 +---Error in t.yab, line 2: Oh no ... +127618 + +127674 +execute$() +127688 +print foo$(a$,b$) +128723 + +128736 +execute() +128776 +exit +129181 +iscomputeron +129575 +pause +129963 +peek +131190 +peek$ +136253 +3a +139214 + +139235 +poke +139270 +rem +140508 +sleep +141622 +system$() +141981 +system() +142570 +thread get +143193 +thread remove +144542 +time$ +145465 +to +146634 +// +147188 +: +147692 +&Drawing +148325 +& +148327 +draw circle +148339 +draw curve +148998 +draw dot +149983 +draw ellipse +150564 +draw flush +151303 +draw get +152433 +draw get$ +154379 +draw image +155792 +draw line +157698 +draw rect +158270 +draw set +158926 +draw text +162295 +& +163465 +ismousein() +163477 +keyboard message$() +164199 +message$ +166088 +message send +168421 +_Scripting:...| +169326 + +169339 +mouse message$() +169566 +mousemove$ +171590 +MOUSE SET Option$ +172254 +shortcut +172760 +"S" for the shift key +173560 + +173712 +"O" for ALT-O +173862 + +173927 +ALT-X +174351 + +174394 +&Printing +175345 +& +175347 +printer +175355 +printer setup +177728 +& +178752 +menu +178757 +Menu$ = "--" +179225 +then the menu item will be a separator line. +179282 +"S" for the shift key +179755 +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" +180004 +"O" for ALT-O +180055 + +180120 +For the menu Head$ "File": +180918 + +181168 +menu set +182260 +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +183063 + +183212 +popupmenu +184323 +submenu +185971 +Menu$ = "--" +186555 +then the submenu item will be a separator line. +186615 +"S" for the shift key +187091 +These modifiers can be combined, but the following combinations do not work: "SO", "SC" and "SCO" +187340 +"O" for ALT-O +187391 + +187456 +submenu set +190342 +Option$ = "Disable" -- grey out the item so it cannot be selected anymore +191218 + +191367 +& +192114 +boxview +192122 +stackview +193545 +stackview get +195659 +stackview set +195950 +& +196407 +button +196414 +button image +197729 +calendar +199470 +calendar get$ +201137 +calendar set +201630 +checkbox +202055 +checkbox image +203312 +checkbox set +205539 +colorcontrol +205838 +colorcontrol get +207860 +colorcontrol set +208468 +columnbox +208804 +columnbox add +214014 +columnbox clear +215195 +columnbox color +215563 +columnbox column +216608 +columnbox count +217767 +columnbox get +218205 +columnbox get$ +218740 +columnbox remove +219283 +columnbox select +219640 +listbox +220095 +listbox add +223060 +listbox clear +223538 +listbox count +223833 +listbox get +224229 +listbox get$ +224716 +listbox remove +225134 +listbox select +225473 +listbox sort +226118 +radiobutton +226830 +radiobutton set +228564 +statusbar +228970 +statusbar set +230439 +text +230937 +text set +232125 +textedit +233243 +textedit add +233536 +textedit clear +233748 +textedit color +234090 +textedit get +234392 +textedit get$ +234747 +textedit set +235021 +tooltip +237966 +tooltip color +239646 +&Localization +240934 +& +240936 +localize +240945 +# A comment starts with a # +242509 + +242633 +translate$() +244199 +&Sound +244952 +& +244954 +beep +244959 +bell +245193 +sound play +245556 +sound stop +246481 +sound wait +246855 +&Window +247260 +& +247262 +alert +247268 +filepanel +249046 +window open +252336 +window close +255051 +window count +255543 +window get +256170 +window set +257891 diff --git a/yab-IDE/data/autocompletion b/yab-IDE/data/autocompletion new file mode 100644 index 0000000..5c78b52 --- /dev/null +++ b/yab-IDE/data/autocompletion @@ -0,0 +1,174 @@ +alert +arraydim +arraysize +boxview +break +button +case +calendar +checkbox +chr$ +circle +clear +clipboard +close +collapse +color +colorcontrol +column +columnbox +compile +continue +copy +count +curve +data +date$ +default +draw +dropbox +dropzone +ellipse +else +elseif +elsif +end +endif +endsub +eof +eor +error +euler +execute +exit +expand +export +false +filepanel +flush +frac +getscreen$ +glob +gosub +goto +hashmarks +hide +image +inkey$ +input +instr +interrupt +ismousein +keyboard +label +layout +left$ +len +let +line +listbox +load$ +local +localize +log +loop +lower$ +ltrim$ +max +menu +message$ +mid$ +min +mod +mouse +new +next +not +open +option +paste$ +pause +peek +peek$ +pi +poke +popupmenu +print +printer +putscreen +radiobutton +ran +read +reading +rect +rect +redim +rem +remove +repeat +resize +restore +return +reverse +right$ +rinstr +rtrim$ +save$ +screen +scrollbar +seek +select +set +setup +show +sig +sin +sleep +slider +sort +soundplay +spincontrol +split +split$ +splitview +sqr +sqrt +stackview +static +step +str$ +sub +submenu +subroutine +svg +switch +system +system$ +tabview +tan +tell +text +text +textcontrol +textedit +texturl +then +time$ +token +token$ +tooltip +translate$ +treebox +trim$ +true +until +upper$ +using +val +view +wait +wend +while +window +writing +xor diff --git a/yab-IDE/data/color1 b/yab-IDE/data/color1 new file mode 100644 index 0000000..e771b1d --- /dev/null +++ b/yab-IDE/data/color1 @@ -0,0 +1,153 @@ +EXECUTE +EXECUTE$ +COMPILE +ENDSUB +ENDIF +END-IF +ENDWHILE +END-WHILE +ENDSWITCH +END-SWITCH +ENDSWITCH$ +END-SWITCH$ +EXPORT +ERROR +FOR +BREAK +SWITCH +CASE +DEFAULT +LOOP +DO +TO +AS +READING +WRITING +STEP +NEXT +WHILE +WEND +REPEAT +UNTIL +GOTO +GOSUB +SUB +SUBROUTINE +LOCAL +STATIC +ON +INTERRUPT +CONTINUE +LABEL +IF +THEN +ELSE +ELSIF +ELSEIF +ENDIF +FI +OPEN +CLOSE +SEEK +TELL +PRINT +USING +REVERSE +COLOR +COLOUR +INPUT +RETURN +DIM +REDIM +END +EXIT +READ +DATA +RESTORE +? +WINDOW +PRINTER +SETUP +PUTSCREEN +GETSCREEN$ +NEW +WAIT +PAUSE +SLEEP +BELL +BEEP +LET +ARRAYDIM +ARRAYDIMENSION +ARRAYSIZE +BIND +SET +LOCALIZE +BUTTON +ALERT +MENU +CHECKBOX +RADIOBUTTON +TEXTCONTROL +LISTBOX +DROPBOX +ADD +REMOVE +TEXT +RECT +DRAW +FLUSH +FILEPANEL +LAYOUT +TEXTEDIT +SHOW +HIDE +COUNT +VIEW +BOXVIEW +TABVIEW +ELLIPSE +DOT +LINE +CURVE +CIRCLE +CLEAR +TEXT +RECT +SLIDER +HASHMARKS +OPTION +RESIZE +DROPZONE +COLORCONTROL +TREEBOX +SORT +TOOLTIP +COLUMNBOX +COLUMN +CLIPBOARD +COPY +SUBMENU +KEYBOARD +SELECT +CALENDAR +SCROLLBAR +COLLAPSE +EXPAND +SOUNDPLAY +SPLITVIEW +STACKVIEW +TEXTURL +SPINCONTROL +POPUPMENU +PASTE$ +IMAGE +SVG +GET$ +LOAD$ +SAVE$ +MOUSE +ISMOUSEIN +GET +TRANSLATE$ +MESSAGE$ diff --git a/yab-IDE/data/color2 b/yab-IDE/data/color2 new file mode 100644 index 0000000..4ce7511 --- /dev/null +++ b/yab-IDE/data/color2 @@ -0,0 +1,54 @@ +@ +SIN +ASIN +COS +ACOS +TAN +ATAN +EXP +LOG +SQRT +SQR +INT +FRAC +ABS +SIG +MOD +RAN +MIN +MAX +LEFT$ +RIGHT$ +MID$ +LOWER$ +UPPER$ +LTRIM$ +RTRIM$ +TRIM$ +INSTR +RINSTR +LEN +VAL +EOF +STR$ +INKEY$ +CHR$ +ASC +HEX$ +BIN$ +DEC +AT +SCREEN +SYSTEM$ +SYSTEM +DATE$ +TIME$ +PEEK +PEEK$ +POKE +TOKEN +TOKEN$ +SPLIT +SPLIT$ +GLOB +DOCU$ diff --git a/yab-IDE/data/color3 b/yab-IDE/data/color3 new file mode 100644 index 0000000..426a100 --- /dev/null +++ b/yab-IDE/data/color3 @@ -0,0 +1,9 @@ +PI +EULER +TRUE +FALSE +AND +OR +NOT +EOR +XOR diff --git a/yab-IDE/data/color4 b/yab-IDE/data/color4 new file mode 100644 index 0000000..2af2c3e --- /dev/null +++ b/yab-IDE/data/color4 @@ -0,0 +1,4 @@ +REM +DOC +// +DOCU diff --git a/yab-IDE/data/color5 b/yab-IDE/data/color5 new file mode 100644 index 0000000..99b8586 --- /dev/null +++ b/yab-IDE/data/color5 @@ -0,0 +1,28 @@ +^ +* +< +> += +! +- ++ +* +/ +: +( +) +, +. +; +# +" +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 diff --git a/yab-IDE/img/Loading.png b/yab-IDE/img/Loading.png new file mode 100644 index 0000000..768e643 Binary files /dev/null and b/yab-IDE/img/Loading.png differ diff --git a/yab-IDE/img/Running.png b/yab-IDE/img/Running.png new file mode 100644 index 0000000..e86148f Binary files /dev/null and b/yab-IDE/img/Running.png differ diff --git a/yab-IDE/img/Splash.png b/yab-IDE/img/Splash.png new file mode 100644 index 0000000..349f5e8 Binary files /dev/null and b/yab-IDE/img/Splash.png differ diff --git a/yab-IDE/img/arrowdown.png b/yab-IDE/img/arrowdown.png new file mode 100644 index 0000000..3c12b8e Binary files /dev/null and b/yab-IDE/img/arrowdown.png differ diff --git a/yab-IDE/img/arrowright.png b/yab-IDE/img/arrowright.png new file mode 100644 index 0000000..a1567d7 Binary files /dev/null and b/yab-IDE/img/arrowright.png differ diff --git a/yab-IDE/img/bindd.png b/yab-IDE/img/bindd.png new file mode 100644 index 0000000..3d1e362 Binary files /dev/null and b/yab-IDE/img/bindd.png differ diff --git a/yab-IDE/img/bindn.png b/yab-IDE/img/bindn.png new file mode 100644 index 0000000..1a11e40 Binary files /dev/null and b/yab-IDE/img/bindn.png differ diff --git a/yab-IDE/img/bindp.png b/yab-IDE/img/bindp.png new file mode 100644 index 0000000..4bb0bc9 Binary files /dev/null and b/yab-IDE/img/bindp.png differ diff --git a/yab-IDE/img/closed.png b/yab-IDE/img/closed.png new file mode 100644 index 0000000..c4f0771 Binary files /dev/null and b/yab-IDE/img/closed.png differ diff --git a/yab-IDE/img/closen.png b/yab-IDE/img/closen.png new file mode 100644 index 0000000..e2a9d07 Binary files /dev/null and b/yab-IDE/img/closen.png differ diff --git a/yab-IDE/img/closep.png b/yab-IDE/img/closep.png new file mode 100644 index 0000000..e0d9f3f Binary files /dev/null and b/yab-IDE/img/closep.png differ diff --git a/yab-IDE/img/copyd.png b/yab-IDE/img/copyd.png new file mode 100644 index 0000000..3616add Binary files /dev/null and b/yab-IDE/img/copyd.png differ diff --git a/yab-IDE/img/copyn.png b/yab-IDE/img/copyn.png new file mode 100644 index 0000000..f8f62d2 Binary files /dev/null and b/yab-IDE/img/copyn.png differ diff --git a/yab-IDE/img/copyp.png b/yab-IDE/img/copyp.png new file mode 100644 index 0000000..1d3e191 Binary files /dev/null and b/yab-IDE/img/copyp.png differ diff --git a/yab-IDE/img/cutd.png b/yab-IDE/img/cutd.png new file mode 100644 index 0000000..7177d5a Binary files /dev/null and b/yab-IDE/img/cutd.png differ diff --git a/yab-IDE/img/cutn.png b/yab-IDE/img/cutn.png new file mode 100644 index 0000000..9d171c5 Binary files /dev/null and b/yab-IDE/img/cutn.png differ diff --git a/yab-IDE/img/cutp.png b/yab-IDE/img/cutp.png new file mode 100644 index 0000000..79237b7 Binary files /dev/null and b/yab-IDE/img/cutp.png differ diff --git a/yab-IDE/img/debugd.png b/yab-IDE/img/debugd.png new file mode 100644 index 0000000..cdcb703 Binary files /dev/null and b/yab-IDE/img/debugd.png differ diff --git a/yab-IDE/img/debugn.png b/yab-IDE/img/debugn.png new file mode 100644 index 0000000..33f6b11 Binary files /dev/null and b/yab-IDE/img/debugn.png differ diff --git a/yab-IDE/img/debugp.png b/yab-IDE/img/debugp.png new file mode 100644 index 0000000..7a2dccb Binary files /dev/null and b/yab-IDE/img/debugp.png differ diff --git a/yab-IDE/img/gespeichert.png b/yab-IDE/img/gespeichert.png new file mode 100644 index 0000000..ac5fa68 Binary files /dev/null and b/yab-IDE/img/gespeichert.png differ diff --git a/yab-IDE/img/guid.png b/yab-IDE/img/guid.png new file mode 100644 index 0000000..f38df37 Binary files /dev/null and b/yab-IDE/img/guid.png differ diff --git a/yab-IDE/img/guin.png b/yab-IDE/img/guin.png new file mode 100644 index 0000000..304d7ae Binary files /dev/null and b/yab-IDE/img/guin.png differ diff --git a/yab-IDE/img/guip.png b/yab-IDE/img/guip.png new file mode 100644 index 0000000..408a30c Binary files /dev/null and b/yab-IDE/img/guip.png differ diff --git a/yab-IDE/img/helpd.png b/yab-IDE/img/helpd.png new file mode 100644 index 0000000..d2f78e1 Binary files /dev/null and b/yab-IDE/img/helpd.png differ diff --git a/yab-IDE/img/helpn.png b/yab-IDE/img/helpn.png new file mode 100644 index 0000000..4a62bf5 Binary files /dev/null and b/yab-IDE/img/helpn.png differ diff --git a/yab-IDE/img/helpp.png b/yab-IDE/img/helpp.png new file mode 100644 index 0000000..0af34fb Binary files /dev/null and b/yab-IDE/img/helpp.png differ diff --git a/yab-IDE/img/idea.png b/yab-IDE/img/idea.png new file mode 100644 index 0000000..8f1424f Binary files /dev/null and b/yab-IDE/img/idea.png differ diff --git a/yab-IDE/img/info.png b/yab-IDE/img/info.png new file mode 100644 index 0000000..b7d7ea8 Binary files /dev/null and b/yab-IDE/img/info.png differ diff --git a/yab-IDE/img/logo.png b/yab-IDE/img/logo.png new file mode 100644 index 0000000..304af04 Binary files /dev/null and b/yab-IDE/img/logo.png differ diff --git a/yab-IDE/img/newd.png b/yab-IDE/img/newd.png new file mode 100644 index 0000000..01fc292 Binary files /dev/null and b/yab-IDE/img/newd.png differ diff --git a/yab-IDE/img/newn.png b/yab-IDE/img/newn.png new file mode 100644 index 0000000..56facb2 Binary files /dev/null and b/yab-IDE/img/newn.png differ diff --git a/yab-IDE/img/newp.png b/yab-IDE/img/newp.png new file mode 100644 index 0000000..2a7532c Binary files /dev/null and b/yab-IDE/img/newp.png differ diff --git a/yab-IDE/img/nicht-gespeichert.png b/yab-IDE/img/nicht-gespeichert.png new file mode 100644 index 0000000..d4af810 Binary files /dev/null and b/yab-IDE/img/nicht-gespeichert.png differ diff --git a/yab-IDE/img/nichtgespeichert grau.png b/yab-IDE/img/nichtgespeichert grau.png new file mode 100644 index 0000000..6419c0b Binary files /dev/null and b/yab-IDE/img/nichtgespeichert grau.png differ diff --git a/yab-IDE/img/nichtgespeichert halbtransparent.png b/yab-IDE/img/nichtgespeichert halbtransparent.png new file mode 100644 index 0000000..a4cb985 Binary files /dev/null and b/yab-IDE/img/nichtgespeichert halbtransparent.png differ diff --git a/yab-IDE/img/nichtgespeichert.png b/yab-IDE/img/nichtgespeichert.png new file mode 100644 index 0000000..aec632a Binary files /dev/null and b/yab-IDE/img/nichtgespeichert.png differ diff --git a/yab-IDE/img/opend.png b/yab-IDE/img/opend.png new file mode 100644 index 0000000..1ce32a5 Binary files /dev/null and b/yab-IDE/img/opend.png differ diff --git a/yab-IDE/img/openn.png b/yab-IDE/img/openn.png new file mode 100644 index 0000000..97158aa Binary files /dev/null and b/yab-IDE/img/openn.png differ diff --git a/yab-IDE/img/openp.png b/yab-IDE/img/openp.png new file mode 100644 index 0000000..665e73d Binary files /dev/null and b/yab-IDE/img/openp.png differ diff --git a/yab-IDE/img/optionsd.png b/yab-IDE/img/optionsd.png new file mode 100644 index 0000000..a6ac774 Binary files /dev/null and b/yab-IDE/img/optionsd.png differ diff --git a/yab-IDE/img/optionsn.png b/yab-IDE/img/optionsn.png new file mode 100644 index 0000000..28f7d7b Binary files /dev/null and b/yab-IDE/img/optionsn.png differ diff --git a/yab-IDE/img/optionsp.png b/yab-IDE/img/optionsp.png new file mode 100644 index 0000000..223f642 Binary files /dev/null and b/yab-IDE/img/optionsp.png differ diff --git a/yab-IDE/img/pasted.png b/yab-IDE/img/pasted.png new file mode 100644 index 0000000..043ce32 Binary files /dev/null and b/yab-IDE/img/pasted.png differ diff --git a/yab-IDE/img/pasten.png b/yab-IDE/img/pasten.png new file mode 100644 index 0000000..c6aadbb Binary files /dev/null and b/yab-IDE/img/pasten.png differ diff --git a/yab-IDE/img/pastep.png b/yab-IDE/img/pastep.png new file mode 100644 index 0000000..ecc6bb2 Binary files /dev/null and b/yab-IDE/img/pastep.png differ diff --git a/yab-IDE/img/patternd.png b/yab-IDE/img/patternd.png new file mode 100644 index 0000000..63bd82e Binary files /dev/null and b/yab-IDE/img/patternd.png differ diff --git a/yab-IDE/img/patternn.png b/yab-IDE/img/patternn.png new file mode 100644 index 0000000..d200967 Binary files /dev/null and b/yab-IDE/img/patternn.png differ diff --git a/yab-IDE/img/patternp.png b/yab-IDE/img/patternp.png new file mode 100644 index 0000000..d17dd72 Binary files /dev/null and b/yab-IDE/img/patternp.png differ diff --git a/yab-IDE/img/redod.png b/yab-IDE/img/redod.png new file mode 100644 index 0000000..e6e0f54 Binary files /dev/null and b/yab-IDE/img/redod.png differ diff --git a/yab-IDE/img/redon.png b/yab-IDE/img/redon.png new file mode 100644 index 0000000..da63660 Binary files /dev/null and b/yab-IDE/img/redon.png differ diff --git a/yab-IDE/img/redop.png b/yab-IDE/img/redop.png new file mode 100644 index 0000000..1e9e058 Binary files /dev/null and b/yab-IDE/img/redop.png differ diff --git a/yab-IDE/img/rund.png b/yab-IDE/img/rund.png new file mode 100644 index 0000000..f7e81b9 Binary files /dev/null and b/yab-IDE/img/rund.png differ diff --git a/yab-IDE/img/runn.png b/yab-IDE/img/runn.png new file mode 100644 index 0000000..401fcb1 Binary files /dev/null and b/yab-IDE/img/runn.png differ diff --git a/yab-IDE/img/runp.png b/yab-IDE/img/runp.png new file mode 100644 index 0000000..8f0f61e Binary files /dev/null and b/yab-IDE/img/runp.png differ diff --git a/yab-IDE/img/runtermd.png b/yab-IDE/img/runtermd.png new file mode 100644 index 0000000..37a719b Binary files /dev/null and b/yab-IDE/img/runtermd.png differ diff --git a/yab-IDE/img/runtermn.png b/yab-IDE/img/runtermn.png new file mode 100644 index 0000000..3a0676b Binary files /dev/null and b/yab-IDE/img/runtermn.png differ diff --git a/yab-IDE/img/runtermp.png b/yab-IDE/img/runtermp.png new file mode 100644 index 0000000..dab6563 Binary files /dev/null and b/yab-IDE/img/runtermp.png differ diff --git a/yab-IDE/img/saved.png b/yab-IDE/img/saved.png new file mode 100644 index 0000000..7873c8a Binary files /dev/null and b/yab-IDE/img/saved.png differ diff --git a/yab-IDE/img/saven.png b/yab-IDE/img/saven.png new file mode 100644 index 0000000..ec16fe7 Binary files /dev/null and b/yab-IDE/img/saven.png differ diff --git a/yab-IDE/img/savep.png b/yab-IDE/img/savep.png new file mode 100644 index 0000000..a2521d2 Binary files /dev/null and b/yab-IDE/img/savep.png differ diff --git a/yab-IDE/img/searchd.png b/yab-IDE/img/searchd.png new file mode 100644 index 0000000..6464b29 Binary files /dev/null and b/yab-IDE/img/searchd.png differ diff --git a/yab-IDE/img/searchn.png b/yab-IDE/img/searchn.png new file mode 100644 index 0000000..50dfc74 Binary files /dev/null and b/yab-IDE/img/searchn.png differ diff --git a/yab-IDE/img/searchp.png b/yab-IDE/img/searchp.png new file mode 100644 index 0000000..4abff4c Binary files /dev/null and b/yab-IDE/img/searchp.png differ diff --git a/yab-IDE/img/stop.png b/yab-IDE/img/stop.png new file mode 100644 index 0000000..0cc1322 Binary files /dev/null and b/yab-IDE/img/stop.png differ diff --git a/yab-IDE/img/undod.png b/yab-IDE/img/undod.png new file mode 100644 index 0000000..2f37888 Binary files /dev/null and b/yab-IDE/img/undod.png differ diff --git a/yab-IDE/img/undon.png b/yab-IDE/img/undon.png new file mode 100644 index 0000000..2a6ada6 Binary files /dev/null and b/yab-IDE/img/undon.png differ diff --git a/yab-IDE/img/undop.png b/yab-IDE/img/undop.png new file mode 100644 index 0000000..3a40cfb Binary files /dev/null and b/yab-IDE/img/undop.png differ diff --git a/yab-IDE/img/warning.png b/yab-IDE/img/warning.png new file mode 100644 index 0000000..6b7c478 Binary files /dev/null and b/yab-IDE/img/warning.png differ diff --git a/yab-IDE/img/yablogo.png b/yab-IDE/img/yablogo.png new file mode 100644 index 0000000..3c99a72 Binary files /dev/null and b/yab-IDE/img/yablogo.png differ diff --git a/yab-IDE/src/yab-IDE.yab b/yab-IDE/src/yab-IDE.yab new file mode 100755 index 0000000..e423046 --- /dev/null +++ b/yab-IDE/src/yab-IDE.yab @@ -0,0 +1,3918 @@ +#!yab + +doc Author: Jan Bungeroth +doc Thanks to: Genki, Lelldorin, lorglas, Stargater, DasJott +doc (c) 2006-2015 in terms of the Artistic License + +doc +doc The yab-IDE provides you with an integrated development suite for yab +doc Enjoy. +path() +versionnumber$="2.2.4" + +settingsRCSOff = true +globalConfigDir$ = trim$(system$("finddir B_USER_SETTINGS_DIRECTORY"))+"/yab-ide/" + +if(LoadSettings() = 1) then + + MAXFILES = 20 + DEBUG = true + + + settingsYabDir$ = path$ //"/boot/apps/yab-1.7/" + globalProjectDir$ = trim$(system$("finddir B_USER_DIRECTORY"))+"/yab_work/Programs/" + yabDir$ = yabpath$() + ideDir$ = path$ //settingsYabDir$ + "yab-IDE/" + + buildDir$ = trim$(system$("finddir B_USER_DIRECTORY"))+"/yab_work/BuildFactory/" + globalHelpDir$ = settingsYabDir$ + "Documentation/" + + settingsLangUse = true + settingsLangPath$ = "x-vnd.yab-IDE" + + settingsAutoIndent = true + settingsAutoCompletion = true + settingsACNumChar = 2 + settingsX = 50 + settingsY = 50 + settingsWidth = peek("desktopwidth")-100 + if(settingsWidth<600) settingsWidth = 600 + settingsHeight = peek("desktopheight")-100 + settingsFullScreen = false + settingsFullEditor = false + settingsVSplitDivider = 180 + settingsV2SplitDivider = 41 + settingsHSplitDivider = settingsHeight-240 + settingsCalcPatternX = 200 + settingsCalcPatternY = 150 + settingsColorSelectX = 100 + settingsColorSelectY = 100 + settingsColorSelectR = 255 + settingsColorSelectG = 255 + settingsColorSelectB = 255 + settingsAskForSaving = true + settingsFindCS = false + settingsOldSearch$ = "" + settingsFindAlert = true + settingsReformatAlert = true + settingsReformatUndoAlert = true + settingsTabSpaces = 4 + settingsFontFamily$ = "DejaVu Sans Mono" + settingsFontStyle$ = "Book" + settingsFontSize = 12 + globalRealFontSize = 15 + settingsYabParam$ = "" + settingsProgParam$ = "" + + dim globalAllNames$(MAXFILES) + dim globalTextFinder(MAXFILES) + + for i=1 to MAXFILES + globalAllNames$(i) = "" + globalTextFinder(i) = 0 + next i + +endif + + +restartSettingsLangUse = settingsLangUse +textcolor_r = 0 +textcolor_g = 0 +textcolor_b = 0 + +// globalNoRCS = system("test -e /boot/beos/bin/ci") or system("test -e /boot/beos/bin/co") or system("test -e /boot/beos/bin/rlog") or settingsRCSOff +globalNoRCS = settingsRCSOff +globalCurrentText = 0 +globalHSplitDivider = settingsHSplitDivider +globalReformatUndo = false +globalSelectErrorLines = true +globalNewNumber = 0 +globalNumOpenFiles = 0 +globalWasChanged = false +globalRealOS$ = upper$(system$("uname -o")) +globalRealOS$ = left$(globalRealOS$, 4) + +oldSpinner = 1 + +if(settingsLangUse) then + localize settingsLangPath$ +endif + + +OpenMainWindow() +ActivateMenus(false) +UpdateStatusbar() + +LoadOpenFiles() + +if(settingsFullScreen) then + menu set "View", "Full screen", "mark", "MainView" + window set "MainView", "moveto", 0,0 + window set "MainView", "resizeto", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MinimumTo", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MaximumTo", peek("desktopwidth")-1, peek("desktopheight")-1 +endif +if(settingsFullEditor) then + oldSplitX = splitview get "VSplit", "Divider" +// oldSplitY = splitview get "HSplit", "Divider" + tmp = window get "MainView", "Height" + splitview set "HSplit", "Divider", tmp-51 + splitview set "VSplit", "Divider", 0 + menu set "View", "Maximize editor", "mark", "MainView" +endif + +dim msg$(1) +dim pattern(8,8) + +inloop = true +while(inloop) + sleep 0.01 + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + switch(msg$(i)) + case "ToolbarNew" + case MyTranslate$("MainView:File:New...") + foundEmpty = 0 + for j=1 to MAXFILES + if(globalAllNames$(j) = "") then + foundEmpty = j + break + endif + next j + if(not foundEmpty) then + alert MyTranslate$("Sorry, you can not open more than ")+str$(MAXFILES)+MyTranslate$(" files at once!\n\nPlease close one or more other files first."), "Ok", "Warning" + else + NewDocument(foundEmpty) + if(globalNumOpenFiles = 1) then + ActivateMenus(true) + splitview set "V2Split", "Divider", settingsV2SplitDivider + endif + endif + break + case "ToolbarOpen" + case MyTranslate$("MainView:File:Open...") + foundEmpty = 0 + for j=1 to MAXFILES + if(globalAllNames$(j) = "") then + foundEmpty = j + break + endif + next j + if(not foundEmpty) then + alert MyTranslate$("Sorry, you can not open more than ")+str$(MAXFILES)+MyTranslate$(" files at once!\n\nPlease close one or more other files first."), "Ok", "Warning" + else + tmp$ = filepanel "Load-File", "Open", globalProjectDir$ + if(tmp$<>"") then + foundProject = false + for j = 1 to MAXFILES + if(globalAllNames$(j) = tmp$) then + alert "File is already open.", "Ok", "info" + ActivateText(j) + foundProject = true + break + endif + next j + if(foundProject) break + + handle = open(tmp$, "r") + if(handle) then + WaitWindow(tmp$) + text$ = "" + while(not eof(handle)) + t$ = GetLine$(handle)+"\n" + if(len(t$)*8>4000) textedit set "Text"+str$(foundEmpty), "textwidth", len(t$)*8+8 + text$ = text$ + t$ + wend + close(handle) + globalCurrentText = foundEmpty + textedit add "Text"+str$(globalCurrentText), text$ + textedit set "Text"+str$(globalCurrentText), "changed", false + textedit set "Text"+str$(globalCurrentText), "gotoline", ReadLineFromAttr(tmp$) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + globalAllNames$(globalCurrentText) = tmp$ + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/gespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(tmp$) // "Filename", t, GetFileName$(tmp$) + columnbox select "FileBox", t+1 + globalTextFinder(globalCurrentText) = t+1 + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + globalNumOpenFiles = globalNumOpenFiles + 1 + if(globalNumOpenFiles = 1) then + ActivateMenus(true) + splitview set "V2Split", "Divider", settingsV2SplitDivider + endif + globalProjectDir$ = GetDirectory$(tmp$) + window close "WaitWindow" + else + alert MyTranslate$("Error while loading file:\n\n")+tmp$, "Ok", "Stop" + endif + endif + endif + break + case "ToolbarClose" + case MyTranslate$("MainView:File:Close") + if(textedit get "Text"+str$(globalCurrentText), "hasChanged") then + tmpSave = alert MyTranslate$("File \"")+GetFileName$(globalAllNames$(globalCurrentText))+MyTranslate$("\" not saved!\n\nSave the file now?"), "Cancel", "Close", "Save", "warning" + if(tmpSave = 1) break + if(tmpSave = 3) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + endif + + textedit clear "Text"+str$(globalCurrentText) + globalAllNames$(globalCurrentText) = "" + + columnbox remove "FileBox", globalTextFinder(globalCurrentText) + closeFinished = 0 + newCurrent = 0 + for tmpClose = 1 to MAXFILES + if(globalTextFinder(tmpClose)>globalTextFinder(globalCurrentText)) then + if(globalTextFinder(tmpClose) = globalTextFinder(globalCurrentText) + 1) then + closeFinished = globalTextFinder(tmpClose) - 1 + newCurrent = tmpClose + endif + globalTextFinder(tmpClose) = globalTextFinder(tmpClose) - 1 + endif + next tmpClose + + if(closeFinished=0) then + closeFinished = globalTextFinder(globalCurrentText) - 1 + if(closeFinished = 0) then + newCurrent = 0 + else + for j = 1 to MAXFILES + if(globalTextFinder(j) = globalTextFinder(globalCurrentText)-1) then + newCurrent = j + break + endif + next j + endif + endif + + globalTextFinder(globalCurrentText) = 0 + globalCurrentText = newCurrent + + if(closeFinished=0) then + stackview set "Stack", MAXFILES+2 + stackview set "Lines", MAXFILES+2 + settingsV2SplitDivider = splitview get "V2Split", "Divider" + splitview set "V2Split", "Divider", 0 + ActivateMenus(false) + else + ActivateText(globalCurrentText) + endif + globalNumOpenFiles = globalNumOpenFiles - 1 + break + case "ToolbarSave" + case MyTranslate$("MainView:File:Save") + tmpNull = SaveCurrentFile() + break + case MyTranslate$("MainView:File:Save as...") + tmpSaveAs$ = filepanel "Save-File", "Save", GetDirectory$(globalAllNames$(globalCurrentText)), GetFileName$(globalAllNames$(globalCurrentText)) + print tmpSaveAs$ + if(tmpSaveAs$<>"") then + handle = open(tmpSaveAs$, "w") + if(handle) then + print #handle textedit get$ "Text"+str$(globalCurrentText); + close(handle) + tmpCurrentLine = textedit get "Text"+str$(globalCurrentText), "currentline" + attribute set "Int", "linenumber", "tmpCurrentLine", tmpSaveAs$ + textedit set "Text"+str$(globalCurrentText), "changed", false + globalAllNames$(globalCurrentText) = tmpSaveAs$ + columnbox clear "FileBox" + for j=1 to MAXFILES + for k=1 to MAXFILES + if(globalTextFinder(j)=k) then + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/gespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(globalAllNames$(j)) + break + endif + next k + next j + columnbox select "FileBox", globalTextFinder(globalCurrentText) + else + alert "File could not be saved!", "Ok", "warning" + endif + endif + break + case MyTranslate$("MainView:File:Save as template...") + SaveAsTemplate() + break + case MyTranslate$("MainView:File:Export as HTML...") + ExportAsHTML() + break + case MyTranslate$("MainView:File:Page setup...") + printer setup globalConfigDir$+"printersetup" + break + case MyTranslate$("MainView:File:Print...") + if(globalCurrentText>0) then + err = printer globalAllNames$(globalCurrentText), globalConfigDir$+"printersetup", "Text"+str$(globalCurrentText) + if(err = 4) then + printer setup "/tmp/printersetup" + err = printer globalAllNames$(globalCurrentText), "/tmp/printersetup", "Text"+str$(globalCurrentText) + system("rm -f /tmp/printersetup >/dev/null") + endif + if(err>1 and err<5) then + alert "Error while printing!", "Ok", "warning" + endif + endif + break + case "_QuitRequested" + // TODO make backups and save open files + inloop = false + if(not settingsFullScreen) then + settingsX = window get "MainView", "Position-X" + settingsY = window get "MainView", "Position-Y" + settingsWidth = window get "MainView", "Width" + settingsHeight = window get "MainView", "Height" + endif + if(not settingsFullEditor) then + settingsVSplitDivider = splitview get "VSplit", "Divider" + settingsV2SplitDivider = splitview get "V2Split", "Divider" + settingsHSplitDivider = splitview get "HSplit", "Divider" + endif + break + case "MainView:_QuitRequested" + case MyTranslate$("MainView:File:Quit") + tmpSelect = 1 + if(globalCurrentText>0) then + for j=1 to MAXFILES + if(textedit get "Text"+str$(j), "hasChanged") then + tmpSelect = alert "Some files are not saved!\n\nDo you really want to quit?", "Quit", "Cancel", "", "warning" + break + endif + next j + endif + if(tmpSelect = 1) then + inloop = false + if(not settingsFullScreen) then + settingsX = window get "MainView", "Position-X" + settingsY = window get "MainView", "Position-Y" + settingsWidth = window get "MainView", "Width" + settingsHeight = window get "MainView", "Height" + endif + if(not settingsFullEditor) then + settingsVSplitDivider = splitview get "VSplit", "Divider" + settingsV2SplitDivider = splitview get "V2Split", "Divider" + settingsHSplitDivider = splitview get "HSplit", "Divider" + endif + endif + break + case "ToolbarCut" + case MyTranslate$("MainView:Edit:Cut") + textedit set "Text"+str$(globalCurrentText), "Cut" + break + case "ToolbarCopy" + case MyTranslate$("MainView:Edit:Copy") + if(globalIsHelp) then + textedit set "Text"+str$(MAXFILES+1), "Copy" + else + textedit set "Text"+str$(globalCurrentText), "Copy" + endif + break + case "ToolbarPaste" + case MyTranslate$("MainView:Edit:Paste") + textedit set "Text"+str$(globalCurrentText), "Paste" + break + case "ToolbarUndo" + case MyTranslate$("MainView:Edit:Undo") + textedit set "Text"+str$(globalCurrentText), "Undo" + break + case MyTranslate$("MainView:Edit:Select all") + if(globalIsHelp) then + textedit set "Text"+str$(MAXFILES+1), "Select-All" + else + textedit set "Text"+str$(globalCurrentText), "Select-All" + endif + break + case MyTranslate$("MainView:Edit:Clear") + textedit set "Text"+str$(globalCurrentText), "Clear" + break + case MyTranslate$("MainView:Edit:Find") + option set "ToolbarText", "focus", true + break + case MyTranslate$("MainView:Edit:Find again") + if(settingsOldSearch$<>"") then + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + case MyTranslate$("MainView:Edit:Find and replace") + if(settingsFullEditor) then + splitview set "VSplit", "Divider", oldSplitX + splitview set "HSplit", "Divider", oldSplitY + menu set "View", "Maximize editor", "plain", "MainView" + settingsFullEditor = false + endif + tabview set "HTab", 3 + option set "FindTCFind", "Focus", true + break + case "ToolbarRun" + case MyTranslate$("MainView:Program:Run") + isNotSaved = textedit get "Text"+str$(globalCurrentText), "hasChanged" + askForSaving = 3 + if(settingsAskForSaving and isNotSaved) then + askForSaving = alert "Program is not saved.\n\nSave it now?", "Cancel", "Save Always", "Save Now", "info" + endif + + if(askForSaving>1) then + if(askForSaving = 2) settingsAskForSaving = true + if(isNotSaved) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + RunProgram(globalAllNames$(globalCurrentText)) + endif + break + case "ToolbarRunTerm" + case MyTranslate$("MainView:Program:Run in Terminal") + isNotSaved = textedit get "Text"+str$(globalCurrentText), "hasChanged" + askForSaving = 3 + if(settingsAskForSaving and isNotSaved) then + askForSaving = alert "Program is not saved.\n\nSave it now?", "Cancel", "Save Always", "Save Now", "info" + endif + + if(askForSaving>1) then + if(askForSaving = 2) settingsAskForSaving = true + if(isNotSaved) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + RunInTerminal(globalAllNames$(globalCurrentText)) + endif + break + case MyTranslate$("MainView:Program:Set run parameters...") + SetRunParameters() + break + case "ToolbarBuild" + case MyTranslate$("MainView:Program:Build Factory...") + isNotSaved = textedit get "Text"+str$(globalCurrentText), "hasChanged" + askForSaving = 3 + if(settingsAskForSaving and isNotSaved) then + askForSaving = alert "Program is not saved.\n\nSave it now?", "Cancel", "Save Always", "Save Now", "info" + endif + + if(askForSaving>1) then + if(askForSaving = 2) settingsAskForSaving = true + if(isNotSaved) then + tmpSave = SaveCurrentFile() + if(not tmpSave) break + endif + Building() + endif + break + case MyTranslate$("MainView:Program:Open project folder...") + system("open " + globalProjectDir$) + break + case "ToolbarPattern" + case MyTranslate$("MainView:Tools:Pattern editor...") + OpenCalcPattern(settingsCalcPatternX,settingsCalcPatternY) + break + case MyTranslate$("MainView:Tools:Color selection...") + OpenColorSelection(settingsColorSelectX,settingsColorSelectY, settingsColorSelectR, settingsColorSelectG, settingsColorSelectB) + break + case MyTranslate$("MainView:Tools:ASCII table...") + AsciiWindow() + break + case MyTranslate$("MainView:View:Next file") + findNext = false + tmpCounter = globalCurrentText + while(not findNext) + tmpCounter = tmpCounter + 1 + if(tmpCounter>MAXFILES) tmpCounter = 1 + if(tmpCounter = globalCurrentText) then + findNext = true + else + if(globalAllNames$(tmpCounter)<>"") then + globalCurrentText = tmpCounter + ActivateText(globalCurrentText) + findNext = true + endif + endif + wend + break + case MyTranslate$("MainView:View:Previous file") + findNext = false + tmpCounter = globalCurrentText + while(not findNext) + tmpCounter = tmpCounter - 1 + if(tmpCounter=0) tmpCounter = MAXFILES + if(tmpCounter = globalCurrentText) then + findNext = true + else + if(globalAllNames$(tmpCounter)<>"") then + globalCurrentText = tmpCounter + ActivateText(globalCurrentText) + findNext = true + endif + endif + wend + break + case MyTranslate$("MainView:View:Full screen") + if settingsFullScreen then + menu set "View", "Full screen", "plain", "MainView" + currentDivider = peek("desktopheight")-1 - splitview get "HSplit", "Divider" + window set "MainView", "moveto", settingsX,settingsY + window set "MainView", "MinimumTo", 600,300 + window set "MainView", "MaximumTo", 2000, 2000 + window set "MainView", "resizeto", settingsWidth, settingsHeight + splitview set "HSplit", "Divider", settingsHeight-currentDivider + settingsFullScreen = false + else + settingsX = window get "MainView", "Position-X" + settingsY = window get "MainView", "Position-Y" + settingsWidth = window get "MainView", "Width" + settingsHeight = window get "MainView", "Height" + currentDivider = settingsHeight - splitview get "HSplit", "Divider" + menu set "View", "Full screen", "mark", "MainView" + window set "MainView", "moveto", 0,0 + window set "MainView", "resizeto", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MinimumTo", peek("desktopwidth")-1, peek("desktopheight")-1 + window set "MainView", "MaximumTo", peek("desktopwidth")-1, peek("desktopheight")-1 + splitview set "HSplit", "Divider", peek("desktopheight")-1-currentDivider + settingsFullScreen = true + endif + break + case MyTranslate$("MainView:View:Maximize editor") + if(settingsFullEditor) then + splitview set "VSplit", "Divider", oldSplitX + splitview set "HSplit", "Divider", oldSplitY + menu set "View", "Maximize editor", "plain", "MainView" + settingsFullEditor = false + else + oldSplitX = splitview get "VSplit", "Divider" + oldSplitY = splitview get "HSplit", "Divider" + tmp = window get "MainView", "Height" + splitview set "HSplit", "Divider", tmp-51 + splitview set "VSplit", "Divider", 0 + menu set "View", "Maximize editor", "mark", "MainView" + settingsFullEditor = true + endif + break + case MyTranslate$("MainView:View:Auto indent") + if(settingsAutoIndent) then + menu set "View", "Auto indent", "plain", "MainView" + else + menu set "View", "Auto indent", "mark", "MainView" + endif + settingsAutoIndent = not settingsAutoIndent + for tmpAllFiles = 1 to MAXFILES + textedit set "Text"+str$(tmpAllFiles), "autoindent", settingsAutoIndent + next tmpAllFiles + break + case MyTranslate$("MainView:View:Auto completion") + if(settingsAutoCompletion) then + menu set "View", "Auto completion", "plain", "MainView" + else + menu set "View", "Auto completion", "mark", "MainView" + endif + settingsAutoCompletion = not settingsAutoCompletion + for tmpAllFiles = 1 to MAXFILES + textedit set "Text"+str$(tmpAllFiles), "has-autocompletion", settingsAutoCompletion + next tmpAllFiles + break + case MyTranslate$("MainView:View:Reformat sourcecode") + reformatUndo$ = textedit get$ "Text"+str$(globalCurrentText) + globalReformatUndo = true + menu set "View", "Undo reformat", "enable", "MainView" + textedit clear "Text"+str$(globalCurrentText) + //tmp$ = ReformatSource$(reformatUndo$) + textedit add "Text"+str$(globalCurrentText),ReformatSource$(reformatUndo$) + if(ReformatError(false,0)<>0 and settingsReformatAlert) then + tmp = alert "Reformating did not close all open loops and conditions.\nReformating currently does not support loops and conditions opened and closed by a colon (:).\nE.g. while(loop):wend\n\nYou can undo the reformating before doing any further changes.", "Do not show this warning again", "Ok" , "", "warning" + if(tmp = 1) settingsReformatAlert = false + endif + break + case MyTranslate$("MainView:View:Undo reformat") + tmp = alert "Changes made since reformating will be lost!", "Cancel", "Do not show this warning again", "Undo reformating", "warning" + if(tmp > 1) then + if(tmp=2) settingsReformatUndoAlert = false + globalReformatUndo = false + textedit clear "Text"+str$(globalCurrentText) + textedit add "Text"+str$(globalCurrentText), reformatUndo$ + menu set "View", "Undo reformat", "disable", "MainView" + endif + break + case MyTranslate$("MainView:View:Refresh colors") + textedit color "Text"+str$(globalCurrentText), "textcolor", textcolor_r, textcolor_g, textcolor_b + break + case "ToolbarOptions" + case MyTranslate$("MainView:View:Options...") + OptionWindow() + break + case "ToolbarHelp" + case MyTranslate$("MainView:Help:Short command help...") + system("open "+globalHelpDir$+"yab-Commands &") + break + case MyTranslate$("MainView:Help:Yabasic manual...") + system("open "+globalHelpDir$+"yabasic.html &") + break + case MyTranslate$("MainView:Help:Online resources:German BeUsergroup...") + system("open http://www.beusergroup.de &") + break + case MyTranslate$("MainView:Help:Online resources:BeSly database...") + system("open http://www.besly.de &") + break + case MyTranslate$("MainView:Help:Online resources:Yabasic homepage...") + system("open http://www.yabasic.de &") + break + case MyTranslate$("MainView:Help:Online resources:Haikuware yab forum...") + system("open http://haikuware.com/forum/yab &") + break + case MyTranslate$("MainView:Help:About...") + AboutWindow() + break + + // the find and replace tabview + case "FindCS:ON" + case "FindCS:OFF" + settingsFindCS = not settingsFindCS + break + case "FindFind" + settingsOldSearch$ = textcontrol get$ "FindTCFind" + if(settingsOldSearch$<>"") then + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + case "FindReplace" + settingsOldSearch$ = textcontrol get$ "FindTCFind" + if(settingsOldSearch$<>"") then + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + if(searchLineNum <> -1) then + changestring() + + endif + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + case "FindReplAll" + if(settingsFindAlert) then + tmpAlert = alert "The operation \"Replace All\" can not be reverted!\n\nDo you want to continue?", "Cancel", "Do not show this warning again", "Ok", "warning" + if(tmpAlert = 1) break + if(tmpAlert = 2) settingsFindAlert = false + endif + settingsOldSearch$ = textcontrol get$ "FindTCFind" + if(settingsOldSearch$<>"") then + searchLineNum = 0 + while(searchLineNum<>-1) + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + if(searchLineNum <> -1) then + changestring() + endif + wend + option set "Text"+str$(globalCurrentText), "Focus", true + endif + break + + // the immediate tabview + case "ImmediateExecute" + tmp$ = textcontrol get$ "ImmediateInput" + ImmediateExec(tmp$) + break + + end switch + + // the output listbox, handle error messages + if((left$(msg$(i),22) = "YabOutputList:_Select:") or (left$(msg$(i),22) = "YabOutputList:_Invoke:")) then + tmp$ = listbox get$ "YabOutputList", val(right$(msg$(i),len(msg$(i))-22)) + if(left$(tmp$,8) = "---Error") then + num = instr(tmp$, "line ") + if(num) then + num = num + 5 + number$ = "" + repeat + number$ = number$ + mid$(tmp$,num,1) + num = num + 1 + until (mid$(tmp$,num,1) = ":") + num = val(number$) + + errorFileName$ = globalAllNames$(globalCurrentText) + errorFileFound = false + rightBound = instr(tmp$, ".yab") + if(rightBound) then + errorFileName$ = mid$(tmp$, 13, rightBound-13+4) + endif + if(errorFileName$<>globalAllNames$(globalCurrentText)) then + // check whether library is loaded already... + for tmpCheckName = 1 to MAXFILES + if((left$(errorFileName$,1) = "/" and errorFileName$ = globalAllNames$(tmpCheckName)) or (left$(errorFileName$,1) <> "/" and right$(globalAllNames$(tmpCheckName),len(errorFileName$)) = errorFileName$)) then + ActivateText(tmpCheckName) + errorFileFound = true + break + endif + next tmpCheckName + // otherwise load it now + else + errorFileFound = true + endif + + if(errorFileFound) then + textedit set "Text"+str$(globalCurrentText),"gotoline", num+7 + textedit set "Text"+str$(globalCurrentText),"gotoline", num + textedit set "Text"+str$(globalCurrentText),"select", num + if(globalSelectErrorLines) option set "Text"+str$(globalCurrentText),"focus", true + endif + endif + endif + endif + + + // the search field in the toolbar + if(left$(msg$(i),12) = "ToolbarText:" or msg$(i) = "ToolbarFind") then + if(msg$(i) = "ToolbarFind") then + settingsOldSearch$ = textcontrol get$ "ToolbarText" + else + settingsOldSearch$ = right$(msg$(i), len(msg$(i))-12) + endif + if(settingsFindCS) then + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Case-Sensitive-Find", settingsOldSearch$ + else + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", settingsOldSearch$ + endif + if(DEBUG) print searchLineNum + option set "Text"+str$(globalCurrentText), "Focus", true + endif + + // the find and replace tabview + // if(left$(msg$(i),11) = "FindTCFind:" and ) then + // option set "FindTCReplace", "focus", true + // endif + // if(left$(msg$(i),14) = "FindTCReplace:") then + // option set "FindFind", "focus", true + // endif + + + // the immediate tabview + if(left$(msg$(i),15) = "ImmediateInput:") then + ImmediateExec(right$(msg$(i), len(msg$(i))-15)) + endif + + // the project columnbox + if(left$(msg$(i),15) = "FileBox:_Select") then + tmp$ = right$(msg$(i),len(msg$(i))-16) + for tmpFiles = 1 to MAXFILES // arraysize(globalTextFinder(),1) + if(DEBUG) print val(tmp$), globalTextFinder(tmpFiles) + if(globalTextFinder(tmpFiles)=val(tmp$)) then + ActivateText(tmpFiles) + break + endif + next tmpFiles + endif + + // something dropped on the textedit + if(left$(msg$(i),18) = "V2Split2:_Dropped:" and globalCurrentText<>0) then + tmp$ = right$(msg$(i),len(msg$(i))-18) + handle = open(tmp$, "r") + if(handle) then + WaitWindow(tmp$) + text$ = "" + while(not eof(handle)) + text$ = text$ + GetLine$(handle)+"\n" + wend + close(handle) + tmp = textedit get "Text"+str$(globalCurrentText), "currentline" + textedit add "Text"+str$(globalCurrentText), left$(text$,len(text$)-1) + textedit set "Text"+str$(globalCurrentText), "changed", true + textedit set "Text"+str$(globalCurrentText), "gotoline", tmp + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + window close "WaitWindow" + else + alert MyTranslate$("Error while loading file:\n\n")+tmp$, "Ok", "warning" + endif + endif + + // something dropped on the project columnbox + if(left$(msg$(i),17) = "VSplit1:_Dropped:") then + foundEmpty = 0 + for j=1 to MAXFILES + if(globalAllNames$(j) = "") then + foundEmpty = j + break + endif + next j + if(not foundEmpty) then + alert MyTranslate$("Sorry, you can not open more than ")+str$(MAXFILES)+MyTranslate$(" files at once!\n\nPlease close one or more other files first."), "Ok", "Warning" + else + tmp$ = right$(msg$(i),len(msg$(i))-17) + foundProject = false + for j = 1 to MAXFILES + if(globalAllNames$(j) = tmp$) then + alert "File is already open.", "Ok", "info" + ActivateText(j) + foundProject = true + break + endif + next j + if(not foundProject) then + handle = open(tmp$, "r") + if(handle) then + WaitWindow(tmp$) + text$ = "" + while(not eof(handle)) + text$ = text$ + GetLine$(handle)+"\n" + wend + close(handle) + globalCurrentText = foundEmpty + textedit add "Text"+str$(globalCurrentText), left$(text$,len(text$)-1) + textedit set "Text"+str$(globalCurrentText), "changed", false + textedit set "Text"+str$(globalCurrentText), "gotoline", ReadLineFromAttr(tmp$) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + globalAllNames$(globalCurrentText) = tmp$ + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + window close "WaitWindow" + else + alert MyTranslate$("Error while loading file:\n\n")+tmp$, "Ok", "Stop" + endif + endif + endif + endif + + // help selected + if(left$(msg$(i),9) = "HelpTree:") then + tmp$ = right$(msg$(i), len(msg$(i))-17) + tmp$ = treebox get$ "HelpTree", val(tmp$) + t$ = SyntaxGetInfoText$(ideDir$+"data/Help_En.dat", ideDir$+"data/Help_En_Index.dat", tmp$) + if(t$<>"") then + textedit clear "Text"+str$(MAXFILES+1) + textedit add "Text"+str$(MAXFILES+1), t$ + endif + endif + + // search help + if(left$(msg$(i),9) = "HelpFind:") then + tmp$ = right$(msg$(i), len(msg$(i))-9) + tmp$ = trim$(tmp$) + tmp$ = lower$(tmp$) + t$ = SyntaxGetInfoText$(ideDir$+"data/Help_En.dat", ideDir$+"data/Help_En_Index.dat", tmp$) + if(t$<>"") then + textedit clear "Text"+str$(MAXFILES+1) + textedit add "Text"+str$(MAXFILES+1), t$ + endif + endif + next i + + if(globalCurrentText>0 and not globalWasChanged and textedit get "Text"+str$(globalCurrentText), "hasChanged") then + globalWasChanged = true + columnbox add "FileBox", 1, globalTextFinder(globalCurrentText), 20, "__Icon__="+ideDir$+"img/nichtgespeichert.png" + endif + + UpdateStatusbar() + + if(settingsFullEditor) then + tmp = window get "MainView", "Height" - 74 + if(splitview get "VSplit", "Divider" <> 0 or splitview get "HSplit", "Divider" <> tmp) then + settingsFullEditor = false + menu set "View", "Maximize editor", "plain", "MainView" + endif + endif + + if(globalCurrentText > 0) then + // Update the line numbers + // we are cheeting a bit :), we calculate the numbers for a 1200-pixel high view + scroll = textedit get "Text"+str$(globalCurrentText), "vertical-scrollbar" + v2Split = splitview get "V2Split", "divider" + if(scroll<>oldScroll or v2Split<>oldV2Split) then + scrollLine = int(scroll/globalRealFontSize) + scrollPos = mod(scroll,globalRealFontSize) + UpdateLines(scrollPos, 1200, scrollLine, globalRealFontSize) + oldScroll = scroll + oldV2Split = v2Split + // scrollLine = int((scroll+2)/15)+1 + // scrollPos = mod((globalHSplitDivider-1-peek("scrollbarwidth")+scroll),15)+5 + // scrollPos = mod((1000+scroll),15)+5 + // UpdateLines(scrollPos, globalHSplitDivider-1-peek("scrollbarwidth"), scrollLine, 15) + // UpdateLines(scrollPos, 1200, scrollLine, 15) + // oldScroll = scroll + endif + + // Check the spincontrol + spinner = spincontrol get "ToolbarGotoLine" + if(spinner <> oldSpinner) then + textedit set "Text"+str$(globalCurrentText), "gotoline", spinner + textedit set "Text"+str$(globalCurrentText), "select", 0 + textedit set "Text"+str$(globalCurrentText), "select", spinner + option set "Text"+str$(globalCurrentText), "Focus", true + oldSpinner = spinner + endif + endif + + // switch tabs from help to files and vice versa + if(globalIsHelp and tabview get "Tree" = 1) then + globalIsHelp = false + splitview set "V2Split", "divider", helpOldV2Split + if(globalCurrentText>0) then + ActivateHelpMenus(1) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + else + ActivateHelpMenus(0) + stackview set "Stack", MAXFILES+2 + stackview set "Lines", MAXFILES+2 + endif + endif + if(not globalIsHelp and tabview get "Tree" = 2) then + ActivateHelpMenus(-1) + globalIsHelp = true + stackview set "Stack", MAXFILES+1 + stackview set "Lines", MAXFILES+1 + helpOldV2Split = splitview get "V2Split", "divider" + splitview set "V2Split", "divider", 0 + endif +wend + +window close "MainView" +SaveSettings() + +// Open main window with everything +sub OpenMainWindow() + local vsplitheight, hsplitheight, tabwidth, i, handle + local tmp$ + local err, x, y + + x = peek("desktopwidth") + y = peek("desktopheight") + + // open initialize the main window + window open settingsX-3000,settingsY-3000 to settingsX+settingsWidth-3000,settingsY+settingsHeight-3000, "MainView", "yab-IDE" + + window open x/2-250-3000, y/2-200-3000 to x/2+249-3000,y/2+199-3000, "Splash", "" + window set "Splash", "look", "bordered" + err = draw image 0,0, ideDir$+"img/Splash.png", "Splash" + draw set "HighColor", 56,61,127, "Splash" + draw set "DejaVu Sans Mono,Bold,18", "Splash" + draw text 30, 280, "Version "+versionnumber$, "Splash" + window set "Splash", "moveto", x/2-250,y/2-200 + set_up_BuildFactory() + if(err>0) window close "Splash" + + + + window set "MainView", "look", "document" + window set "MainView", "MinimumTo", 600,300 + + // set all menus + menu "File", "New...", "N", "MainView" + menu "File", "Open...", "O", "MainView" + menu "File", "Close", "W", "MainView" + menu "File", "--", "", "MainView" + menu "File", "Save", "S", "MainView" + menu "File", "Save as...", "", "MainView" + menu "File", "Save as template...", "", "MainView" + menu "File", "Export as HTML...", "", "MainView" + + menu "File", "--", "", "MainView" + menu "File", "Page setup...", "", "MainView" + menu "File", "Print...", "P", "MainView" + menu "File", "--", "", "MainView" + menu "File", "Quit", "Q", "MainView" + + menu "Edit", "Undo", "Z", "MainView" + menu "Edit", "--", "", "MainView" + menu "Edit", "Cut", "X", "MainView" + menu "Edit", "Copy", "C", "MainView" + menu "Edit", "Paste", "V", "MainView" + menu "Edit", "--", "", "MainView" + menu "Edit", "Select all", "A", "MainView" + menu "Edit", "--", "", "MainView" + menu "Edit", "Find", "F", "MainView" + menu "Edit", "Find again", "G", "MainView" + menu "Edit", "Find and replace", "E", "MainView" + + menu "Program", "Run", "R", "MainView" + menu "Program", "Run in Terminal", "T", "MainView" + menu "Program", "--", "", "MainView" + menu "Program", "Set run parameters...", "SR", "MainView" + menu "Program", "--", "", "MainView" + menu "Program", "Build Factory...", "B", "MainView" + menu "Program", "--", "", "MainView" + menu "Program", "Open project folder...", "SO", "MainView" + + if(not globalNoRCS) then + menu "RCS", "Check In", "CI", "MainView" + menu "RCS", "Check Out", "CO", "MainView" + menu "RCS", "--", "", "MainView" + menu "RCS", "Version History...", "CV", "MainView" + endif + + menu "Tools", "Pattern editor...", "CP", "MainView" + menu "Tools", "Color selection...", "CC", "MainView" + menu "Tools", "--", "", "MainView" + menu "Tools", "ASCII table...", "CA", "MainView" + + menu "View", "Next file", ".", "MainView" + menu "View", "Previous file", ",", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Full screen", "CF", "MainView" + menu "View", "Maximize editor", "CE", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Auto indent", "", "MainView" + menu "View", "Auto completion", "", "MainView" + menu "View", "Refresh colors", "", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Reformat sourcecode", "CR", "MainView" + menu "View", "Undo reformat", "", "MainView" + menu "View", "--", "", "MainView" + menu "View", "Options...", "", "MainView" + if settingsFullScreen menu set "View", "Full screen", "mark", "MainView" + if settingsFullEditor menu set "View", "Maximize editor", "mark", "MainView" + if settingsAutoIndent menu set "View", "Auto indent", "mark", "MainView" + if settingsAutoCompletion menu set "View", "Auto completion", "mark", "MainView" + menu set "View", "Undo reformat", "disable", "MainView" + + menu "Help", "Short command help...", "H", "MainView" + menu "Help", "Yabasic manual...", "M", "MainView" + menu "Help", "--", "", "MainView" + menu "Help", "Online resources", "", "MainView" + submenu "Help", "Online resources", "German BeUsergroup...", "", "MainView" + submenu "Help", "Online resources", "BeSly database...", "", "MainView" + submenu "Help", "Online resources", "Yabasic homepage...", "", "MainView" + submenu "Help", "Online resources", "Haikuware yab forum...", "", "MainView" + menu "Help", "--", "", "MainView" + menu "Help", "About...", "", "MainView" + + // set the toolbar + ToolbarCreate(0,peek("menuheight")+1,2000, "Toolbar", ideDir$+"img/", "MainView") + ToolbarAddIcon("ToolbarNew", "New", "newp.png", "newn.png", "newd.png") + ToolbarAddIcon("ToolbarOpen", "Open", "openp.png", "openn.png", "opend.png") + ToolbarAddIcon("ToolbarSave", "Save", "savep.png", "saven.png", "saved.png") + ToolbarAddIcon("ToolbarClose", "Close", "closep.png", "closen.png", "closed.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarCut", "Cut", "cutp.png", "cutn.png", "cutd.png") + ToolbarAddIcon("ToolbarCopy", "Copy", "copyp.png", "copyn.png", "copyd.png") + ToolbarAddIcon("ToolbarPaste", "Paste", "pastep.png", "pasten.png", "pasted.png") + ToolbarAddIcon("ToolbarUndo", "Undo", "undop.png", "undon.png", "undod.png") + // ToolbarAddIcon("ToolbarFind", "Find", "searchp.png", "searchn.png", "searchd.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarRun", "Run", "runp.png", "runn.png", "rund.png") + ToolbarAddIcon("ToolbarRunTerm", "Run in Terminal", "runtermp.png", "runtermn.png", "runtermd.png") + // ToolbarAddIcon("ToolbarDebug", "Debugger", "debugp.png", "debugn.png", "debugd.png") + ToolbarAddIcon("ToolbarBuild", "Build Factory", "bindp.png", "bindn.png", "bindd.png") + // ToolbarAddSeparator() + // ToolbarAddIcon("ToolbarGui", "GUI Designer", "guip.png", "guin.png", "guid.png") + ToolbarAddSeparator() + ToolbarAddIcon("ToolbarPattern", "Pattern editor", "patternp.png", "patternn.png", "patternd.png") + ToolbarAddIcon("ToolbarOptions", "Options", "optionsp.png", "optionsn.png", "optionsd.png") + ToolbarAddIcon("ToolbarHelp", "yab Help", "helpp.png", "helpn.png", "helpd.png") + ToolbarAddSeparator() + + spincontrol 383,2, "ToolbarGotoLine", "Go to Line:", 1, 100000, 1, "Toolbar" + tooltip "ToolbarGotoLine", "Go to Line" + draw set "highcolor", 185,185,185, "Toolbar" + draw line 430,5 to 400,25, "Toolbar" + draw set "highcolor", 239,239,239, "Toolbar" + draw line 431,5 to 401,25, "Toolbar" + + button image 538,7, "ToolbarFind", ideDir$+"img/searchp.png", ideDir$+"img/searchn.png", ideDir$+"img/searchd.png", "Toolbar" + tooltip "ToolbarFind", "Find" + textcontrol 553,5 to 640,25, "ToolbarText", "", settingsOldSearch$, "Toolbar" + draw set "highcolor", 185,185,185, "Toolbar" + draw line 510,5 to 480,25, "Toolbar" + draw set "highcolor", 239,239,239, "Toolbar" + draw line 511,5 to 481,25, "Toolbar" + + // layout "top, left, right", "Toolbar" + draw set "highcolor", 200,200,200, "Toolbar" + draw line 0,29 to 2000,29, "Toolbar" + draw set "highcolor", 184,184,184, "Toolbar" + draw line 0,30 to 2000,30, "Toolbar" + draw set "highcolor", 239,239,239, "Toolbar" + draw line 0,31 to 2000,31, "Toolbar" + + + // vertical splitview + layout "standard", "MainView" + splitview 0,peek("menuheight")+31, settingsWidth,settingsHeight-peek("scrollbarwidth"), "VSplit", true, true, "MainView" + splitview set "VSplit", "Divider", settingsVSplitDivider + splitview set "VSplit", "MinimumSizes", 0,400 + + // horizontal splitview + splitview 0,0, settingsWidth-settingsVSplitDivider,settingsHeight-peek("scrollbarwidth")+1, "HSplit", false, true, "VSplit2" + splitview set "HSplit", "Divider", settingsHSplitDivider + splitview set "HSplit", "MinimumSizes", 100,51 + + splitview 0,0, settingsWidth-settingsVSplitDivider,settingsHSplitDivider-1, "V2Split", true,false, "HSplit1" + splitview set "V2Split", "Divider", 0 + splitview set "V2Split", "MinimumSizes", 0,300 + + + vsplitheight = settingsHeight - peek("menuheight")-peek("scrollbarwidth") + + // tabview and treeboxes in the left vertical splitview + tabview 0,1 to settingsVSplitDivider-1,vsplitheight-32, "Tree", "bottom", "VSplit1" + tabview add "Tree", " Files " + tabview add "Tree", " Help " + columnbox 0,0 to settingsVSplitDivider-10,vsplitheight-42-peek("tabheight"), "FileBox", false, "no-border, resizable", "Tree1" + columnbox column "FileBox", " ", 1, 20, 20, 20, "align-center" + columnbox column "FileBox", "Filename",2, 300, 32, settingsVSplitDivider-32, "align-left" + columnbox color "FileBox", "Selection-Active", 220,220,250 + columnbox color "FileBox", "Row-Divider", 255,255,255 + + treebox 0,0 to settingsVSplitDivider-10, vsplitheight-42-peek("tabheight")-40, "HelpTree", 1, "Tree2" + layout "left,bottom,right", "Tree2" + textcontrol 0,vsplitheight-42-peek("tabheight")-30 to settingsVSplitDivider-14,vsplitheight-42-peek("tabheight")-10, "HelpFind", "Command", "", "Tree2" + layout "standard", "Tree2" + + view dropzone "VSplit1" + view dropzone "V2Split2" + + // a stackview with textedits in the upper right splitview + // implement a dynamic stackview in future! + // stackview 0,0 to settingsWidth-settingsVSplitDivider-11,settingsHSplitDivider-1, "Stack", MAXFILES+2, "HSplit1" + stackview 0,0 to settingsWidth-settingsVSplitDivider-11-4,settingsHSplitDivider-1, "Stack", MAXFILES+2, "V2Split2" + stackview 0,0 to settingsV2SplitDivider,settingsHSplitDivider-1, "Lines", MAXFILES+2, "V2Split1" + for i=1 to MAXFILES + // textedit 37,0 to settingsWidth-settingsVSplitDivider-12,settingsHSplitDivider-1, "Text"+str$(i), 3, "Stack"+str$(i) + textedit 1,1 to settingsWidth-settingsVSplitDivider-12-5,settingsHSplitDivider-2, "Text"+str$(i), 3, "Stack"+str$(i) + textedit set "Text"+str$(i), "wordwrap", false + textedit set "Text"+str$(i), "textwidth", 4000 + textedit set "Text"+str$(i), "tabwidth", settingsTabSpaces*7 + textedit set "Text"+str$(i), "font", settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize) + textedit set "Text"+str$(i), "autoindent", settingsAutoIndent + + // layout "left,top,bottom", "Lines"+str$(i) + // view 0,0 to 36,settingsHSplitDivider-1, "Lines"+str$(i), "LineStack"+str$(i) + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "Lines"+str$(i) + layout "standard", "Stack"+str$(i) + + textedit set "Text"+str$(i), "autocomplete-start", settingsACNumChar + handle = open(ideDir$+"/data/autocompletion") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit set "Text"+str$(i), "autocomplete", tmp$ + wend + close(handle) + endif + + handle = open(ideDir$+"/data/color1") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color1", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color2") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color2", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color3") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color3", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color4") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "color4", tmp$ + wend + close(handle) + endif + handle = open(ideDir$+"/data/color5") + if(handle) then + while(not eof(handle)) + line input #handle tmp$ + textedit color "Text"+str$(i), "char-color", tmp$ + wend + close(handle) + endif + next i + + textedit 1,1 to settingsWidth-settingsVSplitDivider-12-5,settingsHSplitDivider-2, "Text"+str$(MAXFILES+1), 1, "Stack"+str$(MAXFILES+1) + textedit set "Text"+str$(MAXFILES+1), "font", settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize) + textedit set "Text"+str$(MAXFILES+1), "editable", false + textedit color "Text"+str$(MAXFILES+1), "color1", "Name:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Synopsis:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Description:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Example:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Design:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Layout:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Message:" + textedit color "Text"+str$(MAXFILES+1), "color1", "Related:" + SyntaxLoadTree(ideDir$+"data/Help_En.dat", "HelpTree") + + // UpdateLines(0, globalHSplitDivider-1-peek("scrollbarwidth"), 1, 15) + UpdateLines(0, 1200, 1, globalRealFontSize) + + layout "h-center, v-center", "Stack"+str$(MAXFILES+2) + // view (settingsWidth-settingsVSplitDivider-12)/2-150,(settingsHSplitDivider-1)/2-190 to (settingsWidth-settingsVSplitDivider-12)/2+150,(settingsHSplitDivider-1)/2+190, "Logo", "Stack"+str$(MAXFILES+2) + view (settingsWidth-settingsVSplitDivider-12-41-4)/2-150,(settingsHSplitDivider-1)/2-190 to (settingsWidth-settingsVSplitDivider-12-41-4)/2+150,(settingsHSplitDivider-1)/2+190, "Logo", "Stack"+str$(MAXFILES+2) + draw set "bgcolor", 255,255,255, "Stack"+str$(MAXFILES+2) + draw set "bgcolor", 255,255,255, "Logo" + err = draw image 0,0 to 350,-1, ideDir$+"img/logo.png", "Logo" + stackview set "Stack", MAXFILES+2 + stackview set "Lines", MAXFILES+2 + layout "standard", "Stack"+str$(MAXFILES+2) + + hsplitheight = settingsHeight-settingsHSplitDivider-peek("scrollbarwidth")-peek("menuheight")-42 + + // the tabview in the lower right splitview + tabview 0,0 to settingsWidth-settingsVSplitDivider-11,hsplitheight, "HTab", "bottom", "HSplit2" + tabview add "HTab", "yab Output" + tabview add "HTab", "Immediate" + tabview add "HTab", "Find and replace" + if(not globalNoRCS) then + tabview add "HTab", "Version Control" + endif + + hsplitheight = hsplitheight-peek("tabheight")-12 + tabwidth = settingsWidth-settingsVSplitDivider-21 + + // the output box + listbox 0,0 to tabwidth,hsplitheight, "YabOutputList", 1, "HTab1" + + // the immediate stuff + layout "left,right,top", "HTab2" + textcontrol 5,5 to tabwidth-110,25, "ImmediateInput", "Command", "", "HTab2" + layout "right,top", "HTab2" + button tabwidth-100,3 to tabwidth-10,23, "ImmediateExecute", "Execute", "HTab2" + layout "standard", "HTab2" + textedit 10,35 to tabwidth-10,hsplitheight-10, "ImmediateOutput", 1, "HTab2" + textedit set "ImmediateOutput", "editable", false + + // search and replace + layout "left,top", "HTab3" + w = draw get "Text-width", MyTranslate$("Find:"), "HTab3" + draw text 55-w,23, "Find:", "HTab3" + w = draw get "Text-width", MyTranslate$("Replace:"), "HTab3" + draw text 55-w,48, "Replace:", "HTab3" + textcontrol 55,10 to 290,30, "FindTCFind", "", "", "HTab3" + textcontrol 55,35 to 290,55, "FindTCReplace", "", "", "HTab3" + checkbox 55,60, "FindCS", "Case Sensitive", settingsFindCS, "HTab3" + MyLine(300,5,300,90,"HTab3") + button 310,10 to 460,30, "FindFind", "Find", "HTab3" + button 310,35 to 460,55, "FindReplace", "Find and replace", "HTab3" + button 310,60 to 460,80, "FindReplAll", "Replace All", "HTab3" + + // the statusbar + layout "left, bottom", "MainView" + view 0,settingsHeight-peek("scrollbarwidth") to 2000,settingsHeight, "Statusbar", "MainView" + draw set "highcolor", 200,200,200, "Statusbar" + draw line 0,0 to 2000,0, "Statusbar" + draw set "highcolor", 184,184,184, "Statusbar" + draw line 0,1 to 2000,1, "Statusbar" + draw set "highcolor", 239,239,239, "Statusbar" + draw line 0,2 to 2000,2, "Statusbar" + + if(window count>1) window close "Splash" + + window set "MainView", "moveto", settingsX, settingsY + + return +end sub + + +// (De-)activate menus +sub ActivateMenus(toActivate) + local tmp$ + + if(toActivate) then + tmp$ = "Enable" + else + tmp$ = "Disable" + endif + + menu set "File", "Close", tmp$, "MainView" + menu set "File", "Save", tmp$, "MainView" + menu set "File", "Save as...", tmp$, "MainView" + menu set "File", "Save as template...", tmp$, "MainView" + menu set "File", "Export as HTML...", tmp$, "MainView" + menu set "File", "Page setup...", tmp$, "MainView" + menu set "File", "Print...", tmp$, "MainView" + + menu set "Edit", "Undo", tmp$, "MainView" + menu set "Edit", "Cut", tmp$, "MainView" + menu set "Edit", "Copy", tmp$, "MainView" + menu set "Edit", "Paste", tmp$, "MainView" + menu set "Edit", "Select all", tmp$, "MainView" + menu set "Edit", "Find", tmp$, "MainView" + menu set "Edit", "Find again", tmp$, "MainView" + menu set "Edit", "Find and replace", tmp$, "MainView" + + menu set "Program", "Run", tmp$, "MainView" + menu set "Program", "Run in Terminal", tmp$, "MainView" + menu set "Program", "Set run parameters...", tmp$, "MainView" + menu set "Program", "Build Factory...", tmp$, "MainView" + menu set "Program", "Open project folder...", tmp$, "MainView" + + if(not globalNoRCS) then + menu set "RCS", "Check In", tmp$, "MainView" + menu set "RCS", "Check Out", tmp$, "MainView" + menu set "RCS", "Version History...", tmp$, "MainView" + endif + + menu set "Tools", "Pattern editor...", tmp$, "MainView" + menu set "Tools", "Color selection...", tmp$, "MainView" + + menu set "View", "Next file", tmp$, "MainView" + menu set "View", "Previous file", tmp$, "MainView" + menu set "View", "Auto indent", tmp$, "MainView" + menu set "View", "Auto completion", tmp$, "MainView" + menu set "View", "Refresh colors", tmp$, "MainView" + menu set "View", "Reformat sourcecode", tmp$, "MainView" + menu set "View", "Undo reformat", "disable", "MainView" + menu set "View", "Options...", tmp$, "MainView" + + option set "ToolbarSave", "Enabled", toActivate + option set "ToolbarClose", "Enabled", toActivate + option set "ToolbarCut", "Enabled", toActivate + option set "ToolbarCopy", "Enabled", toActivate + option set "ToolbarPaste", "Enabled", toActivate + option set "ToolbarUndo", "Enabled", toActivate + option set "ToolbarFind", "Enabled", toActivate + option set "ToolbarText", "Enabled", toActivate + option set "ToolbarRun", "Enabled", toActivate + option set "ToolbarRunTerm", "Enabled", toActivate + option set "ToolbarPattern", "Enabled", toActivate + option set "ToolbarBuild", "Enabled", toActivate + option set "ToolbarOptions", "Enabled", toActivate + option set "ToolbarGotoLine", "Enabled", toActivate + + option set "FindTCFind", "Enabled", toActivate + option set "FindTCReplace", "Enabled", toActivate + option set "FindCS", "Enabled", toActivate + option set "FindFind", "Enabled", toActivate + option set "FindReplace", "Enabled", toActivate + option set "FindReplAll", "Enabled", toActivate + + return +end sub + +// (De-)activate menus when help is selected +sub ActivateHelpMenus(toActivate) + local tmp$ + + if(toActivate = 1) then + tmp$ = "Enable" + else + tmp$ = "Disable" + endif + + if(toActivate = -1) then + menu set "File", "Open...", tmp$, "MainView" + menu set "File", "New...", tmp$, "MainView" + else + menu set "File", "Open...", "Enable", "MainView" + menu set "File", "New...", "Enable", "MainView" + endif + menu set "File", "Close", tmp$, "MainView" + menu set "File", "Save", tmp$, "MainView" + menu set "File", "Save as...", tmp$, "MainView" + menu set "File", "Save as template...", tmp$, "MainView" + menu set "File", "Export as HTML...", tmp$, "MainView" + + menu set "Edit", "Undo", tmp$, "MainView" + menu set "Edit", "Cut", tmp$, "MainView" + menu set "Edit", "Paste", tmp$, "MainView" + menu set "Edit", "Find and replace", tmp$, "MainView" + + menu set "Program", "Run", tmp$, "MainView" + menu set "Program", "Run in Terminal", tmp$, "MainView" + menu set "Program", "Set run parameters...", tmp$, "MainView" + menu set "Program", "Build Factory...", tmp$, "MainView" + menu set "Program", "Open project folder...", tmp$, "MainView" + + if(not globalNoRCS) then + menu set "RCS", "Check In", tmp$, "MainView" + menu set "RCS", "Check Out", tmp$, "MainView" + menu set "RCS", "Version History...", tmp$, "MainView" + endif + + menu set "Tools", "Pattern editor...", tmp$, "MainView" + menu set "Tools", "Color selection...", tmp$, "MainView" + + menu set "View", "Next file", tmp$, "MainView" + menu set "View", "Previous file", tmp$, "MainView" + menu set "View", "Auto indent", tmp$, "MainView" + menu set "View", "Auto completion", tmp$, "MainView" + menu set "View", "Refresh colors", tmp$, "MainView" + menu set "View", "Reformat sourcecode", tmp$, "MainView" + menu set "View", "Undo reformat", "disable", "MainView" + + if(toActivate = -1) then + option set "ToolbarOpen", "Enabled", false + option set "ToolbarNew", "Enabled", false + toActivate = 0 + else + option set "ToolbarOpen", "Enabled", true + option set "ToolbarNew", "Enabled", true + endif + option set "ToolbarSave", "Enabled", toActivate + option set "ToolbarClose", "Enabled", toActivate + option set "ToolbarCut", "Enabled", toActivate + option set "ToolbarPaste", "Enabled", toActivate + option set "ToolbarUndo", "Enabled", toActivate + option set "ToolbarText", "Enabled", toActivate + option set "ToolbarRun", "Enabled", toActivate + option set "ToolbarRunTerm", "Enabled", toActivate + option set "ToolbarPattern", "Enabled", toActivate + option set "ToolbarBuild", "Enabled", toActivate + option set "ToolbarGotoLine", "Enabled", toActivate + + option set "FindTCReplace", "Enabled", toActivate + option set "FindReplace", "Enabled", toActivate + option set "FindReplAll", "Enabled", toActivate + + return +end sub + +// Update the line numbering +sub UpdateLines(starty, height, topline, fontHeight) + local i, pos + local t$ + + if(globalCurrentText > 0) then + pos = splitview get "V2Split", "Divider" - 3 + draw flush "Lines"+str$(globalCurrentText) + for i=fontHeight-4-starty to height step fontHeight + t$ = str$(int(i/fontHeight)+topline+1) + draw text pos-(draw get "text-width", t$, "Lines"+str$(globalCurrentText)),i, t$, "Lines"+str$(globalCurrentText) + next i + endif + return +end sub + +// Open new file +sub NewDocument(foundEmpty) + local inloop + local browse$ + local i, n, err, nTemplates, isButton + local handle, handle2 + local x, y, winSize, w, t + local t$, txt$ + + x = (peek("desktopwidth")-500)/2 + y = (peek("desktopheight")-390)/2-50 + if(y<50) y=50 + + window open x+200-3000,y+150-3000 to x+700-3000,y+440-3000, "NewWindow", "yab-IDE New Program" + window set "NewWindow", "Feel", "Modal-App" + window set "NewWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("New yab Program", "NewWindow", 500) + + text 10,50, "NewText1", "Please select one of the available templates for your program:", "NewWindow" + listbox 10,70 to 166,200, "NewList", 1, "NewWindow" + + handle = open(ideDir$+"Templates/TemplateList", "r") + if(handle>0) then + nTemplates = 0 + while(not eof(handle)) + nTemplates = nTemplates + 1 + dim tmp$(nTemplates) + tmp$(nTemplates) = GetLine$(handle)+"\n" + tmp$(nTemplates) = left$(tmp$(nTemplates), len(tmp$(nTemplates))-1) + if(left$(tmp$(nTemplates),1) = "#") nTemplates = nTemplates - 1 + wend + close handle + else + dim tmp$(1) + tmp$(1) = "Empty" + nTemplates = 1 + endif + for i = 1 to nTemplates step 4 + listbox add "NewList", tmp$(i) + next i + view 190,70 to 490,200, "NewImage", "NewWindow" + + browse$ = globalProjectDir$+"untitled"+str$(GetNewNumber(globalProjectDir$))+".yab" + + textcontrol 10,220 to 400,240, "NewName", "Name:", browse$, "NewWindow" + button 410,220 to 490,240, "NewBrowse", "Browse...", "NewWindow" + + checkbox image 10,270, "NewAdvanced", ideDir$+"img/arrowdown.png", ideDir$+"img/arrowright.png", "", "", false, "NewWindow" + winSize = false + text 20,270, "NewText2", "Advanced Options", "NewWindow" + button 430,260 to 490,280, "NewOk", "Ok", "NewWindow" + option set "NewOk", "enabled", false + isButton = false + + draw set "highcolor", 185,185,185, "NewWindow" + draw line 0,252 to 500,252, "NewWindow" + draw line 0,292 to 500,292, "NewWindow" + draw set "highcolor", 239,239,239, "NewWindow" + draw line 0,253 to 500,253, "NewWindow" + draw line 0,293 to 500,293, "NewWindow" + + // button 260,300 to 280,310, "NewHelp", "?", "NewWindow" + button 350,295 to 490,325, "NewDel", "Remove Template", "NewWindow" + option set "NewDel", "enabled", false + + if(not globalNoRCS) then + checkbox 10, 300, "NewCheckbox", "Use RCS Version Control", settingsUseRCS, "NewWindow" + // option set "NewCheckbox", "enabled", false + // option set "NewHelp", "enabled", false + endif + + textcontrol 10,330 to 490,350, "NewProject", "Project Directory", globalProjectDir$, "NewWindow" + + window set "NewWindow", "moveto", x,y + + inloop = true + dim msg$(1) + while(inloop) + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + if(left$(msg$(i),16) = "NewList:_Invoke:") then + msg$(i) = "NewOk" + endif + switch(msg$(i)) + case "NewOk" + if(j>0) then + browse$ = textcontrol get$ "NewName" + if(arraysize(tmp$(), 1) = 1) then + txt$ = "" + else + handle = open(ideDir$+"Templates/"+tmp$(j), "r") + if(handle) then + while(not eof(handle)) + txt$ = txt$ + GetLine$(handle)+"\n" + wend + close(handle) + // txt$ = left$(txt$, len(txt$)-1) + else + alert MyTranslate$("Could not open template: ")+tmp$(j)+"\n\n"+MyTranslate$("Opening an empty file instead."), "Ok", "warning" + txt$ = "" + endif + endif + globalCurrentText = foundEmpty + textedit add "Text"+str$(globalCurrentText), txt$ + textedit set "Text"+str$(globalCurrentText), "changed", true + textedit set "Text"+str$(globalCurrentText), "gotoline", 1 + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + globalAllNames$(globalCurrentText) = browse$ + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/nichtgespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(browse$) + columnbox select "FileBox", t+1 + + globalTextFinder(globalCurrentText) = t+1 + + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + globalNewNumber = globalNewNumber + 1 + globalNumOpenFiles = globalNumOpenFiles + 1 + inloop = false + endif + break + case "NewAdvanced:ON" + case "NewAdvanced:OFF" + winSize = not winSize + if(winSize) then + window set "NewWindow", "MinimumTo", 500,360 + window set "NewWindow", "MaximumTo", 500,360 + window set "NewWindow", "ResizeTo", 500,360 + else + window set "NewWindow", "MinimumTo", 500,290 + window set "NewWindow", "MaximumTo", 500,290 + window set "NewWindow", "ResizeTo", 500,290 + endif + break + case "NewBrowse" + browse$ = filepanel "Save-File", "New", globalProjectDir$ + if(browse$<>"") textcontrol set "NewName", browse$ + break + case "NewWindow:_QuitRequested" + inloop = false + break + case "_QuitRequested" + //emergency break + exit(1) + break + case "NewDel" + t$ = listbox get$ "NewList", (j-1)/4+1 + t = alert MyTranslate$("Really delete template")+" \""+t$+"\"?", "Yes", "Cancel", "", "warning" + if(t = 1) then + if((j-1)/4+1 < 4) then + alert "This standard template can not be deleted!", "Ok", "warning" + else + handle = open(ideDir$+"Templates/TemplateList", "r") + handle2 = open("/tmp/TemplateList", "w") + if(handle) then + if(handle2) then + while(not eof(handle)) + t$ = GetLine$(handle)+"\n" + if(left$(t$,len(t$)-1)<>tmp$(j)) then + print #handle2 t$; + else + t$ = GetLine$(handle)+"\n" + t$ = GetLine$(handle)+"\n" + t$ = GetLine$(handle)+"\n" + endif + wend + close(handle2) + system("mv /tmp/TemplateList "+ideDir$+"Templates/TemplateList") + system("rm "+ideDir$+tmp$(j+1)) + system("rm "+ideDir$+"Templates/"+tmp$(j)) + listbox remove "NewList", (j-1)/4+1 + listbox select "NewList", (j-5)/4+1 + msg$(i) = "NewList:_Select:"+str$((j-5)/4+1) + alert "Template successfully removed.", "Ok", "info" + else + alert "Error while deleting template!", "Ok", "stop" + endif + close(handle) + else + alert "Error while deleting template!", "Ok", "stop" + endif + endif + endif + + break + end switch + if(left$(msg$(i),16) = "NewList:_Select:") then + draw rect 0,0 to 200,140, "NewImage" + draw flush "NewImage" + j = (val(mid$(msg$(i),17,len(msg$(i))-1))-1)*4+1 + if(arraysize(tmp$(),1)>=j+1) then + err = draw image 50,0 to 250,100, ideDir$+tmp$(j+1), "NewImage" + endif + if(arraysize(tmp$(),1)>=j+2) then + draw text 10,110, tmp$(j+2), "NewImage" + endif + if(arraysize(tmp$(),1)>=j+3) then + draw text 10,125, tmp$(j+3), "NewImage" + endif + if(not isButton) then + isButton = false + option set "NewOk", "enabled", true + option set "NewDel", "enabled", true + endif + endif + next i + wend + + window close "NewWindow" +end sub + +sub GetNewNumber(dir$) + local tmp$ + local num: local i: local ret + local numFound + local t$(1) + + numFound = false + ret = 0 + tmp$ = system$("ls "+dir$+"untitled*.yab") + num = token(tmp$, t$(), "\n") + while(not numFound) + numFound = true + for i=1 to num + tmp$ = left$(t$(i), len(t$(i))-4) + tmp$ = right$(tmp$, len(tmp$)-8-len(dir$)) + if(ret = val(tmp$)) then + ret = ret + 1 + numFound = false + break + endif + next i + if(numFound) then + for i=1 to MAXFILES + tmp$ = dir$+"untitled"+str$(ret)+".yab" + if(globalAllNames$(i) = tmp$) then + ret = ret + 1 + numFound = false + break + endif + next i + endif + wend + return ret +end sub + +sub ImmediateExec(command$) + local result$ + + if(instr(command$, "input")) then + alert "Suspecting user input, therefore starting in a terminal.", "Ok", "info" + result$ = system$("Terminal "+yabDir$+" -enter -execute '"+command$+":exit'") + else + result$ = system$(yabDir$+" -execute '"+command$+":exit' 2>&1") + result$ = left$(result$, len(result$)-1) + + textedit clear "ImmediateOutput" + textedit add "ImmediateOutput", result$ + endif + + return +end sub + +sub GetFileName$(directory$) + local lastSlash + local j + + lastSlash = 0 + for j=1 to len(directory$) + if(mid$(directory$,j,1)="/" and mid$(directory$,j-1,1)<>"/") + lastSlash = j + next j + + return right$(directory$,len(directory$)-lastSlash) +end sub + +sub GetDirectory$(directory$) + local lastSlash + local j + + lastSlash = 0 + for j=1 to len(directory$) + if(mid$(directory$,j,1)="/" and mid$(directory$,j-1,1)<>"/") + lastSlash = j + next j + + return left$(directory$,lastSlash) +end sub + +sub ActivateText(num) + globalCurrentText = num + globalWasChanged = textedit get "Text"+str$(globalCurrentText), "hasChanged" + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + option set "Text"+str$(globalCurrentText), "focus", true + columnbox select "FileBox", globalTextFinder(num) + oldScroll = -1 + return +end sub + +sub ReadLineFromAttr(filename$) + a$=attribute get$ "",filename$ + if instr (a$,"linenumber") then + return attribute get "linenumber", filename$ + else return 0 + endif +end sub + +sub UpdateStatusbar() + static oldText$ + local newText$ + + if(globalCurrentText = 0) then + if(oldText$<>"") then + oldText$ = "" + draw flush "Statusbar" + draw set "highcolor", 200,200,200, "Statusbar" + draw line 0,0 to 2000,0, "Statusbar" + draw set "highcolor", 184,184,184, "Statusbar" + draw line 0,1 to 2000,1, "Statusbar" + draw set "highcolor", 239,239,239, "Statusbar" + draw line 0,2 to 2000,2, "Statusbar" + endif + return + endif + + newText$ = globalAllNames$(globalCurrentText) + if(textedit get "Text"+str$(globalCurrentText), "hasChanged") then + newText$ = newText$ + MyTranslate$(" (not saved) ") + else + newText$ = newText$ + " " + endif + + newText$ = newText$ + MyTranslate$("Line:")+" "+str$(textedit get "Text"+str$(globalCurrentText), "currentline") + newText$ = newText$ + " / "+str$(textedit get "Text"+str$(globalCurrentText), "countlines") + + + if(oldText$<>newText$) then + draw flush "Statusbar" + draw set "highcolor", 200,200,200, "Statusbar" + draw line 0,0 to 2000,0, "Statusbar" + draw set "highcolor", 184,184,184, "Statusbar" + draw line 0,1 to 2000,1, "Statusbar" + draw set "highcolor", 239,239,239, "Statusbar" + draw line 0,2 to 2000,2, "Statusbar" + draw set "highcolor", 0,0,0, "Statusbar" + draw text 5,13, "File: ", "Statusbar" + // draw set "highcolor", 0,200,0, "Statusbar" + draw text (5+draw get "Text-Width", MyTranslate$("File: "), "Statusbar"),13, newText$, "Statusbar" + // draw text (5+draw get "Text-Width", "Status: ", "Statusbar"),11, globalAllNames$(globalCurrentText)+" saved", "Statusbar" + oldText$ = newText$ + endif + + return +end sub + +sub WaitWindow(text$) + local x + local y + local width + local err + + x = peek("desktopwidth")/2 - 125 + y = peek("desktopheight")/2 - 100 + window open x,y to x+249,y+79, "WaitWindow", "" + window set "WaitWindow", "feel", "modal-app" + window set "WaitWindow", "look", "modal" + window set "WaitWindow", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + err = draw image 0,0, ideDir$+"img/Loading.png", "WaitWindow" + + w = draw get "text-width", GetFileName$(text$), "WaitWindow" + text 143-w/2,32, "TWait", GetFileName$(text$), "WaitWindow" + + w = draw get "text-width", MyTranslate$("Please wait..."), "WaitWindow" + text 143-w/2,60, "TRunning2", "Please wait...", "WaitWindow" + + draw set "Bitstream Vera Sans, Bold Oblique, 14", "WaitWindow" + w = draw get "text-width", MyTranslate$("Loading Program"), "WaitWindow" + draw text 143-w/2,20, "Loading Program", "WaitWindow" + + return +end sub + +// Run the program and display its output +sub RunProgram(yabFile$) + local tmp$, unique$ + local num, i, t, teamID, pos + local x, y, err, w + + if(isRunning) return + isRunning = true + + // easy way to make the tmp file sort-of unique + unique$ = date$+time$ + + x = peek("desktopwidth")/2 - 125 + y = peek("desktopheight")/2 - 100 + window open x,y to x+249,y+79, "Running", "" + window set "Running", "feel", "modal-app" + window set "Running", "look", "modal" + window set "Running", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + err = draw image 0,0, ideDir$+"img/Running.png", "Running" + + w = draw get "text-width", GetFileName$(yabFile$), "Running" + text 143-w/2,32, "TRunning", GetFileName$(yabFile$), "Running" + button 150,50 to 240,75, "BRunning", "Break", "Running" + + draw set "Bitstream Vera Sans, Bold Oblique, 14", "Running" + w = draw get "text-width", MyTranslate$("Running Program"), "Running" + draw text 143-w/2,20, "Running Program", "Running" + + // text 5,5, "TRunning", MyTranslate$("Now Running: ")+GetFileName$(yabFile$), "Running" + // button 50,25 to 150,45, "BRunning", "Break", "Running" + listbox clear "YabOutputList" + window set "Running", "deactivate" + + if DEBUG print "cd "+GetDirectory$(yabFile$)+";"+yabDir$+" "+settingsYabParam$+" "+yabFile$+" "+settingsProgParam$+" &>/tmp/yab-log."+unique$+" &" + system("cd "+GetDirectory$(yabFile$)+";"+yabDir$+" "+settingsYabParam$+" "+yabFile$+" "+settingsProgParam$+" &>/tmp/yab-log."+unique$+" &") + sleep 0.1 + while(teamID <> -1) + teamID = thread get "teamid", yabDir$+" "+param$+yabFile$ + + handle = open("/tmp/yab-log."+unique$,"r") + if(handle) then + seek handle,pos + while(not eof(handle)) + tmp$ = GetLine$(handle)+"\n" + listbox add "YabOutputList", left$(tmp$, len(tmp$)-1) + listbox select "YabOutputList", listbox count "YabOutputList" + pos = tell(handle) + wend + close(handle) + endif + + if(instr(message$, "BRunning")) then + t = thread remove "teamid", teamID + if(not t) alert "Error! Program could not be killed.", "Oops", "stop" + break + endif + sleep 0.1 + wend + + window close "Running" + + system("rm -f "+"/tmp/yab-log."+unique$+" >/dev/null") + + isRunning = false + return +end sub + +// Run the program in a terminal +sub RunInTerminal(yabFile$) + local tmp$, param$ + local num, i, t, pos + local x, y, err, w + + if(isRunning) return + isRunning = true + + x = peek("desktopwidth")/2 - 150 + y = peek("desktopheight")/2 - 100 + window open x,y to x+299,y+79, "Running", "" + window set "Running", "feel", "modal-app" + window set "Running", "look", "modal" + window set "Running", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + err = draw image 0,0, ideDir$+"img/Running.png", "Running" + + w = draw get "text-width", GetFileName$(yabFile$), "Running" + text 168-w/2,32, "TRunning", GetFileName$(yabFile$), "Running" + + w = draw get "text-width", MyTranslate$("Close terminal to break program"), "Running" + text 168-w/2,60, "TRunning2", "Close terminal to break program", "Running" + + draw set "Bitstream Vera Sans, Bold Oblique, 14", "Running" + w = draw get "text-width", MyTranslate$("Running Program"), "Running" + draw text 168-w/2,20, "Running Program", "Running" + + window set "Running", "deactivate" + sleep 0.1 + + param$ = settingsYabParam$ + " -enter" + tmp$ = system$("Terminal "+yabDir$+" "+param$+" "+yabFile$+" "+settingsProgParam$+" 2>&1") + window close "Running" + + listbox clear "YabOutputList" + dim result$(1) + num = split(tmp$, result$(), "\n") + for i = 1 to num + listbox add "YabOutputList", result$(i) + next i + + isRunning = false + return +end sub + +sub AboutWindow() + local x + local y + local width + local t + + x = peek("desktopwidth")/2 - 200 + y = peek("desktopheight")/2 - 200 + window open x-3000,y-3000 to x+400-3000, y+300-3000, "AboutWindow", "" + window set "AboutWindow", "look", "bordered" + window set "AboutWindow", "feel", "modal-app" + window set "AboutWindow", "MaximumTo", 400,300 + window set "AboutWindow", "MinimumTo", 400,300 + window set "AboutWindow", "Flags", "not-closable, not-zoomable, not-h-resizable, not-v-resizable" + + draw set "bgcolor", 255,255,255, "AboutWindow" + draw set "lowcolor", 255,255,255, "AboutWindow" + + width = draw get "text-width", "(c) 2006-2015 in terms of the Artistic License", "AboutWindow" + draw text 198-width/2, 260, "(c) 2006-2015 in terms of the Artistic License", "AboutWindow" + width = draw get "text-width", "Coded by Jan, graphics by Genki, thanks to BeSly", "AboutWindow" + draw text 200-width/2, 240, "Coded by Jan, graphics by Genki, thanks to BeSly", "AboutWindow" + + if(peek$("os") = "Haiku") then + draw set "DejaVu Sans, Bold, 18", "AboutWindow" + else + draw set "Swis721 BT, Bold, 18", "AboutWindow" + endif + width = draw get "text-width", "yab-IDE", "AboutWindow" + draw text 200-width/2, 25, "yab-IDE", "AboutWindow" + if(peek$("os") = "Haiku") then + draw set "DejaVu Sans, Bold, 10", "AboutWindow" + else + draw set "Swis721 BT, Bold, 10", "AboutWindow" + endif + width = draw get "text-width", "Version "+versionnumber$, "AboutWindow" + draw text 200-width/2, 40, "Version "+versionnumber$, "AboutWindow" + + t = draw image 100,50 to 300,-1, ideDir$+"img/yablogo.png", "AboutWindow" + + button 100,265 to 300,290, "AboutButton", "Close", "AboutWindow" + option set "AboutButton", "focus", true + + window set "AboutWindow", "moveto", x,y + + while(not instr(message$, "AboutButton")) + wend + + + window close "AboutWindow" + return +end sub + +sub SaveAsTemplate() + local x: local y + local w: local i: local n + local isButton + local handle: local handle2 + local inloop + local msg$(1) + local name$: local description1$: local description2$: local image$ + local t$ + + x = (peek("desktopwidth")-600)/2 + y = (peek("desktopheight")-200)/2-50 + if(y<50) y=50 + + window open x-3000,y-3000 to x+600-3000,y+200-3000, "SaveTempWindow", "yab-IDE Save as Template" + window set "SaveTempWindow", "Feel", "Modal-App" + window set "SaveTempWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Save as Template", "SaveTempWindow", 600) + + text 10,50, "SaveTempText1", "Save your code as a template for other programs:", "SaveTempWindow" + textcontrol 10,70 to 380,90, "SaveTempName", "Template Name", "", "SaveTempWindow" + text 10,98, "SaveTempText2", "Description (not more than 30 characters per line)", "SaveTempWindow" + textcontrol 5,110 to 380,120, "SaveTempDes1", "", "", "SaveTempWindow" + textcontrol 5,130 to 380,150, "SaveTempDes2", "", "", "SaveTempWindow" + + draw set "highcolor", 0,0,0, "SaveTempWindow" + draw set "lowcolor", 255,255,0, "SaveTempWindow" + draw set 0, "240225195135015030060120" + draw rect 390,50 to 590,150, "SaveTempWindow" + draw set 0, "lowsolidfill" + draw set "lowcolor", 216,216,216, "SaveTempWindow" + draw rect 400,60 to 580,140, "SaveTempWindow" + draw set 0, "highsolidfill" + + w = draw get "Text-width", MyTranslate$("Drop image here"), "SaveTempWindow" + draw text 490-w/2,105, "Drop image here", "SaveTempWindow" + view dropzone "SaveTempWindow" + + draw set "highcolor", 185,185,185, "SaveTempWindow" + draw line 0,162 to 600,162, "SaveTempWindow" + draw set "highcolor", 239,239,239, "SaveTempWindow" + draw line 0,163 to 600,163, "SaveTempWindow" + + button 530,170 to 590,190, "SaveTempOk", "Save", "SaveTempWindow" + option set "SaveTempOk", "enabled", false + isButton = false + + option set "SaveTempName", "focus", true + + window set "SaveTempWindow", "moveto", x,y + + inloop = true + while(inloop) + n = split(message$, msg$(), ":|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + // check for emergency exit + if(i > 1) then + if(msg$(i) = "_QuitRequested" and msg$(i-1) <> "SaveTempWindow") then + exit(1) + endif + else + if(msg$(i) = "_QuitRequested") then + exit(1) + endif + endif + switch(msg$(i)) + case "_Dropped" + if(arraysize(msg$(),1)>=i+1) then + w = draw image 390,50 to 590,150, msg$(i+1), "SaveTempWindow" + if(w<>0) then + alert "Could not load image!", "Ok", "warning" + else + image$ = msg$(i+1) + endif + endif + break + case "SaveTempOk" + name$ = left$(textcontrol get$ "SaveTempName", 50) + description1$ = left$(textcontrol get$ "SaveTempDes1", 30) + description2$ = left$(textcontrol get$ "SaveTempDes2", 30) + imageShort$ = GetFileName$(image$) + system("cp "+image$+" "+ideDir$+"Templates/img/"+imageShort$) + handle = open(ideDir$+"Templates/TemplateList", "a") + if(handle) then + print #handle "#" + print #handle name$ + print #handle "Templates/img/"+imageShort$ + print #handle description1$ + print #handle description2$ + close(handle) + handle2 = open(ideDir$+"Templates/"+name$, "w") + if(handle2) then + t$ = textedit get$ "Text"+str$(globalCurrentText) + print #handle t$; + close(handle2) + else + alert "Error while saving template!", "Ok", "warning" + endif + else + alert "Error while saving template!", "Ok", "warning" + endif + inloop = false + break + case "_QuitRequested" + inloop = false + break + end switch + next i + + name$ = textcontrol get$ "SaveTempName" + if(name$<>"" and not isButton) then + option set "SaveTempOk", "enabled", true + isButton = true + endif + if(name$="" and isButton) then + option set "SaveTempOk", "enabled", false + isButton = false + endif + wend + + window close "SaveTempWindow" + return +end sub + +sub SaveCurrentFile() +local savetext$ + handle = open(globalAllNames$(globalCurrentText), "w") + if(handle) then + savetext$=textedit get$ "Text"+str$(globalCurrentText) + if right$(savetext$,1)<>chr$(10) savetext$=savetext$+chr$(10) + print #handle savetext$; + close(handle) + tmpCurrentLine = textedit get "Text"+str$(globalCurrentText), "currentline" + print "ATTR SET "; + print str$(tmpCurrentLine) + attribute set "Int", "linenumber", str$(tmpCurrentLine), globalAllNames$(globalCurrentText) + textedit set "Text"+str$(globalCurrentText), "changed", false + globalWasChanged = false + columnbox add "FileBox", 1, globalTextFinder(globalCurrentText), 20, "__Icon__="+ideDir$+"img/gespeichert.png" + else + alert "File could not be saved!", "Ok", "warning" + return false + endif + return true +end sub + +sub Header(headerText$, window$, size) + local w + local head$ + + head$ = window$+"Header" + layout "none", window$ + view 0,0 to size,40, head$, window$ + draw set "bgcolor", 230,230,255, head$ + draw set "lowcolor", 230,230,255, head$ + if(peek$("os") = "Haiku") then + draw set "DejaVu Sans, Condensed Bold, 18", head$ + else + draw set "Swis721 BT, Bold, 18", head$ + endif + draw set "highcolor", 0,0,0, head$ + w = draw get "Text-width", MyTranslate$(headerText$), head$ + draw text size-w-10,25, headerText$, head$ + draw set "highcolor", 239,239,239, head$ + draw line 0,40 to size,40, head$ + draw set "highcolor", 185,185,185, head$ + draw line 0,39 to size,39, head$ + return +end sub + +// open the build factory window +sub Building() + local x, y, inloop, isEmpty + local binName$, t$, myTab$, result$ + local msg$(1) + local i, n, tmp + + + x = (peek("desktopwidth")-500)/2 + y = (peek("desktopheight")-400)/2-50 + if(y<50) y=50 + + window open x-3000,y-3000 to x+500-3000,y+400-3000, "BuildWindow", "yab-IDE Build Factory" + window set "BuildWindow", "Feel", "Modal-App" + window set "BuildWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Build Factory", "BuildWindow", 500) + + if(right$(globalAllNames$(globalCurrentText),4) = ".yab") then + binName$ = left$(globalAllNames$(globalCurrentText), len(globalAllNames$(globalCurrentText))-4) + else + binName$= globalAllNames$(globalCurrentText)+".bin" + endif + + while (instr(binName$, "/")) + pos=instr(binName$, "/") + binName$=right$(binName$,len(binName$)-pos) + wend + + + isEmpty = false + + textcontrol 10,50 to 380,70, "BuildPath", "Target file name:", binName$, "BuildWindow" + AppSig$="application/x-vnd.yab-app" + textcontrol 10,80 to 380,100, "AppSig", "Application Signature:", AppSig$, "BuildWindow" + //button 390,50 to 490,70, "BuildBrowse", "Browse", "BuildWindow" + + button 390,100 to 490,130, "BuildBuild", "Create Binary", "BuildWindow" + + MyLine(0,140,500,140, "BuildWindow") + textedit 10,155 to 490,390, "BuildOutput", 3, "BuildWindow" + textedit set "BuildOutput", "editable", false + textedit set "BuildOutput", "wordwrap", false + textedit set "BuildOutput", "textwidth", 4000 + + window set "BuildWindow", "moveto", x, y + + if(left$(system$("gcc 2>&1"),4) <> "gcc:") then + alert "The compiler GCC was not found!\n\nPlease install a complete Haiku system.", "Ok", "stop" + window close "BuildWindow" + return + endif + + textedit add "BuildOutput", MyTranslate$("Build Factory Output\n\n") + + inloop = true + while(inloop) + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + switch(msg$(i)) + case "BuildBuild" + option set "BuildBuild", "enabled", false + option set "BuildPath", "enabled", false + //option set "BuildBrowse", "enabled", false + option set "AppSig", "enabled", false + AppSig$=textcontrol get$ "AppSig" + if AppSig$="" AppSig$="application/x-vnd.yab-app" + binName$=textcontrol get$ "BuildPath" + textedit add "BuildOutput", MyTranslate$("Please wait, processing... (this may take a long time!)\n\n") + print "cd "+buildDir$+"; "+yabDir$+" BuildFactory.yab "+binName$+" "+globalAllNames$(globalCurrentText)+" "+AppSig$+" 2>&1\n\n" + result$ = system$("cd "+buildDir$+"; yab BuildFactory.yab "+binName$+" "+globalAllNames$(globalCurrentText)+" "+AppSig$+" yab-ide 2>&1") + textedit add "BuildOutput", result$ + + + option set "BuildBuild", "enabled", true + option set "BuildPath", "enabled", true + //option set "BuildBrowse", "enabled", true + option set "AppSig", "enabled", true + + if(IfExists(buildDir$+"/"+binName$)) then + alert "Build was successful", "Ok", "info" + else + alert "Build failed!", "Ok", "warning" + endif + system("rm "+ buildDir$+"/"+binName$) + break + //case "BuildBrowse" + // t$ = filepanel "save-file", "Save", GetDirectory$(binName$) + // if(t$<>"") then + // textcontrol set "BuildPath", t$ + // binName$ = t$ + // endif + // break + case "_QuitRequested" + case "BuildWindow:_QuitRequested" + inloop = false + break + end switch + next i + if(not isEmpty and textcontrol get$ "BuildPath" = "") then + AppSig$=textcontrol get$ "AppSig" + option set "BuildBuild", "enabled", false + isEmpty = true + endif + if(isEmpty and textcontrol get$ "BuildPath" <> "") then + AppSig$=textcontrol get$ "AppSig" + option set "BuildBuild", "enabled", true + isEmpty = false + endif + + + + wend + window close "BuildWindow" + return +end sub + +// open the option window +sub OptionWindow() + local x, y, inloop + local msg$(1), style$(1) + local styleNum, styleCount + local i, n, optCurrent + local tmp$ + local handle, j, hasItem + local family$, style$, size$ + local defaultFamily + + x = (peek("desktopwidth")-650)/2 + y = (peek("desktopheight")-400)/2-50 + if(y<50) y=50 + + window open x+100-3000,y+150-3000 to x+750-3000,y+550-3000, "OptWindow", "yab-IDE Options" + window set "OptWindow", "Feel", "Modal-App" + window set "OptWindow", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Options", "OptWindow", 650) + + draw set "highcolor", 185,185,185, "OptWindow" + draw line 11,51 to 138,51, "OptWindow" + draw line 10,50 to 139,50, "OptWindow" + draw line 11,51 to 11,388, "OptWindow" + draw line 10,50 to 10,389, "OptWindow" + draw set "highcolor", 239,239,239, "OptWindow" + draw line 12,389 to 139,389, "OptWindow" + draw line 11,390 to 139,390, "OptWindow" + draw line 139,52 to 139,389, "OptWindow" + draw line 140,51 to 140,390, "OptWindow" + draw set "highcolor", 0,0,0, "OptWindow" + + treebox 12,52 to 138,388, "OptTree", 0, "OptWindow" + // treebox add "OptTree", "Interpreter" + // treebox add "OptTree", "Interpreter", "Libraries", true + // treebox add "OptTree", "Interpreter", "Execution", true + treebox add "OptTree", "Editor" + treebox add "OptTree", "Editor", "Auto completion", true + // treebox add "OptTree", "Editor", "Syntax Highlighting", true + treebox add "OptTree", "Editor", "General", true + treebox add "OptTree", "Environment" + if(not settingsRCSOff) treebox add "OptTree", "Environment", "Version Control", true + treebox add "OptTree", "Environment", "Language", true + treebox add "OptTree", "Environment", "Directories", true + treebox select "OptTree", 2 + + // button 430,370 to 530,390, "OptDefault", "Default", "OptWindow" + // button 540,370 to 640,390, "OptOk", "Close", "OptWindow" + + // MyLine(0,362,650,362,"OptWindow") + + optCurrent = 1 + stackview 150,50 to 640,390, "OptStack", 4, "OptWindow" + + // General + boxview 0,0 to 490, 340, "OptBox3", "General", 2, "OptStack1" + spincontrol 10,5, "OptGenSpin", "Number of spaces per tab:", 1,20,1, "OptBox3" + spincontrol set "OptGenSpin", settingsTabSpaces + MyLine(10,35,470,35, "OptBox3") + checkbox 10,45, "OptGenSaving", "Ask about saving before running a program", settingsAskForSaving, "OptBox3" + checkbox 10,65, "OptGenReformat", "Show warning when reformating sourcecode did not close all loops and conditions", settingsReformatAlert, "OptBox3" + checkbox 10,85, "OptGenReformatUndo", "Show warning before undo reformating", settingsReformatUndoAlert, "OptBox3" + checkbox 10,105, "OptGenReplaceAll", "Show warning before applying Replace All", settingsFindAlert, "OptBox3" + MyLine(10,135,470,135, "OptBox3") + + text 10,145, "OptGenTxt", "Select font for editor:", "OptBox3" + dropbox 12,165 to 240,185, "OptGenFontFamily", "Font Family", "OptBox3" + dropbox 250,165 to 370,185, "OptGenFontStyle", "Font Style", "OptBox3" + spincontrol 380,160, "OptGenFontSize", "Font Size", 8,50,1, "OptBox3" + + n = token(draw get$ "FontFamily", msg$(), "|") + for i = 1 to n + dropbox add "OptGenFontFamily", msg$(i) + if(msg$(i) = settingsFontFamily$) j = i + if(msg$(i) = "Courier10 BT") defaultFamily = i + next i + if(j>0) then + dropbox select "OptGenFontFamily", j + n = token(draw get$ settingsFontFamily$, msg$(), "|") + for i = 1 to n + dropbox add "OptGenFontStyle", msg$(i) + if(msg$(i) = settingsFontStyle$) j = i + next i + if(j>0) dropbox select "OptGenFontStyle", j + endif + spincontrol set "OptGenFontSize", settingsFontSize + + view 20,205 to 460,255, "OptGenSample", "OptBox3" + draw set "bgcolor", 255,255,255, "OptGenSample" + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "OptGenSample" + n = draw get "text-width", MyTranslate$("My hovercraft is full of eels."), "OptGenSample" + draw text (440-n)/2,(50-settingsFontSize)/2+settingsFontSize, "My hovercraft is full of eels.", "OptGenSample" + MyLine(10,290,470,290,"OptBox3") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox3" + + // Syntax Highlighing + // boxview 0,0 to 490, 340, "OptBox4", "Syntax Highlighting", 2, "OptStack2" + + // Auto completion + boxview 0,0 to 490, 340, "OptBox5", "Auto completion", 2, "OptStack2" + checkbox 10,10, "OptACCheck", "Enable auto completion", settingsAutoCompletion, "OptBox5" + spincontrol 10,30, "OptACNum", "Number of characters for starting completion:", 1,20,1, "OptBox5" + spincontrol set "OptACNum", settingsACNumChar + MyLine(10,60,470,60,"OptBox5") + listbox 10,75 to 180,275, "OptACList", 1, "OptBox5" + textcontrol 190,185 to 470,205, "OptACTC", "New Entry:", "", "OptBox5" + button 320,215 to 470,235, "OptACAdd", "Add New Entry", "OptBox5" + MyLine(190,245,470,245,"OptBox5") + MyLine(190,175,470,175,"OptBox5") + button 370,255 to 470,275, "OptACRemove", "Remove Entry", "OptBox5" + text 190,75, "OptACText1", "Note: You have to restart the IDE to update the", "OptBox5" + text 190,90, "OptACText2", "autocompletion when removing entries.", "OptBox5" + handle = open(ideDir$+"data/autocompletion", "r") + if(handle) then + while(not eof(handle)) + tmp$ = GetLine$(handle)+"\n" + listbox add "OptACList", left$(tmp$, len(tmp$)-1) + wend + close(handle) + endif + MyLine(10,290,470,290,"OptBox5") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox5" + + // Dirs + boxview 0,0 to 490, 340, "OptBox6", "Directories", 2, "OptStack3" + text 10,10, "OptDirTxt", "Note: Only change the directories, when you know what you are doing!", "OptBox6" + MyLine(10,30,470,30, "OptBox6") + textcontrol 10,45 to 470,65, "OptDirBinDir", "Default yab Binary", yabDir$, "OptBox6" + // MyLine(10,45,470,45, "OptBox6") + // textcontrol 10,60 to 360,80, "OptDirProjDir", "Project Directory", globalProjectDir$, "OptBox6" + textcontrol 10,80 to 470,100, "OptDirYabDir", "Default yab Directory", settingsYabDir$, "OptBox6" + MyLine(10,115,470,115, "OptBox6") + MyLine(10,290,470,290,"OptBox6") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox6" + + // Language + boxview 0,0 to 490, 340, "OptBox8", "Language", 2, "OptStack4" + checkbox 10,10, "OptLangCheck", "Use automatic localization", restartSettingsLangUse, "OptBox8" + MyLine(10,40,470,40,"OptBox8") + columnbox 10,55 to 470,275, "OptLangList", false, "", "OptBox8" + columnbox column "OptLangList", "Supported Languages", 1, 460,460,460, "align-left" + MyLine(10,290,470,290,"OptBox8") + button 320,297 to 470,317, "OptDefault", "Factory Settings", "OptBox8" + columnbox color "OptLangList", "Selection-Active", 220,220,250 + columnbox color "OptLangList", "Row-Divider", 255,255,255 + tmp$ = system$("ls /boot/common/data/locale/catalogs/"+settingsLangPath$+"/*.catalog") + n = token(tmp$, msg$(), "\n") + for i = 1 to n + columnbox add "OptLangList", 1,i,18,msg$(i) + next i + + window set "OptWindow", "moveto", x,y + + inloop = true + while(inloop) + n = split(message$, msg$(), "|") + for i = 1 to n + if(DEBUG and msg$(i)<>"") print msg$(i) + switch(msg$(i)) + case "_QuitRequested" + // emergency quit + exit(1) + break + case "OptOk" + case "OptWindow:_QuitRequested" + inloop = false + break + + // General + case "OptGenSaving:ON" + case "OptGenSaving:OFF" + settingsAskForSaving = not settingsAskForSaving + break + case "OptGenReformat:ON" + case "OptGenReformat:OFF" + settingsReformatAlert = not settingsReformatAlert + break + case "OptGenReformatUndo:ON" + case "OptGenReformatUndo:OFF" + settingsReformatUndoAlert = not settingsReformatUndoAlert + break + case "OptGenReplaceAll:ON" + case "OptGenReplaceAll:OFF" + settingsFindAlert = not settingsFindAlert + break + + // Autocompletion + case "OptACCheck" + settingsAutoCompletion = not settingsAutoCompletion + break + case "OptACRemove" + break + case "OptACAdd" + tmp$ = textcontrol get$ "OptACTC" + if(tmp$<>"") then + hasItem = false + for j=1 to listbox count "OptACList" + if(tmp$ = listbox get$ "OptACList", i) then + hasItem = true + break + endif + next j + if(not hasItem) then + listbox add "OptACList", tmp$ + listbox sort "OptACList" + else + alert "Entry already exists.", "Ok", "info" + endif + endif + break + + // Language + case "OptLangCheck:ON" + case "OptLangCheck:OFF" + restartSettingsLangUse = not restartSettingsLangUse + alert "Restart yab-IDE to change localization", "Ok", "info" + break + + // Default + case "OptDefault" + t = stackview get "OptStack" + switch(t) + case 1 + settingsAskForSaving = true + settingsReformatAlert = true + settingsReformatUndoAlert = true + settingsFindAlert = true + settingsTabSpaces = 4 + settingsFontStyle$ = "Roman" + settingsFontSize = 12 + spincontrol set "OptGenSpin", settingsTabSpaces + checkbox set "OptGenSaving", settingsAskForSaving + checkbox set "OptGenReformat", settingsReformatAlert + checkbox set "OptGenReformatUndo", settingsReformatUndoAlert + checkbox set "OptGenReplaceAll", settingsFindAlert + dropbox select "OptGenFontFamily", defaultFamily + if(settingsFontFamily$<> "Courier10 BT") then + settingsFontFamily$ = "Courier10 BT" + dropbox clear "OptGenFontStyle" + styleCount = token(draw get$ settingsFontFamily$, style$(), "|") + for styleNum = 1 to styleCount + dropbox add "OptGenFontStyle", style$(styleNum) + next styleNum + dropbox select "OptGenFontStyle", 1 + OptionUpdateSample() + endif + spincontrol set "OptGenFontSize", settingsFontSize + for j = 1 to MAXFILES + textedit set "Text"+str$(j), "TabWidth", settingsTabSpaces*7 + next j + break + case 2 + settingsAutoCompletion = true + settingsACNumChar = 2 + checkbox set "OptACCheck", settingsAutoCompletion + spincontrol set "OptACNum", settingsACNumChar + break + case 3 + if(system("test -d /boot/apps/Development/yab-1.0/") = 0) then + settingsYabDir$ = "/boot/apps/Development/yab-1.0/" + elsif(system("test -d /boot/apps/yab-1.0/") = 0) then + settingsYabDir$ = "/boot/apps/yab-1.0/" + else + alert "Could not find yab 1.0 directory!\n\nPlease do a proper installation.", "Ok", "warning" + endif + textcontrol set "OptDirYabDir", settingsYabDir$ + + if(system("test -e /boot/home/config/bin/yab") = 0) then + yabDir$ = "/boot/home/config/bin/yab" + else + alert "Could not find yab binary!\n\nPlease do a proper installation.", "Ok", "warning" + endif + textcontrol set "OptDirBinDir", yabDir$ + break + case 4 + if(restartSettingsLangUse = false) then + restartSettingsLangUse = true + checkbox set "OptLangCheck",restartSettingsLangUse + alert "Restart yab-IDE to change localization", "Ok", "info" + endif + break + end switch + break + end switch + + // Font stuff + if(left$(msg$(i), 17) = "OptGenFontFamily:") then + settingsFontFamily$ = right$(msg$(i), len(msg$(i))-17) + dropbox clear "OptGenFontStyle" + styleCount = token(draw get$ settingsFontFamily$, style$(), "|") + for styleNum = 1 to styleCount + dropbox add "OptGenFontStyle", style$(styleNum) + next styleNum + dropbox select "OptGenFontStyle", 1 + settingsFontStyle$ = style$(1) + OptionUpdateSample() + endif + if(left$(msg$(i), 16) = "OptGenFontStyle:") then + settingsFontStyle$ = right$(msg$(i), len(msg$(i))-16) + OptionUpdateSample() + endif + + if(left$(msg$(i), 8) = "OptACTC:") then + option set "OptACAdd", "focus", true + endif + if(left$(msg$(i), 16) = "OptTree:_Select:") then + t = val(right$(msg$(i), len(msg$(i))-16)) + tmp$ = treebox get$ "OptTree", t + switch(tmp$) + case MyTranslate$("General"): t = 1: break + // case MyTranslate$("Syntax Highlighting"): t = 2: break + case MyTranslate$("Auto completion"): t = 2: break + case MyTranslate$("Directories"): t = 3: break + case MyTranslate$("Language"): t = 4: break + // case MyTranslate$("Version Control"): t = 6: break + default: t = 0: break + end switch + if(t>0) then + stackview set "OptStack", t + optCurrent = t + endif + endif + + if(left$(msg$(i), 13) = "OptDirYabDir:") then + tmp$ = right$(msg$(i), len(msg$(i))-13) + if(system("test -d "+tmp$) = 0) then + settingsYabDir$ = tmp$ + alert MyTranslate$("New yab directory set to:\n\n")+tmp$+MyTranslate$("\n\nRestart the IDE using the new directory."), "Ok", "info" + else + alert MyTranslate$("Invalid directory:\n\n")+tmp$, "Ok", "warning" + textcontrol set "OptDirYabDir", settingsYabDir$ + endif + endif + if(left$(msg$(i), 13) = "OptDirBinDir:") then + tmp$ = right$(msg$(i), len(msg$(i))-13) + if(system("test -e "+tmp$) = 0) then + yabDir$ = tmp$ + alert MyTranslate$("yab binary set to:\n\n")+tmp$, "Ok", "info" + else + alert MyTranslate$("Invalid file:\n\n")+tmp$, "Ok", "warning" + textcontrol set "OptDirBinDir", yabDir$ + endif + endif + next i + if(spincontrol get "OptGenFontSize" <> settingsFontSize) then + settingsFontSize = spincontrol get "OptGenFontSize" + OptionUpdateSample() + endif + if(spincontrol get "OptGenSpin" <> settingsTabSpaces) then + settingsTabSpaces = spincontrol get "OptGenSpin" + for j = 1 to MAXFILES + textedit set "Text"+str$(j), "TabWidth", settingsTabSpaces*7 + next j + endif + wend + + window close "OptWindow" + + return +end sub + +// draw the example text (OptionWindow) +sub OptionUpdateSample() + local n + local scroll, scrollLine, scrollPos + + draw flush "OptGenSample" + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "OptGenSample" + n = draw get "text-width", MyTranslate$("My hovercraft is full of eels."), "OptGenSample" + draw text (440-n)/2,50-(50-settingsFontSize)/2, "My hovercraft is full of eels.", "OptGenSample" + for n = 1 to MAXFILES + textedit set "Text"+str$(n), "font", settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize) + draw set settingsFontFamily$+","+settingsFontStyle$+","+str$(settingsFontSize), "Lines"+str$(n) + next n + if(globalCurrentText>0) then + globalRealFontSize = textedit get "Text"+str$(globalCurrentText), "line-height", 1 + scroll = textedit get "Text"+str$(globalCurrentText), "vertical-scrollbar" + scrollLine = int(scroll/globalRealFontSize) + scrollPos = mod(scroll,globalRealFontSize) + UpdateLines(scrollPos, 1200, scrollLine, globalRealFontSize) + endif + return +end sub + +// draw a sort of 3D line +sub MyLine(x1,y1,x2,y2,View$) + draw set "highcolor", 185,185,185, View$ + draw line x1,y1 to x2,y2, View$ + draw set "highcolor", 239,239,239, View$ + if(x1=x2) then + draw line x1+1,y1 to x2+1,y2, View$ + else + draw line x1,y1+1 to x2,y2+1, View$ + endif + draw set "highcolor", 0,0,0, View$ + return +end sub + +// only translates when a translation is wanted +sub MyTranslate$(txt$) + if(settingsLangUse) return menu translate$(txt$) + return txt$ +end sub + +// returns true if filename$ exists +sub IfExists(filename$) + return not system("test -e "+filename$) +end sub + +// Create a new toolbar. +// +// x1,y1 is the upper left starting point +// x2 is the right border of the toolbar +// note: the toolbar is always 30 pixels in height! +// id$ is the toolbar ID +// dir$ is the directory, where the icons can be found +// view$ is the view on which the Toolbar is created +// +// Note: this will change the layout of your view view$. +sub ToolbarCreate(x1,y1,x2, id$, dir$, view$) + layout "left, right", view$ + view x1,y1 to x2,y1+32, id$, view$ + // layout "left,right", id$ + draw set "bgcolor", 222,219,222, id$ + // view 0,30 to x2,32, id$+"line", id$ + // draw set "bgcolor", 185,185,185, id$+"line" + layout "none", id$ + position = 10 + directory$ = dir$ + toolbarview$ = id$ + return +end sub + +// Add an icon to the toolbar. +sub ToolbarAddIcon(id$, tooltip$, pressed$, normal$, disabled$) + button image position,7, id$, directory$+pressed$, directory$+normal$, directory$+disabled$, toolbarview$ + tooltip id$, tooltip$ + position = position + 25 + return +end sub + +// Add a separator to the toolbar. +sub ToolbarAddSeparator() + draw set "highcolor", 185,185,185, toolbarview$ + draw line position-2,5 to position-2,25,toolbarview$ + draw set "highcolor", 239,239,239, toolbarview$ + draw line position-1,5 to position-1,25, toolbarview$ + position = position + 5 + return +end sub + +// Open the pattern calculation window +sub OpenCalcPattern(x,y) + local i, j, w + local msg$(1) + local inloop, n + + window open x,y to x+259,y+400, "CalcPattern", "yab-IDE Pattern editor" + window set "CalcPattern", "Feel", "Modal-App" + window set "CalcPattern", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Pattern editor", "CalcPattern", 260) + + draw set "highcolor", 239,239,239, "CalcPattern" + draw line 0,300 to 259,300, "CalcPattern" + draw set "highcolor", 185,185,185, "CalcPattern" + draw line 0,299 to 259,299, "CalcPattern" + + view 10,50 to 249,289, "VDraw", "CalcPattern" + draw set "bgcolor", 255, 255, 255, "VDraw" + draw set "lowcolor", 0, 0, 0, "VDraw" + + view 10,310 to 90,390, "VPattern", "CalcPattern" + draw set "bgcolor", 255, 255, 255, "VPattern" + draw set "lowcolor", 0, 0, 0, "VPattern" + draw set "highcolor", 255, 255, 255, "VPattern" + + button 100,370 to 249,390, "CalcPatternInsert", "Insert Pattern", "CalcPattern" + + UpdatePattern(pattern()) + draw set 0, "LowSolidFill" + draw set "lowcolor", 0, 0, 0, "VDraw" + for i = 0 to 7 + for j = 0 to 7 + if(pattern(i,j) = 1) then + draw rect i*30,j*30 to i*30+29,j*30+29, "VDraw" + endif + next j + next i + draw set 0, "HighSolidFill" + + inloop = true + while(inloop) + CalcPatternMouse(pattern()) + n = token(message$, msg$(), "|") + for i = 1 to n + switch(msg$(i)) + case "CalcPatternInsert" + textedit add "Text"+str$(globalCurrentText), CalcPatternInsert$(pattern()) + break + case "CalcPattern:_QuitRequested" + settingsCalcPatternX = window get "CalcPattern", "Position-X" + settingsCalcPatternY = window get "CalcPattern", "Position-Y" + window close "CalcPattern" + inloop = false + break + case "_QuitRequested" + //emergency break + exit(1) + break + end switch + next i + wend + return +end sub + +// mouse stuff (PatternEditor) +sub CalcPatternMouse(pattern()) + local help$ + local i, j, refresh + + mousex = 0 + mousey = 0 + mouselmb = 0 + mousemmb = 0 + mousermb = 0 + + + refresh = 0 + + if(ismousein("VDraw")) then + GetMouseData("VDraw",239,239) + endif + + if(mouselmb) then + x = int(mousex/30) + y = int(mousey/30) + if(pattern(x,y) = 0) then + pattern(x,y) = 1 + draw set "lowcolor", 0, 0, 0, "VDraw" + draw set 0, "LowSolidFill" + draw rect x*30,y*30 to x*30+29,y*30+29, "VDraw" + UpdatePattern(pattern()) + refresh = refresh + 1 + endif + endif + + if(mousermb) then + x = int(mousex/30) + y = int(mousey/30) + if(pattern(x,y) = 1) then + pattern(x,y) = 0 + draw set "lowcolor", 255, 255, 255, "VDraw" + draw set 0, "LowSolidFill" + draw rect x*30,y*30 to x*30+29,y*30+29, "VDraw" + draw set "lowcolor", 0, 0, 0, "VDraw" + UpdatePattern(pattern()) + refresh = refresh + 1 + endif + endif + + if(refresh = 15) then + draw flush "VDraw" + draw flush "VPattern" + draw set "lowcolor", 0, 0, 0, "VDraw" + for i = 0 to 7 + for j = 0 to 7 + if(pattern(i,j)) then + draw set 0, "LowSolidFill" + draw rect i*30,j*30 to i*30+29,j*30+29, "VDraw" + draw set 0, "HighSolidFill" + endif + next j + next i + UpdatePattern(pattern()) + refresh = 0 + endif + + return +end sub + +// get pattern string (PatternEditor) +sub CalcPatternInsert$(pattern()) + local i, j + local t$, p$ + + p$ = "\"" + for i = 0 to 7 + t$ = "" + for j = 0 to 7 + t$ = t$ + str$(1-pattern(j,i)) + next j + t = dec(t$,2) + if(t<100) p$ = p$ + "0" + if(t<10) p$ = p$ + "0" + p$ = p$ + str$(t) + next i + p$ = p$ + "\"" + return p$ +end sub + +// get mouse stuff (PatternEditor) +sub GetMouseData(view$,maxx, maxy) + local n + local mouse$(1) + + mousemsg$ = mouse message$(view$) + n = split(mousemsg$, mouse$(), ":") + mousex = val(mouse$(1)) + mousey = val(mouse$(2)) + mouselmb = val(mouse$(3)) + mousemmb = val(mouse$(4)) + mousermb = val(mouse$(5)) + if(mousex<0) mousex = 0 + if(mousey<0) mousey = 0 + if(mousex>maxx) mousex = maxx + if(mousey>maxy) mousey = maxy + + return +end sub + +// update pattern (PatternEditor) +sub UpdatePattern(pattern()) + local i, j + local t$, p$ + + for i = 0 to 7 + t$ = "" + for j = 0 to 7 + t$ = t$ + str$(1-pattern(j,i)) + next j + t = dec(t$,2) + if(t<100) p$ = p$ + "0" + if(t<10) p$ = p$ + "0" + p$ = p$ + str$(t) + next i + draw flush "VPattern" + draw set 0, p$ + draw rect 0,0 to 80,80, "VPattern" + draw set 0, "HighSolidFill" + return +end sub + +// Open the color selection window +sub OpenColorSelection(x,y,r,g,b) + local i, j, w, n, num + local tmp$, msg$(1), col$(1) + local inloop + + window open x,y to x+366,y+270, "ColorSelect", "yab-IDE Color selection" + window set "ColorSelect", "Feel", "Modal-App" + window set "ColorSelect", "Flags", "not-zoomable, not-h-resizable, not-v-resizable" + + Header("Color selection", "ColorSelect", 366) + + draw set "highcolor", 239,239,239, "ColorSelect" + draw line 0,233 to 366,233, "ColorSelect" + draw line 71,55 to 71,116, "ColorSelect" + draw line 10,116 to 71,116, "ColorSelect" + draw set "highcolor", 185,185,185, "ColorSelect" + draw line 0,232 to 366,232, "ColorSelect" + draw line 9,54 to 9,115, "ColorSelect" + draw line 9,54 to 70,54, "ColorSelect" + + view 10,55 to 70,115, "ColorSelectRect", "ColorSelect" + draw set "highcolor", r,g,b, "ColorSelectRect" + draw rect 0,0 to 60,60, "ColorSelectRect" + colorcontrol 80,59, "ColorControl", "ColorSelect" + colorcontrol set "ColorControl", r,g,b + + draw set "highcolor", 0,0,0, "ColorSelect" + draw text 10,140, "Default Colors:", "ColorSelect" + draw set 1, "HighSolidFill" + for i = 45 to 305 step 30 + for j=155 to 186 step 30 + draw set 1, "HighSolidFill" + draw rect i,j to i+30,j+30, "ColorSelect" + draw set 0, "HighSolidFill" + tmp$ = str$((j-125)/30)+str$((i-15)/30) + view i+1,j+1 to i+29,j+29, "Color"+tmp$, "ColorSelect" + switch tmp$ + case "11" + draw set "bgcolor", 0,0,0, "Color11" + tooltip "Color11", "Black" + break + case "12" + draw set "bgcolor", 96,96,96, "Color12" + tooltip "Color12", "Darken 4" + break + case "13" + draw set "bgcolor", 128,128,128, "Color13" + tooltip "Color13", "Darken 3" + break + case "14" + draw set "bgcolor", 152,152,152, "Color14" + tooltip "Color14", "Darken 2" + break + case "15" + draw set "bgcolor", 184,184,184, "Color15" + tooltip "Color15", "Darken 1" + break + case "16" + draw set "bgcolor", 216,216,216, "Color16" + tooltip "Color16", "Default Background" + break + case "17" + draw set "bgcolor", 232,232,232, "Color17" + tooltip "Color17", "Lighten 1" + break + case "18" + draw set "bgcolor", 240,240,240, "Color18" + tooltip "Color18", "Lighten 2" + break + case "19" + draw set "bgcolor", 255,255,255, "Color19" + tooltip "Color19", "White" + break + case "21" + draw set "bgcolor", 255,0,0, "Color21" + tooltip "Color21", "Red" + break + case "22" + draw set "bgcolor", 192,128,0, "Color22" + tooltip "Color22", "Brown" + break + case "23" + draw set "bgcolor", 255,255,0, "Color23" + tooltip "Color23", "Yellow" + break + case "24" + draw set "bgcolor", 0,255,0, "Color24" + tooltip "Color24", "Green" + break + case "25" + draw set "bgcolor", 0,255,255, "Color25" + tooltip "Color25", "Cyan" + break + case "26" + draw set "bgcolor", 128,192,255, "Color26" + tooltip "Color26", "Light Blue" + break + case "27" + draw set "bgcolor", 0,0,255, "Color27" + tooltip "Color27", "Blue" + break + case "28" + draw set "bgcolor", 255,0,255, "Color28" + tooltip "Color28", "Magenta" + break + case "29" + draw set "bgcolor", 192,128,255, "Color29" + tooltip "Color29", "Light Magenta" + break + end switch + next j + next i + + draw set 0, "HighSolidFill" + + button 256,240 to 356,260, "ColorSelectInsert", "Insert Color", "ColorSelect" + + inloop = true + while(inloop) + ColorSelectMouse() + n = token(message$, msg$(), "|") + for i = 1 to n + if(left$(msg$(i),13) = "ColorControl:") then + tmp$ = right$(msg$(i), len(msg$(i))-13) + dim col$(3) + num = token(tmp$, col$(), ":") + if(num = 3) then + draw flush "ColorSelectRect" + draw set "highcolor", val(col$(1)), val(col$(2)), val(col$(3)), "ColorSelectRect" + draw rect 0,0 to 60,60, "ColorSelectRect" + endif + endif + switch(msg$(i)) + case "ColorSelectInsert" + textedit add "Text"+str$(globalCurrentText), ColorSelectInsert$() + break + case "ColorSelect:_QuitRequested" + settingsColorSelectX = window get "ColorSelect", "Position-X" + settingsColorSelectY = window get "ColorSelect", "Position-Y" + settingsColorSelectR = colorcontrol get "ColorControl", "red" + settingsColorSelectG = colorcontrol get "ColorControl", "green" + settingsColorSelectB = colorcontrol get "ColorControl", "blue" + window close "ColorSelect" + inloop = false + break + case "_QuitRequested" + //emergency break + exit(1) + break + end switch + next i + wend + return +end sub + +// get the color string (ColorSelect) +sub ColorSelectInsert$() + local r, g, b + + r = colorcontrol get "ColorControl", "red" + g = colorcontrol get "ColorControl", "green" + b = colorcontrol get "ColorControl", "blue" + + return " "+str$(r)+", "+str$(g)+", "+str$(b) +end sub + +// check mouse in ColorSelect +sub ColorSelectMouse() + local i, j + local tmp$ + + for i = 1 to 9 + for j = 1 to 2 + tmp$ = "Color"+str$(j)+str$(i) + if(ismousein(tmp$) and IsButtonPressed(tmp$)) then + switch tmp$ + case "Color11" + SetColor(0,0,0) + break + case "Color12" + SetColor(96,96,96) + break + case "Color13" + SetColor(128,128,128) + break + case "Color14" + SetColor(152,152,152) + break + case "Color15" + SetColor(184,184,184) + break + case "Color16" + SetColor(216,216,216) + break + case "Color17" + SetColor(232,232,232) + break + case "Color18" + SetColor(240,240,240) + break + case "Color19" + SetColor(255,255,255) + break + case "Color21" + SetColor(255,0,0) + break + case "Color22" + SetColor(192,128,0) + break + case "Color23" + SetColor(255,255,0) + break + case "Color24" + SetColor(0,255,0) + break + case "Color25" + SetColor(0,255,255) + break + case "Color26" + SetColor(128,192,255) + break + case "Color27" + SetColor(0,0,255) + break + case "Color28" + SetColor(255,0,255) + break + case "Color29" + SetColor(192,128,255) + break + end switch + endif + next j + next i +end sub + +// check for pressed mouse button (ColorSelect) +sub IsButtonPressed(view$) + local n, t + local mouselmb + + t = false + dim mouse$(1) + repeat + mousemsg$ = mouse message$(view$) + n = split(mousemsg$, mouse$(), ":") + mouselmb = val(mouse$(3)) + if(mouselmb) t = true + if(not ismousein(view$)) then + t = false + mouselmb = 0 + endif + until (mouselmb = 0) + return t +end sub + +// set a color to RGB (ColorSelect) +sub SetColor(r,g,b) + colorcontrol set "ColorControl", r,g,b + draw flush "ColorSelectRect" + draw set "highcolor", r,g,b, "ColorSelectRect" + draw rect 0,0 to 60,60, "ColorSelectRect" + return +end sub + +// beautify the code by reformating it +sub ReformatSource$(code$) + local tablevel, num, i, j, k + local tmp$, returnSource$ + local hasThen, isInTicks, firstcase + + dim beginCommand$(12) + dim endCommand$(15) + + beginCommand$(1) = "if" + beginCommand$(2) = "switch" + beginCommand$(3) = "for" + beginCommand$(4) = "while" + beginCommand$(5) = "do" + beginCommand$(6) = "repeat" + beginCommand$(7) = "case" + beginCommand$(8) = "default" + beginCommand$(9) = "else" + beginCommand$(10) = "elsif" + beginCommand$(11) = "sub" + beginCommand$(12) = "export" + + endCommand$(1) = "end if" + endCommand$(2) = "end-if" + endCommand$(3) = "endif" + endCommand$(4) = "fi" + endCommand$(5) = "end switch" + endCommand$(6) = "end-switch" + endCommand$(7) = "next" + endCommand$(8) = "wend" + endCommand$(9) = "loop" + endCommand$(10) = "until" + endCommand$(11) = "else" + endCommand$(12) = "elsif" + endCommand$(13) = "end sub" + endCommand$(14) = "case" + endCommand$(15) = "default" + + dim reformat$(1) + tablevel = 0 + firstcase = 0 + num = split(code$, reformat$(), "\n") + + for i=1 to num + tmp$ = ltrim$(lower$(reformat$(i))) + for j=1 to 15 + if(left$(tmp$, len(endCommand$(j))) = endCommand$(j) and (len(tmp$) = len(endCommand$(j)) or instr(" \n\t\f\v\r(:/", mid$(tmp$,len(endCommand$(j))+1,1)))) then + if(not firstcase) then + if(j = 5 or j = 6) tablevel = tablevel - 1 + tablevel = tablevel - 1 + // if(tablevel<0) tablevel = 0 + endif + firstcase = 0 + break + endif + next j + + for j=1 to tablevel + returnSource$ = returnSource$ + "\t" + next j + + for j=1 to 12 + if(left$(tmp$, len(beginCommand$(j))) = beginCommand$(j) and (len(tmp$) = len(beginCommand$(j)) or instr(" \n\t\f\v\r(:/", mid$(tmp$,len(beginCommand$(j))+1,1)))) then + hasThen = true + if(beginCommand$(j) = "switch") then + firstcase = 1 + elsif(beginCommand$(j) = "if") then + isInTicks = false + hasThen = false + for k=1 to len(tmp$)-3 + if(mid$(tmp$,k,1)="\"" and mid$(tmp$,k-1,1)<>"\\") isInTicks = not isInTicks + if(not isInTicks and mid$(tmp$,k,4) = "then") then + hasThen = true + break + endif + next k + endif + if(hasThen) tablevel = tablevel + 1 + break + endif + next j + returnSource$ = returnSource$ + ltrim$(reformat$(i)) + if(i0 and left$(tmp$,10) <> "/bin/grep ") then + ret = val(mid$(tmp$, t+7+len(programName$), len(tmp$)-t-7-len(programName$))) + endif + + return ret +end sub + +// Send the kill signal to all members of the team of programName$ +// Returns true when successful and false otherwise +sub KillTeam(programName$) + local ps$(1) + local found + local i, n + + n = token(system$("ps "+programName$), ps$(), chr$(10)) + found = false + + while(i<=n) + if(instr(ps$(i), programName$)) then + found = true + i = i + 1 + while(val(ps$(i))>0 and i<=n) + system("kill "+str$(val(ps$(i)))) + i = i + 1 + wend + endif + i = i + 1 + wend + + return found +end sub + +// Load the syntax tree into the given tree box from the TreeFile$ file. +sub SyntaxLoadTree(TreeFile$, TreeBoxID$) + local info, level, handle, inloop + local tmp$ + + + // Clear the treebox first + treebox clear TreeBoxID$ + + // count the number of info texts + info = 0 + // three levels: toplevel, sublevel and info text level + level = 0 + // read data from file return the file handle + handle = open (TreeFile$, "r") + if(not handle) return 0 + + // read the file + inloop = true + while(not eof(handle) and inloop) + tmp$ = GetLine$(handle) + // if it is not a comment... + if(not (left$(tmp$,1) = "&")) then + switch level + case 0 // toplevel + treebox add TreeBoxID$, tmp$ + break + case 1 // sublevel + n = instr(tmp$, ":") + treebox add TreeBoxID$, left$(tmp$,n-1), right$(tmp$, len(tmp$)-n), 0 + break + end switch + else + if(instr(tmp$, "toplevel")) level = 0 + if(instr(tmp$, "sublevel")) level = 1 + if(instr(tmp$, "infotext")) inloop = false + endif + wend + close handle + return 1 +end sub + +// Read the info text for Command$ from TreeFile$ with the index file IndexFile$. +sub SyntaxGetInfoText$(TreeFile$, IndexFile$, Command$) + local handle, position, inloop + local infotext$ + + // first read the seek position + inloop = true + handle = open (IndexFile$, "r") + if(not handle) return "" + + while(not eof(handle) and inloop) + tmp$ = GetLine$(handle) + if(tmp$=Command$) then + if (not eof(handle)) then + tmp$ = GetLine$(handle) + position = val(tmp$) + endif + inloop = false + endif + wend + close handle + + // a seek position is found; return the info text. + handle = open (TreeFile$, "r") + if(not handle) return "" + seek handle, position, "begin" + tmp$ = GetLine$(handle) + inloop = true + while(not eof(handle) and inloop) + tmp$ = GetLine$(handle) + if(left$(tmp$,1) = "&") then + inloop = false + else + infotext$ = infotext$ + tmp$ + chr$(10) + endif + wend + close handle + + return infotext$ +end sub + +// Read a line from a file +sub GetLine$(handle) + local tmp$, retString$ + + while(tmp$<>chr$(10) and tmp$<>chr$(13) and not eof(handle)) + tmp$ = chr$(peek(handle)) + if(tmp$<>chr$(10) and tmp$<>chr$(13)) retString$ = retString$ + tmp$ + wend + + return retString$ +end sub + +// Open ASCII table window +sub AsciiWindow() + local n, x, y + + window open 200,100 to 600,515, "AsciiView", "yab-IDE ASCII table" + window set "AsciiView", "flags", "Not-Zoomable, not-h-resizable, not-v-resizable" + + Header("ASCII table", "AsciiView", 400) + + draw set "highcolor", 239,239,239, "AsciiView" + draw line 6,405 to 395,405, "AsciiView" + draw line 395,51 to 395,405, "AsciiView" + draw set "highcolor", 185,185,185, "AsciiView" + draw line 5,50 to 394,50, "AsciiView" + draw line 5,50 to 5,404, "AsciiView" + draw set "highcolor", 255,255,255, "AsciiView" + draw rect 6,51 to 394,404, "AsciiView" + draw set "highcolor", 0,0,0, "AsciiView" + + x = 10 + y = 65 + for n = 32 TO 126 + draw text x,y, str$(n)+chr$(32)+chr$(n), "AsciiView" + x = x+50 + if x >= 365 then + x = 10 + y = y+30 + end if + next n + + while(not instr(message$, "Quit")) + wend + window close "AsciiView" + return +end sub + +// set the run parameters +sub SetRunParameters() + local tmp$ + local inloop + + window open 200,100 to 500,215, "RunParam", "yab-IDE Set run parameters" + window set "RunParam", "flags", "Not-Zoomable, not-h-resizable, not-v-resizable" + + Header("Set run parameters", "RunParam", 300) + + textcontrol 10,50 to 290,70, "RunParamYab", "yab Parameters:", settingsYabParam$, "RunParam" + textcontrol 10,80 to 290,110, "RunParamProg", "Program Parameters:", settingsProgParam$, "RunParam" + + inloop = true + while(inloop) + if(instr(message$, "Quit")) then + settingsYabParam$ = textcontrol get$ "RunParamYab" + settingsProgParam$ = textcontrol get$ "RunParamProg" + inloop = false + endif + wend + + window close "RunParam" + return +end sub + +// load settings on start-up +sub LoadSettings() + local handle, i, j + local tmp$ + + handle = open(globalConfigDir$+"ide-settings", "r") + if(not handle) return 1 + + while(not eof(handle)) + line input #handle tmp$ + if(left$(tmp$, 1)<>"#") then + i = i + 1 + switch(i) + case 1: settingsYabDir$ = tmp$: break + case 2: globalProjectDir$ = tmp$: break + case 3: yabDir$ = tmp$: break + case 4: ideDir$ = tmp$: break + case 5: buildDir$ = tmp$: break + case 6: globalHelpDir$ = tmp$: break + case 7: settingsLangUse = val(tmp$): break + case 8: settingsLangPath$ = tmp$: break + case 9: settingsAutoIndent = val(tmp$): break + case 10: settingsAutoCompletion = val(tmp$): break + case 11: settingsACNumChar = val(tmp$): break + case 12: settingsX = val(tmp$): break + case 13: settingsY = val(tmp$): break + case 14: settingsWidth = val(tmp$): break + case 15: settingsHeight = val(tmp$): break + case 16: settingsFullScreen = val(tmp$): break + case 17: settingsFullEditor = val(tmp$): break + case 18: settingsVSplitDivider = val(tmp$): break + case 19: settingsV2SplitDivider = val(tmp$): break + case 20: settingsHSplitDivider = val(tmp$): break + case 21: settingsCalcPatternX = val(tmp$): break + case 22: settingsCalcPatternY = val(tmp$): break + case 23: settingsColorSelectX = val(tmp$): break + case 24: settingsColorSelectY = val(tmp$): break + case 25: settingsColorSelectR = val(tmp$): break + case 26: settingsColorSelectG = val(tmp$): break + case 27: settingsColorSelectB = val(tmp$): break + case 28: settingsAskForSaving = val(tmp$): break + case 29: settingsFindCS = val(tmp$): break + case 30: settingsOldSearch$ = tmp$: break + case 31: settingsFindAlert = val(tmp$): break + case 32: settingsReformatAlert = val(tmp$): break + case 33: settingsReformatUndoAlert = val(tmp$): break + case 34: settingsTabSpaces = val(tmp$): break + case 35: break + case 36: settingsFontFamily$ = tmp$: break + case 37: settingsFontStyle$ = tmp$: break + case 38: settingsFontSize = val(tmp$): break + case 39: globalRealFontSize = val(tmp$): break + case 40: DEBUG = val(tmp$): break + case 41: MAXFILES = val(tmp$): break + case 42: settingsYabParam$ = tmp$: break + case 43: settingsProgParam$ = tmp$: break + end switch + endif + wend + close(handle) + + dim globalAllNames$(MAXFILES) + dim globalTextFinder(MAXFILES) + + for j=1 to MAXFILES + globalAllNames$(j) = "" + globalTextFinder(j) = 0 + next j + + if(i = 43) return 0 + return 1 +end sub + +// load last opened files on start-up +sub LoadOpenFiles() + local handle, mainhandle, j, t + local text$, t$ + + mainhandle = open(globalConfigDir$+"ide-openfiles", "r") + if(mainhandle) then + j = 1 + while(not eof(mainhandle) and j<=MAXFILES) + globalAllNames$(j) = GetLine$(mainhandle) + handle = open(globalAllNames$(j), "r") + if(handle) then + WaitWindow(globalAllNames$(j)) + text$ = "" + while(not eof(handle)) + t$ = GetLine$(handle)+"\n" + if(len(t$)*8>4000) textedit set "Text"+str$(j), "textwidth", len(t$)*8+8 + text$ = text$ + t$ + wend + close(handle) + globalCurrentText = j + textedit add "Text"+str$(globalCurrentText), text$ + textedit set "Text"+str$(globalCurrentText), "changed", false + textedit set "Text"+str$(globalCurrentText), "gotoline", ReadLineFromAttr(globalAllNames$(j)) + stackview set "Stack", globalCurrentText + stackview set "Lines", globalCurrentText + t = columnbox count "FileBox" + columnbox add "FileBox", 1, t+1,20, "__Icon__="+ideDir$+"img/gespeichert.png" + columnbox add "FileBox", 2, t+1,20, GetFileName$(globalAllNames$(j)) // "Filename", t, GetFileName$(tmp$) + columnbox select "FileBox", t+1 + globalTextFinder(globalCurrentText) = t+1 + option set "Text"+str$(globalCurrentText), "focus", true + oldScroll = -1 + globalNumOpenFiles = globalNumOpenFiles + 1 + if(globalNumOpenFiles = 1) then + ActivateMenus(true) + splitview set "V2Split", "Divider", settingsV2SplitDivider + endif + window close "WaitWindow" + else + globalAllNames$(j) = "" + endif + j = j + 1 + wend + close(mainhandle) + endif + + return +end sub + +// Export as HTML +sub ExportAsHTML() + local browse$ + + browse$ = filepanel "Save-File", "Export as HTML", globalProjectDir$ + if(browse$<>"") then + + handle = open(browse$, "w") + if(handle) then + print #handle "" + print #handle "" + print #handle " " + print #handle " " + GetFileName$(globalAllNames$(globalCurrentText)) + "" + print #handle " " + print #handle " " + print #handle " " + print #handle " " + print #handle "
"
+        		print #handle textedit get$ "Text"+str$(globalCurrentText);
+			print #handle "    
" + print #handle " " + print #handle "" + close(handle) + else + alert "File could not be saved!", "Ok", "warning" + return false + endif + endif +end sub + +// Save all settings before exiting +sub SaveSettings() + local handle, i + + if(system("test -d "+globalConfigDir$) = 1) then + system("mkdir "+left$(globalConfigDir$, len(globalConfigDir$)-1)) + endif + + handle = open(globalConfigDir$+"ide-settings", "w") + if(handle) then + print #handle "# yab IDE 2.2 config file" + print #handle "# " + print #handle "# Comments start with a # as first character on a line" + print #handle "# Only change this file when you know what you are doing!" + print #handle "# Do not change the order of the lines in this file!" + print #handle "# " + print #handle "# yab directory (ends on /)" + print #handle settingsYabDir$ + print #handle "# Program directory (ends on /)" + print #handle globalProjectDir$ + print #handle "# yab binary location" + print #handle yabDir$ + print #handle "# IDE directory (ends on /)" + print #handle ideDir$ + print #handle "# BuildFactory directory (ends on /)" + print #handle buildDir$ + print #handle "# Help directory (ends on /)" + print #handle globalHelpDir$ + print #handle "# Use localization (0 = false, 1 = true)" + print #handle restartSettingsLangUse + print #handle "# localization mimetype" + print #handle settingsLangPath$ + print #handle "# Auto indent (0 = false, 1 = true)" + print #handle settingsAutoIndent + print #handle "# Auto completion (0 = false, 1 = true)" + print #handle settingsAutoCompletion + print #handle "# Auto completion starts at character count:" + print #handle settingsACNumChar + print #handle "# X-coordinates of main window" + print #handle settingsX + print #handle "# Y-coordinates of main window" + print #handle settingsY + print #handle "# Width of main window" + print #handle settingsWidth + print #handle "# Height of main window" + print #handle settingsHeight + print #handle "# Start in fullscreen (0 = false, 1 = true)" + print #handle settingsFullScreen + print #handle "# Start in maximized editor (0 = false, 1 = true)" + print #handle settingsFullEditor + print #handle "# Position of main vertical divider" + print #handle settingsVSplitDivider + print #handle "# Position of the vertical divider for the line numbers" + print #handle settingsV2SplitDivider + print #handle "# Position of main horizontal divider" + print #handle settingsHSplitDivider + print #handle "# X-coordinate of the pattern editor window" + print #handle settingsCalcPatternX + print #handle "# Y-coordinate of the pattern editor window" + print #handle settingsCalcPatternY + print #handle "# X-coordinate of the color selection window" + print #handle settingsColorSelectX + print #handle "# Y-coordinate of the color selection window" + print #handle settingsColorSelectY + print #handle "# Red value for last selected color in color selection window" + print #handle settingsColorSelectR + print #handle "# Green value for last selected color in color selection window" + print #handle settingsColorSelectG + print #handle "# Blue value for last selected color in color selection window" + print #handle settingsColorSelectB + print #handle "# Ask for saving before running a program (0 = false, 1 = true)" + print #handle settingsAskForSaving + print #handle "# Is \"find\" case sensitive? (0 = false, 1 = true)" + print #handle settingsFindCS + print #handle "# Last search string" + print #handle settingsOldSearch$ + print #handle "# Show warning before applying Replace All (0 = false, 1 = true)" + print #handle settingsFindAlert + print #handle "# Show warning when reformating sourcecode did not close all loops and conditions (0 = false, 1 = true)" + print #handle settingsReformatAlert + print #handle "# Show warning before undo reformating (0 = false, 1 = true)" + print #handle settingsReformatUndoAlert + print #handle "# Number of spaces per tab" + print #handle settingsTabSpaces + print #handle "# Unused field (was: use Haiku tabs on ZETA)." + print #handle 0 + print #handle "# Font family name" + print #handle settingsFontFamily$ + print #handle "# Font style" + print #handle settingsFontStyle$ + print #handle "# Font size" + print #handle settingsFontSize + print #handle "# Real font size" + print #handle globalRealFontSize + print #handle "# Print out IDE debug information (0 = false, 1 = true)" + print #handle DEBUG + print #handle "# Maximum number of files the IDE can handle" + print #handle MAXFILES + print #handle "# yab runtime parameters (default is empty)" + print #handle settingsYabParam$ + print #handle "# Program runtime parameters (default is empty)" + print #handle settingsProgParam$ + + close(handle) + endif + + handle = open(globalConfigDir$+"ide-openfiles", "w") + if(handle) then + for i=1 to MAXFILES + if(globalAllNames$(i)<>"") print #handle globalAllNames$(i) + next i + close(handle) + endif + return +end sub + +sub path() +if (!peek("isbound")) then +path$=system$("ps") +x=instr(path$,"/yab-IDE.yab") +path$=left$(path$,x) +for x=len(path$)-1 to 1 step -1 + if (instr(path$," ",x) and catch=0) catch=x+1 +next +path$=right$(path$,len(path$)-catch) +path$=trim$(path$) +path$="/"+path$ +else +path$=trim$(peek$("directory") ) +path$=path$+"/" +end if + +end sub + + +sub yabpath$() + +if system("test -e /boot/home/config/non-packaged/bin/yab") = 0 then + return "/boot/home/config/non-packaged/bin/yab" +elseif system("test -e /boot/home/config/bin/yab") = 0 then + return "/boot/home/config/bin/yab" +elseif system("test -e /boot/system/bin/yab") = 0 then + return "/boot/system/bin/yab" + +endif + +local cmd$ +cmd$="test -e "+settingsYabDir$ +if system(cmd$)=0 then + return settingsYabDir$ +endif + +return "error" +end sub + +sub set_up_BuildFactory() +local DataDir$ + +local handel +local ddir$ + +DataDir$=trim$(system$("finddir B_USER_DIRECTORY")) + + + + +x=system("mkdir "+DataDir$+"/yab_work") +system("mkdir ~/config/settings/yab") +y=system("ls "+DataDir$+"/yab_work/BuildFactory") +y=y+system("ls "+DataDir$+"/yab_work/Programs") +if x=0 or y>0 then + system("cp -ur "+ideDir$+"/BuildFactory "+DataDir$+"/yab_work") + system("cp -ur "+ideDir$+"Programs "+DataDir$+"/yab_work") + system ("cp -ur "+ideDir$+"img "+DataDir$+"/yab_work/Programs") + system("cp -ur "+ideDir$+"Programs/libs/* /boot/home/config/settings/yab") + + + handle=open(DataDir$+"/yab_work/BuildFactory/srcfiles","r") + + + while(not eof(#handle)) + input #handle a$ + system("cp -u "+ideDir$+"/src/"+a$+" "+DataDir$+"/yab_work/BuildFactory/"+a$) + end while + close handle + + system("cp -ur "+ideDir$+"/src/column "+DataDir$+"/yab_work/BuildFactory") +end if + +x=1 +open #1, ideDir$+"/src/YabMain.cpp","r" +open #2, DataDir$+"/yab_work/BuildFactory/parts/YabMain.cpp.end","w" + +while(not eof(#1)) + line input #1 a$ + if x>9 then + print #2 a$ + end if + x=x+1 +wend +close #1 +close #2 + +end sub + + + + +sub changestring() + +TextLine$ = TEXTEDIT GET$"Text"+str$(globalCurrentText), searchLineNum +TextLine$=rtrim$(TextLine$ ) +FindPart$=textcontrol get$ "FindTCFind" +FindPart$=trim$(FindPart$) +if(settingsFindCS) then + x=instr(TextLine$, FindPart$) +else + x=instr(upper$(TextLine$), upper$(FindPart$)) + +endif +if x>0 then + x=x-1 + TextPart$= textcontrol get$ "FindTCReplace" + TextPart$=rtrim$(TextPart$) + TextLine$=left$(TextLine$,x)+TextPart$+right$(TextLine$,len(TextLine$)-(x+(len(FindPart$)))) + TEXTEDIT SET "Text"+str$(globalCurrentText), "select", searchLineNum + TEXTEDIT SET "Text"+str$(globalCurrentText), "cut" + TEXTEDIT SET "Text"+str$(globalCurrentText), "select", searchLineNum + TEXTEDIT ADD "Text"+str$(globalCurrentText), TextLine$ + TEXTEDIT SET "Text"+str$(globalCurrentText), "gotoline", searchLineNum + searchLineNum = textedit get "Text"+str$(globalCurrentText), "Find", TextPart$ + +endif + +end sub