Re: [CODE][LONG] Line input function (NEW PROBLEM)

From: Mike Breuer (mbreuer@new.rr.com)
Date: 06/08/01


----- Original Message -----
From: "Jim Persson" <jim@LINUX.NU>
Sent: Friday, June 08, 2001 9:13 AM
> i would like the function to operate to make something like this possible
>
> line_input(ch->desc, "First Name", &f_name);         // It should wait for
> the input here and then continue
> line_input(ch->desc, "Prompt 2", &l_name);           // Same here
> sprintf(buf, "Hi %s %s\r\n", f_name, l_name);         // and then execute
> this

Obviously this won't work for the same reason the other one wouldn't work.  To
solve the problem, I would suggest a modification to the line input function
and the descriptor_data structure (See my original email for previous code
modifications):

in structs.h:

struct descriptor_data {
   socket_t     descriptor;     /* file descriptor for socket           */
-  void (*callback)(struct descriptor_data *, char *);
+  void (*callback)(struct descriptor_data *, char *, void *);
+  void *argument;

Then modify the case statement in interpreter.c:

  case CON_LINE_INPUT:
    if (d->callback)
-     d->callback(d, arg);
+     d->callback(d, arg, d->argument);
    else
      log("SYSERR: No callback specified for line input.");
    d->callback = NULL;
+   d->argument = NULL;
    STATE(d) = CON_PLAYING;
  break;

Then modify line_input:

-void line_input( struct descriptor_data *d, const char *prompt,
                 void (*callback)(struct descriptor_data *, char *) ) {
+void line_input( struct descriptor_data *d, const char *prompt,
                 void (*callback)(struct descriptor_data *, char *, void *),
                 void *argument ) {
  d->callback = callback;
+ d->argument = argument;
  STATE(d) = CON_LINE_INPUT;
  SEND_TO_Q(prompt, d);
}

You will have to add the void * parameter to all of your callbacks, and now
you can pass along context information which you can use however you want.
For example:

+void parse_last(struct descriptor_data *, char *, void *);

+void parse_first( struct descriptor_data *d, char *name, void *ignore) {
+  line_input(d, "Enter last name: ", parse_last, str_dup(name));
+}

+void parse_last( struct descriptor_data *d, char *name, void *context ) {
+  sprintf(buf, "Hi %s %s.\r\n", (char *)context, name);
+  SEND_TO_Q(buf, d);
+  free(context); /* Don't forget this! */
+}

And then somewhere in your code:

...
line_input(ch->desc, "Enter first name: ", parse_first, NULL);

NOTE: Technically it is possible to do this with fewer arguments by accessing
the members of struct descriptor_data directly.  I personally prefer the style
described above because it makes the code a little more readable.  Also note
that if you want to pass more than one argument to line_input that you can
create a structure containing your arguments and pass a pointer to that.

Mike

P.S. I suggest reading the FAQ at the bottom of this message so you don't get
dropped from the list.

--
   +---------------------------------------------------------------+
   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
   +---------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/05/01 PST