1Introduction 2============ 3 4In the world of BeOS programming, a "resource" is data that is bundled with your application. 5Typical examples are the application's icons and its signature, but you can attach any data you 6want (bitmaps, text, cursors, etc). You stuff this data into a .rsrc file that will be linked to 7your application when it is compiled. 8 9Because .rsrc files have a binary file format, you need to use special tools to edit them, such as 10FileTypes, QuickRes, or Resourcer. Alternatively, you can use a "resource compiler". This is a 11command line tool that takes a text-based resource script and turns it into a .rsrc file. 12 13With a resource compiler, you express your resources as ASCII text using a special definition 14language, which makes the resource files much easier to edit and maintain. You no longer need 15separate GUI tools to build your .rsrc files, and you can even automate the whole process by 16calling the compiler from your Makefile or Jamfile. Resource scripts will also make your life 17easier if you use version control, because version control doesn't handle .rsrc files very well. 18 19BeOS R5 comes with an (experimental) resource compiler called "beres", and a corresponding 20decompiler called "deres". rc is an open source replacement (and enhancement) of these tools. It 21is (mostly) backwards compatible, so you should be able to compile your old .rdef files without any 22problems. 23 24How to install 25============== 26 27- Copy ``rc`` into ``/boot/home/config/non-packaged/bin`` 28- Copy ``librdef.so`` into ``/boot/home/config/non-packaged/lib`` 29- Let's party! 30 31Note: rc comes preinstalled in Haiku already. 32 33Writing resource scripts 34======================== 35 36Writing resource scripts is not difficult, although the syntax may take some getting used to. A 37resource script is a plain text file with one or more resource definition statements. In addition, 38it may contain C or C++ style comments. By convention, resource script files have the extension ".rdef". 39 40Here is an example of a simple resource script: 41 42.. code-block:: c 43 44 resource(1) true; /* this is a comment */ 45 resource(2) 123; // and so is this 46 resource(3) 3.14; 47 resource(4) "hello world"; 48 resource(5) $"0123456789ABCDEF"; 49 50When compiled, this script produces a resource file with five resources. The above example also 51illustrates the types of data that resources are allowed to have: boolean, integer, floating point, 52character string (UTF-8), and raw data buffer (hexadecimal). 53 54By default, integer data is stored as a 32-bit int, and floating point data is stored as a 4-byte 55float. If you want to change the way the data is stored, you have to cast it: 56 57.. code-block:: c 58 59 resource(6) (int8) 123; 60 resource(7) (double) 3.14; 61 62You can cast integer data to the following types: int8, uint8, int16, uint16, int32, uint32, int64, 63uint64, ssize_t, size_t, off_t, time_t, float, double, raw. You can cast floating point data to: 64float, double, raw. You are not allowed to cast boolean, string, or raw data to other types. 65 66In addition to casting, you can also change the resource's type code. This does not change the way 67the data is stored, only what it is called. To change the type code of a resource: 68 69.. code-block:: 70 71 resource(8) #'dude' 123; 72 73This changes the type of resource 8 to the four-character-code 'dude'. If you did not change it, it 74would be 'LONG', which stands for 32-bit integer. By changing the type code, you assign a new 75meaning to the resource. You can also specify type codes as decimal or hexadecimal numbers: 76 77.. code-block:: 78 79 resource(9) #200 123; 80 resource(10) #0xC8 123; 81 82For historical reasons, you may also enclose the type code in parens, but that is not the preferred 83notation. Type casts and type codes can be combined: 84 85.. code-block:: 86 87 resource(11) #'dude' (int8) 123; 88 resource(11) (#'dude') (int8) 123; 89 90In the above examples, we have given the resources numeric IDs. The combination of ID and type code 91must be unique in the resource file; you cannot have two int32 resources with ID 1, for example. 92However, it is perfectly fine (but not necessarily a good idea) to do the following, because the 93data types are different: 94 95.. code-block:: c 96 97 resource(12) 123; 98 resource(12) "w00t!"; 99 100For your own convenience, you can also name resources. Unlike the ID/type code combination, names 101do not have to be unique. 102 103.. code-block:: c 104 105 resource(13, "Friday") "Bad Luck"; 106 107You can also do simple maths. The emphasis here is on simple because the number of operators is 108limited, they only work on integer data (or anything that can be cast to integer), and the result 109is always 32-bit integer as well. Still, the lazy amongst you may find it handy: 110 111.. code-block:: c 112 113 resource(14) 2 * (4 + 3); 114 115Since it is likely that you will be using these resources from a C/C++ program, it may be 116convenient to refer to them by symbolic names instead of hardcoded numeric ID's. The rdef format 117allows you to do this: 118 119.. code-block:: c 120 121 { 122 R_AppName = 1, 123 R_SomeOtherThing = 2 124 }; 125 126 resource(R_AppName) "MyKillerApp"; 127 128The compiler will automatically substitute the symbol R_AppName with the number 1. (You don't have 129to start these symbol names with the prefix ``R_``, but it is somewhat of a convention.) 130 131Now how do you tell your C/C++ app about these symbolic names? You simply put the enum into a 132header file that you include both from your application's source code and your rdef file. The 133header file, which we'll call "myresources.h", now looks like this: 134 135.. code-block:: c 136 137 { 138 R_AppName = 1, 139 R_SomeOtherThing = 2 140 } 141 142And the rdef file becomes this: 143 144.. code-block:: c 145 146 #include "myresources.h" 147 148 resource(R_AppName) "MyKillerApp"; 149 150Don't let the .h suffix fool you: the header file is still considered to be an rdef file, and must 151contain valid rdef syntax. If you add any other C/C++ code, your resource script will fail to 152compile. Of course, you shouldn't add any other rdef syntax to the header either (unless you want 153your C++ compiler to start complaining). Besides comments, the only safe thing to put in that 154header file is the enum statement, because both rdef and C/C++ understand it. 155 156Just like IDs, symbolic identifiers can be combined with a name: 157 158.. code-block:: c 159 160 resource(R_AppName, "AppName") "MyKillerApp"; 161 162If you don't specify a name, and invoke the compiler with the ``--auto-names`` option, it 163automatically uses the symbolic ID for the name as well. So the ID of the following resource is 1 164(because that is what R_AppName corresponds to) and its name becomes "R_AppName": 165 166.. code-block:: c 167 168 resource(R_AppName) "MyKillerApp"; 169 170Big fat resources 171================= 172 173The resources we have made so far consisted of a single data item, but you can also supply a 174collection of data values. The simplest of these compound data structures is the array: 175 176.. code-block:: c 177 178 resource(20) array { 1234, 5678 }; 179 180An array is nothing more than a raw buffer. The above statement takes the two 32-bit integers 1234 181and 5678 and stuffs them into a new 64-bit buffer. You can put any kind of data into an array, even 182other arrays: 183 184.. code-block:: c 185 186 resource(21) array 187 { 188 "hello", 189 3.14, 190 true, 191 array { "a", "nested", "array" }, 192 $"AABB" 193 }; 194 195It is up to you to remember the structure of this array, because array resources don't keep track 196of what kind of values you put into them and where you put these values. For that, we have messages. 197A message resource is a flattened BMessage: 198 199.. code-block:: 200 201 resource(22) message('blah') 202 { 203 "Name" = "Santa Claus", 204 "Number" = 3.14, 205 "Array" = array { "a", "nested", "array" }, 206 "Other Msg" = message { "field" = "value" } 207 }; 208 209A message has an optional "what" code, in this case 'blah', and one or more fields. A field has a 210name (between double quotes), a value, and a data type. By default, the field assumes the type of 211its data, but you can also specify an explicit data type and type code in front of the field name: 212 213.. code-block:: 214 215 resource(23) message('bla2') 216 { 217 "integer1" = (int8) 123, // use cast to change data type 218 int16 "integer2" = 12345, // specify data type 219 #'dude' "buffer1" = $"aabbccdd", // specify a new type code 220 #'dude' raw "buffer2" = $"aabbccdd" // you can also combine them 221 }; 222 223A special type of message is the "archive". The BeOS API allows you to take a BArchivable class an 224flatten it into a BMessage. You can also add such archives to your resource scripts: 225 226.. code-block:: 227 228 resource(24) #'BBMP' archive BBitmap 229 { 230 "_frame" = rect { 0.0, 0.0, 63.0, 31.0 }, 231 "_cspace" = 8200, 232 "_bmflags" = 1, 233 "_rowbytes" = 256, 234 "_data" = array 235 { 236 ... /* here goes the bitmap data */ ... 237 } 238 }; 239 240So what's this "rect" thing in the "_frame" field? Besides arrays and messages, the compiler also 241supports a number of other data structures from the BeAPI: 242 243+-----------+-------------------------+--------------------------------+ 244| Type | Corresponds to | Fields | 245+===========+=========================+================================+ 246| point | BPoint, B_POINT_TYPE | float x, y | 247+-----------+-------------------------+--------------------------------+ 248| rect | BRect, B_RECT_TYPE | float left, top, right, bottom | 249+-----------+-------------------------+--------------------------------+ 250| rgb_color | rgb_color, B_COLOR_TYPE | uint8 red, greed, blue, alpha | 251+-----------+-------------------------+--------------------------------+ 252 253To add a color resource to your script, you can do: 254 255.. code-block:: c 256 257 resource(25) rgb_color { 255, 128, 0, 0 }; 258 259Or you can use the field names, in which case the order of the fields does not matter: 260 261.. code-block:: c 262 263 resource(26) rgb_color 264 { 265 blue = 0, green = 128, alpha = 0, red = 255 266 }; 267 268You can also make your own data structures, or as we refer to them, "user-defined types". Suppose 269that your application wants to store its GUI elements in the resources: 270 271.. code-block:: 272 273 type #'menu' menu 274 { 275 string name, 276 int32 count, // how many items 277 array items // the menu items 278 }; 279 280 type #'item' menuitem 281 { 282 string name, 283 message msg, 284 bool enabled = true // default value is "true" 285 }; 286 287A type has a name, an optional type code, and one or more fields. You are advised not to pick a 288type code that already belongs to one of the built-in types, to avoid any confusion. Each field has 289a data type, a name, and a default value. If you don't specify a default, it is typically 0 or 290empty. To create a new menu resource using the types from the above example, you might do: 291 292.. code-block:: 293 294 resource(27) menu 295 { 296 name = "File", 297 count = 3, 298 items = array 299 { 300 menuitem { "New...", message('fnew') }, 301 menuitem { "Print...", message('fprt'), false }, 302 menuitem { "Exit", message('_QRQ') } 303 } 304 }; 305 306Like an array, a type resource doesn't remember its internal structure. You can regard types as 307fancy arrays that are easier to fill in, a template if you will. User-defined types work under the 308same rules as the built-in types point, rect, and rgb_color, so you can specify the fields in order 309or by their names. If you don't specify a field, its default value will be used. 310 311Types can also have a default resource ID and/or name. If you omit to give the resource an ID or a 312name, it uses the defaults from its data type. For example, this: 313 314.. code-block:: c 315 316 type myint { int32 i }; 317 resource(10, "MyName") myint { 123 }; 318 319Is equivalent to this: 320 321.. code-block:: c 322 323 type(10, "MyName") myint { int32 i }; 324 resource myint { 123 }; 325 326And to save you even more typing, simple types that have only one field can also be specified as: 327 328.. code-block:: c 329 330 resource myint 123; 331 332Most data types have a fixed size; a uint16 is always 2 bytes long, a float always comprises 4 333bytes, and so on. But the sizes of string and raw data resources depend on what you put in them. 334Sometimes you may want to force these kinds of resources to have a fixed size as well. You can do 335this as follows: 336 337.. code-block:: c 338 339 type fixed { string s[64] }; 340 341Any resources with type "fixed" will always contain a 64-byte string, no matter how many characters 342you actually specify. Too much data will be truncated; too little data will be padded with zeroes. 343Note that string resources are always terminated with a null character, so string "s" in the above 344type only allows for 63 real characters. The number between the square brackets always indicates 345bytes (unlike C/C++ arrays which use a similar notation). 346 347If you have (large) binary files that you want to include in the resources, such as pictures of 348Buffy, you don't need to convert the binary data to text form first. You can simply "import" the 349file: 350 351.. code-block:: 352 353 resource(22) #'PNG ' import "buffy.png"; 354 355Imported resources are always arrays (raw data), and you can specify the import statement 356everywhere that array data is valid. 357 358Application resources 359===================== 360 361All BeOS applications (except command line apps) have a basic set of resources, such as a MIME 362signature, launch flags, icons, and a few others. Adding these kinds of resources is easy, because 363rc also has a number of built-in types for that: 364 365+---------------+------------------------------+--------------------------------------------------+ 366| Type | Corresponds to | Fields | 367+===============+==============================+==================================================+ 368| app_signature | the apps's MIME signature | string signature | 369+---------------+------------------------------+--------------------------------------------------+ 370| app_flags | the application launch flags | uint32 flags | 371+---------------+------------------------------+--------------------------------------------------+ 372| app_version | version information | uint32 major, middle, minor, variety, internal | 373| | | string short_info, long_info | 374+---------------+------------------------------+--------------------------------------------------+ 375| large_icon | 32x32 icon | array of 1024 bytes | 376+---------------+------------------------------+--------------------------------------------------+ 377| mini_icon | 16x16 icon | array of 256 bytes | 378+---------------+------------------------------+--------------------------------------------------+ 379| vector_icon | HVIF vector icon (type VICN) | array of bytes | 380+---------------+------------------------------+--------------------------------------------------+ 381| file_types | supported file types | message | 382+---------------+------------------------------+--------------------------------------------------+ 383 384Here are some examples on how to use these resources. These things are also documented in the 385Storage Kit section of the BeBook, so refer to that for more information. 386 387The signature: 388 389.. code-block:: c 390 391 resource app_signature "application/x-vnd.YourName.YourApp"; 392 393The application flags determine how your application is launched. You must 'OR' together a combination of the following symbols: 394 395- ``B_SINGLE_LAUNCH`` 396- ``B_MULTIPLE_LAUNCH`` 397- ``B_EXCLUSIVE_LAUNCH`` 398- ``B_BACKGROUND_APP`` 399- ``B_ARGV_ONLY`` 400 401For example: 402 403.. code-block:: c 404 405 resource app_flags B_SINGLE_LAUNCH | B_BACKGROUND_APP; 406 407The version information resource contains a number of fields for you to fill in. Most are pretty 408obvious, except maybe for the "variety" field. It can take one of the following values: 409 410``B_APPV_DEVELOPMENT`` 411 development version 412 413``B_APPV_ALPHA`` 414 alpha version 415 416``B_APPV_BETA`` 417 beta version 418 419``B_APPV_GAMMA`` 420 gamma version 421 422``B_APPV_GOLDEN_MASTER`` 423 golden master 424 425``B_APPV_FINAL`` 426 release version 427 428For example: 429 430.. code-block:: c 431 432 resource app_version 433 { 434 major = 1, 435 middle = 0, 436 minor = 0, 437 variety = B_APPV_BETA, 438 internal = 0, 439 short_info = "My Cool Program", 440 long_info = "My Cool Program - Copyright Me" 441 }; 442 443The supported file types resource contains a list of MIME types, not unlike this: 444 445.. code-block:: c 446 447 resource file_types message 448 { 449 "types" = "text/plain", 450 "types" = "text" 451 }; 452 453Compiling 454========= 455 456rc is a command line tool, which means you must run it from a Terminal window. Typical usage example: 457 458.. code-block:: sh 459 460 rc -o things.rsrc things.rdef 461 462This tells rc that you wish to compile the script "things.rdef" to the resource file "things.rsrc". 463The default name for the output file is "out.rsrc", but you can change that with the ``-o`` 464or ``--output`` switch, just like we did here. 465 466You can specify multiple rdef files if you wish, and they will all be compiled into one big 467resource file. If your rdef files #include files that are not in the current working directory, 468you can add include paths with the ``-I`` or ``--include`` option. For a complete list of options, 469type ``rc --help``. 470 471If your project uses a Makefile, you can have rc automatically generate the resource file for you: 472 473.. code-block:: make 474 475 things.rsrc: things.rdef 476 rc -o $@ $^</PRE></BLOCKQUOTE> 477 478.. TODO: also explain how to integrate rc in jamfiles 479 480Decompiling 481=========== 482 483Of course you can write the resource scripts by hand, but if you already have a .rsrc file you can 484tell rc to decompile it. This will produce a ready-to-go rdef script, and save you some trouble. 485(Although in some cases it may be necessary to edit the script a little to suit your needs.) Note 486that rc isn't limited to just .rsrc files; you can decompile any file that has resources, 487including applications. 488 489For example, to decompile the file "things.rsrc" into "things.rdef", do: 490 491.. code-block:: sh 492 493 rc --decompile -o things.rdef things.rsrc 494 495The decompiler produces an rdef resource script with the name "out.rdef", but you can change that 496name with the ``-o`` or ``--output`` switches. If you specify the ``--auto-names`` option, rc will also 497write a C/C++ header file. Any resources whose name is a valid C/C++ identifier will be added to 498the header file. Now your program can access the resource using this symbolic name. 499 500Note: Even though rc can decompile multiple .rsrc files into one script, it does not detect 501conflicts in resource names or IDs. In such cases, the resulting .rdef and/or .h files may give 502errors when you try to compile them. 503 504Authors 505======= 506 507The rc resource compiler and its companion library librdef were written by `Matthijs Hollmans <mailto:mahlzeit@users.sourceforge.net>`_ for the `Haiku <http://www.haiku-os.org>`_ project. Thanks to Ingo Weinhold for the Jamfile and the Jam rules. Comments, bug reports, suggestions, and patches are welcome! 508