Cocoa, Apple and PureBasic

PureBasic on Apple computers is now a long history but was not always a love story. Back in october 2005, the first version of PureBasic for OS X was released. We spent almost a year to write the PowerPC support for the compiler, which was a real challenge. Believe it or not, 4 months later, the first x86 mac was out with Apple touting all the benefits of the new new x86 processors and letting down the good old PowerPC. That’s was quite a shock for us and it was obvious than all the hard work put in the PowerPC version was lost, as no major mainstream OS run on these processors. So far so good, as x86 was already support on Windows and Linux version of PureBasic, we thought it would be a peace a cake to support OS X. Not really. It was a nightmare to make it work, as Apple forced all API call to have the x86 stack 16 bytes aligned ! PureBasic indeed wasn’t designed for such stack alignment on function calls, as Windows and Linux don’t need such strict rules (btw, it was never mentioned in the Intel doc as well). So we overhauled all the calling code in the compiler to add exception when calling a function or procedure in PureBasic OS X x86. It definitely took some time, as the first public version to support it was released in http://www.purebasic.com/news55.php”>december 2008 (granted, we did some other thing in between but it gives an idea).

But that’s not the end of the story. When we started the port of PureBasic on OS X in 2003, we decided to use the Carbon framework as it was the advised framework for C programmer. All PureBasic functions are done in C on other platforms so it was the right choice at the time. Doing all the GUI commands (Window, Gadget, Menu, ToolBar, StatusBar, 2DDrawing, Drag’n’Drop etc.) for Carbon requiered a lot of efforts, as these libraries are big and fully featured. The Carbon API isn’t very well designed, old school, and morever plagged with redraw and clipping bugs. We added tons of fix only to have something almost working. But if you look in the PureBasic bug forums for OS X, you will find a lot of small remaining issues. Ok, it wasn’t perfect and hard to achieve, but it was working. And Apple ditched it once again. In 2007, Apple announced than the Carbon based application won’t be supported in 64 bit mode. Adobe, Microsoft and several other major companies complained about this fact but the decision was made and here again we knew we would one day rewrite the whole PureBasic command set using the Cocoa alternative. We don’t have that many user on OS X, as it still have nowaday a small user base compared to Windows, but the work put to support OS X outweigh the other OS by a great factor. That’s interesting to understand how companies handle their user base. Apple, which both do hardware and software always push the software forward quickly, and deprecate its hardware in the same time. You want the new OS ? Buy a new mac. The developers are advised to follow as well, and if they don’t want to, that’s not Apple problem. Microsoft on the other side don’t do hardware, so they want their OS to run on any possible PC. Very old PC can still run Windows 7, granted you get enough memory. Microsoft takes care of their developers and of backward compatibility. Here is a small quote from Joel’s blog which resumes the thing:

I first heard about this from one of the developers of the hit game SimCity, who told me that there was a critical bug in his application: it used memory right after freeing it, a major no-no that happened to work OK on DOS but would not work under Windows where memory that is freed is likely to be snatched up by another running application right away. The testers on the Windows team were going through various popular applications, testing them to make sure they worked OK, but SimCity kept crashing. They reported this to the Windows developers, who disassembled SimCity, stepped through it in a debugger, found the bug, and added special code that checked if SimCity was running, and if it did, ran the memory allocator in a special mode in which you could still use memory after freeing it.

Microsoft don’t deprecate an API, they still support it, side by side with the new one. That’s more work for them, but million of developers don’t have to rewrite they code from scratch at every major Windows version. And more important, binary executable still work, without a change. That’s two way of handling progress, and none are really bad. Indeed from the PureBasic point of view, we prefer to focus on new features than rewriting our working toolkit in another technology.

That said, we do care about our community and we promized a Cocoa support for OS X some time (years) ago. As Apple is pushing even more with the MacOS X AppStore which will soon banish Carbon applications, it was the right time to dive into Objective-C and the new framework. Timo (Fr34k) did the base framework for the Gadget and Window library in Cocoa and run prelimary test between regular C libraries and Objective-C one. The results were concluding, and I take back his work and continued it. After one full week and half on the Cocoa framework, I have to admit that’s it’s much superior to Carbon, and I would like to share this experience with you. Once you get used to the very strange bracket based Objective-C syntax, you can achieve the same work in much less coding lines:

ScrollAreaGadget
Carbon: 487 lines
Cocoa: 163 lines

SpinGadget
Carbon: 379 lines
Cocoa: 254 lines

