View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0000522 | LDMud 3.3 | Efuns | public | 2008-01-04 17:55 | 2018-01-29 21:57 |
| Reporter | Gnomi | Assigned To | Gnomi | ||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | resolved | Resolution | fixed | ||
| Platform | i686 | OS | Debian GNU/Linux | OS Version | 3.1 |
| Product Version | 3.3 | ||||
| Target Version | 3.3.719 | Fixed in Version | 3.3.719 | ||
| Summary | 0000522: Starting an input_to from within an ed session doesn't behave intuitively | ||||
| Description | From within an ed session you can call commands using a bang. But if that command starts an input_to the driver shows the prompt of that input_to, but the user input stills goes to the ed session. It is not until the ed session ended that the input_to function gets the input. A simple solution would be to put the ed session into the input_to list, so it can be stacked just like a normal input_to. (A long term solution is already mentioned as TODO in ed.c, let the mudlib do the ed command interpretation.) Greetings, Gnomi | ||||
| Tags | No tags attached. | ||||
| Attached Files | bug522.diff (53,645 bytes)
Index: trunk.ed/test/t-0000522.c
===================================================================
--- trunk.ed/test/t-0000522.c (Revision 0)
+++ trunk.ed/test/t-0000522.c (Revision 0)
@@ -0,0 +1,120 @@
+#include "/inc/base.inc"
+
+#include "/sys/input_to.h"
+
+/* These functions are for the clone (the player object). */
+int active;
+void start_client()
+{
+ net_connect("127.0.0.1", query_mud_port());
+ active = 1;
+}
+
+int logon(int flag)
+{
+ enable_telnet(0);
+ set_prompt("");
+
+ add_action("test_action", "test");
+
+ if(active)
+ ed("/dummy","ed_ends");
+ return 1;
+}
+
+void ed_ends()
+{
+}
+
+int test_action(string str)
+{
+ input_to("test_input_to", INPUT_PROMPT, "+");
+ return 1;
+}
+
+void test_input_to(string str)
+{
+ if(str != "=")
+ {
+ msg("Failed: Wrong message received.\n");
+ shutdown(1);
+ return;
+ }
+
+ write("A\n"); // Not a number as 'ed' would show.
+}
+
+/* These functions are for the blueprint (the virtual player that
+ sends us the commands). */
+
+void receive(string str, int nr)
+{
+ if(!strstr(str, "\"dummy\" ") || !strstr(str, "/dummy,"))
+ {
+ input_to("receive", 0, nr);
+ return;
+ }
+
+ if(!nr)
+ {
+ if(strstr(str,":"))
+ {
+ msg("Failed: Ed prompt expected.\n");
+ shutdown(1);
+ return;
+ }
+
+ str = str[1..];
+ }
+
+ // We just verify, that the prompt
+ // corresponds to the answer.
+ if(str != "+A" && str != ":0")
+ {
+ msg("Failed: Received %Q as the %d. line.\n", str, nr+1);
+ shutdown(1);
+ return;
+ }
+
+ if(nr)
+ {
+ msg("Success.\n");
+ shutdown(0);
+ }
+ else
+ input_to("receive", 0, 1);
+}
+
+object connect()
+{
+ enable_telnet(0);
+ set_prompt("");
+
+ write("!test\n=\n=\n");
+ call_out(#'shutdown, 1, 1); // If something goes wrong.
+ input_to("receive", 0, 0);
+
+ return clone_object(this_object()); // Just a dummy object.
+}
+
+void run_test()
+{
+ msg("\nRunning test for #0000522:\n"
+ "--------------------------\n");
+
+ /* Waiting until LDMud is ready for users. */
+ call_out("run_test2", 0);
+}
+
+void run_test2()
+{
+ object dummy;
+ dummy = clone_object(this_object());
+ dummy->start_client();
+}
+
+string *epilog(int eflag)
+{
+ run_test();
+ return 0;
+}
Index: trunk.ed/HISTORY
===================================================================
--- trunk.ed/HISTORY (Revision 2584)
+++ trunk.ed/HISTORY (Arbeitskopie)
@@ -87,6 +87,8 @@
'--enable-access-control', '--with-access-file', '--with-access-log'
and their config.h symbols ACCESS_FILE and ACCESS_LOG just give
the default values.
+ + Ed sessions are removed when an object becomes non-interactive.
+ + Multiple ed sessions per interactive are allowed.
12-Jan-2009 -- 3.3.718
Index: trunk.ed/src/comm.c
===================================================================
--- trunk.ed/src/comm.c (Revision 2584)
+++ trunk.ed/src/comm.c (Arbeitskopie)
@@ -195,7 +195,25 @@
/* Amazing how complicated networking can be, hm? */
/*-------------------------------------------------------------------------*/
+/* Types */
+/* --- struct input_to_s: input_to() datastructure
+ *
+ * input-to structures describe a pending input_to() for a given
+ * interactive object. It is a specialization of input_s,
+ * which therefore must be the first element.
+ */
+typedef struct input_to_s input_to_t;
+
+struct input_to_s {
+ input_t input;
+ callback_t fun; /* The function to call, and its args */
+ p_uint eval_nr; /* The thread number where this started. */
+};
+
+/*-------------------------------------------------------------------------*/
+/* Variables */
+
interactive_t *all_players[MAX_PLAYERS];
/* Pointers to the structures of the interactive users.
* Unused entries are NULL.
@@ -455,6 +473,7 @@
static void mccp_telnet_neg(int);
static void free_input_to(input_to_t *);
+static void free_input_handler(input_t *);
static void telnet_neg(interactive_t *);
static void send_will(int);
static void send_wont(int);
@@ -696,7 +715,7 @@
fprintf(stderr, " .ob: %p", ip->ob);
if (ip->ob) fprintf(stderr, " (%s)", get_txt(ip->ob->name));
putc('\n', stderr);
- fprintf(stderr, " .input_to: %p\n", ip->input_to);
+ fprintf(stderr, " .input_handler: %p\n", ip->input_handler);
fprintf(stderr, " .modify_command: %p", ip->modify_command);
if (ip->modify_command) fprintf(stderr, " (%s)", get_txt(ip->modify_command->name));
putc('\n', stderr);
@@ -3147,7 +3166,8 @@
/* If the user is not in ed, don't let him issue another command
* before the poll comes again.
*/
- if (O_GET_SHADOW(ip->ob)->ed_buffer
+ if (ip->input_handler
+ && ip->input_handler->type == INPUT_ED
&& CmdsGiven < ALLOWED_ED_CMDS)
{
CmdsGiven++;
@@ -3252,9 +3272,18 @@
interactive->closing = MY_TRUE;
current_object = ob;
+
+ /* If the object is not destructed, save any ed buffers. */
+
+ if ( !(ob->flags & O_DESTRUCTED) )
+ {
+ command_giver = ob;
+ abort_input_handler(interactive);
+ }
+
save_privilege = malloc_privilege;
- /* If the object is not destructed, inform the master */
+ /* If the object is still not destructed, inform the master */
if ( !(ob->flags & O_DESTRUCTED) )
{
@@ -3356,12 +3385,12 @@
/* Release all associated resources */
- while (interactive->input_to)
+ while (interactive->input_handler)
{
- input_to_t * it = interactive->input_to;
+ input_t * ih = interactive->input_handler;
- interactive->input_to = it->next;
- free_input_to(it);
+ interactive->input_handler = ih->next;
+ free_input_handler(ih);
}
if (interactive->modify_command)
@@ -3615,7 +3644,7 @@
new_interactive->tls_session = NULL;
new_interactive->tls_cb = NULL;
#endif
- new_interactive->input_to = NULL;
+ new_interactive->input_handler = NULL;
put_number(&new_interactive->prompt, 0);
new_interactive->modify_command = NULL;
new_interactive->closing = MY_FALSE;
@@ -3959,26 +3988,26 @@
*/
{
- input_to_t *it;
+ input_t *ih;
if (ip->noecho & IGNORE_BANG)
return ip->noecho;
- for (it = ip->input_to; it; it = it->next)
- if (it->noecho & IGNORE_BANG)
- return it->noecho;
+ for (ih = ip->input_handler; ih; ih = ih->next)
+ if (ih->noecho & IGNORE_BANG)
+ return ih->noecho;
return 0;
} /* find_no_bang() */
/*-------------------------------------------------------------------------*/
-Bool
-call_function_interactive (interactive_t *i, char *str)
+static Bool
+call_input_to (interactive_t *i, char *str, input_to_t *it)
-/* Perform a pending input_to() for this user <i> and the input <str>
- * Return TRUE if an input_to() was pending and executed, and FALSE
+/* Call the input_to handler <it> for this user <i> and the input <str>.
+ * Return TRUE if this handler was executed successfully, and FALSE
* if the input was not processed.
*
- * This function is called by the backend as part of the input processing.
+ * This function is only called by call_function_interactive().
*/
{
@@ -3986,64 +4015,14 @@
/* Current input_to, static so that longjmp() won't clobber it. */
struct error_recovery_info error_recovery_info;
-
- input_to_t *it;
object_t *ob; /* object holding <function> */
- it = i->input_to;
- /* _Are_ there an input_to() pending? */
- if (!it)
- return MY_FALSE;
-
- /* Yes, there are. Check if we have to handle input escape. */
- if (*str == input_escape && str[1])
- {
- input_to_t * prev;
-
- for (prev = NULL
- ; it && !(it->noecho & IGNORE_BANG)
- ; prev = it, it = it->next)
- NOOP;
-
- if (it)
- {
- /* Move this 'IGNORE_BANG' input_to to the top of list
- * since it's the one we're going to execute.
- */
- if (prev)
- {
- prev->next = it->next;
- it->next = i->input_to;
- i->input_to = it;
- }
-
- if (!(i->noecho & NOECHO) != !(it->noecho & NOECHO_REQ)) {
- /* !message for ECHO-context while in NOECHO - simulate the
- * echo by sending the (remaining) raw data we got.
- */
- add_message("%s\n", str + i->chars_ready);
- i->chars_ready = 0;
- }
-
- /* Don't hide the leading input escape */
- }
- else
- {
- /* Bang-input but no matching input_to(): return */
- return MY_FALSE;
- }
- }
-
/* We got the right input_to_t. Check if it's still valid. */
ob = callback_object(&(it->fun));
if (!ob)
{
/* Sorry, the object has selfdestructed ! */
- set_noecho(i, it->next ? it->next->noecho : 0
- , it->next ? it->next->local : MY_FALSE
- , MY_TRUE);
- i->input_to = it->next;
free_input_to(it);
return MY_FALSE;
}
@@ -4051,33 +4030,17 @@
if (O_PROG_SWAPPED(ob)
&& load_ob_from_swap(ob) < 0)
{
- set_noecho(i, it->next ? it->next->noecho : 0
- , it->next ? it->next->local : MY_FALSE
- , MY_TRUE);
- i->input_to = it->next;
free_input_to(it);
errorf("Out of memory: unswap object '%s'.\n", get_txt(ob->name));
return MY_FALSE;
}
- /* if there is a series of noecho/charmode input, we should only
- * negotiate when we know that the state actually should change.
- * In other words: should the input_to function request NOECHO
- * again, the NOECHO_STALE bit will be cleared and we will not
- * turn NOECHO off after the call.
- */
- if (i->noecho)
- {
- i->noecho |= NOECHO_STALE;
- }
-
/* Clear the input_to() reference in case the function called
* sets up a new one.
*/
current_it = *it;
- i->input_to = it->next;
xfree(it);
- free_svalue(¤t_it.prompt); /* Don't need this anymore */
+ free_svalue(¤t_it.input.prompt); /* Don't need this anymore */
/* Activate the local error recovery context */
@@ -4105,17 +4068,108 @@
rt_context = error_recovery_info.rt.last;
- /* If NOECHO is no longer needed, turn it off. */
+ /* Done */
+ return MY_TRUE;
+}
- if (i->noecho & NOECHO_STALE)
+/*-------------------------------------------------------------------------*/
+Bool
+call_function_interactive (interactive_t *i, char *str)
+
+/* Execute a pending input handler for this user <i> and the input <str>
+ * Return TRUE if an input_to() or ed() was pending and executed, and FALSE
+ * if the input was not processed.
+ *
+ * This function is called by the backend as part of the input processing.
+ */
+
+{
+ input_t *ih;
+ ih = i->input_handler;
+
+ /* _Are_ there an input_to() pending? */
+ if (!ih)
+ return MY_FALSE;
+
+ /* Yes, there are. Check if we have to handle input escape. */
+ if (*str == input_escape && str[1])
{
- set_noecho(i, i->input_to ? i->input_to->noecho : 0
- , i->input_to ? i->input_to->local : MY_FALSE
- , MY_TRUE);
+ input_t * prev;
+
+ for (prev = NULL
+ ; ih && !(ih->noecho & IGNORE_BANG)
+ ; prev = ih, ih = ih->next)
+ NOOP;
+
+ if (ih)
+ {
+ /* Move this 'IGNORE_BANG' input_to to the top of list
+ * since it's the one we're going to execute.
+ */
+ if (prev)
+ {
+ prev->next = ih->next;
+ ih->next = i->input_handler;
+ i->input_handler = ih;
+ }
+
+ if (!(i->noecho & NOECHO) != !(ih->noecho & NOECHO_REQ)) {
+ /* !message for ECHO-context while in NOECHO - simulate the
+ * echo by sending the (remaining) raw data we got.
+ */
+ add_message("%s\n", str + i->chars_ready);
+ i->chars_ready = 0;
+ }
+
+ /* Don't hide the leading input escape */
+ }
+ else
+ {
+ /* Bang-input but no matching input_to(): return */
+ return MY_FALSE;
+ }
}
- /* Done */
- return MY_TRUE;
+ switch (ih->type)
+ {
+ case INPUT_TO:
+ {
+ Bool res;
+
+ i->input_handler = ih->next;
+
+ /* if there is a series of noecho/charmode input, we should only
+ * negotiate when we know that the state actually should change.
+ * In other words: should the input_to function request NOECHO
+ * again, the NOECHO_STALE bit will be cleared and we will not
+ * turn NOECHO off after the call.
+ */
+ if (i->noecho)
+ {
+ i->noecho |= NOECHO_STALE;
+ }
+
+ res = call_input_to(i, str, (input_to_t*) ih);
+
+ /* If NOECHO is no longer needed, turn it off. */
+
+ if (i->noecho & NOECHO_STALE)
+ {
+ set_noecho(i, i->input_handler ? i->input_handler->noecho : 0
+ , i->input_handler ? i->input_handler->local : MY_FALSE
+ , MY_TRUE);
+ }
+
+ return res;
+ }
+
+ case INPUT_ED:
+ ed_cmd(str, ih);
+ return MY_TRUE;
+ }
+
+ return MY_FALSE;
+
} /* call_function_interactive() */
/*-------------------------------------------------------------------------*/
@@ -4141,37 +4195,30 @@
return MY_FALSE;
if (!(O_SET_INTERACTIVE(ip, ob))
|| ip->closing
- || ( !append && ip->input_to != NULL
- && ip->input_to->eval_nr == eval_number)
)
{
return MY_FALSE;
}
- it->noecho = noecho;
- it->local = local_change;
+ if (!append && ip->input_handler != NULL)
+ {
+ input_t * ih = ip->input_handler;
- /* Appended input_tos never count. */
- it->eval_nr = eval_number - (append ? 1 : 0);
+ while (ih && ih->type != INPUT_TO)
+ ih = ih->next;
- if (!append || ip->input_to == NULL)
- {
- it->next = ip->input_to;
- ip->input_to = it;
+ if (ih && ((input_to_t*)ih)->eval_nr == eval_number)
+ return MY_FALSE;
}
- else
- {
- input_to_t * ptr = ip->input_to;
- while (ptr->next != NULL)
- ptr = ptr->next;
+ it->input.noecho = noecho;
+ it->input.local = local_change;
+ it->input.type = INPUT_TO;
- ptr->next = it;
- it->next = NULL;
- }
+ /* Appended input_tos never count. */
+ it->eval_nr = eval_number - (append ? 1 : 0);
- if (noecho || ip->noecho)
- set_noecho(ip, noecho, local_change, MY_FALSE);
+ add_input_handler(ip, &(it->input), append);
return MY_TRUE;
} /* set_call() */
@@ -4298,11 +4345,11 @@
if (!(O_SET_INTERACTIVE(ip, command_giver)))
fatal("print_prompt() of non-interactive object\n");
- if (ip->input_to != NULL)
+ if (ip->input_handler != NULL)
{
- prompt = &ip->input_to->prompt;
+ prompt = &ip->input_handler->prompt;
}
- else if (NULL == (prompt = get_ed_prompt(ip)))
+ else
{
prompt = &ip->prompt;
if (prompt->type != T_CLOSURE && prompt->type != T_STRING)
@@ -6186,45 +6233,50 @@
for(i = 0 ; i < MAX_PLAYERS; i++)
{
- input_to_t * it, * prev;
+ input_t * ih, * prev;
object_t *ob;
if (all_players[i] == NULL)
continue;
/* Remove stale input_to data */
- for ( prev = NULL, it = all_players[i]->input_to; it != NULL; )
- {
- input_to_t *tmp;
- ob = callback_object(&(it->fun));
- if (ob)
+ for ( prev = NULL, ih = all_players[i]->input_handler; ih != NULL; )
+ if (ih->type == INPUT_TO)
{
- prev = it;
- it = it->next;
- }
- else
- {
- /* The object has selfdestructed */
-
- if (prev == NULL)
+ input_to_t *tmp = (input_to_t*) ih;
+ ob = callback_object(&(tmp->fun));
+ if (ob)
{
- set_noecho(all_players[i]
- , it->next ? it->next->noecho : 0
- , it->next ? it->next->local : MY_FALSE
- , MY_TRUE);
- all_players[i]->input_to = it->next;
+ prev = ih;
+ ih = ih->next;
}
else
{
- prev->next = it->next;
- }
+ /* The object has selfdestructed */
- tmp = it;
- it = it->next;
+ if (prev == NULL)
+ {
+ set_noecho(all_players[i]
+ , ih->next ? ih->next->noecho : 0
+ , ih->next ? ih->next->local : MY_FALSE
+ , MY_TRUE);
+ all_players[i]->input_handler = ih->next;
+ }
+ else
+ {
+ prev->next = ih->next;
+ }
- free_input_to(tmp);
+ ih = ih->next;
+
+ free_input_to(tmp);
+ }
}
- }
+ else
+ {
+ prev = ih;
+ ih = ih->next;
+ }
/* Remove stale snooping monsters */
ob = all_players[i]->snoop_by;
@@ -6265,7 +6317,7 @@
for (i = 0; i <= max_player; i++)
{
interactive_t *pl;
- input_to_t *it;
+ input_t *ih;
pl = all_players[i];
if (!pl)
@@ -6273,10 +6325,16 @@
sum += sizeof(*pl);
- for (it = pl->input_to; it != NULL; it = it->next)
- sum += sizeof(*it);
-
- sum += ed_buffer_size(O_GET_EDBUFFER(pl->ob));
+ for (ih = pl->input_handler; ih != NULL; ih = ih->next)
+ switch(ih->type)
+ {
+ case INPUT_TO:
+ sum += sizeof(input_to_t);
+ break;
+ case INPUT_ED:
+ sum += ed_buffer_size(ih);
+ break;
+ }
}
if (sbuf)
@@ -6350,6 +6408,56 @@
#endif /* ERQ_DEMON */
} /* count_comm_refs() */
+/*-------------------------------------------------------------------------*/
+void
+clear_input_refs (input_t *i)
+
+/* GC Support: Clear all references from input_t <i>.
+ */
+
+{
+ switch (i->type)
+ {
+ case INPUT_TO:
+ {
+ input_to_t *it = (input_to_t*) i;
+
+ clear_ref_in_callback(&(it->fun));
+ clear_ref_in_vector(&(it->input.prompt), 1);
+
+ break;
+ }
+ case INPUT_ED:
+ clear_ed_buffer_refs(i);
+ break;
+ }
+} /* clear_input_refs() */
+
+/*-------------------------------------------------------------------------*/
+void
+count_input_refs (input_t *i)
+
+/* GC Support: Count all references from input_t <i>.
+ */
+
+{
+ switch (i->type)
+ {
+ case INPUT_TO:
+ {
+ input_to_t *it = (input_to_t*) i;
+
+ count_ref_in_callback(&(it->fun));
+ count_ref_in_vector(&(it->input.prompt), 1);
+
+ break;
+ }
+ case INPUT_ED:
+ count_ed_buffer_refs(i);
+ break;
+ }
+} /* count_input_refs() */
+
#endif /* GC_SUPPORT */
@@ -6656,7 +6764,7 @@
for (i = 0; i < MAX_PLAYERS; i++)
{
object_t *ob;
- input_to_t *it;
+ input_t *ih;
if (all_players[i] == 0)
continue;
@@ -6671,11 +6779,21 @@
}
} /* end of snoop-processing */
- for ( it = all_players[i]->input_to; it; it = it->next)
- {
- count_callback_extra_refs(&(it->fun));
- count_extra_ref_in_vector(&it->prompt, 1);
- }
+ for ( ih = all_players[i]->input_handler; ih; ih = ih->next)
+ switch(ih->type)
+ {
+ case INPUT_TO:
+ {
+ input_to_t *it = (input_to_t*) ih;
+ count_callback_extra_refs(&(it->fun));
+ count_extra_ref_in_vector(&it->input.prompt, 1);
+ break;
+ }
+ case INPUT_ED:
+ count_ed_buffer_extra_refs(ih);
+ break;
+ }
+
if ( NULL != (ob = all_players[i]->modify_command) )
count_extra_ref_in_object(ob);
count_extra_ref_in_vector(&all_players[i]->prompt, 1);
@@ -7317,13 +7435,13 @@
xallocate(it, sizeof *it, "new input_to");
init_empty_callback(&(it->fun));
- put_number(&(it->prompt), 0);
+ put_number(&(it->input.prompt), 0);
/* If SET_PROMPT was specified, collect it */
if (iflags & INPUT_PROMPT)
{
- transfer_svalue(&(it->prompt), arg+2);
+ transfer_svalue(&(it->input.prompt), arg+2);
extra--;
extra_arg++;
}
@@ -7393,11 +7511,136 @@
{
free_callback(&(it->fun));
- free_svalue(&(it->prompt));
+ free_svalue(&(it->input.prompt));
xfree(it);
} /* free_input_to() */
/*-------------------------------------------------------------------------*/
+static void
+free_input_handler (input_t *ih)
+
+/* Deallocate the input_t structure <ih> and all referenced memory.
+ */
+
+{
+ switch (ih->type)
+ {
+ case INPUT_TO:
+ free_input_to((input_to_t*) ih);
+ break;
+
+ case INPUT_ED:
+ free_ed_buffer(ih);
+ break;
+ }
+
+} /* free_input_handler() */
+
+/*-------------------------------------------------------------------------*/
+void
+abort_input_handler (interactive_t *ip)
+
+/* Called from destruct_object to finish some input handlers,
+ * specifically save all ed sessions.
+ */
+{
+ input_t ** ptr = &(ip->input_handler);
+
+ while (*ptr)
+ {
+ switch ((*ptr)->type)
+ {
+ case INPUT_ED:
+ {
+ input_t * ed_buf = *ptr;
+
+ *ptr = (*ptr)->next;
+ save_ed_buffer(ed_buf);
+ break;
+ }
+
+ default:
+ ptr = &((*ptr)->next);
+ break;
+ }
+ }
+} /* abort_input_handler() */
+
+/*-------------------------------------------------------------------------*/
+void
+add_input_handler (interactive_t *ip, input_t *ih, Bool append)
+
+/* Put the input handler <ih> in front of the input handler list of
+ * the interactive <ip>.
+ * If <append> is TRUE, the handler is appended to the list.
+ */
+{
+ if (!append || ip->input_handler == NULL)
+ {
+ ih->next = ip->input_handler;
+ ip->input_handler = ih;
+ }
+ else
+ {
+ input_t * ptr = ip->input_handler;
+
+ while (ptr->next != NULL)
+ ptr = ptr->next;
+
+ ptr->next = ih;
+ ih->next = NULL;
+ }
+
+ if (ih->noecho || ip->noecho)
+ set_noecho(ip, ih->noecho, ih->local, MY_FALSE);
+
+} /* add_input_handler() */
+
+/*-------------------------------------------------------------------------*/
+void
+remove_input_handler (interactive_t *ip, input_t *ih)
+
+/* Remove the input handler <ih> from the input handler list of
+ * the interactive <ip>. <ih> is not freed.
+ */
+{
+ input_t * ptr = ip->input_handler;
+
+ if (ptr == ih)
+ {
+ ip->input_handler = ih->next;
+ return;
+ }
+
+ while (ptr)
+ {
+ if (ptr->next == ih)
+ {
+ ptr->next = ih->next;
+ break;
+ }
+ ptr = ptr->next;
+ }
+
+} /* remove_input_handler() */
+
+/*-------------------------------------------------------------------------*/
+input_t *
+get_input_handler (interactive_t *ip, input_type_t type)
+
+/* Returns the first input handler from <ip> of type <type>.
+ */
+{
+ input_t *ih;
+
+ for (ih = ip->input_handler; ih; ih = ih->next)
+ if (ih->type == type)
+ return ih;
+
+ return NULL;
+} /* get_input_handler */
+
+/*-------------------------------------------------------------------------*/
svalue_t *
f_query_input_pending (svalue_t *sp)
@@ -7415,11 +7658,21 @@
interactive_t *ip;
ob = sp->u.ob;
- if (O_SET_INTERACTIVE(ip, ob) && ip->input_to)
+ if (O_SET_INTERACTIVE(ip, ob) && ip->input_handler)
{
- cb = callback_object(&(ip->input_to->fun));
- if (cb)
- sp->u.ob = ref_object(cb, "query_input_pending");
+ input_t *ih = ip->input_handler;
+
+ while (ih && ih->type != INPUT_TO)
+ ih = ih->next;
+
+ if (ih)
+ {
+ cb = callback_object(&(((input_to_t*)ih)->fun));
+ if (cb)
+ sp->u.ob = ref_object(cb, "query_input_pending");
+ else
+ put_number(sp, 0);
+ }
else
put_number(sp, 0);
}
@@ -7480,8 +7733,9 @@
}
/* Process the command, terminating out when possible */
- do {
- input_to_t *it;
+ do
+ {
+ input_t *ih;
interactive_t *ip;
/* Get the interactive object.
@@ -7489,7 +7743,7 @@
* an input_to set, fail.
*/
if (!(O_SET_INTERACTIVE(ip, arg[0].u.ob))
- || ip->closing || ip->input_to == NULL
+ || ip->closing || ip->input_handler == NULL
)
{
rc = -1;
@@ -7498,12 +7752,17 @@
/* Search for the right input_to */
- for ( it = ip->input_to
- ; it != NULL
- ; it = it->next)
+ for ( ih = ip->input_handler
+ ; ih != NULL
+ ; ih = ih->next)
{
+ input_to_t *it;
Bool found = MY_FALSE;
+ if (ih->type != INPUT_TO)
+ continue;
+ it = (input_to_t*) ih;
+
switch (arg[1].type)
{
case T_STRING:
@@ -7544,12 +7803,12 @@
break;
}
- if (it != NULL)
+ if (ih != NULL)
{
/* We found the input_to: now count at which position it is */
- for ( rc = 0
- ; it->next != NULL
- ; it = it->next, rc++) NOOP ;
+ for ( rc = 0; ih->next != NULL; ih = ih->next)
+ if (ih->type == INPUT_TO)
+ rc++;
break;
}
@@ -7619,9 +7878,10 @@
/* Process the command, bailing out whenever necessary */
- do {
- input_to_t * prev;
- input_to_t *it;
+ do
+ {
+ input_t * prev;
+ input_t *ih;
removedFirst = MY_FALSE;
@@ -7630,34 +7890,32 @@
* an input_to set, fail.
*/
if (!(O_SET_INTERACTIVE(ip, arg[0].u.ob))
- || ip->closing || ip->input_to == NULL
+ || ip->closing || ip->input_handler == NULL
)
{
rc = 0;
break;
}
- /* If no filter argument has been given, just remove
- * the first input to.
- */
- if (num_arg < 2)
- {
- it = ip->input_to;
- ip->input_to = it->next;
- free_input_to(it);
- removedFirst = MY_TRUE;
- rc = 1;
- break;
- }
+ /* Search for the right input_to */
- /* There is a filter argument: search for the right input_to */
-
- for (prev = NULL, it = ip->input_to
- ; it != NULL
- ; prev = it, it = it->next)
+ for (prev = NULL, ih = ip->input_handler
+ ; ih != NULL
+ ; prev = ih, ih = ih->next)
{
+ input_to_t *it;
Bool found = MY_FALSE;
+ if (ih->type != INPUT_TO)
+ continue;
+ it = (input_to_t*) ih;
+
+ /* If no filter argument has been given, just remove
+ * the first input to.
+ */
+ if (num_arg < 2)
+ break;
+
switch (arg[1].type)
{
case T_STRING:
@@ -7698,18 +7956,18 @@
break;
}
- if (it != NULL)
+ if (ih != NULL)
{
/* We found the input_to: remove it */
if (prev == NULL)
{
- ip->input_to = it->next;
+ ip->input_handler = ih->next;
removedFirst = MY_TRUE;
}
else
- prev->next = it->next;
+ prev->next = ih->next;
- free_input_to(it);
+ free_input_to((input_to_t*)ih);
rc = 1;
break;
}
@@ -7722,8 +7980,8 @@
{
if (ip->noecho)
ip->noecho |= NOECHO_STALE;
- set_noecho(ip, ip->input_to ? ip->input_to->noecho : ip->noecho
- , ip->input_to ? ip->input_to->local : MY_FALSE
+ set_noecho(ip, ip->input_handler ? ip->input_handler->noecho : ip->noecho
+ , ip->input_handler ? ip->input_handler->local : MY_FALSE
, MY_FALSE
);
}
@@ -7754,7 +8012,7 @@
{
vector_t *v;
int num_pending;
- input_to_t *it;
+ input_t *ih;
interactive_t *ip;
/* Get the interactive object.
@@ -7762,7 +8020,7 @@
* an input_to set, the efun will return the empty array.
*/
if (!(O_SET_INTERACTIVE(ip, sp->u.ob))
- || ip->closing || ip->input_to == NULL
+ || ip->closing || ip->input_handler == NULL
)
{
num_pending = 0;
@@ -7771,9 +8029,11 @@
{
/* Count the number of pending input_tos.
*/
- for ( num_pending = 0, it = ip->input_to
- ; it != NULL
- ; it = it->next, num_pending++) NOOP ;
+ for ( num_pending = 0, ih = ip->input_handler
+ ; ih != NULL
+ ; ih = ih->next)
+ if (ih->type == INPUT_TO)
+ num_pending++;
}
/* Allocate the result arrray and fill it in */
@@ -7783,14 +8043,23 @@
{
int i;
- for (i = num_pending, it = ip->input_to
+ for (i = num_pending, ih = ip->input_handler
; --i >= 0
- ; it = it->next
+ ; ih = ih->next
)
{
- vector_t *vv;
- object_t *ob;
+ vector_t *vv;
+ object_t *ob;
+ input_to_t *it;
+ if (ih->type != INPUT_TO)
+ {
+ i++;
+ continue;
+ }
+
+ it = (input_to_t*) ih;
+
ob = callback_object(&(it->fun));
if (!ob)
continue;
Index: trunk.ed/src/comm.h
===================================================================
--- trunk.ed/src/comm.h (Revision 2584)
+++ trunk.ed/src/comm.h (Arbeitskopie)
@@ -8,7 +8,7 @@
# include <zlib.h>
#endif
-#include "simulate.h" /* callback_t for input_to_t */
+#include "simulate.h" /* callback_t for TLS */
#include "svalue.h"
#include "pkg-tls.h"
@@ -152,20 +152,27 @@
typedef char discarded_msg_state_t;
-/* --- struct input_to_s: input_to() datastructure
+enum input_type_e {
+ INPUT_TO /* A normal input_to. */
+ , INPUT_ED /* An ed() session. */
+};
+
+typedef enum input_type_e input_type_t;
+
+/* --- struct input_s: Stack of input handlers.
*
- * input-to structures describe a pending input_to() for a given
- * interactive object. Every object can have one input-to pending, the
- * pointer to the structure is stored in the interactive sentence structure.
+ * input_s represents all pending input handlers, which
+ * are at this time either normal input_to()s or ed() sessions.
+ * Every interactive object can have these input handlers,
+ * the pointer to the structure is stored in the interactive
+ * sentence structure.
*/
-
-struct input_to_s {
- input_to_t *next;
- svalue_t prompt; /* the prompt, may be 0 */
- char noecho; /* the requested "noecho" state */
- Bool local; /* TRUE if a CHARMODE change is local only */
- callback_t fun; /* The function to call, and its args */
- p_uint eval_nr; /* The thread number where this started. */
+struct input_s {
+ input_t *next;
+ input_type_t type;
+ svalue_t prompt; /* the prompt, may be 0 */
+ char noecho; /* the requested "noecho" state */
+ Bool local; /* TRUE if a CHARMODE change is local only */
};
/* --- struct interactive_s: an interactive connection
@@ -184,7 +191,7 @@
struct interactive_s {
SOCKET_T socket; /* The socket structure */
object_t *ob; /* Points back to the associated object */
- input_to_t *input_to; /* != NULL: defines function to be
+ input_t *input_handler; /* != NULL: defines function to be
called with next input line */
object_t *modify_command; /* modify_command() handler() */
svalue_t prompt; /* The prompt to print. */
@@ -425,8 +432,15 @@
#ifdef GC_SUPPORT
extern void clear_comm_refs(void);
extern void count_comm_refs(void);
+extern void clear_input_refs(input_t *it);
+extern void count_input_refs(input_t *it);
#endif /* GC_SUPPORT */
+extern void add_input_handler(interactive_t *ip, input_t *ih, Bool append);
+extern void remove_input_handler(interactive_t *ip, input_t *ih);
+extern void abort_input_handler(interactive_t *ip);
+extern input_t *get_input_handler(interactive_t *ip, input_type_t type);
+
extern char *query_host_name(void);
extern char *get_host_ip_number(void);
extern svalue_t *f_query_snoop(svalue_t *sp);
Index: trunk.ed/src/sent.h
===================================================================
--- trunk.ed/src/sent.h (Revision 2584)
+++ trunk.ed/src/sent.h (Arbeitskopie)
@@ -34,8 +34,7 @@
*
* SENT_SHADOW:
* The sentence is of type 'shadow_sentence' and describes
- * an object shadow. It also holds the ed_buffer_t* for
- * objects using the editor.
+ * an object shadow.
*
*---------------------------------------------------------------------------
*/
@@ -111,8 +110,8 @@
* list.
*
* Additionally the shadow sentence is used to hold additionally information
- * used by the object for short time. Such information is the ed_buffer_t
- * for editor uses, and the interactive_t for interactive objects.
+ * used by the object for short time. Such information is the interactive_t
+ * for interactive objects.
*/
struct shadow_s
{
@@ -120,7 +119,6 @@
object_t *shadowing; /* "prev": the shadowed object */
object_t *shadowed_by; /* "next": the shadowing object */
- ed_buffer_t *ed_buffer; /* the editor buffer, if needed */
interactive_t *ip; /* the information for interactive objects */
};
@@ -128,7 +126,6 @@
#define O_GET_SHADOW(ob) ((shadow_t *)(ob)->sent)
#define O_GET_INTERACTIVE(ob) (O_GET_SHADOW(ob)->ip)
-#define O_GET_EDBUFFER(ob) (O_GET_SHADOW(ob)->ed_buffer)
/* Expand to an expression suitable to query or set the
* indicated attribute. No checks are performed.
Index: trunk.ed/src/gcollect.c
===================================================================
--- trunk.ed/src/gcollect.c (Revision 2584)
+++ trunk.ed/src/gcollect.c (Arbeitskopie)
@@ -93,7 +93,6 @@
#include "call_out.h"
#include "closure.h"
#include "comm.h"
-#include "ed.h"
#include "efuns.h"
#include "filestat.h"
#include "heartbeat.h"
@@ -1985,15 +1984,6 @@
ob->ref = 0;
clear_string_ref(ob->name);
clear_ref_in_vector(ob->variables, ob->prog->num_variables);
- if (ob->flags & O_SHADOW)
- {
- ed_buffer_t *buf;
-
- if ( NULL != (buf = O_GET_EDBUFFER(ob)) )
- {
- clear_ed_buffer_refs(buf);
- } /* end of ed-buffer processing */
- }
if (was_swapped)
{
swap(ob, was_swapped);
@@ -2009,16 +1999,15 @@
for(i = 0 ; i < MAX_PLAYERS; i++)
{
- input_to_t * it;
+ input_t * it;
if (all_players[i] == NULL)
continue;
- for ( it = all_players[i]->input_to; it != NULL; it = it->next)
+ for ( it = all_players[i]->input_handler; it != NULL; it = it->next)
{
clear_memory_reference(it);
- clear_ref_in_callback(&(it->fun));
- clear_ref_in_vector(&(it->prompt), 1);
+ clear_input_refs(it);
}
#ifdef USE_TLS
@@ -2151,22 +2140,15 @@
if (ob->sent)
{
sentence_t *sent;
- ed_buffer_t *buf;
sent = ob->sent;
if (ob->flags & O_SHADOW)
{
note_ref(sent);
- if ( NULL != (buf = ((shadow_t *)sent)->ed_buffer) )
- {
- note_ref(buf);
- count_ed_buffer_refs(buf);
- } /* end of ed-buffer processing */
/* If there is a ->ip, it will be processed as
* part of the player object handling below.
*/
-
sent = sent->next;
}
if (sent)
@@ -2188,7 +2170,7 @@
for(i = 0 ; i < MAX_PLAYERS; i++)
{
- input_to_t * it;
+ input_t * it;
if (all_players[i] == NULL)
continue;
@@ -2225,11 +2207,10 @@
}
} /* end of snoop-processing */
- for ( it = all_players[i]->input_to; it != NULL; it = it->next)
+ for ( it = all_players[i]->input_handler; it != NULL; it = it->next)
{
note_ref(it);
- count_ref_in_callback(&(it->fun));
- count_ref_in_vector(&(it->prompt), 1);
+ count_input_refs(it);
} /* end of input_to processing */
#ifdef USE_TLS
Index: trunk.ed/src/backend.c
===================================================================
--- trunk.ed/src/backend.c (Revision 2584)
+++ trunk.ed/src/backend.c (Arbeitskopie)
@@ -671,8 +671,6 @@
execute_command(buff+1, command_giver);
}
}
- else if (O_GET_EDBUFFER(command_giver))
- ed_cmd(buff);
else if (call_function_interactive(ip, buff))
NOOP;
else
Index: trunk.ed/src/interpret.c
===================================================================
--- trunk.ed/src/interpret.c (Revision 2584)
+++ trunk.ed/src/interpret.c (Arbeitskopie)
@@ -216,7 +216,6 @@
#include "call_out.h"
#include "closure.h"
#include "comm.h"
-#include "ed.h"
#include "efuns.h"
#include "exec.h"
#include "filestat.h"
@@ -20100,14 +20099,6 @@
if (was_swapped)
swap_program(ob);
-
- if (ob->flags & O_SHADOW)
- {
- ed_buffer_t *buf;
-
- if ( NULL != (buf = O_GET_SHADOW(ob)->ed_buffer) )
- count_ed_buffer_extra_refs(buf);
- }
} /* count_extra_ref_in_object() */
/*-------------------------------------------------------------------------*/
Index: trunk.ed/src/simulate.c
===================================================================
--- trunk.ed/src/simulate.c (Revision 2584)
+++ trunk.ed/src/simulate.c (Arbeitskopie)
@@ -2470,17 +2470,16 @@
errorf("Master failed to clean inventory in prepare_destruct\n");
}
- if (ob->flags & O_SHADOW)
+ if (O_IS_INTERACTIVE(ob))
{
- shadow_t *sh;
+ interactive_t *ip = O_GET_INTERACTIVE(ob);
object_t *save = command_giver;
command_giver = ob;
- sh = O_GET_SHADOW(ob);
- if (sh->ip)
- trace_level |= sh->ip->trace_level;
- if (sh->ed_buffer)
- save_ed_buffer();
+ trace_level |= ip->trace_level;
+
+ abort_input_handler(ip);
+
command_giver = save;
}
destruct(ob);
@@ -2582,15 +2581,6 @@
shadow_sent = O_GET_SHADOW(ob);
- if (shadow_sent->ed_buffer)
- {
- object_t *save = command_giver;
-
- command_giver = ob;
- free_ed_buffer();
- command_giver = save;
- }
-
/* The chain of shadows is a double linked list. Take care to update
* it correctly.
*/
@@ -3033,7 +3023,6 @@
p->sent.type = SENT_SHADOW;
p->shadowing = NULL;
p->shadowed_by = NULL;
- p->ed_buffer = NULL;
p->ip = NULL;
return p;
} /* new_shadow_sent() */
@@ -3072,7 +3061,6 @@
sh = O_GET_SHADOW(ob);
if (!sh->ip
- && !sh->ed_buffer
&& !sh->shadowing
&& !sh->shadowed_by
)
Index: trunk.ed/src/ed.c
===================================================================
--- trunk.ed/src/ed.c (Revision 2584)
+++ trunk.ed/src/ed.c (Arbeitskopie)
@@ -175,9 +175,12 @@
/* The ed_buffer holds all the information for one editor session.
*/
+typedef struct ed_buffer_s ed_buffer_t;
struct ed_buffer_s
{
+ input_t input; /* It's an input handler. */
+
Bool diag; /* True: diagnostic-output?*/
Bool truncflg; /* True: truncate long line flag
* Note: not used anywhere */
@@ -207,7 +210,6 @@
string_t *exit_fn; /* Function to be called when player exits */
/* TODO: Make this a callback */
object_t *exit_ob; /* Object holding <exit_fn> */
- svalue_t prompt; /* Editor prompt, a counted shared string */
};
/* ed_buffer.flag values
@@ -229,8 +231,8 @@
/* Macros handling the current ed_buffer for less typing */
-#define ED_BUFFER (current_ed_buffer)
-#define EXTERN_ED_BUFFER (O_GET_SHADOW(command_giver)->ed_buffer)
+#define ED_BUFFER (current_ed_buffer)
+#define EXTERN_ED_BUFFER(ih) ((ed_buffer_t*) (ih))
#define P_DIAG (ED_BUFFER->diag)
#define P_TRUNCFLG (ED_BUFFER->truncflg)
@@ -365,12 +367,13 @@
/*-------------------------------------------------------------------------*/
size_t
-ed_buffer_size (ed_buffer_t *buffer)
+ed_buffer_size (input_t *ih)
/* Return the size of the memory allocated for the <buffer>
*/
{
+ ed_buffer_t *buffer = (ed_buffer_t*) ih;
size_t sum;
long line;
LINE *pLine;
@@ -396,8 +399,8 @@
*/
{
- free_mstring(ed_buffer->prompt.u.str);
- ed_buffer->prompt.u.str = ref_mstring(prompt);
+ free_mstring(ed_buffer->input.prompt.u.str);
+ ed_buffer->input.prompt.u.str = ref_mstring(prompt);
} /* set_ed_prompt() */
/*-------------------------------------------------------------------------*/
@@ -474,24 +477,6 @@
}
/*-------------------------------------------------------------------------*/
-svalue_t *
-get_ed_prompt (interactive_t *ip)
-
-/* Return a pointer to the prompt svalue in <ip>->ed_buffer.
- * Return NULL if <ip> is not editing.
- */
-
-{
- ed_buffer_t *ed_buffer;
-
- if (NULL != (ed_buffer = O_GET_EDBUFFER(ip->ob)))
- {
- return &(ed_buffer->prompt);
- }
- return NULL;
-} /* get_ed_prompt() */
-
-/*-------------------------------------------------------------------------*/
static void
count_blanks (int line)
@@ -3160,13 +3145,11 @@
string_t *new_path;
svalue_t *setup;
ed_buffer_t *old_ed_buffer;
+ interactive_t *ip;
- if (!command_giver || !(O_IS_INTERACTIVE(command_giver)))
+ if (!command_giver || !(O_SET_INTERACTIVE(ip, command_giver)))
errorf("Tried to start an ed session on a non-interative player.\n");
- if (EXTERN_ED_BUFFER)
- errorf("Tried to start an ed session, when already active.\n");
-
/* Check for read on startup, since the buffer is read in. But don't
* check for write, since we may want to change the file name.
*/
@@ -3175,28 +3158,30 @@
return;
/* Never trust the master... it might be as paranoid as ourselves...
- * Starting another ed session in valid_read() looks stupid, but
- * possible.
*/
if (!command_giver
|| !(command_giver->flags & O_SHADOW)
|| command_giver->flags & O_DESTRUCTED
- || EXTERN_ED_BUFFER)
+ )
{
return;
}
old_ed_buffer = ED_BUFFER;
- EXTERN_ED_BUFFER =
- ED_BUFFER = (ed_buffer_t *)xalloc(sizeof (ed_buffer_t));
+ ED_BUFFER = (ed_buffer_t *)xalloc(sizeof (ed_buffer_t));
memset(ED_BUFFER, '\0', sizeof (ed_buffer_t));
+ ED_BUFFER->input.type = INPUT_ED;
+
ED_BUFFER->truncflg = MY_TRUE;
ED_BUFFER->flags |= EIGHTBIT_MASK | TABINDENT_MASK;
ED_BUFFER->shiftwidth= 4;
- put_ref_string(&(ED_BUFFER->prompt), STR_ED_PROMPT);
+ put_ref_string(&(ED_BUFFER->input.prompt), STR_ED_PROMPT);
ED_BUFFER->CurPtr = &ED_BUFFER->Line0;
+
+ add_input_handler(ip, &(ED_BUFFER->input), MY_FALSE);
+
if (exit_fn)
{
ED_BUFFER->exit_fn = ref_mstring(exit_fn);
@@ -3248,12 +3233,13 @@
/*-------------------------------------------------------------------------*/
void
-clear_ed_buffer_refs (ed_buffer_t *b)
+clear_ed_buffer_refs (input_t *ih)
/* GC Support: Clear all references from ed_buffer <b>.
*/
{
+ ed_buffer_t *b = (ed_buffer_t*) ih;
object_t *ob;
if (b->fname)
@@ -3279,17 +3265,18 @@
/* For the RE cache */
clear_regexp_ref(b->oldpat);
- clear_ref_in_vector(&b->prompt, 1);
+ clear_ref_in_vector(&b->input.prompt, 1);
}
/*-------------------------------------------------------------------------*/
void
-count_ed_buffer_refs (ed_buffer_t *b)
+count_ed_buffer_refs (input_t *ih)
/* GC Support: Count all references from ed_buffer <b>.
*/
{
+ ed_buffer_t *b = (ed_buffer_t*) ih;
object_t *ob;
LINE *line;
@@ -3325,7 +3312,7 @@
if (b->oldpat)
count_regexp_ref(b->oldpat);
- count_ref_in_vector(&b->prompt, 1);
+ count_ref_in_vector(&b->input.prompt, 1);
}
#endif /* GC_SUPPORT */
@@ -3333,12 +3320,13 @@
#ifdef DEBUG
/*-------------------------------------------------------------------------*/
void
-count_ed_buffer_extra_refs (ed_buffer_t *b)
+count_ed_buffer_extra_refs (input_t *ih)
/* Count refs in ed_buffer <b> to debug refcounts.
*/
{
+ ed_buffer_t *b = (ed_buffer_t*) ih;
object_t *ob;
if ( NULL != (ob = b->exit_ob) )
@@ -3349,7 +3337,7 @@
/*-------------------------------------------------------------------------*/
void
-free_ed_buffer (void)
+free_ed_buffer (input_t *ih)
/* Deallocate the ed_buffer of the command_giver and call the exit function
* if set.
@@ -3361,13 +3349,14 @@
{
string_t *name;
object_t *ob;
+ interactive_t *ip;
- ED_BUFFER = EXTERN_ED_BUFFER;
+ ED_BUFFER = EXTERN_ED_BUFFER(ih);
clrbuf();
ob = ED_BUFFER->exit_ob;
name = ED_BUFFER->exit_fn;
- free_svalue(&ED_BUFFER->prompt);
+ free_svalue(&ED_BUFFER->input.prompt);
if(P_OLDPAT)
{
@@ -3377,9 +3366,9 @@
if (P_FNAME)
free_mstring(P_FNAME);
-
+ if (O_SET_INTERACTIVE(ip, command_giver))
+ remove_input_handler(ip, ih);
xfree(ED_BUFFER);
- EXTERN_ED_BUFFER = NULL;
if (name)
{
@@ -3393,8 +3382,6 @@
current_object = ob;
secure_apply(name, ob, 0);
- /* might call efun ed, thus setting (EXTERN_)ED_BUFFER again
- */
current_object = save;
}
if (ob)
@@ -3409,7 +3396,7 @@
/*-------------------------------------------------------------------------*/
void
-ed_cmd (char *str)
+ed_cmd (char *str, input_t *ih)
/* Called from the backend with a new line of player input in <str>.
*/
@@ -3419,7 +3406,7 @@
ed_buffer_t *old_ed_buffer;
old_ed_buffer = ED_BUFFER;
- ED_BUFFER = EXTERN_ED_BUFFER;
+ ED_BUFFER = EXTERN_ED_BUFFER(ih);
if (P_MORE)
{
print_help2();
@@ -3467,7 +3454,7 @@
switch (status)
{
case EOF:
- free_ed_buffer();
+ free_ed_buffer(&(ED_BUFFER->input));
ED_BUFFER = old_ed_buffer;
return;
@@ -3512,7 +3499,7 @@
/*-------------------------------------------------------------------------*/
void
-save_ed_buffer (void)
+save_ed_buffer (input_t *ih)
/* Called when the command_giver is destructed in an edit session.
* The function calls master->get_ed_buffer_save_file() to get a filename
@@ -3523,10 +3510,10 @@
{
svalue_t *stmp;
string_t *fname;
- interactive_t *save = O_GET_INTERACTIVE(command_giver);
+ interactive_t *save;
(void)O_SET_INTERACTIVE(save, command_giver);
- ED_BUFFER = EXTERN_ED_BUFFER;
+ ED_BUFFER = EXTERN_ED_BUFFER(ih);
push_ref_string(inter_sp, P_FNAME ? P_FNAME : STR_EMPTY);
stmp = apply_master(STR_GET_ED_FNAME,1);
if (save)
@@ -3553,7 +3540,7 @@
dowrite(1, P_LASTLN, fname , MY_FALSE);
free_mstring(fname);
}
- free_ed_buffer();
+ free_ed_buffer(ih);
}
/*-------------------------------------------------------------------------*/
@@ -3625,21 +3612,20 @@
*/
{
- object_t *ob;
- shadow_t *sent;
+ object_t *ob;
+ interactive_t *ip;
+ input_t *ih;
ob = sp->u.ob;
deref_object(ob, "query_editing");
- if (ob->flags & O_SHADOW
- && NULL != (sent = O_GET_SHADOW(ob))
- && sent->ed_buffer)
+
+ if (O_SET_INTERACTIVE(ip, ob)
+ && (ih = get_input_handler(ip, INPUT_ED)) != NULL)
{
- if ( NULL != (ob = sent->ed_buffer->exit_ob) )
- {
+ if ( NULL != (ob = ((ed_buffer_t*) ih)->exit_ob) )
sp->u.ob = ref_object(ob, "query_editing");
- return sp;
- }
- put_number(sp, 1);
+ else
+ put_number(sp, 1);
}
else
{
Index: trunk.ed/src/typedefs.h
===================================================================
--- trunk.ed/src/typedefs.h (Revision 2584)
+++ trunk.ed/src/typedefs.h (Arbeitskopie)
@@ -15,13 +15,12 @@
typedef struct callback_s callback_t; /* simulate.h */
typedef struct case_list_entry_s case_list_entry_t; /* switch.h */
typedef struct case_state_s case_state_t; /* switch.h */
-typedef struct ed_buffer_s ed_buffer_t; /* ed.c */
typedef struct function_s function_t; /* exec.h */
typedef struct ident_s ident_t; /* lex.h */
typedef struct include_s include_t; /* exec.h */
typedef struct inherit_s inherit_t; /* exec.h */
typedef struct interactive_s interactive_t; /* comm.h */
-typedef struct input_to_s input_to_t; /* comm.h */
+typedef struct input_s input_t; /* comm.h */
typedef struct instr_s instr_t; /* exec.h */
typedef struct lambda_s lambda_t; /* closure.h */
typedef struct linenumbers_s linenumbers_t; /* exec.h */
Index: trunk.ed/src/ed.h
===================================================================
--- trunk.ed/src/ed.h (Revision 2584)
+++ trunk.ed/src/ed.h (Arbeitskopie)
@@ -6,21 +6,20 @@
/* --- Prototypes --- */
-extern size_t ed_buffer_size (ed_buffer_t *buffer);
-extern svalue_t * get_ed_prompt (interactive_t *ip);
+extern size_t ed_buffer_size (input_t *ih);
#ifdef GC_SUPPORT
-extern void clear_ed_buffer_refs(ed_buffer_t *b);
-extern void count_ed_buffer_refs(ed_buffer_t *b);
+extern void clear_ed_buffer_refs(input_t *ih);
+extern void count_ed_buffer_refs(input_t *ih);
#endif /* GC_SUPPORT */
#ifdef DEBUG
-extern void count_ed_buffer_extra_refs(ed_buffer_t *b);
+extern void count_ed_buffer_extra_refs(input_t *ih);
#endif
-extern void free_ed_buffer(void);
-extern void ed_cmd(char *str);
-extern void save_ed_buffer(void);
+extern void free_ed_buffer(input_t *ih);
+extern void save_ed_buffer(input_t *ih);
+extern void ed_cmd(char *str, input_t *ih);
extern svalue_t *v_ed(svalue_t *sp, int num_arg);
extern svalue_t *f_query_editing(svalue_t *sp);
Index: trunk.ed/CHANGELOG
===================================================================
--- trunk.ed/CHANGELOG (Revision 2584)
+++ trunk.ed/CHANGELOG (Arbeitskopie)
@@ -1,6 +1,10 @@
This file lists all changes made to the game driver in all glory detail.
See the file HISTORY for a user-oriented summary of all the changes.
+??-May-2009 (Gnomi)
+ - (ed.c, comm.c) Put ed sessions into the input_to list of interactive
+ objects, so now they have a common noecho and prompt handling. (Bug #522)
+
12-May-2009 (Fuchur)
- (object.c) compile fix for !USE_NEW_INLINES
- (prolang.y) forbid accessing closure arguments from within the
| ||||
|
|
I'd like to do this, but putting the ed_buffer pointer into the input_to structure would mean subordinating them to interactive_t instead of object_t. As a result, the ed session would be destroyed on a relogin just as input_tos are destroyed now. Furthermore there is a TODO item that goes in the opposite direction: * TODO: Make it possible to attach an editor to any object, and let * TODO:: the editor communicate via efuns - no direct io. Despite all that I would like to do this, because input_to and ed share a lot similarities. |
|
|
I uploaded a patch that does that. |
|
|
Committed as r2595. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2008-01-04 17:55 | Gnomi | New Issue | |
| 2008-06-30 03:03 | Gnomi | Status | new => assigned |
| 2008-06-30 03:03 | Gnomi | Assigned To | => Gnomi |
| 2009-01-29 07:15 | Gnomi | Note Added: 0000939 | |
| 2009-05-09 06:15 | Gnomi | Target Version | => 3.3.719 |
| 2009-05-14 14:14 | Gnomi | File Added: bug522.diff | |
| 2009-05-14 14:14 | Gnomi | Note Added: 0001107 | |
| 2009-05-20 11:33 | Gnomi | Project | LDMud => LDMud 3.3 |
| 2009-05-27 12:17 | Gnomi | Note Added: 0001168 | |
| 2009-05-27 12:17 | Gnomi | Status | assigned => resolved |
| 2009-05-27 12:17 | Gnomi | Fixed in Version | => 3.3.719 |
| 2009-05-27 12:17 | Gnomi | Resolution | open => fixed |
| 2010-11-16 09:42 | Gnomi | Source_changeset_attached | => ldmud.git master 8ada51f9 |
| 2018-01-29 18:59 | Gnomi | Source_changeset_attached | => ldmud.git master 8ada51f9 |
| 2018-01-29 21:57 | Gnomi | Source_changeset_attached | => ldmud.git master 8ada51f9 |