quakeforge/libs/gamecode/builtins/bi_inputline.c
Bill Currie 246ab0009c Change Con_ClearTyping to take a save flag that will cause the current line
(if not empty) to be saved in the inputline history.

Clear the input (but put in history) of say or say team when pressing escape.

Don't say or say_team if the text is empty.
2002-08-28 16:02:43 +00:00

251 lines
5.9 KiB
C

/*
bi_inputline.c
CSQC inputline builtins
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/console.h"
#include "QF/draw.h"
#include "QF/progs.h"
#include "QF/sys.h"
#include "QF/zone.h"
typedef struct {
inputline_t **lines;
int max_lines;
void (*draw)(inputline_t *il);
} il_resources_t;
//FIXME need to robustify the interface to avoid segfaults caused by errant
//progs
static inputline_t *
get_inputline (progs_t *pr, int arg, const char *func)
{
pr_type_t *handle;
inputline_t *line;
if (arg <= ((pr_type_t *) pr->zone - pr->pr_globals)
|| arg >= (pr->zone_size / sizeof (pr_type_t)))
PR_RunError (pr, "%s: Invalid inputline_t", func);
handle = pr->pr_globals + arg;
line = *(inputline_t **)handle;
if (!line)
PR_RunError (pr, "Invalid inputline_t");
return line;
}
static void
bi_InputLine_Create (progs_t *pr)
{
il_resources_t *res = PR_Resources_Find (pr, "InputLine");
inputline_t **line = 0;
int i;
int lines = P_INT (pr, 0);
int size = P_INT (pr, 1);
int prompt = P_INT (pr, 2);
pr_type_t *handle;
for (i = 0; i < res->max_lines; i++)
if (!res->lines[i]) {
line = &res->lines[i];
break;
}
if (!line) {
Sys_Printf ("out of resources\n");
R_INT (pr) = 0;
return;
}
*line = Con_CreateInputLine (lines, size, prompt);
if (!*line) {
Sys_Printf ("failed to create inputline\n");
R_INT (pr) = 0;
return;
}
(*line)->draw = res->draw;
handle = PR_Zone_Malloc (pr, sizeof (inputline_t *));
*(inputline_t**)handle = *line;
R_INT (pr) = handle - pr->pr_globals;
}
static void
bi_InputLine_SetUserData (progs_t *pr)
{
inputline_t *line = get_inputline (pr, P_INT (pr, 0),
"InputLine_SetWidth");
pr_type_t *data = P_POINTER (pr, 1);
line->user_data = data;
}
static void
bi_InputLine_SetWidth (progs_t *pr)
{
inputline_t *line = get_inputline (pr, P_INT (pr, 0),
"InputLine_SetWidth");
int width = P_INT (pr, 1);
line->width = width;
}
static void
bi_InputLine_Destroy (progs_t *pr)
{
il_resources_t *res = PR_Resources_Find (pr, "InputLine");
pr_type_t *handle;
int arg = P_INT (pr, 0);
int i;
inputline_t *line;
if (arg <= ((pr_type_t *) pr->zone - pr->pr_globals)
|| arg >= (pr->zone_size / sizeof (pr_type_t)))
PR_RunError (pr, "InputLine_Destroy: Invalid inputline_t");
handle = pr->pr_globals + arg;
line = *(inputline_t **)handle;
if (!line)
PR_RunError (pr, "InputLine_Destroy: Invalid inputline_t");
for (i = 0; i < res->max_lines; i++)
if (res->lines[i] == line) {
Con_DestroyInputLine (line);
res->lines = 0;
PR_Zone_Free (pr, handle);
}
}
static void
bi_InputLine_Clear (progs_t *pr)
{
inputline_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_Clear");
int save = P_INT (pr, 1);
Con_ClearTyping (line, save);
}
static void
bi_InputLine_Process (progs_t *pr)
{
inputline_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_Process");
int ch = P_INT (pr, 1);
Con_ProcessInputLine (line, ch);
}
/*
bi_InputLine_SetText
Sets the inputline to a specified text
*/
static void
bi_InputLine_SetText (progs_t *pr)
{
inputline_t *il = get_inputline (pr, P_INT (pr, 0), "InputLine_SetText");
const char *str = P_STRING (pr, 1);
/* this was segfault trap:
il->lines[il->edit_line][0] is promt character
*/
strncpy(il->lines[il->edit_line] + 1,str,il->line_size - 1);
il->lines[il->edit_line][il->line_size-1] = '\0';
}
/*
bi_InputLine_GetText
Gets the text from a inputline
*/
static void
bi_InputLine_GetText (progs_t *pr)
{
inputline_t *il = get_inputline (pr, P_INT (pr, 0), "InputLine_GetText");
RETURN_STRING(pr, il->lines[il->edit_line]+1);
}
static void
bi_InputLine_Draw (progs_t *pr)
{
inputline_t *il = get_inputline (pr, P_INT (pr, 0), "InputLine_Draw");
il->draw (il);
}
static void
bi_il_clear (progs_t *pr, void *data)
{
il_resources_t *res = (il_resources_t *)data;
int i;
for (i = 0; i < res->max_lines; i++)
if (res->lines[i]) {
Con_DestroyInputLine (res->lines[i]);
res->lines[i] = 0;
}
}
void
InputLine_Progs_Init (progs_t *pr)
{
il_resources_t *res = malloc (sizeof (il_resources_t));
res->max_lines = 64;
res->lines = calloc (sizeof (inputline_t *), res->max_lines);
PR_Resources_Register (pr, "InputLine", res, bi_il_clear);
PR_AddBuiltin (pr, "InputLine_Create", bi_InputLine_Create, -1);
PR_AddBuiltin (pr, "InputLine_SetUserData",
bi_InputLine_SetUserData, -1);
PR_AddBuiltin (pr, "InputLine_SetWidth", bi_InputLine_SetWidth, -1);
PR_AddBuiltin (pr, "InputLine_SetText", bi_InputLine_SetText, -1);
PR_AddBuiltin (pr, "InputLine_GetText", bi_InputLine_GetText, -1);
PR_AddBuiltin (pr, "InputLine_Destroy", bi_InputLine_Destroy, -1);
PR_AddBuiltin (pr, "InputLine_Clear", bi_InputLine_Clear, -1);
PR_AddBuiltin (pr, "InputLine_Process", bi_InputLine_Process, -1);
PR_AddBuiltin (pr, "InputLine_Draw", bi_InputLine_Draw, -1);
}
void
InputLine_Progs_SetDraw (progs_t *pr, void (*draw)(inputline_t *))
{
il_resources_t *res = PR_Resources_Find (pr, "InputLine");
res->draw = draw;
}