ButtonImageGadget
Carbon: 290 lines
Cocoa: 110 lines

We got similar result in other gadget files. Ok, but the Carbon API is known to be verbose due to callback and old design. How does it compare with other OS ?

ScrollAreaGadget
Cocoa: 163 lines
GTK: 323 lines
Win32: 570 lines

SpinGadget
Cocoa: 254 lines
GTK: 487 lines
Win32: 331 lines

ButtonImageGadget
Cocoa: 110 lines
GTK: 284 lines
Win32: 480 lines

All in all, Cocoa wins hands down. Why is that ? To be honest, Win32/GTK PureBasic implementation are for now more mature and tested, so it includes many little fix here and here. That said, Cocoa is a modern API compared to Win32 and GTK, and is object oriented, which means you can chain the calls. For example:

[[[NSTabView alloc] initWithFrame:NSMakeRect(x, y, Width, Height)] autorelease]

In traditional C, you will have 3 lines:

alloc()
initWithFrame()
setAuroRelease()

Which brings us to another nice feature: the autorelease pool. Objective-C use reference counting to automatically free the objects when no-one is using it. So you don’t have to track every free, and in the end it does save some code.

Ok, that’s all for now, Cocoa is on the track and we are making great progress. That means than the next major release of PureBasic will probably brings it as default toolkit and, as a bonus, introduce 64 bit support !

Back in business !

As you probably have noticed, the pace of PureBasic development has slowed down these last months due to full time job for Timo and myself. I’m very aware of the situation and I decided to get back at fulltime on PureBasic early in april ! As always after taking some distance from a project, we have many new ideas to tests and implement and I’m quite excited to get back on core development. We will probably ship one or two bug fix versions and then a new major with a priority for the 64 bit Cocoaified OS X version (which is already running here, but not yet finished/tested). After that, may be some big surprises 😉

Have fun !

PureBasic development

Some questions raised on the forums about the current pace of PureBasic development. The update are less frequent and some users are wondering if it’s not the end of PureBasic. No, it’s definitively not. We want to explain here, why it took longer than usual to release a new version (we had a very fast release cycle for this kind of software): first the current version to release, 4.60, is a big one: it has a lot of new commands, especially on the 3D side, and all these commands needs to have a proper documentation. And I write this documentation. You guess it, it’s boring, and i’m not really enjoying that part. Now, that’s not an excuse to have 2 months between two beta version right ? It should have something else. And you are right. We have since the beginning of the year a daily job, which means less time for PureBasic. We have nothing to hide here. Like most of you, we need to have a real job for a living. And it’s not the first time it happens: during the 10 years of PureBasic development, I have worked 5 years on a daily job, without big impact on PureBasic. So no need to panic, PureBasic is here and will continue to grow. We are also confident that its now a mature and very capable product. To finish on the ‘PureBasic end’ things: if we decide to stop PureBasic (which is very unlikely), we will release it to the community, either in Open Source form, or to a small group which could take over the development.

Some asked for our future plans. Here we go: we plan to release the 4.60 version early on september and a 4.61 bug fix version somewhen in november. In between, we will continue to work on the new features for the next version, we have quite some projet to make it better. So stay tuned !

PureBasic 4.60 Beta1 released!

Its been quiet around here for a while, but now there is big news: The first public beta of the upcoming 4.60 release is out!

This release is mostly about the 3D side of things, but there are new features for application programmers as well. The OGRE engine was updated to version 1.7.0 and we switched the physics engine from ODE to Bullet. Furthermore, there are a ton of new 3D libraries and commands. You can see the full list below. The 3D commands are not documented yet, but we will put up some examples to demonstrate them.

A special thanks to G-Rom and TMyke from the french forum for their help on the new 3D commands!

On the application side of things, the most notable addition is the CanvasGadget() command. It is a simple drawing surface that provides detailed mouse and keyboard events to easily implement custom data views or controls (all cross-platform of course). You can see this new gadget in action in the IDE already: The new file panel and the new color picker tool both make use of it. Other than that, there are some smaller new commands like additions to the LinkedList library for example. All new non-3D commands are already documented in the manual.

The IDE got some additions as well, like the ability to build projects directly from the command-line, or the option to be warned when a file is changed on disk while open in the IDE. Unfortunately, the automation framework that I talked about here on the forum did not make it into this release. It wasn’t finished in time, and its not a big enough priority to justify delaying this release any longer.

