ManiaDrive/raydium/console.c
2025-01-26 18:33:45 +01:00

484 lines
12 KiB
C

/*
Raydium - CQFD Corp.
http://raydium.org/
License: GPL - GNU General Public License, see "gpl.txt" file.
*/
#ifndef DONT_INCLUDE_HEADERS
#include "index.h"
#else
#include "headers/console.h"
#endif
// proto
void raydium_console_exec_last_command(void);
void raydium_console_history_add(char *str);
void raydium_console_init(void)
{
int i;
FILE *fp;
char line[RAYDIUM_MAX_NAME_LEN];
raydium_console_pos=0;
raydium_console_inc=0;
raydium_console_config_max=50;
raydium_console_config_speed=3;
raydium_init_cli_option_default("consoletexture",raydium_console_config_texture,"rgb(0.2,0.2,0.2)");
raydium_init_cli_option_default("consolefont",raydium_console_config_font,"font2.tga");
raydium_console_line_last=-1;
raydium_console_cursor_blink=0;
for(i=0;i<RAYDIUM_CONSOLE_MAX_LINES;i++)
raydium_console_lines[i][0]=0;
raydium_console_get_string[0]=0;
raydium_console_get_string_last[0]=0;
raydium_init_cli_option_default("history",raydium_console_history_filename,
raydium_file_home_path("raydium_history"));
for(i=0;i<RAYDIUM_CONSOLE_MAX_HISTORY;i++)
raydium_console_history[i][0]=0;
raydium_console_history_index_current=-1;
raydium_console_history_index=0;
fp=fopen(raydium_console_history_filename,"rt");
if(fp)
{
while(fgets(line,RAYDIUM_MAX_NAME_LEN,fp))
{
line[strlen(line)-1]=0;
raydium_console_history_add(line);
}
fclose(fp);
}
}
void raydium_console_history_save(void)
{
int i;
FILE *fp;
char last[RAYDIUM_MAX_NAME_LEN];
last[0]=0;
fp=fopen(raydium_console_history_filename,"wt");
if(!fp)
{
raydium_log("console: error: cannot save history file ('%s')",raydium_console_history_filename);
return;
}
for(i=0;i<raydium_console_history_index;i++)
if(strcmp(raydium_console_history[i],last))
{
strcpy(last,raydium_console_history[i]);
fprintf(fp,"%s\n",raydium_console_history[i]);
}
fclose(fp);
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Now DISABLED,
// use raydium_console_gets_callback fptr instead.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int raydium_console_gets(char *where)
{
raydium_log("ERROR: raydium_console_gets is now DISABLED ! See API doc.");
// always here for compat' only, do not use.
/*if(strlen(raydium_console_get_string_last))
{
strcpy(where,raydium_console_get_string_last);
raydium_console_get_string_last[0]=0;
return 1;
} else*/ return 0;
}
void raydium_console_history_previous(void)
{
raydium_console_history_index_current--;
if(raydium_console_history_index_current<0)
{
raydium_console_history_index_current=0;
return;
}
strcpy(raydium_console_get_string,raydium_console_history[raydium_console_history_index_current]);
}
void raydium_console_history_next(void)
{
raydium_console_history_index_current++;
if(raydium_console_history_index_current>=raydium_console_history_index)
{
raydium_console_history_index_current=raydium_console_history_index;
strcpy(raydium_console_get_string,"");
return;
}
strcpy(raydium_console_get_string,raydium_console_history[raydium_console_history_index_current]);
}
void raydium_console_history_add(char *str)
{
int i;
if(raydium_console_history_index==RAYDIUM_CONSOLE_MAX_HISTORY)
{
raydium_console_history_index_current=raydium_console_history_index;
/*
printf("-----\n");
for(i=0;i<RAYDIUM_CONSOLE_MAX_HISTORY;i++)
printf("%s\n",raydium_console_history[i]);
*/
for(i=0;i<RAYDIUM_CONSOLE_MAX_HISTORY-1;i++)
strcpy(raydium_console_history[i],raydium_console_history[i+1]);
strcpy(raydium_console_history[RAYDIUM_CONSOLE_MAX_HISTORY-1],str);
/*
printf("-----\n");
for(i=0;i<RAYDIUM_CONSOLE_MAX_HISTORY;i++)
printf("%s\n",raydium_console_history[i]);
*/
return;
}
raydium_console_history_index_current=raydium_console_history_index+1;
strcpy(raydium_console_history[raydium_console_history_index],str);
raydium_console_history_index++;
}
void raydium_console_exec_script(char *file)
{
FILE *fp;
char command[RAYDIUM_MAX_NAME_LEN];
if(!raydium_console_gets_callback)
{
raydium_log("ERROR: console: script: no command callback is defined, aborded.");
return;
}
fp=raydium_file_fopen(file,"rt");
if(!fp)
{
raydium_log("ERROR: console: script: file not found \"%s\"",file);
return;
}
while(fgets(command,RAYDIUM_MAX_NAME_LEN,fp))
{
strcpy(raydium_console_get_string_last,command);
raydium_console_exec_last_command();
}
fclose(fp);
}
void raydium_console_exec_last_command(void)
{
int treated=0;
void (*f)(char *);
char temp[RAYDIUM_MAX_NAME_LEN];
raydium_console_get_string_last[strlen(raydium_console_get_string_last)-1]=0;
raydium_console_history_add(raydium_console_get_string_last);
if(raydium_console_get_string_last[0]=='!')
{
treated=1;
raydium_console_exec_script(raydium_console_get_string_last+1);
}
if(raydium_console_get_string_last[0]=='>')
{
treated=1;
#ifdef PHP_SUPPORT
raydium_php_exec(raydium_console_get_string_last+1);
#else
raydium_log("ERROR: No PHP support compiled");
#endif
}
if(raydium_console_get_string_last[0]!='/' && !treated)
{
#ifdef PHP_SUPPORT
#define TEMPFILE raydium_file_home_path("temp.delme.php")
FILE *fp;
fp=fopen(TEMPFILE,"wt");
if(!fp) { raydium_log("console: php call: cannot create %s temporary file",TEMPFILE); return; }
fprintf(fp,"<? %s; ?>",raydium_console_get_string_last);
fclose(fp);
raydium_php_exec(TEMPFILE);
treated=1; // all is sended to PHP for now
#endif
}
if(!treated && raydium_console_gets_callback)
{
f=raydium_console_gets_callback;
strcpy(temp,raydium_console_get_string_last+1);
f(temp);
}
}
void raydium_console_line_add(char *format, ...)
{
va_list argptr;
int retlen;
raydium_console_line_last++;
if(raydium_console_line_last>=RAYDIUM_CONSOLE_MAX_LINES)
raydium_console_line_last=0;
va_start(argptr,format);
retlen = vsnprintf(raydium_console_lines[raydium_console_line_last],RAYDIUM_MAX_NAME_LEN - 1,format,argptr);
va_end(argptr);
if(retlen < 0) retlen = 0;
raydium_console_lines[raydium_console_line_last][retlen] = '\0';
}
int raydium_console_history_read(char **hist)
{
int i,start,cpt=0;
cpt=0;
start=raydium_console_line_last;
//for(i=RAYDIUM_CONSOLE_MAX_LINES-1;i>raydium_console_line_last;i--)
for(i=raydium_console_line_last+1;i<RAYDIUM_CONSOLE_MAX_LINES;i++)
{
hist[cpt]=raydium_console_lines[i];
cpt++;
}
//for(i=start;i>=0;i--)
for(i=0;i<=start;i++)
{
hist[cpt]=raydium_console_lines[i];
cpt++;
}
return cpt++;
}
void raydium_console_event(void)
{
#ifdef PHP_SUPPORT
static signed char first=1;
if(first)
{
raydium_texture_find_by_name(raydium_console_config_texture); // cache
// raydium_texture_find_by_name(RAYDIUM_CONSOLE_FONT_SIZE); // cache
raydium_log(" --- This console provides a PHP parser and text completion ---");
first=0;
}
#endif
if(raydium_console_inc!=0) raydium_console_inc*=-1;
else {
if(raydium_console_pos==0) raydium_console_inc=raydium_console_config_speed;
else raydium_console_inc=-raydium_console_config_speed;
}
}
void raydium_console_draw(void)
{
GLfloat y,off;
int i,cpt;
int texsave;
char *hist[RAYDIUM_CONSOLE_MAX_LINES];
raydium_console_pos+=raydium_console_inc*(raydium_frame_time*100);
if(raydium_console_pos<0)
{
raydium_console_pos=0;
raydium_console_inc=0;
}
if(raydium_console_pos>raydium_console_config_max)
{
raydium_console_pos=raydium_console_config_max;
raydium_console_inc=0;
}
if(!raydium_console_pos) return;
raydium_osd_start();
texsave=raydium_texture_current_main;
raydium_texture_current_set_name(raydium_console_config_texture);
raydium_rendering_internal_prepare_texture_render(raydium_texture_current_main);
off=raydium_console_config_max-raydium_console_pos;
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex3f(0,100-raydium_console_pos,0);
glTexCoord2f(1,0);
glVertex3f(100,100-raydium_console_pos,0);
glTexCoord2f(1,1);
glVertex3f(100,100+off,0);
glTexCoord2f(0,1);
glVertex3f(0,100+off,0);
glEnd();
raydium_osd_stop();
y=100-raydium_console_pos+(RAYDIUM_CONSOLE_FONT_SIZE/6.f);
raydium_osd_color_ega('f');
raydium_console_cursor_blink+=(raydium_frame_time*2);
raydium_osd_printf(1,y,RAYDIUM_CONSOLE_FONT_SIZE,RAYDIUM_CONSOLE_FONT_SPACER,raydium_console_config_font,"%s%c",raydium_console_get_string,( (((int)raydium_console_cursor_blink)%2)?'_':' '));
y+=(RAYDIUM_CONSOLE_FONT_SIZE/6.f);
cpt=raydium_console_history_read(hist);
for(i=cpt-1;i>=0;i--)
{
raydium_osd_color_ega('f');
raydium_osd_printf(1,y,RAYDIUM_CONSOLE_FONT_SIZE,RAYDIUM_CONSOLE_FONT_SPACER,raydium_console_config_font,"%s",hist[i]);
y+=(RAYDIUM_CONSOLE_FONT_SIZE/6.f);
}
//raydium_texture_current_set(texsave);
//raydium_rendering_internal_prepare_texture_render(raydium_texture_current);
}
// is alpha, num or '_' ?
int raydium_console_internal_isalphanumuscore(char c)
{
if(c=='_' || isalnum(c)) return 1;
return 0;
}
// "str": RAYDIUM_MAX_NAME_LEN only
void raydium_console_complete(char *str)
{
#ifdef PHP_SUPPORT
char candidates[RAYDIUM_CONSOLE_MAX_COMPLETION][RAYDIUM_MAX_NAME_LEN];
char candidates_type[RAYDIUM_CONSOLE_MAX_COMPLETION];
int n_candidates=0;
char word[RAYDIUM_MAX_NAME_LEN];
char candidate[RAYDIUM_MAX_NAME_LEN];
int word_offset;
int i,j;
int len;
int candidate_min_len;
char c;
// 0 - find last word, and store start offset
len=strlen(str);
//if(len==0) return;
for(i=(len-1);i>=0;i--)
{
if(!raydium_console_internal_isalphanumuscore(str[i]))
{
i++;
break;
}
}
if(i==-1) i=0; // first word of sentence
//if(i<0 || !raydium_console_internal_isalphanumuscore(str[i]))
//return; // empty word
word_offset=i;
strcpy(word,str+i);
len=strlen(word);
// 1 - build candidates list
for(i=0;i<raydium_register_variable_index;i++)
{
strcpy(candidate,raydium_register_variable_name[i]);
candidate[len]=0;
if(!strcmp(candidate,word))
{
candidates_type[n_candidates]=0; // 0 = variable
strcpy(candidates[n_candidates++],raydium_register_variable_name[i]);
}
if(n_candidates==RAYDIUM_CONSOLE_MAX_COMPLETION) break;
}
if(n_candidates<RAYDIUM_CONSOLE_MAX_COMPLETION)
for(i=0;i<raydium_register_function_index;i++)
{
strcpy(candidate,raydium_register_function_list[i].fname);
candidate[len]=0;
if(!strcmp(candidate,word))
{
candidates_type[n_candidates]=1; // 1 = function
strcpy(candidates[n_candidates++],raydium_register_function_list[i].fname);
}
if(n_candidates==RAYDIUM_CONSOLE_MAX_COMPLETION) break;
}
// 2 - no candidate ? only one ?
if(!n_candidates)
return;
if(n_candidates==1)
{
str[word_offset]=0;
if(strlen(str)+strlen(candidates[0]) >= (RAYDIUM_MAX_NAME_LEN-1))
return;
strcat(str,candidates[0]);
if(candidates_type[0])
strcat(str,"(");
else
strcat(str," ");
return;
}
// 3 - more than one candidate : display candidates and find the common root
raydium_console_line_add("> %s",str);
// display
for(i=0;i<n_candidates;i++)
{
if(candidates_type[i])
raydium_console_line_add("%s()",candidates[i]);
else
raydium_console_line_add("$%s",candidates[i]);
}
if(n_candidates==RAYDIUM_CONSOLE_MAX_COMPLETION)
raydium_console_line_add("..."); // limited results
// root: find shortest candidate
candidate_min_len=RAYDIUM_MAX_NAME_LEN+1;
for(i=0;i<n_candidates;i++)
if(strlen(candidates[i])<candidate_min_len)
candidate_min_len=strlen(candidates[i]);
// root: find common chars
for(i=strlen(word);i<=candidate_min_len;i++) // '\0' must be tested, too
{
c=candidates[0][i];
for(j=1;j<n_candidates;j++)
if(c!=candidates[j][i]) // last equiv
{
candidates[0][i]=0;
strcpy(candidate,candidates[0]);
str[word_offset]=0;
if(strlen(str)+strlen(candidate) >= (RAYDIUM_MAX_NAME_LEN-1))
return;
strcat(str,candidate);
return;
}
}
#endif
}