CALLBACK FUNCTIONS VERSION v.3.0 -- 7/4/01 Based on an idea found on the Circle Mailing List. Callback functions - Parsing Single Line/Menu Input through STATE()'s Idea by Jim Persson (jim@LINUX.NU) - he's a sort of newbie :-) Original Mailer code and modifications 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. --------------************************************------------------------ FILE FUNCTION/Struct (where am i?) ************************************************** >>-- structs.h Near the beginning of the file AFTER #define SPECIAL(name) \ INSERT #define C_FUNC(name) \ void (name) (struct descriptor_data *d, char *arg, void *info) ************************************************** >>-- structs.h struct descriptor_data { AFTER struct descriptor_data *next; INSERT C_FUNC(*callback); // Call back function for anything I want to do int callback_depth; // Call back "psuedo-recursiveness" depth void *c_data; // Storage for the Callback function ************************************************** >>-- utils.h Near the beginning of the file AFTER int num_pc_in_room(struct room_data *room); INSERT void line_input(struct descriptor_data *d, const char *prompt, C_FUNC(*callback), void *info); ************************************************** >>-- constants.c const char *connected_types[] = { ADD to the end of the array + "Line Input", // CON_LINE_INPUT ( "\n" }; ************************************************** >>-- utils.c At the END of the file is fine ADD at the end // 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->callback_depth++; // Increase depth of possible recursiveness. d->c_data = (char *)info; STATE(d) = CON_LINE_INPUT; SEND_TO_Q(prompt, d); } ************************************************** >>-- interpreter.c void nanny(struct descriptor_data *d, char *arg) AFTER case CON_CLOSE: break; INSERT case CON_LINE_INPUT: { if (d->callback) { d->callback(d, arg, d->c_data); if (--(d->callback_depth) <= 0) { d->callback = NULL; // if the function wasn't chained, clean up d->callback_depth = 0; // AND wasn't recursive d->c_data = NULL; STATE(d) = CON_PLAYING; } } else { log("SYSERR: No callback function specified for state CON_LINE_INPUT"); STATE(d) = CON_PLAYING; } } break; ************************************************** 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 --- At the top of interpreter.c (These are the prototypes) +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); + // This is how you CHAIN functions together + 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); + // We str_dup()'d this pointer, so we must FREE it + if (info) + free(info); +} ====================== 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