Finally, we are in the process of changing the PureBasic documentation to be more precise and readable when it comes to function parameters and return values. This is still a work in progress which should be finished for the final release. Comments on the new structure are welcome.

These are the changes:

Libraries:
– added CanvasGadget(), CanvasOutput()
– added SetGadgetItemData() for PanelGadget
– added MoveElement(), MergeLists(), SplitList() commands
– added RandomizeList(), RandomizeArray()
– added PushListPosition(), PopListPosition(), PushMapPosition(), PopMapPosition()
– added ImageID parameter to OpenSubMenu()
– added #PB_ListIcon_ThreeState and #PB_ListIcon_Inbetween
– added #PB_Tree_ThreeState and #PB_Tree_Inbetween
– added crossplatform ComboBox events
– added ‘Joint’ library
– added ‘SpecialEffect’ library
– added ‘StaticGeometry’ library
– added CameraPitch(), CameraRoll(), CameraYaw(), SwitchCamera()
– added ApplyEntityForce(), ApplyEntityImpulse(), EntityPitch(), EntityRoll(), EntityYaw(), GetEntityAttribute(),
GetEntityMaterial(), SetEntityAttribute(), SetEntityMaterial()
– added LightDiffuseColor(), SpotLightRange(), LightLookAt(), LightPower(), DisableLightShadows()
– added MaterialDepthWrite(), MaterialSelfIlluminationColor(), MaterialShininess(), GetScriptMaterial()
– added BuildMeshShadowVolume(), CreateLine3D(), CreateCube(), CreateSphere(), CreateCylinder(), CreatePlane(), AddSubMesh()
MeshVertexCount(), UpdateMeshBoundingBox(), MeshRadius(), AddMeshVertex(), MeshVertexNormal(), MeshVertexColor()
MeshVertexTextureCoordinate(), AddMeshFace(), FinishMesh(), NormalizeMesh(), SaveMesh(), SetMeshMaterial(), SubMeshCount()
TransformMesh()
– added NodePitch(), NodeRoll(), NodeYaw()

– changed FindString() ‘StartPosition’ parameter to be optional
– changed WebGadget to use WebKitGtk on Linux
– changed ContainerGadget with #PB_Container_Borderless to no longer add a 2px invisible border on Linux
– changed EntityPhysicBody(), CreateLight(), RenderWorld(), ShowGUI, WorldShadows()

– removed: Get/SetEntityMass(), Get/SetEntityFriction()
– removed: SetMeshData() (temporary, needs to be updated)

IDE:
– added IDE options for commandline project building
– added monitoring of files for changes on disk while they are open in the IDE
– added FilePanel custom implementation with Drag & Drop, Dropdown menu, scrolling also on OSX
– added Diff tool for directories/files
– added Html help viewer for Linux/OSX
– added Help viewer in toolspanel
– new Color Picker tool
– enabled font selection in IDE for OSX
– ProjectPanel now remembers node expanded states

Debugger:
– added maximize button to all debugger windows
– added all IsXxx() and XxxID() functions to the expression parser (for data breakpoints)

Manual:
– The manual is being updated to a new format which more clearly describes
individual function parameters and return values. This is not yet complete,
but will be finished for the final release.

Visit the announcement on the PureBasic forums here.

Coding standards

I’m currently working on a C++ project and the coding standard problem raised again. And again, nobody in the team agree about the style/naming format to adapt. C++ sounds somewhat cursed on this topic. After so much years of existence, no precise coding rules has emerged and everyone is almost authorized to code as he wants to, making the whole project source code quite very heterogeneous and obviously hard to maintain. Java has a clean coding rules and almost everybody is following it without arguing. C# seems to have also a common coding standard, but it doesn’t seems to be that followed. That could be my very small experience in C#, I stand to be corrected. Back to C++. You may think: ‘what a big deal, just pick some rules and stick to it’. That’s the ultimate goal, thanks for your input ! But then, you have to please everyone habit and it’s not that easy. So you’re going to compromize on many thing and at the end, nobody is really happy with the result.

But wait, it’s a PureBasic blog, no ? That’s right and I wondered if we needed strict PureBasic coding standard, but after some thoughts it doesn’t seem to be needed and i will explain why:

– PureBasic comes with a big command set, which implicitly set the the name rules for the function/procedure naming: CamelCase. One down. In C++ you have to choose how to name your functions, your methods and your class. Candidate are numberous: myMethod(), MyMethod(), my_method(), mymethod() and so on.

