hey,
have you tried to compile this without HAVE_KEYBOARDNAV? The remaining line would be "canvas_connect(gl, nobj, 0, indx, kbdnav->kn_ioindex);" which doesn't look right.
Just go for the most obvious solution:
if (connectme) { #ifdef HAVE_KEYBOARDNAV ... #else canvas_connect(gl, indx, 0, nobj, 0); #endif }
Yes, "..." will also have a call to "canvas_connect(gl, indx, 0, nobj, 0);", but that's not a problem. Actually, you don't even save a line because of the additional #ifdefs and the resulting code is much harder to read.
Finally, "..." could simply delegate to a method defined in your source file, so your implementation doesn't clutter the original Pd sources.
Christof
Gesendet: Samstag, 24. August 2019 um 19:31 Uhr Von: "Henri Augusto Bisognini" msndohenri@hotmail.com An: "pd-dev@lists.iem.at" pd-dev@lists.iem.at Betreff: [PD-dev] keyboard navigation: #ifdefs
Hey list! I've been trying to isolate the keyboard navigation as much as i could since you guys said it should be compiled optionally. While a lot of stuff could be moved to it's own file (g_kbdnav.c) there are also a lot of code that need to be in the middle of pd's core functions. For example, here is the modified canvas_obj() function on the g_text.c to not cinlude the code related to keyboard navigation:
https://gist.github.com/HenriAugusto/e417c8f269ad10df2dc3359b907ea588 It's not as pretty as it could be but it's readable (if your editor has code folding you can just hide the relevant lines to see what the code looks like, for example). Is there a better way to do this? Cheers, Henri.
Just in case, those are examples of some other modified core functions: in g_text.c glist_drawiofor(...) - draws a rectangle around the selected in/outlet canvas_howputnew(...) - position a new object exactly below/above to selected in/outlet in g_canvas.c canvas_drawlines(...) - draws lines in different colors while navigating through connections canvas_map(...) - draws each object's index if the user has asked so (useful for the goto functionality)
De: Christof Ressi christof.ressi@gmx.at Enviado: terça-feira, 16 de julho de 2019 14:32 Para: Henri Augusto Bisognini msndohenri@hotmail.com Cc: pd-dev@lists.iem.at pd-dev@lists.iem.at Assunto: Aw: Re: [PD-dev] First complete keyboard navigation prototype
Hi,
But it appears that actually the size of the struct is deduced while compiling. So if you write an external it is going to think the canvas struct is the same size as it was in the pd header files that were used during compilation.
exactly.
When using the pointer to implementation idiom, wouldn't the pointer itself change the size of the struct?
yes, it will
You've said something about that not being a problem when you add it as the last member of the struct but i don't understand why and how that would work.
usually, externals shouldn't care about the *size* the t_editor struct (at least I can't think of any use case), so you can get away with adding new fields at the end (although it's certainly not recommended). Note that those headers aren't really public anyway! However, appending fields conditionally can lead to problems: struct Foo { int a; #ifdef FOO_EX int c; #endif }; Now let's say we need to add another member:
struct Foo { int a; #ifdef FOO_EX int c; #endif
in b; }; If the host compiles with FOO_EX defined and the client doesn't, the latter will assume a wrong offset for 'b'. The solution is to add a field for private data *once*. The advantage is that a) we can hide the private data and b) we can extend it without worrying about compatibility: struct Foo { int a; PrivateFoo *p; }; We can still add public members if needed: struct Foo { int a; void *private; int b; }; 'private' points to a private data structure that is not be visible to clients. There you can conditionally enable members without problems: struct PrivateFoo { #ifdef USE_BAR struct MyFeature feature; #endif }; MyFeature could be in a seperate source file together with your methods and it only gets compiled when needed. Again, have a look at the "t_canvas_private" struct and the "gl_privatedata" member of "_glist" (aka "t_canvas") and do the same for "_editor", e.g.: in g_canvas.h: typedef struct _editor { ... void *e_privatedata; } t_editor; in g_editor.c: #ifdef HAVE_KEYBOARDNAV #include "g_keyboardnav.h" #endif typedef struct _editor_private { #ifdef HAVE_KEYBOARDNAV t_keyboardnav keyboardnav; #endif } t_editor_private; the "t_keyboardnav" struct is defined in "g_keyboardnav.h" and its methods implemented in "g_keyboardnav.c". Both only get compiled when needed. Hope this makes sense. Christof_______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev%5Bhttps://lists.puredata.info/li...]