static void Key_History_Find_Forwards(void) { int i; const char *partial = key_line + 1; char vabuf[1024]; size_t digits = strlen(va(vabuf, sizeof(vabuf), "%i", HIST_MAXLINES)); if (history_line == -1) // editing the "new" line return; if (strcmp(key_line + 1, history_searchstring)) // different string? Start a new search { strlcpy(history_searchstring, key_line + 1, sizeof(history_searchstring)); i = 0; } else i = history_line + 1; if (!*partial) partial = "*"; else if (!( strchr(partial, '*') || strchr(partial, '?') )) // no pattern? partial = va(vabuf, sizeof(vabuf), "*%s*", partial); for ( ; i < CONBUFFER_LINES_COUNT(&history); i++) if (matchpattern_with_separator(ConBuffer_GetLine(&history, i), partial, true, "", false)) { Con_Printf("^2%*i^7 %s\n", (int)digits, i+1, ConBuffer_GetLine(&history, i)); history_line = i; history_matchfound = true; return; } }
// wildcard_least_one: if true * matches 1 or more characters // if false * matches 0 or more characters int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one) { int c1, c2; while (*pattern) { switch (*pattern) { case 0: return 1; // end of pattern case '?': // match any single character if (*in == 0 || strchr(separators, *in)) return 0; // no match in++; pattern++; break; case '*': // match anything until following string if(wildcard_least_one) { if (*in == 0 || strchr(separators, *in)) return 0; // no match in++; } pattern++; while (*in) { if (strchr(separators, *in)) break; // see if pattern matches at this offset if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one)) return 1; // nope, advance to next offset in++; } break; default: if (*in != *pattern) { if (!caseinsensitive) return 0; // no match c1 = *in; if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; c2 = *pattern; if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; if (c1 != c2) return 0; // no match } in++; pattern++; break; } } if (*in) return 0; // reached end of pattern but not end of input return 1; // success }
static void Key_History_Find_All(void) { const char *partial = key_line + 1; int i, count = 0; char vabuf[1024]; size_t digits = strlen(va(vabuf, sizeof(vabuf), "%i", HIST_MAXLINES)); Con_Printf("History commands containing \"%s\":\n", key_line + 1); if (!*partial) partial = "*"; else if (!( strchr(partial, '*') || strchr(partial, '?') )) // no pattern? partial = va(vabuf, sizeof(vabuf), "*%s*", partial); for (i=0; i<CONBUFFER_LINES_COUNT(&history); i++) if (matchpattern_with_separator(ConBuffer_GetLine(&history, i), partial, true, "", false)) { Con_Printf("%s%*i^7 %s\n", (i == history_line) ? "^2" : "^3", (int)digits, i+1, ConBuffer_GetLine(&history, i)); count++; } Con_Printf("%i result%s\n\n", count, (count != 1) ? "s" : ""); }
int matchpattern(const char *in, const char *pattern, int caseinsensitive) { return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false); }