– The constants are prefixed by a ‘#’ in PB, so it can’t clash with variables or anything else. PureBasic comes with a lot of predefined constants, all in CamelCase as well, setting a de facto standard. Again in C++ you have many way to name them: MyConstant, MY_CONSTANT, kMyConstant etc.

– PureBasic help and demo examples are very consistent and always share the same syntax rules which helps to guide the newcomers to format the code the same way.

– There is no “{}” in PureBasic, so the flamewar between K&R and GNU style is avoided, thanks !

When looking at the code snippet pasted on the forums.purebasic.com, I feel there is a common style and it’s very cool to see that. It doesn’t take long to get a grip on someone else code, and that’s a very important part of a programming tool.

Merry Christmas !

Turning ten !

If you take a quick look to the history page on www.purebasic.com, you will see this:

PureBasic 1.60 (AmigaOS) (09/09/2000)

9 september 2000. Seriously. So PureBasic is officially haunting the web since 10 years, which is kind of amazing, for different reasons. Let’s try to step back, catch a time machine, and see what and how it happened.

I got the chance to have a computer very young, at twelve. It was an amstrad CPC 6128, with a very low resolution but colored screen and strange disk format. My main attract was games, games and games. I spent countless hours playing many games (Barbarian anyone ?!). On a side note, in the book sold with the computer, there were some listings to type yourself a game using the build-in BASIC (an old school one, without procedure or even label, so you have to specify the line number to jump at when using GOTO or GOSUB). Out of curiousity, i tried to make it work. It was a ‘dart’ game, and it took forever to type back the printed listing to the computer. The result was rather disappointing, and the game was pretty bad.

A few years later, a friend got an Amiga 500 and when i looked at the games running on it, it was just unbelievable. The graphics and the sounds were way above anything else, and the games availables were just stunning. After a lot of negotiations, my brother and I get the precious, and a brand new Amiga 500+ hit our desk ! We used it a lot as an advanced gaming console, and had a lot of fun. Then the number of games released on the platform decreased to almost zero very quickly due to Commodore bankruptcy, and then my main point of interest changed.

I started programming somewhen in 1994. At first, it was some small tools programmed in, guess it, Basic. When the PureBasic project started, early in 1998, it was a quick attempt to support new PowerPC processors freshly available on the Amiga in a Basic language, with a syntax based on BlitzBasic which was discontinued. It was very small, with few features and very tied to the AmigaOS. It got about 200 build-in commands, an ‘IDE’ which was mostly only a text editing area and a ‘Compile/Run’ menu and a rudimentary runtime debugger. The whole commands were programmed in 680×0 asssembly code, which was the rules on the Amiga to have optimized code. And as the AmigaOS didn’t have memory protection, better check your code twice before running it, especially when dealing with pointers, or it will immediately reboot ! So far i got some positive comments from the internet community (yes, we had internet in 1998, even if it wasn’t fast) about PureBasic and the choice was made to do a Windows and Linux version as soon as possible. I was studing computer science and learned the C programming language, so it was a good time to recode everything in a ‘portable’ way. I didn’t knew so much about real world programming and i made a lot of mistake when porting it in C, and hopefully learned quite a bit from it.

Late in 2000, we publicly released the first Windows version and it was a real achievement, for me and for the future of PureBasic. The real deal started here, as the Windows audience was way larger than the AmigaOS one. We got a lot of feedback (compared to what i expected) and it was a great source of motivation. André jumped into the boat and since then handle the german part of PureBasic. The plan was to add as much as commands as possible to reach the critical mass which could attract users and let them do a complete software without hassle. The releases iteration was much faster than what it is now, because the shipped code was lower quality and we didn’t do synchronized releases between platforms. The development of the different versions on linux, windows and amigaos was very time consuming, as the build was not unified and nothing was virtualized. On Windows, all the libraries were coded in x86 assembly, which was obviously a wrong choice: much longer/harder to develop, not significant size/speed gain most of the time and more important not portable on x64. Timo joined the team and helped a lot to refactor the libs and the build structure.

Then we added quite a number of features, dealing with a lot of API and we reached in 2006 another important mark in PureBasic history: the 4.00 release.  I think than the project took a professional turn at this point. It took 6 years to reach it but then we had some interesting features:

– Flexible commandset, with more than 900 build in commands
– Support for the 3 major operating system (Windows, Linux, OS X), with an high compatibility level
– Buildin unicode & thread support
– Full featured, modern IDE
– Robust debugger, which comes in 3 flavours (console, standalone GUI and IDE integrated)

