Index: console.c
===================================================================
--- console.c	(revision 0)
+++ console.c	(revision 1)
@@ -0,0 +1,440 @@
+/*
+    Raydium - CQFD Corp.
+    http://raydium.cqfd-corp.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;
+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_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)
+{
+// 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 "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);
+    }
+
+}
+
+// need to secure this one too
+void raydium_console_line_add(char *format, ...)
+{
+unsigned char str[RAYDIUM_MAX_NAME_LEN];
+va_list argptr;
+va_start(argptr,format);
+vsprintf(str,format,argptr);
+va_end(argptr);
+
+raydium_console_line_last++;
+if(raydium_console_line_last>=RAYDIUM_CONSOLE_MAX_LINES)
+   raydium_console_line_last=0;
+
+strcpy(raydium_console_lines[raydium_console_line_last],str);
+}
+
+void raydium_console_event(void)
+{
+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;
+int i,start;
+int texsave;
+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;
+raydium_texture_current_set_name(raydium_console_config_texture);
+raydium_rendering_internal_prepare_texture_render(raydium_texture_current);
+
+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,0);
+glTexCoord2f(0,1);
+glVertex3f(0,100,0);
+glEnd();
+
+raydium_osd_stop();
+
+y=100-raydium_console_pos+(RAYDIUM_CONSOLE_FONT_SIZE/6.f);
+
+raydium_osd_printf(1,y,RAYDIUM_CONSOLE_FONT_SIZE,RAYDIUM_CONSOLE_FONT_SPACER,raydium_console_config_font,"%s_",raydium_console_get_string);
+y+=(RAYDIUM_CONSOLE_FONT_SIZE/6.f);
+
+start=raydium_console_line_last;
+for(i=start;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,raydium_console_lines[i]);
+ y+=(RAYDIUM_CONSOLE_FONT_SIZE/6.f);
+ }
+
+for(i=RAYDIUM_CONSOLE_MAX_LINES-1;i>raydium_console_line_last;i--)
+ {
+ raydium_osd_color_ega('f');
+ raydium_osd_printf(1,y,RAYDIUM_CONSOLE_FONT_SIZE,RAYDIUM_CONSOLE_FONT_SPACER,raydium_console_config_font,raydium_console_lines[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)
+{
+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;
+	}
+    }
+}