Quake II RTX doxygen  1.0 dev
prompt.c File Reference
#include "shared/shared.h"
#include "common/common.h"
#include "common/cvar.h"
#include "common/field.h"
#include "common/files.h"
#include "common/prompt.h"

Go to the source code of this file.

Functions

static void Prompt_ShowMatches (commandPrompt_t *prompt, char **matches, int start, int end)
 
static void Prompt_ShowIndividualMatches (commandPrompt_t *prompt, char **matches, int numCommands, int numAliases, int numCvars)
 
static qboolean find_dup (genctx_t *ctx, const char *s)
 
qboolean Prompt_AddMatch (genctx_t *ctx, const char *s)
 
static qboolean needs_quotes (const char *s)
 
void Prompt_CompleteCommand (commandPrompt_t *prompt, qboolean backslash)
 
void Prompt_CompleteHistory (commandPrompt_t *prompt, qboolean forward)
 
void Prompt_ClearState (commandPrompt_t *prompt)
 
char * Prompt_Action (commandPrompt_t *prompt)
 
void Prompt_HistoryUp (commandPrompt_t *prompt)
 
void Prompt_HistoryDown (commandPrompt_t *prompt)
 
void Prompt_Clear (commandPrompt_t *prompt)
 
void Prompt_SaveHistory (commandPrompt_t *prompt, const char *filename, int lines)
 
void Prompt_LoadHistory (commandPrompt_t *prompt, const char *filename)
 
void Prompt_Init (void)
 

Variables

static cvar_t * com_completion_mode
 
static cvar_t * com_completion_treshold
 

Function Documentation

◆ find_dup()

static qboolean find_dup ( genctx_t *  ctx,
const char *  s 
)
static

Definition at line 132 of file prompt.c.

133 {
134  int i, r;
135 
136  for (i = 0; i < ctx->count; i++) {
137  if (ctx->ignorecase)
138  r = Q_strcasecmp(ctx->matches[i], s);
139  else
140  r = strcmp(ctx->matches[i], s);
141 
142  if (!r)
143  return qtrue;
144  }
145 
146  return qfalse;
147 }

Referenced by Prompt_AddMatch().

◆ needs_quotes()

static qboolean needs_quotes ( const char *  s)
static

Definition at line 171 of file prompt.c.

172 {
173  int c;
174 
175  while (*s) {
176  c = *s++;
177  if (c == '$' || c == ';' || !Q_isgraph(c)) {
178  return qtrue;
179  }
180  }
181 
182  return qfalse;
183 }

Referenced by Prompt_CompleteCommand().

◆ Prompt_Action()

char* Prompt_Action ( commandPrompt_t *  prompt)

Definition at line 453 of file prompt.c.

454 {
455  char *s = prompt->inputLine.text;
456  int i, j;
457 
458  Prompt_ClearState(prompt);
459  if (s[0] == 0 || ((s[0] == '/' || s[0] == '\\') && s[1] == 0)) {
460  IF_Clear(&prompt->inputLine);
461  return NULL; // empty line
462  }
463 
464  // save current line in history
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]);
470  }
471  prompt->history[i] = Z_CopyString(s);
472  prompt->inputLineNum++;
473  } else {
474  i = j;
475  }
476 
477  // stop history search
478  prompt->historyLineNum = prompt->inputLineNum;
479 
480  IF_Clear(&prompt->inputLine);
481 
482  return prompt->history[i];
483 }

Referenced by Con_Action(), and Key_Message().

◆ Prompt_AddMatch()

qboolean Prompt_AddMatch ( genctx_t *  ctx,
const char *  s 
)

Definition at line 149 of file prompt.c.

150 {
151  int r;
152 
153  if (ctx->count >= ctx->size)
154  return qfalse;
155 
156  if (ctx->ignorecase)
157  r = Q_strncasecmp(ctx->partial, s, ctx->length);
158  else
159  r = strncmp(ctx->partial, s, ctx->length);
160 
161  if (r)
162  return qtrue;
163 
164  if (ctx->ignoredups && find_dup(ctx, s))
165  return qtrue;
166 
167  ctx->matches[ctx->count++] = Z_CopyString(s);
168  return qtrue;
169 }

