23 #include "shared/shared.h"
24 #include "common/common.h"
25 #include "common/cvar.h"
26 #include "common/field.h"
27 #include "common/files.h"
28 #include "common/prompt.h"
36 int count = end - start;
37 int numCols = 7, numLines;
39 size_t maxlen, len, total;
46 numLines = ceil((
float)count / numCols);
48 for (i = 0; i < numCols; i++) {
49 k = start + numLines * i;
54 for (j = k; j < k + numLines && j < end; j++) {
55 len = strlen(matches[j]);
61 if (maxlen > prompt->widthInChars) {
62 maxlen = prompt->widthInChars;
64 colwidths[i] = maxlen;
67 if (total < prompt->widthInChars) {
70 }
while (numCols > 1);
72 for (i = 0; i < numLines; i++) {
73 for (j = 0; j < numCols; j++) {
74 k = start + j * numLines + i;
79 prompt->printf(
"%s", match);
81 if (len < colwidths[j]) {
83 for (k = 0; k < colwidths[j] - len; k++) {
93 commandPrompt_t *prompt,
102 qsort(matches + offset, numCommands,
sizeof(matches[0]),
SortStrcmp);
104 prompt->printf(
"\n%i possible command%s:\n",
105 numCommands, numCommands != 1 ?
"s" :
"");
108 offset += numCommands;
112 qsort(matches + offset, numCvars,
sizeof(matches[0]),
SortStrcmp);
114 prompt->printf(
"\n%i possible variable%s:\n",
115 numCvars, numCvars != 1 ?
"s" :
"");
122 qsort(matches + offset, numAliases,
sizeof(matches[0]),
SortStrcmp);
124 prompt->printf(
"\n%i possible alias%s:\n",
125 numAliases, numAliases != 1 ?
"es" :
"");
128 offset += numAliases;
132 static qboolean
find_dup(genctx_t *ctx,
const char *s)
136 for (i = 0; i < ctx->count; i++) {
140 r = strcmp(ctx->matches[i], s);
153 if (ctx->count >= ctx->size)
159 r = strncmp(ctx->partial, s, ctx->length);
164 if (ctx->ignoredups &&
find_dup(ctx, s))
167 ctx->matches[ctx->count++] = Z_CopyString(s);
177 if (
c ==
'$' ||
c ==
';' || !Q_isgraph(
c)) {
192 inputField_t *inputLine = &prompt->inputLine;
193 char *text, *partial, *s;
194 int i, argc, currentArg, argnum;
195 size_t size, len, pos;
198 char *matches[MAX_MATCHES], *sortedMatches[MAX_MATCHES];
199 int numCommands, numCvars, numAliases;
201 text = inputLine->text;
202 size = inputLine->maxChars + 1;
203 pos = inputLine->cursorPos;
207 if (inputLine->text[0] !=
'\\' && inputLine->text[0] !=
'/') {
208 memmove(inputLine->text + 1, inputLine->text, size - 1);
209 inputLine->text[0] =
'\\';
230 for (i = 0; i < currentArg; i++) {
241 if (*partial ==
';') {
249 memset(&ctx, 0,
sizeof(ctx));
250 ctx.partial = partial;
251 ctx.length = strlen(partial);
252 ctx.argnum = currentArg;
253 ctx.matches = matches;
254 ctx.size = MAX_MATCHES;
259 numCommands = numCvars = numAliases = 0;
263 numCommands = ctx.count;
266 numCvars = ctx.count - numCommands;
269 numAliases = ctx.count - numCvars - numCommands;
273 pos = strlen(inputLine->text);
274 prompt->tooMany = qfalse;
289 if (ctx.count == 1) {
293 pos +=
Q_concat(text, size,
"\"", matches[0],
"\" ", s, NULL);
295 pos +=
Q_concat(text, size, matches[0],
" ", s, NULL);
298 prompt->tooMany = qfalse;
303 prompt->printf(
"Press TAB again to display all %d possibilities.\n", ctx.count);
304 pos = strlen(inputLine->text);
305 prompt->tooMany = qtrue;
309 prompt->tooMany = qfalse;
312 for (i = 0; i < ctx.count; i++) {
313 sortedMatches[i] = matches[i];
315 qsort(sortedMatches, ctx.count,
sizeof(sortedMatches[0]),
319 first = sortedMatches[0];
320 last = sortedMatches[ctx.count - 1];
323 if (*first != *last) {
324 if (!ctx.ignorecase || Q_tolower(*first) != Q_tolower(*last)) {
328 text[len++] = *first;
329 if (len == size - 1) {
342 if (currentArg + 1 < argc) {
344 pos +=
Q_concat(text + len, size,
" ", s, NULL);
357 for (i = 0; i < ctx.count; i++) {
358 prompt->printf(
"%s\n", sortedMatches[i]);
375 for (i = 0; i < ctx.count; i++) {
381 if (pos >= inputLine->maxChars) {
382 pos = inputLine->maxChars - 1;
384 inputLine->cursorPos = pos;
392 if (!prompt->search) {
393 s = prompt->inputLine.text;
394 if (*s ==
'/' || *s ==
'\\') {
400 prompt->search = Z_CopyString(s);
404 for (i = prompt->historyLineNum + 1; i < prompt->inputLineNum; i++) {
405 s = prompt->history[i & HISTORY_MASK];
406 if (s && strstr(s, prompt->search)) {
407 if (strcmp(s, prompt->inputLine.text)) {
414 j = prompt->inputLineNum - HISTORY_SIZE;
418 for (i = prompt->historyLineNum - 1; i >= j; i--) {
419 s = prompt->history[i & HISTORY_MASK];
420 if (s && strstr(s, prompt->search)) {
421 if (strcmp(s, prompt->inputLine.text)) {
433 prompt->historyLineNum = i;
434 IF_Replace(&prompt->inputLine, prompt->history[i & HISTORY_MASK]);
439 prompt->tooMany = qfalse;
440 if (prompt->search) {
442 prompt->search = NULL;
455 char *s = prompt->inputLine.text;
459 if (s[0] == 0 || ((s[0] ==
'/' || s[0] ==
'\\') && s[1] == 0)) {
465 i = prompt->inputLineNum & HISTORY_MASK;
466 j = (prompt->inputLineNum - 1) & HISTORY_MASK;
467 if (!prompt->history[j] || strcmp(prompt->history[j], s)) {
468 if (prompt->history[i]) {
469 Z_Free(prompt->history[i]);
471 prompt->history[i] = Z_CopyString(s);
472 prompt->inputLineNum++;
478 prompt->historyLineNum = prompt->inputLineNum;
482 return prompt->history[i];
496 if (prompt->historyLineNum == prompt->inputLineNum) {
498 i = prompt->inputLineNum & HISTORY_MASK;
499 if (prompt->history[i]) {
500 Z_Free(prompt->history[i]);
502 prompt->history[i] = Z_CopyString(prompt->inputLine.text);
505 if (prompt->inputLineNum - prompt->historyLineNum < HISTORY_SIZE &&
506 prompt->historyLineNum > 0) {
507 prompt->historyLineNum--;
510 i = prompt->historyLineNum & HISTORY_MASK;
511 IF_Replace(&prompt->inputLine, prompt->history[i]);
525 if (prompt->historyLineNum == prompt->inputLineNum) {
529 prompt->historyLineNum++;
531 i = prompt->historyLineNum & HISTORY_MASK;
532 IF_Replace(&prompt->inputLine, prompt->history[i]);
546 for (i = 0; i < HISTORY_SIZE; i++) {
547 if (prompt->history[i]) {
548 Z_Free(prompt->history[i]);
549 prompt->history[i] = NULL;
553 prompt->historyLineNum = 0;
554 prompt->inputLineNum = 0;
565 FS_FOpenFile(filename, &f, FS_MODE_WRITE | FS_PATH_BASE);
570 if (lines > HISTORY_SIZE) {
571 lines = HISTORY_SIZE;
574 i = prompt->inputLineNum - lines;
578 for (; i < prompt->inputLineNum; i++) {
579 s = prompt->history[i & HISTORY_MASK];
590 char buffer[MAX_FIELD_TEXT];
595 FS_FOpenFile(filename, &f, FS_MODE_READ | FS_TYPE_REAL | FS_PATH_BASE);
600 for (i = 0; i < HISTORY_SIZE; i++) {
601 if ((len =
FS_ReadLine(f, buffer,
sizeof(buffer))) < 1) {
604 if (prompt->history[i]) {
605 Z_Free(prompt->history[i]);
607 prompt->history[i] = memcpy(Z_Malloc(len + 1), buffer, len + 1);
612 prompt->historyLineNum = i;
613 prompt->inputLineNum = i;