Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Need help with structs

This thread is locked; no one can reply to it. rss feed Print
Need help with structs
Doctor Cop
Member #16,833
April 2018
avatar

I am trying to make a change in the position of the scroller through this function but nothing is happening, I suspect that I'm using structs wrongly.
I searched online but the issue couldn't be resolved.

void On_click_scroller(ALLEGRO_EVENT event, SCROLLER *scroll)
{
    if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
        if(event.mouse.x > scroll->x1 && event.mouse.x < scroll->x2 &&
           event.mouse.y > scroll->y1 && event.mouse.y < scroll->y2 && scroll->flag == 0)
           {
            scroll->flag = 1;
            scroll->from_y = event.mouse.y;
           }

}

What could be the problem?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

It doesn't look like the problem is in the code you are showing.

What happens to your scroller when you change the from_y and flag values? Are you redrawing your scroller?

However, the problem could be absolute coordinates vs relative coordinates. Shouldn't you be subtracting scroller->y1 from event.mouse.y?

Doctor Cop
Member #16,833
April 2018
avatar

I have divided it into three functions

#SelectExpand
1SCROLLER scroller_listener(ALLEGRO_EVENT event, SCROLLER scroll) 2{ 3 On_click_scroller(event, &scroll); 4 On_drag_scroller(event, &scroll); 5 On_release_scroller(event, &scroll); 6 7 return scroll; 8} 9 10void On_click_scroller(ALLEGRO_EVENT event, SCROLLER *scroll) 11{ 12 if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) 13 if(event.mouse.x > scroll->x1 && event.mouse.x < scroll->x2 && 14 event.mouse.y > scroll->y1 && event.mouse.y < scroll->y2 && scroll->flag == 0) 15 { 16 scroll->flag = 1; 17 scroll->from_y = event.mouse.y; 18 } 19 20} 21 22void On_drag_scroller(ALLEGRO_EVENT event, SCROLLER *scroll) 23{ 24 if(scroll->flag == 1) 25 scroll->ordinate = event.mouse.y - scroll->from_y; 26} 27 28void On_release_scroller(ALLEGRO_EVENT event,SCROLLER *scroll) 29{ 30 if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) 31 scroll->flag = 0; 32}

I have uploaded the source files in the attachments.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

This function is incorrect because it takes Scroller by value, and not by reference (C++) or pointer (C).

SCROLLER scroller_listener(ALLEGRO_EVENT event, SCROLLER scroll) {
   On_click_scroller(event, &scroll);
   On_drag_scroller(event, &scroll);
   On_release_scroller(event, &scroll);
   return scroll;
}

You're returning a copy of a copy. The SCROLLER returned by the function calls your three callback checks on a local copy of 'scroll'. You need to use pointers.

The function could be changed to :

void scroller_listener(ALLEGRO_EVENT event , SCROLLER* pscroll) {
   On_click_scroller(event , pscroll);
   On_drag_scroller(event , pscroll);
   On_release_scroller(event , pscroll);
   return;
}

And then it should work.

Doctor Cop
Member #16,833
April 2018
avatar

Changed the function but still no difference.

See the attachments.

jmasterx
Member #11,410
October 2009

Have you tried setting breakpoints and using a debugger to see how far it gets? Where does it get stuck, what is the state of the stack where it gets stuck or does not enter.

Doctor Cop
Member #16,833
April 2018
avatar

well, I'm not compiling on Code blocks and I don't know how to use command line GDB. I will have to learn it first to do that.

jmasterx
Member #11,410
October 2009

Oh yeah, using a debugger is an absolute must to be a programmer in 2019.

If you switch to visual studio as your IDE, debugging is a lot easier.

Is there a reason you're not using an IDE like VS or Code blocks?

Doctor Cop
Member #16,833
April 2018
avatar

In job postings, I find that they require the command line compilers and Linux knowledge. It was explicitly said that I need to be able to work with Linux and GCC compiler.

I am making a project for students to learn C programming. They are the people who don't even know how to create header files and how to manage code. Some don't even have enough resources to download an IDE so I decided to go fully command line.

I will look for GDB tutorials shortly.

jmasterx
Member #11,410
October 2009