Four years later, we are at 4.51, which is a general refinement of 4.00. More commands, more stability, more fun. Internally, we have enhanced many things, making our development easier, faster and more robust. Time flies, but it’s great to see what have been achieved. We have very high expectations for the future, there is so much things left to do !

So far, thank you to all the PureBasic folks which are actually using it and make all this possible. See you in 10 years…

API Programming: What’s behind the PB GUI objects

For Windows, this question is quickly answered: HWND. Pretty much everything is of this basic “window”-type and most API commands that deal with windows can be used on most GUI objects. You can also find many code examples on the forums that deal with a lot of common API tasks. The situation is different for Linux and OSX. Here, different Gadgets may have different underlying objects and so it is not entirely clear what functions can be used. There are also a lot less examples around for these systems. Of course when developing programs that run on multiple OS, you will need solutions for all of them.

To help this situation a bit, i have compiled a list of what are the underlying objects behind the PB gadgets and other GUI objects. You can get access to these using functions such as GadgetID(), WindowID(), etc.

Disclaimer:

This information is internal stuff. While many of these things haven’t changed in many years, it is still possible that we decide to change something in the future. Also some Gadgets are heavily modified for PB with custom subclasses or callbacks which also may change in the future and break your code. So as usual: Feel free to use this information, but if it breaks, its not our problem.

So here it goes:
Windows Linux OSX
WindowID() HWND GtkWindow WindowRef
MenuID() HMENU GtkMenuBar / GtkMenu MenuRef
StatusBarID() HWND GtkHBox ControlRef (UserPane)
ToolBarID() HWND GtkToolbar HIToolbarRef
FontID() HFONT PangoFontDescription PB internal pointer
ImageID() HBITMAP GdkPixbuf CGImageRef
GadgetID() HWND GtkWidget ControlRef
ButtonGadget “Button” GtkButton / GtkToggleButton PushButton / BevelButton
ButtonImageGadget “Button” GtkButton / GtkToggleButton PushButton / BevekButton
CalendarGadget “SysMonthCal32” GtkCalendar HIView
CheckBoxGadget “Button” GtkCheckButton CheckBox
ComboBoxGadget “ComboBox” / WC_COMBOBOXEX GtkComboBox / GtkComboBoxEntry PopupButton / HIComboBox
ContainerGadget custom class GtkFixed UserPane
DateGadget DATETIMEPICK_CLASS GtkEntry UserPane
EditorGadget RICHEDIT_CLASS GtkTextView UserPane (rendering a TNXObject)
ExplorerComboGadget WC_COMBOBOXEX GekComboBoxEntry HIComboBox
ExplorerListGadget WC_LISTVIEW GtkTreeView DataBrowser
ExplorerTreeGadget WC_TREEVIEW GtkTreeView DataBrowser
Frame3DGadget “Button” / “Static” GtkFrame GroupBox / UserPane / Separator
HyperLinkGadget “Static” GtkButton UserPane
IPAddressGadget WC_IPADDRESS GtkEntry EditUnicodeText
ImageGadget “Static” GtkImage UserPane
ListIconGadget WC_LISTVIEW GtkTreeView DataBrowser
ListIconGadget “ListBox” GtkTreeView DataBrowser
MDIGadget “MDICLIENT”
OptionGadget “Button” GtkRadioButton RadioButton
PanelGadget “SysTabControl32” GtkNotebook Tabs
ProgressBarGadget PROGRESS_CLASS GtkProgressBar ProgressBar
ScrollAreaGadget custom class GtkScrolledWindow UserPane
ScrollBarGadget “SCROLLBAR” GtkVScrollBar / GtkHScrollBar ScrollBar
ShortcutGadget HOTKEY_CLASS GtkEntry EditUnicodeText
SpinGadget UPDOWN_CLASS + “Edit” GtkHBox containing others UserPane containing others
SplitterGadget custom class GtkVPaned / GtkHPaned UserPane
StringGadget “Edit” GtkEntry EditUnicodeText
TextGadget “Static” GtkLabel StaticText
TrackBarGadget TRACKBAR_CLASS GtkVScale / GtkHScale Slider
TreeGadget WC_TREEVIEW GtkTreeView DataBrowser
WebGadget custom class + ActiveX control GtkMozEmbed HIWebView
Notes:
  • Gadgets all have the same basic type noted in the GadgetID() row. However, Gadgets are devided into “window classes” on Windows, or subclasses of the general GtkWidget on Linux.
  • For Gadgets on Windows: If the entry is noted in “” then this is the class name, if it is not then this is the symbolic constant for the class name. You’ll have to look up the text value in the appropriate header files.
  • On OSX, there are no classes for the controls, its all a ControlRef. The names i noted here are derived from the control creation functions (ie CreateTabsControl()). If you are looking for information, you should start there.
  • Gadgets may have multiple classes depending on the flags on creation.
  • On Linux, many gadgets are placed inside their own container to add a frame or catch events. (GtkFrame, GtkEventBox). The GadgetID() command returns the real gadget in this case, not the container.
  • On OSX, the UserPane controls are drawn by PB itself, so you don’t have much ways to modify them other than the PB commands.

