2004-08-23 00:15:46 +00:00
//DMW
/*
F1 will return to progs . src
F2 will try to open a file with the name of which is on that line . ( excluding comments / tabs ) . Needs conditions .
F3 will give a prompt for typing in a value name to see the value .
F4 will save
F5 will run ( unbreak ) .
F6 will list the stack .
F7 will compile .
F8 will move execution
F9 will set a break point .
F10 will apply code changes .
F11 will step through .
*/
# include "quakedef.h"
# ifdef TEXTEDITOR
2011-05-20 04:10:46 +00:00
static cvar_t alloweditor = SCVAR ( " alloweditor " , " 1 " ) ; //disallow loading editor for stepbystep debugging.
static cvar_t editstripcr = SCVAR ( " edit_stripcr " , " 1 " ) ; //remove \r from eols (on load).
static cvar_t editaddcr = SCVAR ( " edit_addcr " , " 1 " ) ; //make sure that each line ends with a \r (on save).
static cvar_t edittabspacing = SCVAR ( " edit_tabsize " , " 4 " ) ;
cvar_t debugger = SCVAR ( " debugger " , " 1 " ) ;
2004-08-23 00:15:46 +00:00
# undef pr_trace
2011-05-20 04:10:46 +00:00
static progfuncs_t * editprogfuncs ;
2004-08-23 00:15:46 +00:00
typedef struct fileblock_s {
struct fileblock_s * next ;
struct fileblock_s * prev ;
int allocatedlength ;
int datalength ;
int flags ;
char * data ;
} fileblock_t ;
# define FB_BREAK 1
2009-07-11 20:56:09 +00:00
static fileblock_t * cursorblock , * firstblock , * executionblock , * viewportystartblock ;
2004-08-23 00:15:46 +00:00
2011-05-20 04:10:46 +00:00
static void * E_Malloc ( int size )
2004-08-23 00:15:46 +00:00
{
char * mem ;
mem = Z_Malloc ( size ) ;
if ( ! mem )
Sys_Error ( " Failed to allocate enough mem for editor \n " ) ;
return mem ;
}
2011-05-20 04:10:46 +00:00
static void E_Free ( void * mem )
2004-08-23 00:15:46 +00:00
{
Z_Free ( mem ) ;
}
# define GETBLOCK(s, ret) ret = (void *)E_Malloc(sizeof(fileblock_t) + s);ret->allocatedlength = s;ret->data = (char *)ret + sizeof(fileblock_t)
2011-05-20 04:10:46 +00:00
static char OpenEditorFile [ 256 ] ;
2004-08-23 00:15:46 +00:00
qboolean editoractive ; //(export)
qboolean editormodal ; //doesn't return. (export)
2011-05-20 04:10:46 +00:00
static qboolean editorblocking ;
static qboolean madechanges ;
static qboolean insertkeyhit = true ;
static qboolean useeval ;
2004-08-23 00:15:46 +00:00
2011-05-20 04:10:46 +00:00
static char evalstring [ 256 ] ;
2004-08-23 00:15:46 +00:00
2011-05-20 04:10:46 +00:00
static int executionlinenum ; //step by step debugger
static int cursorlinenum , cursorx ;
2004-08-23 00:15:46 +00:00
2011-05-20 04:10:46 +00:00
static int viewportx ;
static int viewporty ;
2004-08-23 00:15:46 +00:00
2005-12-21 03:07:33 +00:00
static int VFS_GETC ( vfsfile_t * fp )
{
unsigned char c ;
VFS_READ ( fp , & c , 1 ) ;
return c ;
}
2004-08-23 00:15:46 +00:00
//newsize = number of chars, EXCLUDING terminator.
2011-05-20 04:10:46 +00:00
static void MakeNewSize ( fileblock_t * block , int newsize ) //this is used to resize a block. It allocates a new one, copys the data frees the old one and links it into the right place
2004-08-23 00:15:46 +00:00
//it is called when the user is typing
{
fileblock_t * newblock ;
newsize = ( newsize + 4 ) & ~ 3 ; //We allocate a bit extra, so we don't need to keep finding a new block for each and every character.
if ( block - > allocatedlength > = newsize )
return ; //Ignore. This block is too large already. Don't bother resizeing, cos that's pretty much pointless.
GETBLOCK ( newsize , newblock ) ;
memcpy ( newblock - > data , block - > data , block - > datalength ) ;
newblock - > prev = block - > prev ;
newblock - > next = block - > next ;
if ( newblock - > prev )
newblock - > prev - > next = newblock ;
if ( newblock - > next )
newblock - > next - > prev = newblock ;
newblock - > datalength = block - > datalength ;
newblock - > flags = block - > flags ;
E_Free ( block ) ;
if ( firstblock = = block )
firstblock = newblock ;
if ( cursorblock = = block )
cursorblock = newblock ;
}
2011-05-20 04:10:46 +00:00
static int positionacross ;
static void GetCursorpos ( void )
2004-08-23 00:15:46 +00:00
{
int a ;
char * s ;
int ts = edittabspacing . value ;
if ( ts < 1 )
ts = 4 ;
for ( a = 0 , positionacross = 0 , s = cursorblock - > data ; a < cursorx & & * s ; s + + , a + + )
{
if ( * s = = ' \t ' )
{
positionacross + = ts ;
positionacross - = cursorx % ts ;
}
else
positionacross + + ;
}
// positionacross = cursorofs;
}
2011-05-20 04:10:46 +00:00
static void SetCursorpos ( void )
2004-08-23 00:15:46 +00:00
{
int a = 0 ;
char * s ;
int ts = edittabspacing . value ;
if ( ts < 1 )
ts = 4 ;
for ( cursorx = 0 , s = cursorblock - > data ; cursorx < positionacross & & * s ; s + + , a + + )
2005-12-21 03:07:33 +00:00
{
2004-08-23 00:15:46 +00:00
if ( * s = = ' \t ' )
{
cursorx + = ts ;
cursorx - = cursorx % ts ;
}
else
cursorx + + ;
}
cursorx = a ;
//just in case
if ( cursorx > cursorblock - > datalength )
cursorx = cursorblock - > datalength ;
}
2011-05-20 04:10:46 +00:00
static void CloseEditor ( void )
2004-08-23 00:15:46 +00:00
{
fileblock_t * b ;
key_dest = key_console ;
editoractive = false ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
editprogfuncs = NULL ;
2004-08-23 00:15:46 +00:00
if ( ! firstblock )
return ;
OpenEditorFile [ 0 ] = ' \0 ' ;
for ( b = firstblock ; b ; )
{
firstblock = b ;
b = b - > next ;
E_Free ( firstblock ) ;
}
madechanges = false ;
2005-05-26 12:55:34 +00:00
editormodal = false ;
2004-08-23 00:15:46 +00:00
firstblock = NULL ;
executionlinenum = - 1 ;
}
2011-05-20 04:10:46 +00:00
static qboolean EditorSaveFile ( char * s ) //returns true if succesful
2004-08-23 00:15:46 +00:00
{
// FILE *F;
fileblock_t * b ;
int len = 0 ;
int pos = 0 ;
char * data ;
for ( b = firstblock ; b ; b = b - > next ) //find total length required.
{
len + = b - > datalength ;
len + = 2 ; //extra for \n
}
data = Hunk_TempAlloc ( len ) ;
for ( b = firstblock ; b ; b = b - > next ) //find total length required.
{
memcpy ( data + pos , b - > data , b - > datalength ) ;
pos + = b - > datalength ;
2009-11-04 21:16:50 +00:00
if ( editaddcr . ival )
2004-08-23 00:15:46 +00:00
{
data [ pos ] = ' \r ' ;
pos + + ;
}
data [ pos ] = ' \n ' ;
pos + + ;
}
COM_WriteFile ( s , data , len ) ;
/*
F = fopen ( s , " wt " ) ;
if ( ! F )
return false ;
for ( b = firstblock ; b ; b = b - > next )
{
fprintf ( F , " %s \n " , b - > data ) ;
}
fclose ( F ) ;
*/
madechanges = false ;
executionlinenum = - 1 ;
return true ;
}
2011-05-20 04:10:46 +00:00
static void EditorNewFile ( void )
2004-08-23 00:15:46 +00:00
{
2005-12-21 03:07:33 +00:00
GETBLOCK ( 64 , firstblock ) ;
2004-08-23 00:15:46 +00:00
GETBLOCK ( 64 , firstblock - > next ) ;
firstblock - > next - > prev = firstblock ;
cursorblock = firstblock ;
cursorlinenum = 0 ;
cursorx = 0 ;
viewportystartblock = NULL ;
madechanges = true ;
executionlinenum = - 1 ;
2005-12-21 03:07:33 +00:00
key_dest = key_editor ;
2004-08-23 00:15:46 +00:00
editoractive = true ;
}
2011-05-20 04:10:46 +00:00
static void EditorOpenFile ( char * name )
2004-08-23 00:15:46 +00:00
{
int i ;
char line [ 8192 ] ;
int len , flen , pos = 0 ;
2005-12-21 03:07:33 +00:00
vfsfile_t * F ;
fileblock_t * b ;
2004-08-23 00:15:46 +00:00
2005-12-21 03:07:33 +00:00
CloseEditor ( ) ;
2004-08-23 00:15:46 +00:00
strcpy ( OpenEditorFile , name ) ;
2005-12-21 03:07:33 +00:00
if ( ! ( F = FS_OpenVFS ( OpenEditorFile , " rb " , FS_GAME ) ) )
2004-08-23 00:15:46 +00:00
{
2011-07-22 15:11:35 +00:00
Q_snprintfz ( OpenEditorFile , sizeof ( OpenEditorFile ) , " src/%s " , name ) ;
2005-12-21 03:07:33 +00:00
if ( ! ( F = FS_OpenVFS ( OpenEditorFile , " rb " , FS_GAME ) ) )
2004-08-23 00:15:46 +00:00
{
2005-12-21 03:07:33 +00:00
Con_Printf ( " Couldn't open file \" %s \" \n A new file will be created \n " , name ) ;
strcpy ( OpenEditorFile , name ) ;
key_dest = key_console ;
EditorNewFile ( ) ;
return ;
2004-08-23 00:15:46 +00:00
}
}
i = 1 ;
2005-12-21 03:07:33 +00:00
flen = VFS_GETLEN ( F ) ;
2004-08-23 00:15:46 +00:00
while ( pos < flen )
{
len = 0 ;
for ( ; ; )
{
2006-03-10 03:50:23 +00:00
if ( pos + len > = flen | | len > sizeof ( line ) - 16 )
2004-08-23 00:15:46 +00:00
break ;
2005-12-21 03:07:33 +00:00
line [ len ] = VFS_GETC ( F ) ;
2004-08-23 00:15:46 +00:00
if ( line [ len ] = = ' \n ' )
break ;
len + + ;
}
pos + = len ;
pos + + ; //and a \n
2009-11-04 21:16:50 +00:00
if ( editstripcr . ival )
2004-08-23 00:15:46 +00:00
{
if ( line [ len - 1 ] = = ' \r ' )
len - - ;
}
b = firstblock ;
GETBLOCK ( len + 1 , firstblock ) ;
firstblock - > prev = b ;
if ( b )
b - > next = firstblock ;
firstblock - > datalength = len ;
memcpy ( firstblock - > data , line , len ) ;
2005-08-03 23:14:59 +00:00
if ( editprogfuncs )
{
2009-04-01 22:03:56 +00:00
if ( editprogfuncs - > ToggleBreak ( editprogfuncs , OpenEditorFile , i , 3 ) )
2005-08-03 23:14:59 +00:00
{
2005-12-21 03:07:33 +00:00
firstblock - > flags | = FB_BREAK ;
2005-08-03 23:14:59 +00:00
}
}
else
2004-08-23 00:15:46 +00:00
{
2005-08-03 23:14:59 +00:00
if ( svprogfuncs )
{
2009-04-01 22:03:56 +00:00
if ( svprogfuncs - > ToggleBreak ( svprogfuncs , OpenEditorFile , i , 3 ) )
2005-08-03 23:14:59 +00:00
{
2005-12-21 03:07:33 +00:00
firstblock - > flags | = FB_BREAK ;
2005-08-03 23:14:59 +00:00
}
}
2004-08-23 00:15:46 +00:00
}
i + + ;
}
if ( firstblock = = NULL )
{
2005-12-21 03:07:33 +00:00
GETBLOCK ( 10 , firstblock ) ;
}
2004-08-23 00:15:46 +00:00
else
for ( ; firstblock - > prev ; firstblock = firstblock - > prev ) ;
2005-12-21 03:07:33 +00:00
VFS_CLOSE ( F ) ;
2004-08-23 00:15:46 +00:00
cursorblock = firstblock ;
cursorx = 0 ;
viewportystartblock = NULL ;
madechanges = false ;
executionlinenum = - 1 ;
2005-12-21 03:07:33 +00:00
key_dest = key_editor ;
2004-08-23 00:15:46 +00:00
editoractive = true ;
}
2009-07-25 11:05:06 +00:00
void Editor_Key ( int key , int unicode )
2004-08-23 00:15:46 +00:00
{
int i ;
if ( keybindings [ key ] [ 0 ] )
if ( ! strcmp ( keybindings [ key ] [ 0 ] , " toggleconsole " ) )
{
key_dest = key_console ;
return ;
}
/* if (CmdAfterSave)
{
switch ( key )
{
case ' Y ' :
case ' y ' :
if ( ! EditorSaveFile ( OpenEditorFile ) )
{
Con_Printf ( " Couldn't save file \" %s \" \n " , OpenEditorFile ) ;
key_dest = key_console ;
}
else if ( ! CmdAfterSaveCalled )
{
CmdAfterSaveCalled = true ;
( * CmdAfterSave ) ( ) ;
CmdAfterSaveCalled = false ;
}
CmdAfterSave = NULL ;
break ;
case ' N ' :
2005-12-21 03:07:33 +00:00
case ' n ' :
2004-08-23 00:15:46 +00:00
( * CmdAfterSave ) ( ) ;
CmdAfterSave = NULL ;
break ;
case ' C ' :
case ' c ' :
CmdAfterSave = NULL ;
break ;
}
return ;
}
*/
if ( key = = K_SHIFT )
return ;
2006-09-18 22:52:33 +00:00
if ( useeval & & key ! = K_F11 & & key ! = K_F5 )
2004-08-23 00:15:46 +00:00
{
switch ( key )
{
case K_ESCAPE :
2005-05-26 12:55:34 +00:00
if ( editprogfuncs )
* editprogfuncs - > pr_trace = 0 ;
useeval = false ;
break ;
case K_F3 :
2004-08-23 00:15:46 +00:00
useeval = false ;
break ;
case K_DEL :
evalstring [ 0 ] = ' \0 ' ;
break ;
case K_BACKSPACE :
i = strlen ( evalstring ) ;
if ( i < 1 )
break ;
evalstring [ i - 1 ] = ' \0 ' ;
break ;
default :
2009-07-25 11:05:06 +00:00
if ( unicode )
{
i = strlen ( evalstring ) ;
evalstring [ i ] = unicode ;
evalstring [ i + 1 ] = ' \0 ' ;
}
2004-08-23 00:15:46 +00:00
break ;
}
return ;
}
/* if (ctrl_down && (key == 'c' || key == K_INS))
key = K_F9 ;
if ( ( ctrl_down & & key = = ' v ' ) | | ( shift_down & & key = = K_INS ) )
key = K_F10 ;
*/
switch ( key )
{
case K_SHIFT :
break ;
case K_ALT :
break ;
case K_CTRL :
break ;
2011-05-20 04:10:46 +00:00
case K_MWHEELUP :
case K_UPARROW :
2004-08-23 00:15:46 +00:00
case K_PGUP :
GetCursorpos ( ) ;
{
2011-05-20 04:10:46 +00:00
int a ;
if ( key = = K_PGUP )
a = ( vid . height / 8 ) / 2 ;
else if ( key = = K_MWHEELUP )
a = 5 ;
else
a = 1 ;
while ( a )
{
a - - ;
if ( cursorblock - > prev )
{
cursorblock = cursorblock - > prev ;
cursorlinenum - - ;
}
}
2004-08-23 00:15:46 +00:00
}
SetCursorpos ( ) ;
break ;
2011-05-20 04:10:46 +00:00
case K_MWHEELDOWN :
case K_DOWNARROW :
2004-08-23 00:15:46 +00:00
case K_PGDN :
GetCursorpos ( ) ;
2011-05-20 04:10:46 +00:00
{
int a ;
if ( key = = K_PGDN )
a = ( vid . height / 8 ) / 2 ;
else if ( key = = K_MWHEELDOWN )
a = 5 ;
else
a = 1 ;
2004-08-23 00:15:46 +00:00
while ( a )
{
a - - ;
if ( cursorblock - > next )
{
cursorblock = cursorblock - > next ;
cursorlinenum + + ;
}
}
}
SetCursorpos ( ) ;
break ;
// case K_BACK:
case K_F1 :
// Editor_f();
break ;
// case K_FORWARD:
case K_F2 :
{
char file [ 1024 ] ;
char * s ;
Q_strncpyz ( file , cursorblock - > data , sizeof ( file ) ) ;
s = file ;
while ( * s )
{
if ( ( * s = = ' / ' & & s [ 1 ] = = ' / ' ) | | ( * s = = ' \t ' ) )
{
* s = ' \0 ' ;
break ;
2005-12-21 03:07:33 +00:00
}
2004-08-23 00:15:46 +00:00
s + + ;
}
if ( * file )
EditorOpenFile ( file ) ;
}
break ;
case K_F3 :
2006-03-10 03:50:23 +00:00
if ( editprogfuncs )
useeval = true ;
2004-08-23 00:15:46 +00:00
break ;
case K_F4 :
EditorSaveFile ( OpenEditorFile ) ;
break ;
2011-10-27 15:46:36 +00:00
case K_F5 : /*stop debugging*/
2004-08-23 00:15:46 +00:00
editormodal = false ;
if ( editprogfuncs )
* editprogfuncs - > pr_trace = false ;
break ;
case K_F6 :
if ( editprogfuncs )
2005-12-21 03:07:33 +00:00
PR_StackTrace ( editprogfuncs ) ;
2004-08-23 00:15:46 +00:00
break ;
2011-10-27 15:46:36 +00:00
case K_F7 : /*save+recompile*/
2004-08-23 00:15:46 +00:00
EditorSaveFile ( OpenEditorFile ) ;
2006-03-10 03:50:23 +00:00
if ( editprogfuncs )
Cbuf_AddText ( " compile \n " , RESTRICT_LOCAL ) ;
2004-08-23 00:15:46 +00:00
break ;
2011-10-27 15:46:36 +00:00
case K_F8 : /*move execution point to here - I hope you move to the same function!*/
2004-08-23 00:15:46 +00:00
executionlinenum = cursorlinenum ;
executionblock = cursorblock ;
break ;
2011-10-27 15:46:36 +00:00
case K_F9 : /*set breakpoint*/
2004-08-23 00:15:46 +00:00
{
int f = 0 ;
2006-03-10 03:50:23 +00:00
if ( editprogfuncs )
{
2011-05-20 04:10:46 +00:00
if ( editprogfuncs - > ToggleBreak ( editprogfuncs , OpenEditorFile , cursorlinenum , 2 ) )
2006-03-10 03:50:23 +00:00
f | = 1 ;
else
f | = 2 ;
}
2005-08-03 23:14:59 +00:00
# ifndef CLIENTONLY
2006-03-10 03:50:23 +00:00
else if ( svprogfuncs )
{
2011-05-20 04:10:46 +00:00
if ( svprogfuncs - > ToggleBreak ( svprogfuncs , OpenEditorFile , cursorlinenum , 2 ) )
2006-03-10 03:50:23 +00:00
f | = 1 ;
else
f | = 2 ;
}
2004-08-23 00:15:46 +00:00
# endif
2006-03-10 03:50:23 +00:00
if ( f & 1 )
cursorblock - > flags | = FB_BREAK ;
else
cursorblock - > flags & = ~ FB_BREAK ;
2004-08-23 00:15:46 +00:00
}
break ;
2011-10-27 15:46:36 +00:00
case K_F10 : //save+apply changes, supposedly
2004-08-23 00:15:46 +00:00
EditorSaveFile ( OpenEditorFile ) ;
Cbuf_AddText ( " applycompile \n " , RESTRICT_LOCAL ) ;
break ;
2011-10-27 15:46:36 +00:00
case K_F11 : //single step
2004-08-23 00:15:46 +00:00
editormodal = false ;
break ;
// case K_STOP:
case K_ESCAPE :
2006-09-18 22:52:33 +00:00
if ( editprogfuncs )
editprogfuncs - > AbortStack ( editprogfuncs ) ;
2004-08-23 00:15:46 +00:00
CloseEditor ( ) ;
break ;
case K_HOME :
cursorx = 0 ;
break ;
case K_END :
cursorx = cursorblock - > datalength ;
break ;
case K_LEFTARROW :
cursorx - - ;
if ( cursorx < 0 )
cursorx = 0 ;
break ;
case K_RIGHTARROW :
cursorx + + ;
if ( cursorx > cursorblock - > datalength )
cursorx = cursorblock - > datalength ;
break ;
case K_BACKSPACE :
cursorx - - ;
if ( cursorx < 0 )
{
fileblock_t * b = cursorblock ;
if ( b = = firstblock ) //no line above to remove to
{
cursorx = 0 ;
break ;
}
cursorlinenum - = 1 ;
madechanges = true ;
cursorblock = b - > prev ;
MakeNewSize ( cursorblock , b - > datalength + cursorblock - > datalength + 5 ) ;
cursorx = cursorblock - > datalength ;
memcpy ( cursorblock - > data + cursorblock - > datalength , b - > data , b - > datalength ) ;
2006-03-10 03:50:23 +00:00
cursorblock - > datalength + = b - > datalength ;
2004-08-23 00:15:46 +00:00
cursorblock - > next = b - > next ;
if ( b - > next )
b - > next - > prev = cursorblock ;
// cursorblock->prev->next = cursorblock->next;
// cursorblock->next->prev = cursorblock->prev;
E_Free ( b ) ;
2005-12-21 03:07:33 +00:00
// cursorblock = b;
2004-08-23 00:15:46 +00:00
break ;
}
case K_DEL : //bksp falls through.
{
int a ;
fileblock_t * b ;
cursorlinenum = - 1 ;
madechanges = true ;
//FIXME: does this work right?
if ( ! cursorblock - > datalength & & cursorblock - > next & & cursorblock - > prev ) //blank line
2005-12-21 03:07:33 +00:00
{
2004-08-23 00:15:46 +00:00
b = cursorblock ;
2005-12-21 03:07:33 +00:00
if ( b - > next )
2004-08-23 00:15:46 +00:00
b - > next - > prev = b - > prev ;
if ( b - > prev )
2005-12-21 03:07:33 +00:00
b - > prev - > next = b - > next ;
2004-08-23 00:15:46 +00:00
if ( cursorblock - > next )
cursorblock = cursorblock - > next ;
else
cursorblock = cursorblock - > prev ;
E_Free ( b ) ;
}
else
{
for ( a = cursorx ; a < cursorblock - > datalength ; a + + )
cursorblock - > data [ a ] = cursorblock - > data [ a + 1 ] ;
cursorblock - > datalength - - ;
}
2006-03-10 03:50:23 +00:00
if ( cursorx > cursorblock - > datalength )
cursorx = cursorblock - > datalength ;
2004-08-23 00:15:46 +00:00
}
break ;
2005-12-21 03:07:33 +00:00
case K_ENTER :
2004-08-23 00:15:46 +00:00
{
fileblock_t * b = cursorblock ;
cursorlinenum = - 1 ;
madechanges = true ;
2006-03-10 03:50:23 +00:00
GETBLOCK ( b - > datalength - cursorx , cursorblock ) ;
2004-08-23 00:15:46 +00:00
cursorblock - > next = b - > next ;
cursorblock - > prev = b ;
b - > next = cursorblock ;
if ( cursorblock - > next )
cursorblock - > next - > prev = cursorblock ;
if ( cursorblock - > prev )
cursorblock - > prev - > next = cursorblock ;
2006-03-10 03:50:23 +00:00
cursorblock - > datalength = b - > datalength - cursorx ;
memcpy ( cursorblock - > data , b - > data + cursorx , cursorblock - > datalength ) ;
b - > datalength = cursorx ;
2004-08-23 00:15:46 +00:00
cursorx = 0 ;
}
break ;
case K_INS :
insertkeyhit = insertkeyhit ? false : true ;
break ;
default :
2009-07-25 11:05:06 +00:00
if ( unicode < ' ' & & unicode ! = ' \t ' ) //we deem these as unprintable
2004-08-23 00:15:46 +00:00
break ;
if ( insertkeyhit ) //insert a char
{
char * s ;
madechanges = true ;
MakeNewSize ( cursorblock , cursorblock - > datalength + 5 ) ; //allocate a bit extra, so we don't need to keep resizing it and shifting loads a data about
s = cursorblock - > data + cursorblock - > datalength ;
while ( s > = cursorblock - > data + cursorx )
{
s [ 1 ] = s [ 0 ] ;
s - - ;
}
cursorx + + ;
cursorblock - > datalength + + ;
2009-07-25 11:05:06 +00:00
* ( s + 1 ) = unicode ;
2004-08-23 00:15:46 +00:00
}
else //over write a char
2005-12-21 03:07:33 +00:00
{
2004-08-23 00:15:46 +00:00
MakeNewSize ( cursorblock , cursorblock - > datalength + 5 ) ; //not really needed
2005-12-21 03:07:33 +00:00
2009-07-25 11:05:06 +00:00
cursorblock - > data [ cursorx ] = unicode ;
2004-08-23 00:15:46 +00:00
cursorx + + ;
2006-03-10 03:50:23 +00:00
if ( cursorx > cursorblock - > datalength )
cursorblock - > datalength = cursorx ;
2004-08-23 00:15:46 +00:00
}
break ;
}
}
2011-05-20 04:10:46 +00:00
static void Draw_Line ( int x , int y , fileblock_t * b , int cursorx )
2004-08-23 00:15:46 +00:00
{
2011-05-20 04:10:46 +00:00
int nx = 0 , nnx ;
2004-08-23 00:15:46 +00:00
qbyte * d = b - > data ;
2011-05-20 04:10:46 +00:00
qbyte * c ;
int i ;
2004-08-23 00:15:46 +00:00
2011-05-20 04:10:46 +00:00
int colour = COLOR_WHITE ;
2004-08-23 00:15:46 +00:00
int ts = edittabspacing . value ;
2011-05-20 04:10:46 +00:00
if ( cursorx > = 0 )
c = d + cursorx ;
2004-08-23 00:15:46 +00:00
else
2011-05-20 04:10:46 +00:00
c = NULL ;
2004-08-23 00:15:46 +00:00
2011-05-20 04:10:46 +00:00
Font_BeginString ( font_conchar , x , y , & x , & y ) ;
2004-08-23 00:15:46 +00:00
if ( ts < 1 )
ts = 4 ;
ts * = 8 ;
if ( b - > flags & ( FB_BREAK ) )
2005-12-21 03:07:33 +00:00
colour = COLOR_RED ; //red
2004-08-23 00:15:46 +00:00
if ( executionblock = = b )
{
if ( colour ) //break point too
2005-01-04 07:27:50 +00:00
colour = COLOR_GREEN ; //green
2004-08-23 00:15:46 +00:00
else
2005-01-04 07:27:50 +00:00
colour = COLOR_YELLOW ; //yellow
2004-08-23 00:15:46 +00:00
}
2011-05-20 04:10:46 +00:00
nx = x ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < b - > datalength ; i + + )
{
if ( * d = = ' \t ' )
{
2011-05-20 04:10:46 +00:00
if ( d = = c )
Font_DrawChar ( nx , y , ( int ) 11 | ( CON_WHITEMASK ) ) ;
2004-08-23 00:15:46 +00:00
nx + = ts ;
2011-05-20 04:10:46 +00:00
nx - = ( nx - x ) % ts ;
2005-12-21 03:07:33 +00:00
d + + ;
continue ;
2004-08-23 00:15:46 +00:00
}
2011-05-20 04:10:46 +00:00
if ( nx < ( int ) vid . pixelwidth )
nnx = Font_DrawChar ( nx , y , ( int ) * d | ( colour < < CON_FGSHIFT ) ) ;
else nnx = vid . pixelwidth ;
if ( d = = c )
Font_DrawChar ( nx , y , ( int ) 11 | ( CON_WHITEMASK ) ) ;
nx = nnx ;
2004-08-23 00:15:46 +00:00
d + + ;
2005-12-21 03:07:33 +00:00
}
2011-05-20 04:10:46 +00:00
/*we didn't do the cursor! stick it at the end*/
if ( c & & c > = d )
Font_DrawChar ( nx , y , ( int ) 11 | ( CON_WHITEMASK ) ) ;
Font_EndString ( font_conchar ) ;
2004-08-23 00:15:46 +00:00
}
2011-05-20 04:10:46 +00:00
static fileblock_t * firstline ( void )
2004-08-23 00:15:46 +00:00
{
int lines ;
fileblock_t * b ;
lines = ( vid . height / 8 ) / 2 - 1 ;
b = cursorblock ;
if ( ! b )
return NULL ;
while ( 1 )
{
if ( ! b - > prev )
return b ;
b = b - > prev ;
lines - - ;
if ( lines < = 0 )
return b ;
}
return NULL ;
}
void Editor_Draw ( void )
{
int x ;
int y ;
2011-05-20 04:10:46 +00:00
int c ;
2004-08-23 00:15:46 +00:00
fileblock_t * b ;
if ( key_dest ! = key_console )
key_dest = key_editor ;
if ( ( editoractive & & cls . state = = ca_disconnected ) | | editormodal )
2011-03-31 01:14:01 +00:00
R2D_EditorBackground ( ) ;
2004-08-23 00:15:46 +00:00
if ( cursorlinenum < 0 ) //look for the cursor line num
{
cursorlinenum = 0 ;
for ( b = firstblock ; b ; b = b - > next )
{
cursorlinenum + + ;
if ( b = = cursorblock )
break ;
2005-12-21 03:07:33 +00:00
}
2004-08-23 00:15:46 +00:00
}
if ( ! viewportystartblock ) //look for the cursor line num
{
y = 0 ;
for ( viewportystartblock = firstblock ; viewportystartblock ; viewportystartblock = viewportystartblock - > prev )
{
y + + ;
if ( y = = viewporty )
break ;
2005-12-21 03:07:33 +00:00
}
2004-08-23 00:15:46 +00:00
}
x = 0 ;
for ( y = 0 ; y < cursorx ; y + + )
{
if ( cursorblock - > data [ y ] = = ' \0 ' )
break ;
else if ( cursorblock - > data [ y ] = = ' \t ' )
{
x + = 32 ;
x & = ~ 31 ;
}
else
x + = 8 ;
}
x = - x + vid . width / 2 ;
if ( x > 0 )
x = 0 ;
2005-12-21 03:07:33 +00:00
2004-08-23 00:15:46 +00:00
if ( madechanges )
2009-11-04 21:16:50 +00:00
Draw_FunString ( vid . width - 8 , 0 , " ! " ) ;
2004-08-23 00:15:46 +00:00
if ( ! insertkeyhit )
2009-11-04 21:16:50 +00:00
Draw_FunString ( vid . width - 16 , 0 , " O " ) ;
Draw_FunString ( 0 , 0 , va ( " %6i:%4i:%s " , cursorlinenum , cursorx + 1 , OpenEditorFile ) ) ;
2004-08-23 00:15:46 +00:00
if ( useeval )
{
if ( ! editprogfuncs )
useeval = false ;
else
{
2006-09-18 22:52:33 +00:00
char * eq ;
2009-11-04 21:16:50 +00:00
Draw_FunString ( 0 , 8 , evalstring ) ;
2006-09-18 22:52:33 +00:00
eq = strchr ( evalstring , ' = ' ) ;
if ( eq )
{
if ( strchr ( eq , ' ; ' ) )
{
* strchr ( eq , ' ; ' ) = ' \0 ' ;
eq = NULL ;
}
else
* eq = ' \0 ' ;
}
2009-11-04 21:16:50 +00:00
Draw_FunString ( vid . width / 2 , 8 , editprogfuncs - > EvaluateDebugString ( editprogfuncs , evalstring ) ) ;
2006-09-18 22:52:33 +00:00
if ( eq )
* eq = ' = ' ;
2004-08-23 00:15:46 +00:00
}
y = 16 ;
}
else
y = 8 ;
b = firstline ( ) ;
for ( ; b ; b = b - > next )
{
2011-05-20 04:10:46 +00:00
c = - 1 ;
2004-08-23 00:15:46 +00:00
if ( b = = cursorblock )
2011-05-20 04:10:46 +00:00
if ( ( int ) ( Sys_DoubleTime ( ) * 4.0 ) & 1 )
c = cursorx ;
Draw_Line ( x , y , b , c ) ;
2004-08-23 00:15:46 +00:00
y + = 8 ;
if ( y > vid . height )
break ;
}
2005-12-21 03:07:33 +00:00
2004-08-23 00:15:46 +00:00
/* if (CmdAfterSave)
{
if ( madechanges )
{
M_DrawTextBox ( 0 , 0 , 36 , 5 ) ;
M_PrintWhite ( 16 , 12 , OpenEditorFile ) ;
M_PrintWhite ( 16 , 28 , " Do you want to save the open file? " ) ;
M_PrintWhite ( 16 , 36 , " [Y]es/[N]o/[C]ancel " ) ;
}
else
{
if ( ! CmdAfterSaveCalled )
{
CmdAfterSaveCalled = true ;
( * CmdAfterSave ) ( ) ;
CmdAfterSaveCalled = false ;
}
CmdAfterSave = NULL ;
}
}
*/
}
2005-08-03 23:14:59 +00:00
int QCLibEditor ( progfuncs_t * prfncs , char * filename , int line , int nump , char * * parms )
2004-08-23 00:15:46 +00:00
{
2011-05-20 04:10:46 +00:00
char * f1 , * f2 ;
if ( editormodal | | line < 0 | | ! debugger . ival )
2004-08-23 00:15:46 +00:00
return line ; //whoops
2010-02-06 01:25:04 +00:00
if ( qrenderer = = QR_NONE )
2004-10-01 22:16:01 +00:00
{
int i ;
char buffer [ 8192 ] ;
char * r ;
2005-12-21 03:07:33 +00:00
vfsfile_t * f ;
2004-10-01 22:16:01 +00:00
if ( line = = - 1 )
return - 1 ;
2005-12-21 03:07:33 +00:00
f = FS_OpenVFS ( filename , " rb " , FS_GAME ) ;
2004-10-01 22:16:01 +00:00
if ( ! f )
Con_Printf ( " %s - %i \n " , filename , line ) ;
else
{
for ( i = 0 ; i < line ; i + + )
{
2005-12-21 03:07:33 +00:00
VFS_GETS ( f , buffer , sizeof ( buffer ) ) ;
2004-10-01 22:16:01 +00:00
}
if ( ( r = strchr ( buffer , ' \r ' ) ) )
{ r [ 0 ] = ' \n ' ; r [ 1 ] = ' \0 ' ; }
Con_Printf ( " %s " , buffer ) ;
2005-12-21 03:07:33 +00:00
VFS_CLOSE ( f ) ;
2004-10-01 22:16:01 +00:00
}
//PF_break(NULL);
return line ;
}
2005-08-03 23:14:59 +00:00
editprogfuncs = prfncs ;
2011-05-20 04:10:46 +00:00
f1 = OpenEditorFile ;
f2 = filename ;
if ( ! strncmp ( f1 , " src/ " , 4 ) )
f1 + = 4 ;
if ( ! strncmp ( f2 , " src/ " , 4 ) )
f2 + = 4 ;
if ( ! editoractive | | strcmp ( f1 , f2 ) )
2004-08-23 00:15:46 +00:00
{
2011-05-20 04:10:46 +00:00
if ( editoractive )
EditorSaveFile ( OpenEditorFile ) ;
2004-08-23 00:15:46 +00:00
2011-05-20 04:10:46 +00:00
EditorOpenFile ( filename ) ;
2004-08-23 00:15:46 +00:00
}
for ( cursorlinenum = 1 , cursorblock = firstblock ; cursorlinenum < line & & cursorblock - > next ; cursorlinenum + + )
cursorblock = cursorblock - > next ;
executionblock = cursorblock ;
if ( ! parms )
{
editormodal = true ;
2005-05-26 12:55:34 +00:00
while ( editormodal & & editoractive & & editprogfuncs )
2004-08-23 00:15:46 +00:00
{
2005-08-03 23:14:59 +00:00
// key_dest = key_editor;
2004-08-23 00:15:46 +00:00
scr_disabled_for_loading = false ;
SCR_UpdateScreen ( ) ;
Sys_SendKeyEvents ( ) ;
2006-09-18 22:52:33 +00:00
S_ExtraUpdate ( ) ;
2004-08-23 00:15:46 +00:00
NET_Sleep ( 100 , false ) ; //any os.
}
editormodal = false ;
}
return line ;
}
2011-05-20 04:10:46 +00:00
void Editor_ProgsKilled ( progfuncs_t * dead )
{
if ( editprogfuncs = = dead )
{
editprogfuncs = NULL ;
editormodal = false ;
}
}
static void Editor_f ( void )
2004-08-23 00:15:46 +00:00
{
2005-08-14 03:55:08 +00:00
if ( Cmd_Argc ( ) ! = 2 )
{
Con_Printf ( " edit <filename> \n " ) ;
return ;
}
2006-03-10 03:50:23 +00:00
editprogfuncs = NULL ;
useeval = false ;
2004-08-23 00:15:46 +00:00
if ( editoractive )
EditorSaveFile ( OpenEditorFile ) ;
EditorOpenFile ( Cmd_Argv ( 1 ) ) ;
// EditorNewFile();
}
void Editor_Init ( void )
{
Cmd_AddCommand ( " edit " , Editor_f ) ;
2005-12-21 03:07:33 +00:00
2004-08-23 00:15:46 +00:00
Cvar_Register ( & alloweditor , " Text editor " ) ;
Cvar_Register ( & editstripcr , " Text editor " ) ;
Cvar_Register ( & editaddcr , " Text editor " ) ;
Cvar_Register ( & edittabspacing , " Text editor " ) ;
2011-05-20 04:10:46 +00:00
Cvar_Register ( & debugger , " Text editor " ) ;
2004-08-23 00:15:46 +00:00
}
# endif