There are plenty of free IDEs for Linux that use GDB and GCC and let you set breakpoints using a gui interface.

https://www.tecmint.com/best-linux-ide-editors-source-code-editors/

There is simply no reason for anyone who codes professionally not to use a debugger. Any company that doesn't, don't go work there.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

GDB primer :

gdb>backtrace (bt)
gdb>bt
Gives you the stack trace

gdb>print x
prints the value of the expression x, including function calls

gdb>break file.ext:###
Sets a breakpoint in file.ext on line ###

gdb>run

gdb>continue
Unpauses execution after hitting a breakpoint

gdb>breakpoints
Tells you the currently selected breakpoints

gdb>info threads
Gives you info on the threads currently executing (paused)

gdb>thread apply all bt
Gives you a backtrace for every thread

gdb>thread #
Switches to thread #

gdb>frame #
Switches to frame #

gdb>info locals
gdb>info globals
Gives you information on local or global variables.

gdb>info globals EXPR
Gives you info on global variables that match EXPR

That pretty much covers the basics of using GDB. You can always type 'help' or 'help TOPIC' and get the runtime info on that command.

Peter Hull
Member #1,136
March 2001

Seems like you aren't calling that listener function anywhere inside the loop?

Doctor Cop
Member #16,833
April 2018
avatar

Thanks Edgar, that was really helpful.
Peter, The file is in the attachments.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

What you're failing to understand is the difference between pass by value and pass by reference. In your code you are still using copies of objects instead of pointers to objects. If you alter a copy, the original remains unchanged. Pass by pointer and then your changes will take effect.

https://stackoverflow.com/questions/2229498/passing-by-reference-in-c

Doctor Cop
Member #16,833
April 2018
avatar

At first, I was using pass by reference but when it didn't compile then I changed it to pass by value.