Referenced by CL_Connect_c(), CL_Name_g(), CL_RecentIP_g(), Cmd_Alias_g(), Cmd_Command_g(), Cmd_Macro_g(), Com_Address_g(), Cvar_Default_g(), Cvar_Variable_g(), FS_Link_g(), gl_texturemode_g(), Key_Bound_g(), Key_Name_g(), SCR_Color_g(), SCR_Draw_g(), SV_AddFilterCmd_c(), SV_DelFilterCmd_c(), SV_Player_g(), SV_StuffCmd_c(), and UI_Menu_g().

◆ Prompt_Clear()

void Prompt_Clear ( commandPrompt_t *  prompt)

Definition at line 540 of file prompt.c.

541 {
542  int i;
543 
544  Prompt_ClearState(prompt);
545 
546  for (i = 0; i < HISTORY_SIZE; i++) {
547  if (prompt->history[i]) {
548  Z_Free(prompt->history[i]);
549  prompt->history[i] = NULL;
550  }
551  }
552 
553  prompt->historyLineNum = 0;
554  prompt->inputLineNum = 0;
555 
556  IF_Clear(&prompt->inputLine);
557 }

Referenced by Con_Shutdown().

◆ Prompt_ClearState()

void Prompt_ClearState ( commandPrompt_t *  prompt)

Definition at line 437 of file prompt.c.

438 {
439  prompt->tooMany = qfalse;
440  if (prompt->search) {
441  Z_Free(prompt->search);
442  prompt->search = NULL;
443  }
444 }

Referenced by Con_ClearTyping(), Key_Console(), Key_Message(), Prompt_Action(), Prompt_Clear(), Prompt_HistoryDown(), and Prompt_HistoryUp().

◆ Prompt_CompleteCommand()

void Prompt_CompleteCommand ( commandPrompt_t *  prompt,
qboolean  backslash 
)

Definition at line 190 of file prompt.c.

