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 |