Thats it. I hope this information is useful to some people, and hopefully we will see some more cross-platform API examples on the forum in the future 🙂

How we make decisions

Since we are on the issue of bug reports (see last post), here is how we made the decision to put “[Done]” in the title of fixed bugreports:

[12:32] <fr34k> this is the point were a bugtracker would be more helpful. there we could filter all solved bugs easily :)
[12:35] <AlphaSND> we already talked about that
[12:35] <AlphaSND> btw, we could change the title of the topic with [Fixed] in it, no ?
[12:35] <fr34k> true
[12:36] <AlphaSND> ok, let's do that starting from now
[12:36] <fr34k> thats a good idea actually, as often people keep posting after the "fixed", so it is no longer obvious from the last post
[12:37] <fr34k> what do we do with stuff that we determine not to fix? (not a bug, not solvable)
[12:37] <fr34k> should be marked as well
[12:37] <AlphaSND> yes
[12:37] <AlphaSND> we could put [Issue] -
[12:37] <fr34k> issue ?
[12:37] <AlphaSND> and move that in Coding Question
[12:38] <AlphaSND> Issue :p
[12:38] <AlphaSND> or [Feature] -
[12:38] <fr34k> lets just put [done] ... its shorter than [fixed] anyway :D
[12:38] <AlphaSND> [Done]
[12:38] <AlphaSND> ok
[12:39] <fr34k> [done] :p
[12:39] <AlphaSND> [Done] Damit !
[12:39] <AlphaSND> :p
[12:39] <fr34k> why ?
[12:40] <AlphaSND> because
[12:40] <fr34k> lets do it differently, so we see who fixed it :D
[12:40] <AlphaSND> man, let's be consistent :p
[12:40] <fr34k> berikco has to write [donE] :D
[12:40] <AlphaSND> :D
[12:40] <fr34k> i noticed, you also always write "Fixed" in the posts, i write "fixed."
[12:41] <fr34k> its not the beginning of a sentence, so there is no reason to write it capital. and its one more key to press damit :p
[12:42] <AlphaSND> It's a full sentence !
[12:42] <AlphaSND> Fixed.
[12:42] <AlphaSND> Uppercase, verb and dot
[12:42] <AlphaSND> :p
[12:43] <fr34k> lol, where have you been when grammar has been tought at school? :D
[12:43] <fr34k> coding probably
[12:43] <AlphaSND> :)
[12:44] <fr34k> now what? :)
[12:44] <AlphaSND> now what what ?
[12:44] <fr34k> i just fixed a bug, what do i write ?
[12:44] <fr34k> the rebell in me wants to write [done] :D
[12:45] <AlphaSND> [Done] -
[12:45] <AlphaSND> i'm the older here :p
[12:45] <fr34k> lol
[12:46] <fr34k> why the " - " btw ? 3 more keys!
[12:46] <AlphaSND> mannnnn !
[12:46] <AlphaSND> to differentiate of the original topic :)
[12:47] <fr34k> hey, i am just trying to optimze here
[12:47] <fr34k> "[Done] - 4.10 and 4.20 Beta 2 - Odd bug"
[12:47] <fr34k> "[done] 4.10 and 4.20 Beta 2 - Odd bug"
[12:47] <fr34k> so much better
[12:47] <AlphaSND> if you fix the bug faster than typing 2 two keys, ok
[12:47] <AlphaSND> the first one is indeed much more sexy ;)
[12:48] <fr34k> compromize: either the D or the "-" has to go ;)
[12:49] <AlphaSND> man, you're damn cra
[12:49] <AlphaSND> zy
[12:49] <fr34k> oh well, i have to go, food time. we'll continue this! :)
[12:49] <AlphaSND> let's remove the - then
[12:49] <fr34k> ha, success :D
[12:49] <AlphaSND> and eidt the 3 i did
[12:49] <fr34k> ok
[13:00] <AlphaSND> http://www.purebasic.fr/english/viewtopic.php?t=30825
[13:00] <AlphaSND> could you look at it, i can't find what's wrong with it
[13:21] <fr34k> re
[13:28] <fr34k> the mdi one is "[donE]" :D
[13:29] <AlphaSND> mouarf :)