191 {
192  inputField_t *inputLine = &prompt->inputLine;
193  char *text, *partial, *s;
194  int i, argc, currentArg, argnum;
195  size_t size, len, pos;
196  char *first, *last;
197  genctx_t ctx;
198  char *matches[MAX_MATCHES], *sortedMatches[MAX_MATCHES];
199  int numCommands, numCvars, numAliases;
200 
201  text = inputLine->text;
202  size = inputLine->maxChars + 1;
203  pos = inputLine->cursorPos;
204 
205  // prepend backslash if missing
206  if (backslash) {
207  if (inputLine->text[0] != '\\' && inputLine->text[0] != '/') {
208  memmove(inputLine->text + 1, inputLine->text, size - 1);
209  inputLine->text[0] = '\\';
210  }
211  text++;
212  size--;
213  pos--;
214  }
215 
216  // parse the input line into tokens
217  Cmd_TokenizeString(text, qfalse);
218 
219  argc = Cmd_Argc();
220 
221  // determine absolute argument number to be completed
222  currentArg = Cmd_FindArgForOffset(pos);
223  if (currentArg == argc - 1 && Cmd_WhiteSpaceTail()) {
224  // start completing new argument if command line has trailing whitespace
225  currentArg++;
226  }
227 
228  // determine relative argument number to be completed
229  argnum = 0;
230  for (i = 0; i < currentArg; i++) {
231  s = Cmd_Argv(i);
232  argnum++;
233  if (*s == ';') {
234  // semicolon starts a new command
235  argnum = 0;
236  }
237  }
238 
239  // get the partial argument string to be completed
240  partial = Cmd_Argv(currentArg);
241  if (*partial == ';') {
242  // semicolon starts a new command
243  currentArg++;
244  partial = Cmd_Argv(currentArg);
245  argnum = 0;
246  }
247 
248  // generate matches
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;
255 
256  if (argnum) {
257  // complete a command/cvar argument
258  Com_Generic_c(&ctx, argnum);
259  numCommands = numCvars = numAliases = 0;
260  } else {
261  // complete a command/cvar/alias name
262  Cmd_Command_g(&ctx);
263  numCommands = ctx.count;
264 
265  Cvar_Variable_g(&ctx);
266  numCvars = ctx.count - numCommands;
267 
268  Cmd_Alias_g(&ctx);
269  numAliases = ctx.count - numCvars - numCommands;
270  }
271 
272  if (!ctx.count) {
273  pos = strlen(inputLine->text);
274  prompt->tooMany = qfalse;
275  goto finish2; // nothing found
276  }
277 
278  pos = Cmd_ArgOffset(currentArg);
279  text += pos;
280  size -= pos;
281 
282  // append whitespace since Cmd_TokenizeString eats it
283  if (currentArg == argc && Cmd_WhiteSpaceTail()) {
284  *text++ = ' ';
285  pos++;
286  size--;
287  }
288 
289  if (ctx.count == 1) {
290  // we have finished completion!
291  s = Cmd_RawArgsFrom(currentArg + 1);
292  if (needs_quotes(matches[0])) {
293  pos += Q_concat(text, size, "\"", matches[0], "\" ", s, NULL);
294  } else {
295  pos += Q_concat(text, size, matches[0], " ", s, NULL);
296  }
297  pos++;
298  prompt->tooMany = qfalse;
299  goto finish1;
300  }
301 
302  if (ctx.count > com_completion_treshold->integer && !prompt->tooMany) {
303  prompt->printf("Press TAB again to display all %d possibilities.\n", ctx.count);
304  pos = strlen(inputLine->text);
305  prompt->tooMany = qtrue;
306  goto finish1;
307  }
308 
309  prompt->tooMany = qfalse;
310 
311  // sort matches alphabethically
312  for (i = 0; i < ctx.count; i++) {
313  sortedMatches[i] = matches[i];
314  }
315  qsort(sortedMatches, ctx.count, sizeof(sortedMatches[0]),
316  ctx.ignorecase ? SortStricmp : SortStrcmp);
317 
318  // copy matching part
319  first = sortedMatches[0];
320  last = sortedMatches[ctx.count - 1];
321  len = 0;
322  do {
323  if (*first != *last) {
324  if (!ctx.ignorecase || Q_tolower(*first) != Q_tolower(*last)) {
325  break;
326  }
327  }
328  text[len++] = *first;
329  if (len == size - 1) {
330  break;
331  }
332 
333  first++;
334  last++;
335  } while (*first);
336 
337  text[len] = 0;
338  pos += len;
339  size -= len;
340 
341  // copy trailing arguments
342  if (currentArg + 1 < argc) {
343  s = Cmd_RawArgsFrom(currentArg + 1);
344  pos += Q_concat(text + len, size, " ", s, NULL);
345  }
346 
347  pos++;
348 
349  prompt->printf("]\\%s\n", Cmd_ArgsFrom(0));
350  if (argnum) {
351  goto multi;
352  }
353 
354  switch (com_completion_mode->integer) {
355  case 0:
356  // print in solid list
357  for (i = 0; i < ctx.count; i++) {
358  prompt->printf("%s\n", sortedMatches[i]);
359  }
360  break;
361  case 1:
362 multi:
363  // print in multiple columns
364  Prompt_ShowMatches(prompt, sortedMatches, 0, ctx.count);
365  break;
366  case 2:
367  default:
368  // resort matches by type and print in multiple columns
369  Prompt_ShowIndividualMatches(prompt, matches, numCommands, numAliases, numCvars);
370  break;
371  }
372 
373 finish1:
374  // free matches
375  for (i = 0; i < ctx.count; i++) {
376  Z_Free(matches[i]);
377  }
378 
379 finish2:
380  // move cursor
381  if (pos >= inputLine->maxChars) {
382  pos = inputLine->maxChars - 1;
383  }
384  inputLine->cursorPos = pos;
385 }

Referenced by Key_Console().

◆ Prompt_CompleteHistory()

