Code: Select all
Loop 1025
matchList .= A_Index ','
matchList := RTrim(matchList, ',')
ih := InputHook('', '', matchList)
MsgBox ; Has already crashed by this point.
Code: Select all
ResultType input_type::SetMatchList(LPTSTR aMatchList, size_t aMatchList_length)
{
LPTSTR *realloc_temp; // Needed since realloc returns NULL on failure but leaves original block allocated.
MatchCount = 0; // Set default.
if (*aMatchList)
{
// If needed, create the array of pointers that points into MatchBuf to each match phrase:
if (!match)
{
if ( !(match = (LPTSTR *)malloc(INPUT_ARRAY_BLOCK_SIZE * sizeof(LPTSTR))) )
return g_script.ScriptError(ERR_OUTOFMEM); // Short msg. since so rare.
MatchCountMax = INPUT_ARRAY_BLOCK_SIZE;
}
// If needed, create or enlarge the buffer that contains all the match phrases:
size_t space_needed = aMatchList_length + 1; // +1 for the final zero terminator.
if (space_needed > MatchBufSize)
{
MatchBufSize = (UINT)(space_needed > 4096 ? space_needed : 4096);
if (MatchBuf) // free the old one since it's too small.
free(MatchBuf);
if ( !(MatchBuf = tmalloc(MatchBufSize)) )
{
MatchBufSize = 0;
return g_script.ScriptError(ERR_OUTOFMEM); // Short msg. since so rare.
}
}
// Copy aMatchList into the match buffer:
LPTSTR source, dest;
for (source = aMatchList, dest = match[MatchCount] = MatchBuf
; *source; ++source)
{
if (*source != ',') // Not a comma, so just copy it over.
{
*dest++ = *source;
continue;
}
// Otherwise: it's a comma, which becomes the terminator of the previous key phrase unless
// it's a double comma, in which case it's considered to be part of the previous phrase
// rather than the next.
if (*(source + 1) == ',') // double comma
{
*dest++ = *source;
++source; // Omit the second comma of the pair, i.e. each pair becomes a single literal comma.
continue;
}
// Otherwise, this is a delimiting comma.
*dest = '\0';
// If the previous item is blank -- which I think can only happen now if the MatchList
// begins with an orphaned comma (since two adjacent commas resolve to one literal comma)
// -- don't add it to the match list:
if (*match[MatchCount])
{
++MatchCount;
match[MatchCount] = ++dest;
*dest = '\0'; // Init to prevent crash on orphaned comma such as "btw,otoh,"
}
if (*(source + 1)) // There is a next element.
{
if (MatchCount >= MatchCountMax) // Rarely needed, so just realloc() to expand.
{
// Expand the array by one block:
if ( !(realloc_temp = (LPTSTR *)realloc(match // Must use a temp variable.
, (MatchCountMax + INPUT_ARRAY_BLOCK_SIZE) * sizeof(LPTSTR))) )
return g_script.ScriptError(ERR_OUTOFMEM); // Short msg. since so rare.
match = realloc_temp;
MatchCountMax += INPUT_ARRAY_BLOCK_SIZE;
}
}
} // for()
*dest = '\0'; // Terminate the last item.
// This check is necessary for only a single isolated case: When the match list
// consists of nothing except a single comma. See above comment for details:
if (*match[MatchCount]) // i.e. omit empty strings from the match list.
++MatchCount;
}
return OK;
}
Code: Select all
...
// If the previous item is blank -- which I think can only happen now if the MatchList
// begins with an orphaned comma (since two adjacent commas resolve to one literal comma)
// -- don't add it to the match list:
if (*match[MatchCount])
{
++MatchCount;
match[MatchCount] = ++dest;
*dest = '\0'; // Init to prevent crash on orphaned comma such as "btw,otoh,"
}
...
Code: Select all
...
// This check is necessary for only a single isolated case: When the match list
// consists of nothing except a single comma. See above comment for details:
if (*match[MatchCount]) // i.e. omit empty strings from the match list.
++MatchCount;
...