I have made these changes and I will be blunt to say that I have tried everything I could (even stack overflow) but couldn't find anything on how to resolve this problem and there doesn't seem to be any good tutorial on struct with pointers in function parameters (or I'm just not good at searching).

Peter Hull
Member #1,136
March 2001

Seems like you aren't calling that listener function anywhere inside the loop?

Doctor Cop
Member #16,833
April 2018
avatar

Peter, I'm calling it inside bt_list_box_listner(); function.

#SelectExpand
1#pragma once 2 3#include <allegro5/allegro5.h> 4#include <allegro5/allegro_primitives.h> 5 6 7// Structure for scroller (a subset of List Box) 8typedef struct SCROLLER 9{ 10 int x, y; 11 int width, height; 12 ALLEGRO_COLOR color; 13 ALLEGRO_COLOR tail_color; 14 15 // To be manipulated by the internal functions 16 int x1, y1, x2, y2; 17 char flag; 18 long from_y; 19 int ordinate; 20 21} SCROLLER; 22 23typedef struct LIST_BOX 24{ 25 int x, y; 26 int width, height; 27 ALLEGRO_COLOR background; 28 ALLEGRO_COLOR seperator_line; 29 SCROLLER scroller; 30} LIST_BOX; 31 32 33 34/////////////////////////////////////////// 35// // 36// LIST_BOX // 37// // 38/////////////////////////////////////////// 39 40// The function to draw the whole List Box 41void list_box(int y); 42 43// The function to Initialize LIST_BOX struct 44LIST_BOX bt_create_list_box(int x, int y, int width, int height, ALLEGRO_COLOR background, ALLEGRO_COLOR seperator_line 45 , ALLEGRO_COLOR scroller_color, ALLEGRO_COLOR tail_color); 46 47// The function to draw List Box in render mode 48void bt_draw_list_box(LIST_BOX box); 49 50// Listen to the ALLEGRO_EVENT (for List Box) 51LIST_BOX bt_list_box_listener(ALLEGRO_EVENT event, LIST_BOX box); 52 53//////////////////////////////////////////// 54 55 56 57/////////////////////////////////////////// 58// // 59// SCROLLER // 60// // 61/////////////////////////////////////////// 62 63// The function to Initialize SCROLLER struct 64SCROLLER create_scroller(int x, int y, int width, int height 65 , ALLEGRO_COLOR tail_color, ALLEGRO_COLOR color); 66 67// The function to draw scroller in render mode 68void draw_scroller(SCROLLER scroll); 69 70// Listen to the ALLEGRO_EVENT (for scroller) 71void scroller_listener(ALLEGRO_EVENT event, SCROLLER *scroll); 72 73void On_click_scroller(ALLEGRO_EVENT event, SCROLLER **scroll); 74 75void On_drag_scroller(ALLEGRO_EVENT event, SCROLLER **scroll); 76 77void On_release_scroller(ALLEGRO_EVENT event, SCROLLER **scroll); 78//////////////////////////////////////////// 79//

Peter Hull
Member #1,136
March 2001

Peter, I'm calling it inside bt_list_box_listner(); function.

Right and where are you calling that?

Doctor Cop
Member #16,833
April 2018
avatar

This is Text_Box.c file

#SelectExpand
1#include "Text_Box.h" 2 3// To be replaced by properly designed functions 4void list_box(int y) 5{ 6 al_draw_filled_rectangle(75, 75, 775, 575, al_map_rgb(12, 83, 95));// rgb(51, 102, 153) 7 8 for(int i=0; i < 475; i+=25) 9 { 10 al_draw_line(100, 100+i, 725, 100+i, al_map_rgb(155, 155, 155), 1); //rgb(182, 182, 182) 11 // al_draw_line(100+i, 100, 100+i, 550, al_map_rgb(255, 255, 255), 1); 12 } 13 14 //al_draw_filled_rectangle(750, 75, 775, 575, al_map_rgb(51, 102, 153)); 15 al_draw_line(763, 100, 763, 550, al_map_rgb(255, 255, 255), 1); //757, 100, 757, 550 16 al_draw_filled_rounded_rectangle(760, 100+y, 765, 200+y, 2, 2, al_map_rgb(255, 255, 70)); 17 18} 19 20//LIST_BOX functions 21///////////////////////////////////////////////////////////////////////////////////////////// 22 23// Initializes the LIST_BOX struct 24LIST_BOX bt_create_list_box(int x, int y, int width, int height, ALLEGRO_COLOR background, ALLEGRO_COLOR seperator_line 25 , ALLEGRO_COLOR scroller_color, ALLEGRO_COLOR tail_color) 26{ 27 LIST_BOX list_box; 28 29 list_box.x = x; 30 list_box.y = y; 31 list_box.width = width; 32 list_box.height = height; 33 list_box.background = background; 34 list_box.seperator_line = seperator_line; 35 36 list_box.scroller = create_scroller(list_box.width+50, list_box.y, 50, list_box.height, tail_color, scroller_color); 37 38 return list_box; 39} 40 41// To be called while rendering 42void bt_draw_list_box(LIST_BOX box) 43{ 44 // Taking measures for the List Box's x2 y2 45 int bg_width_pos = box.x + box.width; 46 int bg_height_pos = box.y + box.height; 47 48 // Drawing background 49 al_draw_filled_rectangle(box.x, box.y, bg_width_pos, bg_height_pos, box.background); 50 51 // I Don't remember why did I do that 52 int loop = box.height - 25; 53 // To draw separator lines 54 for(int i=0; i < loop; i+=25) 55 { 56 al_draw_line(box.x+25, box.y+25+i, bg_width_pos-50, box.y+25+i, box.seperator_line, 1); //rgb(182, 182, 182) 57 58 } 59 60 // Drawing actual scroller 61 draw_scroller(box.scroller); 62} 63 64// Makes changes in the LIST_BOX, to be called in the logical computational part 65LIST_BOX bt_list_box_listener(ALLEGRO_EVENT event, LIST_BOX box) 66{ 67 scroller_listener(event, &box.scroller); 68 return box; 69} 70 71//LIST_BOX functions 72///////////////////////////////////////////////////////////////////////////////////////////// 73SCROLLER create_scroller(int x, int y, int width, int height 74 , ALLEGRO_COLOR tail_color, ALLEGRO_COLOR color) 75{ 76 SCROLLER scroll; 77 78 scroll.x = x; 79 scroll.y = y; 80 scroll.width = width; 81 scroll.height = height; 82 scroll.color = color; 83 scroll.tail_color = tail_color; 84 scroll.flag = 0; 85 scroll.from_y = 0; 86 scroll.ordinate = 0; 87 88 // Scroller button information 89 scroll.x1 = scroll.x + 10; 90 scroll.y1 = scroll.y + 25; 91 scroll.x2 = scroll.x + 15; 92 scroll.y2 = scroll.y + 100; 93 94 return scroll; 95} 96 97 98// The function to draw scroller in render mode 99void draw_scroller(SCROLLER scroll) 100{ 101 102 al_draw_line(scroll.x + 13, scroll.y + 25, scroll.x + 13, scroll.height + scroll.y - 25 103 , scroll.tail_color, 1); 104 al_draw_filled_rounded_rectangle(scroll.x1, scroll.y1+scroll.ordinate, scroll.x2, scroll.y2+scroll.ordinate 105 , 2, 2, scroll.color); 106 107} 108 109// Listen to the ALLEGRO_EVENT (for scroller) 110void scroller_listener(ALLEGRO_EVENT event, SCROLLER* scroll) 111{ 112 On_click_scroller(event, &scroll); 113 On_drag_scroller(event, &scroll); 114 On_release_scroller(event, &scroll); 115} 116 117void On_click_scroller(ALLEGRO_EVENT event, SCROLLER **scroll) 118{ 119 if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) 120 if(event.mouse.x > *(scroll)->x1 && event.mouse.x < *(scroll)->x2 && 121 event.mouse.y > *(scroll)->y1 && event.mouse.y < *(scroll)->y2 && *(scroll)->flag == 0) 122 { 123 *(scroll)->flag = 1; 124 *(scroll)->from_y = event.mouse.y; 125 } 126 127} 128 129void On_drag_scroller(ALLEGRO_EVENT event, SCROLLER **scroll) 130{ 131 if(*(scroll)->flag == 1) 132 *(scroll)->ordinate = event.mouse.y - *(scroll)->from_y; 133} 134 135void On_release_scroller(ALLEGRO_EVENT event,SCROLLER **scroll) 136{ 137 if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) 138 *(scroll)->flag = 0; 139}

This is main.c file

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_primitives.h> 3//#include <allegro5/allegro_image.h> 4#include <allegro5/allegro_font.h> 5#include <allegro5/allegro_ttf.h> 6#include <allegro5/keyboard.h> 7#include <allegro5/mouse.h> 8#include "Text_Box.h" 9 10void menu_icon(int, int, int, int, ALLEGRO_COLOR, int); 11 12#define MAXWIDTH 900 13#define MAXHEIGHT 600 14 15int main() 16{ 17 al_init(); 18 al_init_primitives_addon(); 19 //al_init_image_addon(); 20 al_init_font_addon(); 21 al_init_ttf_addon(); 22 al_install_keyboard(); 23 al_install_mouse(); 24 25 //al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR); 26 27 ALLEGRO_DISPLAY *display = al_create_display(MAXWIDTH, MAXHEIGHT); 28 ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue(); 29 ALLEGRO_EVENT event; 30 ALLEGRO_TIMER *timer = al_create_timer(2.0/60.0); 31 ALLEGRO_COLOR m_color = al_map_rgb(255, 214, 51); 32 ALLEGRO_FONT *font = al_load_ttf_font("res/L.ttf", 14, 1); 33 LIST_BOX list_box = bt_create_list_box(75, 75, 800, 500, al_map_rgb(12, 83, 95), al_map_rgb(155, 155, 155), al_map_rgb(255, 255, 70), al_map_rgb(255, 255, 255)); 34 //ALLEGRO_BITMAP *background = al_load_bitmap("res/background.jpg"); 35 36 37 int x=0, sc_y=0, sc_pointed_y, sc_pointed_y_trigger=0, main_loop = true, menu = 0, scr_prev_pos=0, scroller=1; 38 int width=50, height=50, place_x=25, place_y=25, animate = 0; 39 //enum {}; 40 41 al_register_event_source(queue, al_get_display_event_source(display)); 42 al_register_event_source(queue, al_get_mouse_event_source()); 43 al_register_event_source(queue, al_get_keyboard_event_source()); 44 al_register_event_source(queue, al_get_timer_event_source(timer)); 45 46 al_start_timer(timer); 47 48 while(main_loop) 49 { 50 51 //if(al_is_event_queue_empty(queue)) 52 al_wait_for_event(queue, &event); 53 54 if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 55 main_loop = false; 56 57 else if(event.type == ALLEGRO_EVENT_TIMER) 58 { 59 al_clear_to_color(al_map_rgb(0, 77, 77)); //rgb(153,50,204) 60 61 //al_draw_scaled_bitmap(background, 0, 0, 4896, 3264, 0, 0, 800, 600, 0); 62 al_draw_rounded_rectangle(400-100, 300-20, 400+100, 300+20, 20, 20, al_map_rgb(70, 60, 100), 2); 63 al_draw_filled_rectangle(0, 0, 50, 50, m_color); 64 al_draw_filled_rectangle(0, 50, 50, MAXHEIGHT, al_map_rgb(255, 214, 51)); //rgb(218, 112, 214) rgb(255, 214, 51) al_map_rgb(230, 46, 0) 65 al_draw_line(50, 0, 50, MAXHEIGHT, al_map_rgb(0, 0, 0), 1); 66 menu_icon(50, 50, 25, 25, al_map_rgb(0, 0, 0), animate); 67 bt_draw_list_box(list_box); //list_box(sc_y); 68 69 if(menu) 70 { 71 al_draw_filled_rectangle(50, 0, MAXWIDTH, 50, al_map_rgb(22, 88, 110)); 72 } 73 74 al_flip_display(); 75 al_rest(0.02); 76 } 77 78 else if(event.type == ALLEGRO_EVENT_MOUSE_AXES) 79 { 80 if(event.mouse.x < 50 && event.mouse.y < 50) 81 m_color = al_map_rgb(140, 152, 63); 82 else 83 m_color = al_map_rgb(255, 214, 51); 84 } 85 86 else if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) 87 { 88 //scr_prev_pos = event.mouse.y; 89 90 91 if(event.mouse.x >= (place_x-(width/2)) 92 && event.mouse.x <= (place_x+(width/2)) 93 && event.mouse.y >= (place_y-(height/2)) 94 && event.mouse.y <= (place_y+(height/2))) 95 { 96 if(event.mouse.button == 1) 97 { 98 (5 == animate) ? (animate = 0) : (animate = 5); 99 menu = !menu; 100 } 101 } 102 103 } 104 105 if(event.mouse.x >= 753 && event.mouse.x <= 761 && event.mouse.y >= 100+sc_y && event.mouse.y <= 200+sc_y) 106 { 107 108 if(event.mouse.button == 1) 109 { 110 scroller = 1; 111 112 if(sc_pointed_y_trigger == 1) 113 { 114 sc_pointed_y = event.mouse.y; 115 sc_pointed_y_trigger = 0; 116 } 117 } 118 119 if(scroller) 120 { 121 //if((event.mouse.y - 150) < 550 && (event.mouse.y - 150) > 100) 122 sc_y = event.mouse.y - 150; 123 } 124 } 125 126 else if(event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) 127 { 128 scroller = 0; 129 sc_pointed_y_trigger = 1; 130 //scr_prev_pos = event.mouse.y; 131 } 132 133 if(event.type == ALLEGRO_EVENT_KEY_DOWN) 134 { 135 switch(event.keyboard.keycode) 136 { 137 case ALLEGRO_KEY_ESCAPE : 138 exit(1); 139 break; 140 } 141 } 142 143 } 144 145 list_box = bt_list_box_listener(event, list_box); 146 147 al_destroy_display(display); 148 al_destroy_event_queue(queue); 149 return 0; 150} 151 152void menu_icon(int width, int height, int place_x, int place_y, ALLEGRO_COLOR colorU, int animate) 153{ 154 al_draw_line(place_x-(width/2)+width/4 + animate, place_y-(height/2)+height/3, place_x-(width/2)+width-(width/4) + animate, place_y-(height/2)+height/3, colorU, 5); 155 al_draw_line(place_x-(width/2)+width/4 - animate, place_y-(height/2)+(height/2), place_x-(width/2)+width-(width/4) - animate, place_y-(height/2)+(height/2), colorU, 5); 156 al_draw_line(place_x-(width/2)+width/4 + animate, place_y-(height/2)+height-(height/3), place_x-(width/2)+width-(width/4) + animate, place_y-(height/2)+height-(height/3), colorU, 5); 157}

Peter Hull
Member #1,136
March 2001

Right and where are you calling that?

Doctor Cop
Member #16,833
April 2018
avatar

Right and where are you calling that?

at line no. 145.

  145 list_box = bt_list_box_listener(event, list_box);

I now know it wasn't in the loop.

It's working now and blinking for some reason.
Anyway Thanks Peter.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Okay, Pointer Primer :

First, in C, all variables are pass by value, including pointers. But a pointer happens to hold the address of another object, which can be used to change that object, but not the pointer you pass to the function.

typedef struct DATA {
   int x;
};

Pass by value :

#SelectExpand
1void IncrementLocalDataCopy(DATA d){ 2 d.x++;/// Does nothing to the DATA passed to the function, but affects the local copy 3} 4void IncrementLocalDataPointerCopy(DATA* d){ 5 d->x++;/// The pointer is passed by value, but it references a DATA object named d passed to the function 6} 7void IncementLocalIntCopy(int i) { 8 i++;/// Increments local copy of i, not the int passed to it. 9} 10void IncrementLocalIntPointerCopy(int* iptr) { 11 iptr++;/// = 0;/// Doesn't affect the pointer passed to the function, but affects iptr 12 /// *iptr = &iptr;/// Stores the address of iptr inside the memory pointed to by iptr 13 /// But remember! iptr is a local object and it's address is on the last frame of the stack! 14 /// So now we have leaked a pointer to memory that is out of bounds as soon as the function returns 15 /// Passing the address of a local or temporary object is not good 16 /// It's BAD, MMMKAY? 17}

They are all pass by value, including the pointer. But the pointer allows you to change memory.

Here's a little quiz for you. What does the following code output? Does it compile? Does it run successfully? Why or why not?

DATA d = {1};
int i = 2;
int* iptr = &i;

IncrementLocalDataCopy(d);
IncrementLocalDataPointerCopy(&d);
IncrementLocalIntCopy(i);
IncrementLocalIntPointerCopy(iptr);

printf("d.x is %d , and i is %d\n" , d.x , i);

They are equal
<spoiler>
They equal 2
</spoiler>

Tips on working with pointers :

int i = 0;
int* iptr = &i;/// & Means 'the address of' i
i->x = i->x + 1;/// -> Derefences a pointer and accesses a field
*iptr = 3;/// * Dereferences a pointer and returns a reference to i which is used to assign the value 3
iptr = 0;/// Does nothing to i
*iptr = 4;/// Crashes if you're lucky with a segfault SIGSEGV accessing invalid memory address

And if you ever switch to C++, they introduce a second meaning for & when inside a function signature or variable declaration. It means 'a reference to' an object.

Example :

int i = 0;
int& j = i;/// j now references i
j = 1;/// Directly modifies i through its address
printf("I should be 1, and the value is %d" , i);

There. Learn that, and then tell us why it wasn't working. ;)

Doctor Cop
Member #16,833
April 2018
avatar

Thanks Edgar, for the valuable lesson and I already knew about the references.
I was confused about passing structs as pointer copy because that was my first time doing it and there was a logical error in my program that lead me to believe that I'm using it wrongly.
Thanks again.

Peter Hull
Member #1,136
March 2001

On "pass by value" - I saw something like that recently (OK, a year ago):
https://news.ycombinator.com/item?id=16533862
and the author responded to my comments:
https://news.ycombinator.com/item?id=16537111
(also note the response from munificent aka Bob Nystrom who knows a thing or two ;) )

On the other stuff - GDB would have helped you here

gdb> br bt_list_box_listener
gdb> run

to set a breakpoint on that function and run the program; it would then be obvious it was not being called, since the breakpoint would not be hit.

Doctor Cop
Member #16,833
April 2018
avatar

Thanks Peter!

Go to: