Idea found on the Circle Mailing List. Callback functions - Parsing Single Line/Menu Input through STATE()'s Callback v.1.0 -- 6/10/01 Idea by Jim Persson (jim@LINUX.NU) - he's a sort of newbie :-) Mailer code by Mike Breuer (mbreuer@new.rr.com) Adjustments and modifications by Akuma -- me (doomer18@hotmail.com) Well, all that's needed is modifications to a few files. ====================== in structs.h after '#define SPECIAL(name) \' add this --- #define C_FUNC(name) \ void (name) (struct descriptor_data *d, char *arg, void *info) --- later in the same file in 'struct descriptor_data {' at the end --- C_FUNC(*callback); // Call back function for anything I want to do void *c_data; // Storage for the Callback function }; ====================== in utils.h after 'int num_pc_in_room(struct room_data *room);' --- void line_input(struct descriptor_data *d, const char *prompt, C_FUNC(*callback), void *info); void clean_callback(struct descriptor_data *d); ====================== in interpreter.c:nanny() after 'case CON_CLOSE:' --- + case CON_LINE_INPUT: + if (d->callback) + d->callback(d, arg, d->c_data); + else { + log("SYSERR: No callback function specified for state CON_LINE_INPUT"); + STATE(d) = CON_PLAYING; + } + break; default: --- in interpreter.c at the end of the file is good enough --- +// Called like so from somewhere that you want to ask a question: +// line_input(ch->desc, "Do you want to multi-class to warrior (Yes/No)? ", +// parse_multiclass); +// ONLY USE FROM CON_PLAYING STATE()'s! + +void line_input(struct descriptor_data *d, const char *prompt, + C_FUNC(*callback), void *info) { + d->callback = callback; + d->c_data = (char *)info; + STATE(d) = CON_LINE_INPUT; + SEND_TO_Q(prompt, d); +} + +void clean_callback(struct descriptor_data *d) { + d->callback = NULL; + // I wouldn't recommend passing pointers to objects + // just use for str_duping strings. It is possible though. + + if (d->c_data) FREE(d->c_data); + d->c_data = NULL; + + STATE(d) = CON_PLAYING; +} ====================== And that's it! If you want a test_func, just go somewhere in your code (or make a testing command to see it in action) and add in this: ====================== at the top of the file your putting your test functions in lets just say interpreter.c for now --- +C_FUNC(test_func); +C_FUNC(test_func_chain); --- and later in the file (near the bottom if you choose) --- +C_FUNC(test_func) { + sprintf(buf, "You typed '%s'!\r\n", arg); + SEND_TO_Q(buf, d); + d->c_data = NULL; + line_input(d, "Type something else: ", test_func_chain, str_dup(arg)); +} + +C_FUNC(test_func_chain) { + sprintf(buf, "You typed '%s' and then '%s'... Cool.\r\n", (char *)info, arg); + SEND_TO_Q(buf, d); + // Call ONLY on the LAST function of a chain + clean_callback(d); +} ====================== Now to call the functions and get the ball rolling, I used Jeremy Elson's do_edit from his genolc package and just added in an extra case like so (seeing as how I don't use the do_edit anyway) ====================== at the top of genolc.c after the '#include headers' --- +C_FUNC(test_func); // Don't need test_func_chain b/c it's called by this one --- in do_edit add this in the switch() statement --- switch(a[0]) { + case 't': + line_input(ch->desc, "Test Function : Type something : ", test_func, NULL); + break; case 'a': save_all(); break; ====================== Put this example in, compile, and when you log into the mud type : edit t It should send you to a prompt that tells you to 'Type something: '. After you do so, it'll give you another prompt to 'Type something else: '. On both occasions, it will tell you exactly what you type. >Begin Example (I'll show what I type by preceding it with a '>': edit t Test function : Type something : >Testing, 1, 2, 3 You typed 'Testing, 1, 2, 3'! Type something else: >Woo, It works :-) You typed 'Testing 1, 2, 3' and then 'Woo, It works :-)'... Cool. >End Example And that's an example of how to use this properly... If someone has any questions, feel free to email me about this :-) Have fun with it Akuma the Raging Coder