In the end, i am glad we dropped the ” – “, because i am already having a hard enough time putting the “[Done]” in some of the bugreport titles. People use too descriptive titles in the bug forum it seems. Anyway, we are usually very much on the same page when it comes to the direction that PureBasic should take so big discussions are quite rare. But if we disagree, it gets tough! 😀

A Bug’s Life

Ok, its a cheesy title but it fits. I was asked to write about the process with which we handle bugs. The following is roughly how i handle this. I can’t speak for Fred but i don’t think the approaches are too different. This post is also intended as a guide on how to write effective bug reports about PureBasic, as the report can make a big difference here.

Each bug starts its life when it is posted in the bug reports section. If you want your bug report to be seen, write it in the (english) forums.  People sometimes try to tell me about bugs when they meet me on IRC, but this is a very bad idea. If i am unable to address the issue immediately the report will be buried in the log files and most likely forgotten. I am usually busy while i am on IRC so the chance to get something fixed immediately is very slim. Post it on the forum and it won’t be forgotten. Then we can discuss further details on IRC if you happen to catch me. The english forums is where i manage the bug reports. Anything reported somewhere else (IRC, email, german forums) starts at a huge disadvantage.

The first stage after a bug is posted could be called the “initial viability test”. I read every bug report that is posted the next time i visit the forums. I am not on the forum to specifically fix bugs at this point though so this is just a quick check. The relatively obvious non-bugs get filtered here. For example when the behavior is intentional or somebody confused a feature request with a bug. There are also a number of things that people often think are wrong where it is really just a lack of understanding (every few months somebody thinks GetCurrentDirectory() is wrong for example).

At this point i also run any provided example code if possible (if i have a copy of PureBasic in reach). This is why providing an example code to show the bug is very important even if it is just 5 lines of code and you think it should be plainly obvious. Its not that i am lazy. Remember that in this first stage i am not concentrating on fixing bugs. I am just browsing the forum in the lunch break for example. I am not going to write any test code at this stage, however if i just have to fire up the IDE and run it then i usually do that. When a bug can be reproduced at this stage, it starts its life with a big head start compared to the other reports because once i actually get around to fixing bugs i tend to start with these as i already have a place to start looking.

I usually do not comment the bug report at this point (unless it falls in one of the non-bug categories above) so if you post a report and do not hear anything for a while don’t be alarmed. I did read it and it will not be forgotten. Sometimes it takes very long for a bug to get actually fixed, sometimes it is done really fast. This varies a lot as do the reason for why some bugs take longer to fix. Sometimes we just don’t have a solution. Sometimes the solution would require a larger redesign of a library and is therefore postponed to when other planned changes to that library will be implemented. Sometimes the required work just outweighs the usefulness of the bugfix. In the later category i tend to give priority to bugs that cannot be easily worked around by the user. If a bug can be easily worked around with a few lines of code (but may be would be much more work to fix internally) then it may take longer than others. There is really no general rule here.

This brings me to the issue of “bumping” bug reports. Our usual response is “don’t bump” and sometimes it sounds a bit angry which some people might not understand so i will explain it a bit. To me bumping comes across as a bit rude and i am often very annoyed by it (hence the response). Its like saying “stop working on other stuff and fix my specific problem”. I can understand that a certain bugreport may be important to you and the lack of feedback from our side can be frustrating at times. But try to see the whole thing from my point of view: I am confronted with a large list of bugreports (from multiple OS) and i am trying to get them fixed as best as i can. My time is limited and i can only work on one thing at a time. It may be that i just spent a lot of time trying to fix one or more other bugs and then a comment like “still not fixed” or simply “bump” on a bugreport is just frustrating. I am well aware of the status of that bug because as i said above, i read everything that is posted in the bugs section. Bottom line: if a bug really is important to you and you think it should get more attention then ask nicely, don’t just bump. Explaining your reasons why it is important to you also helps, because if something is really a showstopper for you i may try to make an extra effort to get it fixed. In any case it gets you much further than just making me angry with a “bump” post, thats for sure.