void Prompt_CompleteHistory ( commandPrompt_t *  prompt,
qboolean  forward 
)

Definition at line 387 of file prompt.c.

388 {
389  char *s, *m = NULL;
390  int i, j;
391 
392  if (!prompt->search) {
393  s = prompt->inputLine.text;
394  if (*s == '/' || *s == '\\') {
395  s++;
396  }
397  if (!*s) {
398  return;
399  }
400  prompt->search = Z_CopyString(s);
401  }
402 
403  if (forward) {
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)) {
408  m = s;
409  break;
410  }
411  }
412  }
413  } else {
414  j = prompt->inputLineNum - HISTORY_SIZE;
415  if (j < 0) {
416  j = 0;
417  }
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)) {
422  m = s;
423  break;
424  }
425  }
426  }
427  }
428 
429  if (!m) {
430  return;
431  }
432 
433  prompt->historyLineNum = i;
434  IF_Replace(&prompt->inputLine, prompt->history[i & HISTORY_MASK]);
435 }

Referenced by Key_Console(), and Key_Message().

◆ Prompt_HistoryDown()

void Prompt_HistoryDown ( commandPrompt_t *  prompt)

Definition at line 519 of file prompt.c.

520 {
521  int i;
522 
523  Prompt_ClearState(prompt);
524 
525  if (prompt->historyLineNum == prompt->inputLineNum) {
526  return;
527  }
528 
529  prompt->historyLineNum++;
530 
531  i = prompt->historyLineNum & HISTORY_MASK;
532  IF_Replace(&prompt->inputLine, prompt->history[i]);
533 }

Referenced by Key_Console(), and Key_Message().

◆ Prompt_HistoryUp()

void Prompt_HistoryUp ( commandPrompt_t *  prompt)

Definition at line 490 of file prompt.c.

491 {
492  int i;
493 
494  Prompt_ClearState(prompt);
495 
496  if (prompt->historyLineNum == prompt->inputLineNum) {
497  // save current line in history
498  i = prompt->inputLineNum & HISTORY_MASK;
499  if (prompt->history[i]) {
500  Z_Free(prompt->history[i]);
501  }
502  prompt->history[i] = Z_CopyString(prompt->inputLine.text);
503  }
504 
505  if (prompt->inputLineNum - prompt->historyLineNum < HISTORY_SIZE &&
506  prompt->historyLineNum > 0) {
507  prompt->historyLineNum--;
508  }
509 
510  i = prompt->historyLineNum & HISTORY_MASK;
511  IF_Replace(&prompt->inputLine, prompt->history[i]);
512 }

Referenced by Key_Console(), and Key_Message().

◆ Prompt_Init()

void Prompt_Init ( void  )

Definition at line 621 of file prompt.c.

622 {
623  com_completion_mode = Cvar_Get("com_completion_mode", "1", 0);
624  com_completion_treshold = Cvar_Get("com_completion_treshold", "50", 0);
625 }

Referenced by Qcommon_Init().

◆ Prompt_LoadHistory()

void Prompt_LoadHistory ( commandPrompt_t *  prompt,
const char *  filename 
)

Definition at line 588 of file prompt.c.

589 {
590  char buffer[MAX_FIELD_TEXT];
591  qhandle_t f;
592  int i;
593  ssize_t len;
594 
595  FS_FOpenFile(filename, &f, FS_MODE_READ | FS_TYPE_REAL | FS_PATH_BASE);
596  if (!f) {
597  return;
598  }
599 
600  for (i = 0; i < HISTORY_SIZE; i++) {
601  if ((len = FS_ReadLine(f, buffer, sizeof(buffer))) < 1) {
602  break;
603  }
604  if (prompt->history[i]) {
605  Z_Free(prompt->history[i]);
606  }
607  prompt->history[i] = memcpy(Z_Malloc(len + 1), buffer, len + 1);
608  }
609 
610  FS_FCloseFile(f);
611 
612  prompt->historyLineNum = i;
613  prompt->inputLineNum = i;
614 }

