Beispiel #1
0
/**
 * Substitute placeholders in a command string. Placeholders consist of two characters,
 * the first being a %. Use %% to output a plain % character.
 *
 * - <code>%i</code>: id member of the event
 * - <code>%p</code>: (symbolic events only) local player number
 *
 * @param command  Original command string with the placeholders.
 * @param event    Event data.
 * @param eb       Binding data.
 * @param out      String with placeholders replaced.
 */
static void B_SubstituteInCommand(char const *command, ddevent_t const *event,
                                  evbinding_t *eb, ddstring_t *out)
{
    const char* ptr = command;

    for(; *ptr; ptr++)
    {
        if(*ptr == '%')
        {
            // Escape.
            ptr++;

            // Must have another character in the placeholder.
            if(!*ptr) break;

            if(*ptr == 'i')
            {
                int id = 0;
                switch(event->type)
                {
                    case E_TOGGLE:
                        id = event->toggle.id;
                        break;

                    case E_AXIS:
                        id = event->axis.id;
                        break;

                    case E_ANGLE:
                        id = event->angle.id;
                        break;

                    case E_SYMBOLIC:
                        id = event->symbolic.id;
                        break;

                    default:
                        break;
                }
                Str_Appendf(out, "%i", id);
            }
            else if(*ptr == 'p')
            {
                int id = 0;
                if(event->type == E_SYMBOLIC)
                {
                    id = P_ConsoleToLocal(event->symbolic.id);
                }
                Str_Appendf(out, "%i", id);
            }
            else if(*ptr == '%')
            {
                Str_AppendChar(out, *ptr);
            }
            continue;
        }

        Str_AppendChar(out, *ptr);
    }
}
    virtual void invoke(int player, EventSequenceArg* args, int numArgs)
    {
        if(!strchr(Str_Text(&commandTemplate), '%'))
        {
            DD_Execute(true/*silent*/, Str_Text(&commandTemplate));
            return;
        }

        // Compose the command from the template, inserting values for named arguments.
        /// @todo This logic should be extracted and made into an Str method.
        AutoStr* cmd = AutoStr_NewStd();
        // Reserve an estimate of the composed command length.
        Str_Reserve(cmd, Str_Length(&commandTemplate) + numArgs + 1);

        int len = Str_Length(&commandTemplate);
        const char* start = Str_Text(&commandTemplate);
        const char* ch = start, *substart = start;
        while(ch + 1 < start + len)
        {
            if(ch[0] == '%' && ch[1] && ch[1] != '%')
            {
                Str_PartAppend(cmd, substart, 0, ch - substart);

                if(ch[1] == 'p')
                {
                    Str_AppendChar(cmd, '0' + player);
                }
                else
                {
                    int arg = ch[1] - '0' - 1;
                    DENG_ASSERT(arg >= 0 && arg < 9);
                    Str_AppendChar(cmd, char(args[arg]));
                }
                ch += 2;
                substart = ch;
            }
            else
            {
                ch++;
            }
        }
        // Add anything remaining.
        Str_Append(cmd, substart);

        DD_Execute(true/*silent*/, Str_Text(cmd));
    }