Ok, back to the life of a PB bug. I do most of my bugfixing in larger batches at once (recently fixed 30 bugs for the OSX version in one weekend). You will notice this by a lot of [Done] appearing in the bugreport section. Sometimes Fred and I even have a kind of race about it to see who can dominate the bugs form (i own the OSX one right now obviously). For this i make a list of what i want to get fixed from the forum, sort it by priority and get to work on it. The method for fixing a bug is always the same, even for the very obvious ones: I first have to see the effects of the bug in action. Even if it is pretty clear from the bug description where the problem is in the actual code, i still have to make sure i can see whatever the problem is myself. This is the only way to really know that i fixed the bug afterwards.

This reproduction-phase is the most important (and often most difficult) one. Once again, if you provided a working code example that i could verify when i first read your report this problem is already solved, which is why i tend to fix such bugs first. If not then here is where the testing begins. You can make this alot easier for me by providing as much information as possible, such as the exact OS you are using. GUI related bugs are very often specific to some OS, or even to a specific set of settings. So include this information in your post.

My development PC runs Vista 64bit, but I also run VMWare and have a lot of different Windows versions set up for testing. The same thing goes for Linux: Linux distributions are so many and released so frequently that I usually cannot keep up with the latest release of the popular distributions. I am not somebody to install updates all the time. I do my development on OpenSUSE 11 right now. However, if you include your exact distribution and version, then i will download that and setup a VM for it in no time for testing (thanks to fast internet and VMWare this is really no big deal). With all this VM testing there is one common thing: If i have to test on a specific OS version, i most likely test in a clean install with just enough stuff installed to run PB. So if you have made any large changes (especially on Linux) from the base install which you might think could have an influence on the problem then please include that information.

The most important thing however in the whole reproduction-phase is to know what i am trying to reproduce. It may be plainly obvious to you what the bug you post about is, but it may not be to me, so always tell us what you think the problem is (don’t just post code). I have to know what i am looking for after all. It may also be that the bug does not appear with my testing configuration at all, so the code alone is no help here. Always include these two things in your report: What do you see when you run the code, and what do you think should happen instead. The clearer the report is the easier it is to work on it.

If i cannot reproduce it, i will post asking for more information or feedback from others. Here it helps if others respond with their results and also their system configuration. This usually helps a lot in figuring out bugs that are OS or configuration specific. I have seen posters who did not want any feedback from other users, probably because they feared that the existence of a workaround for their problem may diminish their chances of getting their problem fixed. It is the opposite actually: It would not be the first time that a posted workaround helped a lot in fixing a bug or implementing a new feature. Although it must be said that the existence of a workaround does not necessarily mean that it is a good idea to do it that way in the PB library. In any case, feedback on bugreports or feature requests is always welcome as long as it adds extra information. A simple “+1” is usually not helpful (except when the question was “can anybody else reproduce this”). A bug generally does not get fixed based on how much people provide feedback, but especially when we have trouble reproducing the problem then more information from others certainly helps.

If everything fails and i simply cannot get the bug to appear on any of my systems then things get tricky. I can do things like build special debug versions of libraries or the IDE so the user can help me track it down, but it involves a lot of back and forth. I try to avoid this if possible, but  from time to time there is just no other way.

When the bug is successfully reproduced, it is time to hunt down the cause and fix it. There is really not much to say about this part. It really depends on the kind of problem at hand. It is usually a back and forth between modifying the PB code that shows the problem and the code of the library in question until the problem is found.

When the problem is finally fixed, i do the same steps/run the same code i used to see the bug in the first place once again to make sure it is gone. Depending on the kind of bug, i may add a routine to our unit tests (which are run by Fred’s build script before every release) to make sure it does not come back. I don’t do that too often though, as most of the times it does not really make sense. For example, a bug in any of the many GUI libraries cannot be automatically tested because they need user interaction. Also, many bugs are quite unique and not very likely to appear again, so unittests are a bit of a waste of time here. Its different for the compiler. Here it is much easier to have work in a different area cause bugs that were once fixed to reappear, so Fred maintains a set of unittests for many compiler features. Anyway, this is the end of the PB bug. Now its the obligatory “fixed.” post (or “Fixed” as Fred would write :)) and that is it. One more bug in the “[Done]”-category.