Referenced by Con_PostInit().

◆ Prompt_SaveHistory()

void Prompt_SaveHistory ( commandPrompt_t *  prompt,
const char *  filename,
int  lines 
)

Definition at line 559 of file prompt.c.

560 {
561  qhandle_t f;
562  char *s;
563  int i;
564 
565  FS_FOpenFile(filename, &f, FS_MODE_WRITE | FS_PATH_BASE);
566  if (!f) {
567  return;
568  }
569 
570  if (lines > HISTORY_SIZE) {
571  lines = HISTORY_SIZE;
572  }
573 
574  i = prompt->inputLineNum - lines;
575  if (i < 0) {
576  i = 0;
577  }
578  for (; i < prompt->inputLineNum; i++) {
579  s = prompt->history[i & HISTORY_MASK];
580  if (s) {
581  FS_FPrintf(f, "%s\n", s);
582  }
583  }
584 
585  FS_FCloseFile(f);
586 }

Referenced by Con_Shutdown().

◆ Prompt_ShowIndividualMatches()

static void Prompt_ShowIndividualMatches ( commandPrompt_t *  prompt,
char **  matches,
int  numCommands,
int  numAliases,
int  numCvars 
)
static

Definition at line 92 of file prompt.c.

98 {
99  int offset = 0;
100 
101  if (numCommands) {
102  qsort(matches + offset, numCommands, sizeof(matches[0]), SortStrcmp);
103 
104  prompt->printf("\n%i possible command%s:\n",
105  numCommands, numCommands != 1 ? "s" : "");
106 
107  Prompt_ShowMatches(prompt, matches, offset, offset + numCommands);
108  offset += numCommands;
109  }
110 
111  if (numCvars) {
112  qsort(matches + offset, numCvars, sizeof(matches[0]), SortStrcmp);
113 
114  prompt->printf("\n%i possible variable%s:\n",
115  numCvars, numCvars != 1 ? "s" : "");
116 
117  Prompt_ShowMatches(prompt, matches, offset, offset + numCvars);
118  offset += numCvars;
119  }
120 
121  if (numAliases) {
122  qsort(matches + offset, numAliases, sizeof(matches[0]), SortStrcmp);
123 
124  prompt->printf("\n%i possible alias%s:\n",
125  numAliases, numAliases != 1 ? "es" : "");
126 
127  Prompt_ShowMatches(prompt, matches, offset, offset + numAliases);
128  offset += numAliases;
129  }
130 }

Referenced by Prompt_CompleteCommand().

◆ Prompt_ShowMatches()

static void Prompt_ShowMatches ( commandPrompt_t *  prompt,
char **  matches,
int  start,
int  end 
)
static

Definition at line 33 of file prompt.c.

35 {
36  int count = end - start;
37  int numCols = 7, numLines;
38  int i, j, k;
39  size_t maxlen, len, total;
40  size_t colwidths[6];
41  char *match;
42 
43  // determine number of columns needed
44  do {
45  numCols--;
46  numLines = ceil((float)count / numCols);
47  total = 0;
48  for (i = 0; i < numCols; i++) {
49  k = start + numLines * i;
50  if (k >= end) {
51  break;
52  }
53  maxlen = 0;
54  for (j = k; j < k + numLines && j < end; j++) {
55  len = strlen(matches[j]);
56  if (maxlen < len) {
57  maxlen = len;
58  }
59  }
60  maxlen += 2; // account for intercolumn spaces
61  if (maxlen > prompt->widthInChars) {
62  maxlen = prompt->widthInChars;
63  }
64  colwidths[i] = maxlen;
65  total += maxlen;
66  }
67  if (total < prompt->widthInChars) {
68  break; // this number of columns does fit
69  }
70  } while (numCols > 1);
71 
72  for (i = 0; i < numLines; i++) {
73  for (j = 0; j < numCols; j++) {
74  k = start + j * numLines + i;
75  if (k >= end) {
76  break;
77  }
78  match = matches[k];
79  prompt->printf("%s", match);
80  len = strlen(match);
81  if (len < colwidths[j]) {
82  // pad with spaces
83  for (k = 0; k < colwidths[j] - len; k++) {
84  prompt->printf(" ");
85  }
86  }
87  }
88  prompt->printf("\n");
89  }
90 }

Referenced by Prompt_CompleteCommand(), and Prompt_ShowIndividualMatches().

Variable Documentation

◆ com_completion_mode

cvar_t* com_completion_mode
static

Definition at line 30 of file prompt.c.

Referenced by Prompt_CompleteCommand(), and Prompt_Init().

◆ com_completion_treshold

cvar_t* com_completion_treshold
static

Definition at line 31 of file prompt.c.

Referenced by Prompt_CompleteCommand(), and Prompt_Init().

Cmd_Alias_g
void Cmd_Alias_g(genctx_t *ctx)
Definition: cmd.c:288
Cmd_WhiteSpaceTail
size_t Cmd_WhiteSpaceTail(void)
Definition: cmd.c:879
find_dup
static qboolean find_dup(genctx_t *ctx, const char *s)
Definition: prompt.c:132
Q_strncasecmp
int Q_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: shared.c:642
Cmd_Command_g
void Cmd_Command_g(genctx_t *ctx)
Definition: cmd.c:1634
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
Prompt_ClearState
void Prompt_ClearState(commandPrompt_t *prompt)
Definition: prompt.c:437
com_completion_treshold
static cvar_t * com_completion_treshold
Definition: prompt.c:31
FS_FPrintf
ssize_t FS_FPrintf(qhandle_t f, const char *format,...)
Definition: files.c:2039
Cmd_TokenizeString
void Cmd_TokenizeString(const char *text, qboolean macroExpand)
Definition: cmd.c:1399
needs_quotes
static qboolean needs_quotes(const char *s)
Definition: prompt.c:171
Cmd_RawArgsFrom
char * Cmd_RawArgsFrom(int from)
Definition: cmd.c:1021
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
FS_FOpenFile
ssize_t FS_FOpenFile(const char *name, qhandle_t *f, unsigned mode)
Definition: files.c:1692
Com_Generic_c
void Com_Generic_c(genctx_t *ctx, int argnum)
Definition: common.c:748
Cmd_ArgsFrom
char * Cmd_ArgsFrom(int from)
Definition: cmd.c:981
Cvar_Variable_g
void Cvar_Variable_g(genctx_t *ctx)
Definition: cvar.c:133
forward
static vec3_t forward
Definition: p_view.c:27
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
m
static struct mdfour * m
Definition: mdfour.c:32
SortStricmp
int SortStricmp(const void *p1, const void *p2)
Definition: shared.c:385
Prompt_ShowIndividualMatches
static void Prompt_ShowIndividualMatches(commandPrompt_t *prompt, char **matches, int numCommands, int numAliases, int numCvars)
Definition: prompt.c:92
Prompt_ShowMatches
static void Prompt_ShowMatches(commandPrompt_t *prompt, char **matches, int start, int end)
Definition: prompt.c:33
IF_Replace
void IF_Replace(inputField_t *field, const char *text)
Definition: field.c:67
com_completion_mode
static cvar_t * com_completion_mode
Definition: prompt.c:30
Q_strcasecmp
int Q_strcasecmp(const char *s1, const char *s2)
Definition: shared.c:666
c
statCounters_t c
Definition: main.c:30
Cmd_FindArgForOffset
int Cmd_FindArgForOffset(size_t offset)
Definition: cmd.c:867
IF_Clear
void IF_Clear(inputField_t *field)
Definition: field.c:56
FS_FCloseFile
void FS_FCloseFile(qhandle_t f)
Definition: files.c:759
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
SortStrcmp
int SortStrcmp(const void *p1, const void *p2)
Definition: shared.c:380
Cmd_ArgOffset
size_t Cmd_ArgOffset(int arg)
Definition: cmd.c:856
FS_ReadLine
ssize_t FS_ReadLine(qhandle_t f, char *buffer, size_t size)
Definition: files.c:1590