Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » How to: al_do_multiline_text() & callback functions

Credits go to Edgar Reynaldo for helping out!
This thread is locked; no one can reply to it. rss feed Print
How to: al_do_multiline_text() & callback functions
Joachim Arting
Member #13,584
September 2011

I've been scouring the interwebs for tutorials on callback functions but I've been unable to figure how to use al_do_multiline_text() properly.

What I want:
A. The total number of lines split by al_do_multiline_text()
OR
B. To give the callback function (*cb)(int, const char*, int, void*) access to some class members in order to do som class related stuff every callback (=every line split)

1. Do I have write the function myself or is there a pre-defined function somewhere for the purposes of A?
2. Is it possible to make this callback function a member of a class and if so, how do I define and pass the callback function correctly as an argument in al_do_multiline_text()?
3. What is the purpose of the void* extra parameter?

The 5.2.4 manual seems to assume a level of C++ knowledge I do not have at the moment.

Any help and/or further reference is appreciated.

-------------------------------------------------------------------------------
"Men despise religion. They hate it and are afraid it may be true. The cure for this is first to show that religion is not contrary to reason, but worthy of reverence and respect. Next make it attractive, make good men wish it were true, and then show that it is." - Blaise Pascal

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

These are the latest docs :

al_do_multiline_text

void al_do_multiline_text(const ALLEGRO_FONT *font,
   float max_width, const char *text,
   bool (*cb)(int line_num, const char *line, int size, void *extra),
   void *extra)

Source Code

This function processes the text and splits it into lines as al_draw_multiline_text would, and then calls the callback cb once for every line. This is useful for custom drawing of multiline text, or for calculating the size of multiline text ahead of time. See the documentation on al_draw_multiline_text for an explanation of the splitting algorithm.

For every line that this function splits text into the callback cb will be called once with the following parameters:

  • line_num - the number of the line starting from zero and counting up

  • line - a pointer to the beginning character of the line (see below)

  • size - the size of the line (0 for empty lines)

  • extra - the same pointer that was passed to al_do_multiline_text

Note that line is not guaranteed to be a NUL-terminated string, but will merely point to a character within text or to an empty string in case of an empty line. If you need a NUL-terminated string, you will have to copy line to a buffer and NUL-terminate it yourself. You will also have to make your own copy if you need the contents of line after cb has returned, as line is not guaranteed to be valid after that.

If the callback cb returns false, al_do_multiline_text will stop immediately, otherwise it will continue on to the next line.

Since: 5.1.9

I've been scouring the interwebs for tutorials on callback functions but I've been unable to figure how to use al_do_multiline_text() properly.

What I want:
A. The total number of lines split by al_do_multiline_text()
OR
B. To give the callback function (*cb)(int, const char*, int, void*) access to some class members in order to do som class related stuff every callback (=every line split)

1. Do I have write the function myself or is there a pre-defined function somewhere for the purposes of A?
2. Is it possible to make this callback function a member of a class and if so, how do I define and pass the callback function correctly as an argument in al_do_multiline_text()?
3. What is the purpose of the void* extra parameter?

The 5.2.4 manual seems to assume a level of C++ knowledge I do not have at the moment.

Any help and/or further reference is appreciated.

To answer 1) - you can easily write the function yourself once you understand the parameters and the callback.

2) No. Not unless it is static, which defeats the purpose of using a class. See 3).

3) The void* is a parameter you can use to pass a custom data object to your callback function.

First you need to understand a callback. This is merely another name for a function. The syntax for a function pointer is like so :

return_type (*function_name)(param p1 ...)

This means for your function to work, it needs to match the function signature of the callback. From the manual above we see the signature is :

bool (*cb)(int line_num, const char *line, int size, void *extra)

This means you need to declare a function that returns bool, and accepts the following parameters (int , const char* , int , void*).

The void* there in the callback will be a copy of the void* that was passed to al_do_multiline_text. So you can pass an object to your callback by it's address.

So for A) you could use a simple callback that counts the number of lines, like so :

#SelectExpand
1class LineCounter { 2public : 3 unsigned int count; 4 LineCounter() : count(0) {} 5}; 6 7bool CounterCallback(int line_num , const char* line , int size , void* extra) { 8 LineCounter* linecounter = (LineCounter*)extra; 9 if (line_num == 0) {linecounter->count = 0;} 10 linecounter->count++; 11 return true; 12} 13 14LineCounter lc; 15 16al_do_multiline_text(font , /* Our font */ 17 1000.0f , /* Some really large value */ 18 "a\nb\nc" , /* Some multi line text here */ 19 CounterCallback , /* Use our counter function */ 20 (void*)&lc , /* Pass the address of our line counter */ 21 ); 22printf("%u lines\n" , lc.count);

That should print 3.

B) The void* is merely there to allow you access to custom data, like your class members and methods.

Also, this is really just C. Callbacks are part of C. Now if you wanted a pointer to a member function, that's different.

Joachim Arting
Member #13,584
September 2011

Many thanks Edgar for your thorough and kind explanation, I've successfully implemented my own solution.

Cheers!

-------------------------------------------------------------------------------
"Men despise religion. They hate it and are afraid it may be true. The cure for this is first to show that religion is not contrary to reason, but worthy of reverence and respect. Next make it attractive, make good men wish it were true, and then show that it is." - Blaise Pascal

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Go to: