885 lines
22 KiB
C++
885 lines
22 KiB
C++
|
|
#include "stdafx.h"
|
|
#include "blitzide.h"
|
|
#include "editor.h"
|
|
|
|
static bool locked;
|
|
|
|
#ifdef DEMO
|
|
static const int TEXTLIMIT=16384;
|
|
#else
|
|
static const int TEXTLIMIT=1024*1024-1;
|
|
#endif
|
|
|
|
static const UINT wm_Find=RegisterWindowMessage( FINDMSGSTRING );
|
|
|
|
IMPLEMENT_DYNAMIC( Editor,CWnd )
|
|
BEGIN_MESSAGE_MAP( Editor,CWnd )
|
|
ON_WM_CREATE()
|
|
ON_WM_SIZE()
|
|
ON_WM_SETFOCUS()
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_PAINT()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_CONTROL( EN_CHANGE,1,en_change )
|
|
ON_CONTROL( EN_UPDATE,1,en_update )
|
|
ON_NOTIFY( EN_SELCHANGE,1,en_selchange )
|
|
ON_NOTIFY( EN_PROTECTED,1,en_protected )
|
|
ON_NOTIFY( EN_MSGFILTER,1,en_msgfilter )
|
|
ON_REGISTERED_MESSAGE( wm_Find,onFind )
|
|
END_MESSAGE_MAP()
|
|
|
|
static int blink;
|
|
static set<string> keyWordSet;
|
|
static map<string,string> keyWordMap;
|
|
|
|
static bool isid( int c ){
|
|
return isalnum(c)||c=='_';
|
|
}
|
|
|
|
static bool isfmt( int ch,int nxt ){
|
|
return ch==';' || ch=='\"' || isalpha(ch) || isdigit(ch) || (ch=='$' && isxdigit(nxt));
|
|
}
|
|
|
|
static string rtfbgr( int bgr ){
|
|
return "\\red"+itoa(bgr&0xff)+"\\green"+itoa((bgr>>8)&0xff)+"\\blue"+itoa((bgr>>16)&0xff)+';';
|
|
}
|
|
|
|
DWORD Editor::streamIn( LPBYTE buff,LONG cnt,LONG *done ){
|
|
int n=0;
|
|
while( n<cnt ){
|
|
if( is_curs==is_line.size() ){
|
|
if( is_stream->peek()==EOF ) break;
|
|
is_curs=0;is_line="";int c=0;
|
|
for(;;){
|
|
c=is_stream->get();
|
|
if( c=='\r' || c=='\n' || c==EOF ) break;
|
|
if( c=='\\' || c=='{' || c=='}' ) is_line+='\\';
|
|
is_line+=(char)c;
|
|
}
|
|
formatStreamLine();++is_linenum;
|
|
if( c=='\r' && is_stream->peek()=='\n' ) is_stream->get();
|
|
if( is_stream->peek()==EOF ) is_line+='}';
|
|
}
|
|
int sz=is_line.size()-is_curs;
|
|
if( n+sz>cnt ) sz=cnt-n;
|
|
memcpy( buff+n,is_line.data()+is_curs,sz );
|
|
is_curs+=sz;n+=sz;
|
|
}
|
|
*done=n;
|
|
return 0;
|
|
}
|
|
|
|
DWORD CALLBACK Editor::streamIn( DWORD cookie,LPBYTE buff,LONG cnt,LONG *done ){
|
|
Editor *e=(Editor*)cookie;
|
|
return e->streamIn( buff,cnt,done );
|
|
}
|
|
|
|
DWORD CALLBACK Editor::streamOut( DWORD cookie,LPBYTE buff,LONG cnt,LONG *done ){
|
|
ostream *out=(ostream*)cookie;
|
|
out->write( (char*)buff,cnt );
|
|
*done=cnt;return 0;
|
|
}
|
|
|
|
Editor::Editor( EditorListener *l ):
|
|
listener(l),sizing(false),tabber_width(170),
|
|
fmtBusy(false),findOnly(false),found(false),
|
|
finder(0),selStart(0),selEnd(0),
|
|
findFlags(0),lineToFmt(-1){
|
|
findBuff[0]=replaceBuff[0]=0;
|
|
if( !blink ) blink=GetCaretBlinkTime();
|
|
funcList.setListener( this );
|
|
typeList.setListener( this );
|
|
labsList.setListener( this );
|
|
}
|
|
|
|
Editor::~Editor(){
|
|
}
|
|
|
|
void Editor::resized(){
|
|
CRect r;
|
|
GetClientRect( &r );
|
|
int x=0,y=0,w=r.Width(),h=r.Height();
|
|
if( w ){
|
|
if( tabber_width<4 ) tabber_width=4;
|
|
else if( w-64>0 && tabber_width>w-64 ) tabber_width=w-64;
|
|
}
|
|
editCtrl.MoveWindow( x,y,w-tabber_width-4,y+h );
|
|
tabber.MoveWindow( w-tabber_width+4,y,tabber_width-4,y+h );
|
|
}
|
|
|
|
void Editor::OnPaint(){
|
|
CPaintDC dc( this );
|
|
|
|
CRect r;
|
|
GetClientRect( &r );
|
|
int x=0,y=0,w=r.Width(),h=r.Height();
|
|
|
|
x=w-tabber_width-4;
|
|
w=8;
|
|
|
|
CBrush br( GetSysColor( COLOR_3DFACE ) );
|
|
CRect tr( x,y,x+w,y+h );
|
|
dc.FillRect( &tr,&br );
|
|
|
|
// CRect ar( x,y,x+w,y+w );
|
|
// dc.DrawFrameControl( &ar,DFC_SCROLL,DFCS_SCROLLRIGHT );
|
|
// y+=w;h-=w;
|
|
|
|
CRect dr( x+2,y+2,x+w-2,y+h-2 );
|
|
dc.DrawEdge( &dr,EDGE_RAISED,BF_RECT );
|
|
}
|
|
|
|
void Editor::OnMouseMove( UINT flags,CPoint p ){
|
|
CWnd::OnMouseMove( flags,p );
|
|
|
|
CRect r;
|
|
GetClientRect( &r );
|
|
if( sizing ){
|
|
int dx=p.x-point.x,dy=p.y-point.y;
|
|
tabber_width-=dx;
|
|
resized();Invalidate();
|
|
point=p;
|
|
}else if( abs(p.x-(r.Width()-tabber_width))<4 ){
|
|
SetCursor( AfxGetApp()->LoadStandardCursor( IDC_SIZEWE ) );
|
|
}else{
|
|
SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) );
|
|
}
|
|
}
|
|
|
|
void Editor::OnSize( UINT type,int sw,int sh ){
|
|
CWnd::OnSize( type,sw,sh );
|
|
|
|
resized();
|
|
}
|
|
|
|
void Editor::OnLButtonDown( UINT flags,CPoint p ){
|
|
|
|
CRect r;
|
|
GetClientRect( &r );
|
|
|
|
if( abs(p.x-(r.Width()-tabber_width))<4 ){
|
|
point=p;
|
|
SetCapture();
|
|
SetCursor( AfxGetApp()->LoadStandardCursor( IDC_SIZEWE ) );
|
|
sizing=true;
|
|
}
|
|
}
|
|
|
|
void Editor::OnLButtonUp( UINT flags,CPoint p ){
|
|
if( sizing ){
|
|
SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) );
|
|
ReleaseCapture();
|
|
sizing=false;
|
|
}
|
|
SetFocus();
|
|
}
|
|
|
|
int Editor::OnCreate( LPCREATESTRUCT cs ){
|
|
CWnd::OnCreate( cs );
|
|
|
|
CHARFORMAT fmt;fmt.cbSize=sizeof( fmt );
|
|
fmt.dwMask=CFM_COLOR|CFM_PROTECTED;
|
|
fmt.dwEffects=CFE_PROTECTED;
|
|
fmt.crTextColor=prefs.rgb_default;
|
|
|
|
PARAFORMAT pf;
|
|
memset( &pf,0,sizeof( pf ) );
|
|
pf.cbSize=sizeof( pf );
|
|
pf.dwMask=PFM_TABSTOPS;
|
|
pf.cTabCount=MAX_TAB_STOPS;
|
|
int tabTwips=1440*8/GetDeviceCaps( ::GetDC(0),LOGPIXELSX ) * prefs.edit_tabs;
|
|
for( int k=0;k<MAX_TAB_STOPS;++k ) pf.rgxTabs[k]=k*tabTwips;
|
|
|
|
CRect r( 0,0,0,0 );
|
|
|
|
editCtrl.Create(
|
|
WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|WS_BORDER|
|
|
ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_NOHIDESEL,
|
|
r,this,1 );
|
|
editCtrl.SetFont( &prefs.editFont );
|
|
editCtrl.SetBackgroundColor( false,prefs.rgb_bkgrnd );
|
|
editCtrl.SetDefaultCharFormat( fmt );
|
|
editCtrl.SetEventMask( ENM_CHANGE|ENM_PROTECTED|ENM_KEYEVENTS|ENM_MOUSEEVENTS|ENM_SELCHANGE );
|
|
editCtrl.SetParaFormat( pf );
|
|
editCtrl.LimitText( TEXTLIMIT );
|
|
if( editCtrl.GetLimitText()!=TEXTLIMIT ) AfxMessageBox( "Unable to set editor text Limit" );
|
|
editCtrl.SetModify(false);
|
|
|
|
tabber.Create( WS_CHILD|WS_VISIBLE|TCS_BUTTONS|TCS_HOTTRACK,r,this,2 );
|
|
tabber.SetFont( &prefs.tabsFont );
|
|
tabber.SetPadding( CSize(3,3) );
|
|
|
|
tabber.setListener( this );
|
|
|
|
int bk=prefs.rgb_bkgrnd;
|
|
int fg=prefs.rgb_ident;
|
|
|
|
int ws=WS_CHILD|WS_BORDER;
|
|
|
|
funcList.Create( ws|LVS_LIST|LVS_SHOWSELALWAYS,r,&tabber,1 );
|
|
funcList.SetFont( &prefs.debugFont );
|
|
funcList.SetBkColor( bk );
|
|
funcList.SetTextColor( fg );
|
|
funcList.SetTextBkColor( bk );
|
|
|
|
typeList.Create( ws|LVS_LIST|LVS_SHOWSELALWAYS,r,&tabber,2 );
|
|
typeList.SetFont( &prefs.debugFont );
|
|
typeList.SetBkColor( bk );
|
|
typeList.SetTextColor( fg );
|
|
typeList.SetTextBkColor( bk );
|
|
|
|
labsList.Create( ws|LVS_LIST|LVS_SHOWSELALWAYS,r,&tabber,3 );
|
|
labsList.SetFont( &prefs.debugFont );
|
|
labsList.SetBkColor( bk );
|
|
labsList.SetTextColor( fg );
|
|
labsList.SetTextBkColor( bk );
|
|
|
|
tabber.insert( 0,&funcList,"funcs" );
|
|
tabber.insert( 1,&typeList,"types" );
|
|
tabber.insert( 2,&labsList,"labels" );
|
|
|
|
cursorMoved();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/************************************************* PUBLIC ***********************************************/
|
|
|
|
void Editor::setName( const string &n ){
|
|
name=n;
|
|
}
|
|
|
|
bool Editor::setText( istream &in ){
|
|
// editCtrl.HideCaret();
|
|
fmtBusy=true;
|
|
EDITSTREAM es;
|
|
es.dwCookie=(DWORD)this;
|
|
es.dwError=0;
|
|
es.pfnCallback=streamIn;
|
|
is_line="{{\\colortbl;"+rtfbgr(prefs.rgb_string)+rtfbgr(prefs.rgb_ident)+
|
|
rtfbgr(prefs.rgb_keyword)+rtfbgr(prefs.rgb_comment)+rtfbgr(prefs.rgb_digit)+
|
|
rtfbgr(prefs.rgb_default)+"}";
|
|
int tabTwips=1440*8/GetDeviceCaps( ::GetDC(0),LOGPIXELSX ) * prefs.edit_tabs;
|
|
for( int k=0;k<MAX_TAB_STOPS;++k ) is_line+="\\tx"+itoa( k*tabTwips )+' ';
|
|
is_stream=∈
|
|
is_curs=is_linenum=0;
|
|
funcList.clear();
|
|
typeList.clear();
|
|
labsList.clear();
|
|
editCtrl.StreamIn( SF_RTF,es );
|
|
fmtBusy=false;
|
|
// editCtrl.HideCaret();
|
|
caret();
|
|
return es.dwError==0;
|
|
}
|
|
|
|
void Editor::setModified( bool n ){
|
|
editCtrl.SetModify( n );
|
|
}
|
|
|
|
void Editor::setCursor( int n ){
|
|
int row=(n>>16)&0xffff,col=n&0xffff;
|
|
int pos=editCtrl.LineIndex( row )+col;
|
|
editCtrl.SetSel( pos,pos );
|
|
}
|
|
|
|
string Editor::getName()const{
|
|
return name;
|
|
}
|
|
|
|
bool Editor::getText( ostream &out ){
|
|
fixFmt(true);
|
|
EDITSTREAM es;
|
|
es.dwCookie=(DWORD)&out;
|
|
es.dwError=0;
|
|
es.pfnCallback=streamOut;
|
|
editCtrl.StreamOut( SF_TEXT,es );
|
|
return es.dwError==0;
|
|
}
|
|
|
|
void Editor::cut(){
|
|
editCtrl.Cut();
|
|
}
|
|
|
|
void Editor::copy(){
|
|
editCtrl.Copy();
|
|
}
|
|
|
|
void Editor::paste(){
|
|
editCtrl.PasteSpecial( CF_TEXT,0 );
|
|
}
|
|
|
|
bool Editor::canCutCopy(){
|
|
getSel();return selStart!=selEnd;
|
|
}
|
|
|
|
bool Editor::canPaste(){
|
|
return editCtrl.CanPaste() ? true : false;
|
|
}
|
|
|
|
void Editor::print(){
|
|
|
|
static const int MARG=720; //1440=1 inch
|
|
|
|
CPrintDialog dlg(false);
|
|
int e=dlg.DoModal();if( e==IDCANCEL ) return;
|
|
|
|
HDC hdc=dlg.GetPrinterDC();
|
|
if( !hdc ){
|
|
MessageBox( "Error printing" );
|
|
return;
|
|
}
|
|
|
|
int hr=GetDeviceCaps(hdc,HORZRES),vr=GetDeviceCaps(hdc,VERTRES);
|
|
int px=GetDeviceCaps(hdc,LOGPIXELSX),py=GetDeviceCaps(hdc,LOGPIXELSY);
|
|
|
|
SetMapMode(hdc,MM_TEXT);
|
|
|
|
FORMATRANGE fr={0};
|
|
fr.hdc=fr.hdcTarget=hdc;
|
|
fr.rcPage.left=fr.rcPage.top=0;
|
|
fr.rcPage.right=(hr/px)*1440;
|
|
fr.rcPage.bottom=(vr/py)*1440;
|
|
|
|
//margins
|
|
fr.rc.left=fr.rcPage.left+MARG;
|
|
fr.rc.top=fr.rcPage.top+MARG;
|
|
fr.rc.right=fr.rcPage.right-MARG;
|
|
fr.rc.bottom=fr.rcPage.bottom-MARG;
|
|
|
|
char buff[MAX_PATH];
|
|
strcpy( buff,name.c_str() );
|
|
|
|
DOCINFO di={sizeof(di)};
|
|
di.lpszDocName=buff;
|
|
|
|
getSel();
|
|
int start=selStart,end=selEnd;
|
|
if( start==end ){ start=0;end=editCtrl.GetTextLength(); }
|
|
|
|
StartDoc(hdc,&di);
|
|
while( start<end ){
|
|
StartPage(hdc);
|
|
fr.chrg.cpMin=start;
|
|
fr.chrg.cpMax=end;
|
|
start=editCtrl.FormatRange(&fr,true);
|
|
EndPage(hdc);
|
|
}
|
|
EndDoc(hdc);
|
|
|
|
editCtrl.FormatRange(0,false);
|
|
DeleteDC(hdc);
|
|
}
|
|
|
|
void Editor::find(){
|
|
if( finder ) return;
|
|
finder=new CFindReplaceDialog();
|
|
finder->m_fr.lpstrFindWhat=findBuff;
|
|
finder->m_fr.wFindWhatLen=256;
|
|
finder->m_fr.lpstrReplaceWith=replaceBuff;
|
|
finder->m_fr.wReplaceWithLen=256;
|
|
finder->Create( findOnly=true,0,0,FR_HIDEUPDOWN,this );
|
|
found=false;
|
|
}
|
|
|
|
void Editor::replace(){
|
|
if( finder ) return;
|
|
finder=new CFindReplaceDialog();
|
|
finder->m_fr.lpstrFindWhat=findBuff;
|
|
finder->m_fr.wFindWhatLen=256;
|
|
finder->m_fr.lpstrReplaceWith=replaceBuff;
|
|
finder->m_fr.wReplaceWithLen=256;
|
|
finder->Create( findOnly=false,0,0,FR_HIDEUPDOWN,this );
|
|
found=false;
|
|
}
|
|
|
|
bool Editor::canFind(){
|
|
return finder==0;
|
|
}
|
|
|
|
bool Editor::findNext( bool wrap ){
|
|
long start,end;
|
|
editCtrl.GetSel( start,end );
|
|
|
|
FINDTEXTEX t;
|
|
memset( &t,0,sizeof( t ) );
|
|
t.chrg.cpMin=end;
|
|
t.chrg.cpMax=-1;
|
|
t.lpstrText=findBuff;
|
|
if( editCtrl.FindText( findFlags,&t )>=0 ){
|
|
editCtrl.SetSel( t.chrgText.cpMin,t.chrgText.cpMax );
|
|
return true;
|
|
}
|
|
if( !wrap ) return false;
|
|
t.chrg.cpMin=0;
|
|
t.chrg.cpMax=end;
|
|
if( editCtrl.FindText( findFlags,&t )>=0 ){
|
|
editCtrl.SetSel( t.chrgText.cpMin,t.chrgText.cpMax );
|
|
return true;
|
|
}
|
|
string s( "Can't find \"" );s+=findBuff;s+='\"';
|
|
MessageBox( s.c_str(),"Text not found" );
|
|
if( finder ) finder->SetFocus();
|
|
return false;
|
|
}
|
|
|
|
void Editor::hilight( int pos ){
|
|
int row=(pos>>16)&0xffff,col=pos&0xffff;
|
|
pos=editCtrl.LineIndex( row )+col;
|
|
|
|
editCtrl.HideSelection( true,false );
|
|
getSel();
|
|
bool quote=false;
|
|
int end=pos,len=editCtrl.GetTextLength();
|
|
while( end<len ){
|
|
char temp[8];
|
|
editCtrl.SetSel( end,end+1 );
|
|
editCtrl.GetSelText( temp );
|
|
if( temp[0]=='\"' ) quote=!quote;
|
|
if( !quote && (temp[0]==':' || !isprint( temp[0] )) ) break;
|
|
++end;
|
|
}
|
|
editCtrl.HideSelection( false,false );
|
|
editCtrl.SetSel( pos,end );
|
|
}
|
|
|
|
void Editor::selectAll(){
|
|
editCtrl.SetSel( 0,-1 );
|
|
}
|
|
|
|
void Editor::lock(){
|
|
locked=true;
|
|
}
|
|
|
|
void Editor::unlock(){
|
|
locked=false;
|
|
}
|
|
|
|
string Editor::getKeyword(){
|
|
fixFmt(true);
|
|
getSel();
|
|
int ln=editCtrl.LineFromChar(selStart);
|
|
int pos=selStart-editCtrl.LineIndex( ln );
|
|
string line=getLine( ln );if( pos>line.size() ) return "";
|
|
|
|
//ok, scan back until we have an isapha char preceded by a nonalnum/non '_' char
|
|
for(;;){
|
|
while( pos>0 && ( !isalpha(line[pos]) || isid(line[pos-1]) ) ) --pos;
|
|
if( !isalpha(line[pos]) ) return "";
|
|
int end=pos;while( end<line.size() && isid(line[end]) ) ++end;
|
|
string t=line.substr( pos,end-pos );
|
|
if( keyWordSet.find( t )!=keyWordSet.end() ) return t;
|
|
if( !pos ) return "";
|
|
--pos;
|
|
}
|
|
}
|
|
|
|
bool Editor::getModified(){
|
|
return editCtrl.GetModify() ? true : false;
|
|
}
|
|
|
|
int Editor::getCursor(){
|
|
long start,end;
|
|
editCtrl.GetSel( start,end );
|
|
int row,col;
|
|
row=editCtrl.LineFromChar( start );
|
|
col=start-editCtrl.LineIndex( row );
|
|
return ((row)<<16)|(col);
|
|
}
|
|
|
|
void Editor::getCursor( int *row,int *col ){
|
|
long start,end;
|
|
editCtrl.GetSel( start,end );
|
|
*row=editCtrl.LineFromChar( end );
|
|
*col=end-editCtrl.LineIndex( *row );
|
|
}
|
|
|
|
void Editor::addKeyword( const string &s ){
|
|
keyWordSet.insert( s );
|
|
string t=s;
|
|
for( int k=0;k<t.size();++k ) t[k]=tolower(t[k]);
|
|
keyWordMap[t]=s;
|
|
}
|
|
|
|
/************************************************* PRIVATE ***********************************************/
|
|
|
|
void Editor::endFind(){
|
|
if( !finder ) return;
|
|
finder->DestroyWindow();
|
|
finder=0;
|
|
}
|
|
|
|
LRESULT Editor::onFind( WPARAM w,LPARAM l ){
|
|
if( !finder ) return 0;
|
|
|
|
findFlags=0;
|
|
if( finder->MatchCase() ) findFlags|=FR_MATCHCASE;
|
|
if( finder->MatchWholeWord() ) findFlags|=FR_WHOLEWORD;
|
|
strcpy( findBuff,finder->GetFindString() );
|
|
strcpy( replaceBuff,finder->GetReplaceString() );
|
|
|
|
if( finder->FindNext() ){
|
|
found=findNext( true );
|
|
if( found && findOnly ) endFind();
|
|
}else if( finder->ReplaceCurrent() ){
|
|
if( found ) editCtrl.ReplaceSel( replaceBuff,true );
|
|
found=findNext( true );
|
|
}else if( finder->ReplaceAll() ){
|
|
int cnt=0;
|
|
editCtrl.HideSelection( true,false );
|
|
editCtrl.SetSel( 0,0 );
|
|
while( findNext( false ) ){
|
|
editCtrl.ReplaceSel( replaceBuff,true );
|
|
++cnt;
|
|
}
|
|
endFind();
|
|
char buff[32];itoa( cnt,buff,10 );
|
|
string s( buff );s+=" occurances replaced";
|
|
MessageBox( s.c_str(),"Replace All Done" );
|
|
editCtrl.HideSelection( false,false );
|
|
}
|
|
|
|
if( finder && finder->IsTerminating() ) endFind();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Editor::caret(){
|
|
if( !prefs.edit_blkcursor ) return;
|
|
long start,end;
|
|
editCtrl.GetSel( start,end );
|
|
if( start==end ){
|
|
editCtrl.CreateSolidCaret( 8,13 );
|
|
editCtrl.ShowCaret();
|
|
}else editCtrl.HideCaret();
|
|
}
|
|
|
|
void Editor::OnSetFocus( CWnd *wnd ){
|
|
if( prefs.edit_blkcursor ) SetCaretBlinkTime( 200 );
|
|
editCtrl.SetFocus();
|
|
caret();
|
|
}
|
|
|
|
void Editor::OnKillFocus( CWnd *wnd ){
|
|
CWnd::OnKillFocus( wnd );
|
|
fixFmt(true);
|
|
}
|
|
|
|
string Editor::getLine( int line ){
|
|
int idx1=editCtrl.LineIndex( line );
|
|
int idx2=editCtrl.LineIndex( line+1 );if( idx2==-1 ) idx2=editCtrl.GetTextLength();
|
|
int len=idx2-idx1;
|
|
char *buff=new char[ len>3 ? len+1 : 4 ];
|
|
*(int*)buff=len;
|
|
int out=editCtrl.GetLine( line,buff );
|
|
buff[len]=0;
|
|
string t=string( buff );
|
|
delete [] buff;
|
|
return t;
|
|
}
|
|
|
|
void Editor::funcSelected( int line ){
|
|
int pos=editCtrl.LineIndex( line );
|
|
editCtrl.SetSel( editCtrl.GetTextLength()-1,editCtrl.GetTextLength()-1 );
|
|
editCtrl.SetSel( pos,pos );
|
|
SetFocus();
|
|
}
|
|
|
|
void Editor::currentSet( Tabber *tabber,int index ){
|
|
SetFocus();
|
|
}
|
|
|
|
void Editor::cursorMoved(){
|
|
listener->cursorMoved( this );
|
|
}
|
|
|
|
void Editor::en_update(){
|
|
caret();
|
|
}
|
|
|
|
void Editor::en_msgfilter( NMHDR *nmhdr,LRESULT *result ){
|
|
if( locked || fmtBusy ){ *result=1;return; }
|
|
|
|
*result=0;
|
|
getSel();
|
|
|
|
MSGFILTER *msg=(MSGFILTER*)nmhdr;
|
|
|
|
|
|
if( msg->msg==WM_RBUTTONDOWN ){
|
|
|
|
CPoint p( LOWORD(msg->lParam),HIWORD(msg->lParam) );
|
|
|
|
ClientToScreen( &p );
|
|
|
|
CMenu *menu=blitzIDE.mainFrame->GetMenu();
|
|
|
|
CMenu *edit=menu->GetSubMenu(1);
|
|
|
|
edit->TrackPopupMenu( TPM_LEFTALIGN,p.x,p.y,blitzIDE.mainFrame );
|
|
|
|
}else if( msg->msg==WM_CHAR ){
|
|
if( msg->wParam=='\t' ){
|
|
int lineStart=editCtrl.LineFromChar( selStart );
|
|
int lineEnd=editCtrl.LineFromChar( selEnd );
|
|
if( lineEnd<=lineStart ) return;
|
|
editCtrl.HideSelection( true,false );
|
|
if( GetAsyncKeyState( VK_SHIFT )&0x80000000 ){
|
|
char buff[4];
|
|
for( int line=lineStart;line<lineEnd;++line ){
|
|
int n=editCtrl.LineIndex( line );
|
|
editCtrl.SetSel( n,n+1 );editCtrl.GetSelText( buff );
|
|
if( buff[0]=='\t' ) editCtrl.ReplaceSel( "",true );
|
|
}
|
|
}else{
|
|
for( int line=lineStart;line<lineEnd;++line ){
|
|
int n=editCtrl.LineIndex( line );
|
|
editCtrl.SetSel( n,n );editCtrl.ReplaceSel( "\t",true );
|
|
}
|
|
}
|
|
selStart=editCtrl.LineIndex( lineStart );
|
|
selEnd=editCtrl.LineIndex( lineEnd );
|
|
setSel();*result=1;
|
|
editCtrl.HideSelection( false,false );
|
|
}else if( msg->wParam==13 ){
|
|
if( selStart!=selEnd ) return;
|
|
int k;
|
|
int ln=editCtrl.LineFromChar( selStart );
|
|
int pos=selStart-editCtrl.LineIndex( ln );
|
|
string line=getLine( ln );if( pos>line.size() ) return;
|
|
for( k=0;k<pos && line[k]=='\t';++k ){}
|
|
line="\r\n"+line.substr( 0,k )+'\0';
|
|
editCtrl.ReplaceSel( line.data(),true );
|
|
*result=1;
|
|
}
|
|
}
|
|
caret();
|
|
}
|
|
|
|
void Editor::en_selchange( NMHDR *nmhdr,LRESULT *result ){
|
|
if( !fmtBusy ) fixFmt(false);
|
|
cursorMoved();
|
|
caret();
|
|
}
|
|
|
|
void Editor::en_protected( NMHDR *nmhdr,LRESULT *result ){
|
|
*result=0;if( fmtBusy ) return;
|
|
fmtLineCount=editCtrl.GetLineCount();
|
|
found=false;
|
|
}
|
|
|
|
void Editor::en_change(){
|
|
if( fmtBusy ) return;
|
|
|
|
fmtBusy=true;
|
|
editCtrl.HideSelection( true,false );
|
|
getSel();
|
|
|
|
int begin=editCtrl.LineFromChar( selStart );
|
|
int end=begin+1;
|
|
|
|
int lineCount=editCtrl.GetLineCount();
|
|
int delta=lineCount-fmtLineCount;
|
|
|
|
if( delta>0 ){
|
|
begin-=delta;
|
|
funcList.relocate( begin,delta );
|
|
typeList.relocate( begin,delta );
|
|
labsList.relocate( begin,delta );
|
|
funcList.remove( begin,end );
|
|
typeList.remove( begin,end );
|
|
labsList.remove( begin,end );
|
|
}else if( delta<0 ){
|
|
int t=end-delta;
|
|
funcList.remove( begin,t );
|
|
typeList.remove( begin,t );
|
|
labsList.remove( begin,t );
|
|
funcList.relocate( t,delta );
|
|
typeList.relocate( t,delta );
|
|
labsList.relocate( t,delta );
|
|
}else{
|
|
funcList.remove( begin,end );
|
|
typeList.remove( begin,end );
|
|
labsList.remove( begin,end );
|
|
}
|
|
|
|
for( int n=begin;n<end;++n ) formatLine( n );
|
|
|
|
setSel();editCtrl.HideSelection( false,false );
|
|
fmtBusy=false;
|
|
cursorMoved();
|
|
}
|
|
|
|
void Editor::setFormat( int from,int to,int color,const string &s ){
|
|
editCtrl.SetSel( from,to );
|
|
if( s.size() ){
|
|
char buff[256];
|
|
editCtrl.GetSelText( buff );buff[to-from]=0;
|
|
if( string(buff)!=s ){
|
|
editCtrl.ReplaceSel( s.c_str() );
|
|
editCtrl.SetSel( from,to );
|
|
}
|
|
}
|
|
CHARFORMAT fmt;
|
|
fmt.cbSize=sizeof( fmt );
|
|
DWORD t=editCtrl.GetSelectionCharFormat( fmt );
|
|
if( (t&CFM_COLOR) && fmt.crTextColor==color ) return;
|
|
fmt.dwMask=CFM_COLOR|CFM_PROTECTED;
|
|
fmt.dwEffects=CFE_PROTECTED;
|
|
fmt.crTextColor=color;
|
|
editCtrl.SetSelectionCharFormat( fmt );
|
|
}
|
|
|
|
void Editor::formatStreamLine(){
|
|
string out;
|
|
char cf='0';
|
|
for( int k=0;k<is_line.size(); ){
|
|
int from=k;
|
|
char pf=cf;
|
|
int c=is_line[k],is_sz=is_line.size();
|
|
if( !isgraph( c ) ){
|
|
for( ++k;k<is_sz && !isgraph(is_line[k]);++k ){}
|
|
}else if( !isfmt( c,k+1<is_sz?is_line[k+1]:0 ) ){
|
|
for( ++k;k<is_sz && !isfmt( is_line[k],k+1<is_sz?is_line[k+1]:0 );++k ){}
|
|
cf='6';
|
|
}else if( c==';' ){ //comment?
|
|
k=is_sz;
|
|
cf='4';
|
|
}else if( c=='\"' ){ //string const?
|
|
for( ++k;k<is_sz && is_line[k]!='\"';++k ){}
|
|
if( k<is_sz ) ++k;
|
|
cf='1';
|
|
}else if( isalpha( c ) ){ //ident?
|
|
for( ++k;k<is_sz && isid(is_line[k]);++k ){}
|
|
if( keyWordSet.find( is_line.substr( from,k-from ) )==keyWordSet.end() ) cf='2';
|
|
else cf='3';
|
|
}else if( c=='$' ){
|
|
for( ++k;k<is_sz && isxdigit(is_line[k]);++k ){}
|
|
cf='5';
|
|
}else if( isdigit( c ) ){ //numeric const?
|
|
for( ++k;k<is_sz && isdigit(is_line[k]);++k ){}
|
|
cf='5';
|
|
}
|
|
if( cf!=pf ){
|
|
out+="\\cf";out+=cf;out+=' ';
|
|
}
|
|
out+=is_line.substr( from,k-from );
|
|
}
|
|
if( is_line[0]=='F' && is_line.find( "Function" )==0 ){
|
|
for( int k=8;k<is_line.size();++k ){
|
|
if( isalpha( is_line[k] ) ){
|
|
int start=k;
|
|
for( ++k;k<is_line.size() && isid(is_line[k]);++k ){}
|
|
funcList.insert( is_linenum,is_line.substr( start,k-start ) );
|
|
break;
|
|
}
|
|
}
|
|
}else if( is_line[0]=='T' && is_line.find( "Type" )==0 ){
|
|
for( int k=4;k<is_line.size();++k ){
|
|
if( isalpha( is_line[k] ) ){
|
|
int start=k;
|
|
for( ++k;k<is_line.size() && isid(is_line[k]);++k ){}
|
|
typeList.insert( is_linenum,is_line.substr( start,k-start ) );
|
|
break;
|
|
}
|
|
}
|
|
}else if( is_line[0]=='.' ){
|
|
for( int k=1;k<is_line.size();++k ){
|
|
if( isalpha( is_line[k] ) ){
|
|
int start=k;
|
|
for( ++k;k<is_line.size() && isid(is_line[k]);++k ){}
|
|
labsList.insert( is_linenum,is_line.substr( start,k-start ) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
is_line=out+"\\line ";
|
|
}
|
|
|
|
void Editor::fixFmt( bool fmt ){
|
|
if( lineToFmt<0 || fmtBusy ) return;
|
|
fmtBusy=true;
|
|
editCtrl.HideSelection( true,false );getSel();
|
|
long start=selStart;if( fmt ) selStart=-1;
|
|
formatLine( lineToFmt );
|
|
selStart=start;setSel();editCtrl.HideSelection( false,false );
|
|
fmtBusy=false;
|
|
}
|
|
|
|
void Editor::formatLine( int ln ){
|
|
if( ln<0 || ln>=editCtrl.GetLineCount() ) return;
|
|
|
|
lineToFmt=-1;
|
|
int pos=editCtrl.LineIndex( ln );
|
|
string tline=getLine( ln );
|
|
string line=tolower( tline );
|
|
|
|
int *cf=0;
|
|
string rep;
|
|
for( int k=0;k<line.size(); ){
|
|
rep.resize(0);
|
|
int *pf=cf;
|
|
int from=k,c=line[k],sz=line.size();
|
|
if( !isgraph( c ) ){
|
|
for( ++k;k<sz && !isgraph(line[k]);++k ){}
|
|
}else if( !isfmt( c,k+1<sz?line[k+1]:0 ) ){
|
|
for( ++k;k<sz && !isfmt(line[k],k+1<sz?line[k+1]:0);++k ){}
|
|
cf=&prefs.rgb_default;
|
|
}else if( c==';' ){ //comment?
|
|
k=sz;
|
|
cf=&prefs.rgb_comment;
|
|
}else if( c=='\"' ){ //string const?
|
|
for( ++k;k<sz && line[k]!='\"';++k ){}
|
|
if( k<sz ) ++k;
|
|
cf=&prefs.rgb_string;
|
|
}else if( isalpha( c ) ){ //ident?
|
|
for( ++k;k<sz && isid(line[k]);++k ){}
|
|
cf=&prefs.rgb_ident;pf=0;
|
|
if( selStart<=pos+from || selStart>pos+k ){
|
|
map<string,string>::iterator it=keyWordMap.find( line.substr( from,k-from ) );
|
|
if( it!=keyWordMap.end() ){
|
|
rep=it->second;cf=&prefs.rgb_keyword;
|
|
}
|
|
}else lineToFmt=ln;
|
|
}else if( c=='$' && k+1<sz && isxdigit(line[k+1]) ){
|
|
for( ++k;k<sz && isxdigit(line[k]);++k ){}
|
|
cf=&prefs.rgb_digit;
|
|
}else if( isdigit( c ) ){ //numeric const?
|
|
for( ++k;k<sz && isdigit(line[k]);++k ){}
|
|
cf=&prefs.rgb_digit;
|
|
}
|
|
if( cf!=pf ) setFormat( pos+from,pos+k,*cf,rep );
|
|
}
|
|
if( line[0]=='f' && line.find( "function" )==0 ){
|
|
for( int k=8;k<line.size();++k ){
|
|
if( isalpha( line[k] ) ){
|
|
int start=k;
|
|
for( ++k;k<line.size() && isid(line[k]);++k ){}
|
|
funcList.insert( ln,tline.substr( start,k-start ) );
|
|
break;
|
|
}
|
|
}
|
|
}else if( line[0]=='t' && line.find( "type" )==0 ){
|
|
for( int k=4;k<line.size();++k ){
|
|
if( isalpha( line[k] ) ){
|
|
int start=k;
|
|
for( ++k;k<line.size() && isid(line[k]);++k ){}
|
|
typeList.insert( ln,tline.substr( start,k-start ) );
|
|
break;
|
|
}
|
|
}
|
|
}else if( line[0]=='.' ){
|
|
for( int k=1;k<line.size();++k ){
|
|
if( isalpha( line[k] ) ){
|
|
int start=k;
|
|
for( ++k;k<line.size() && isid(line[k]);++k ){}
|
|
labsList.insert( ln,tline.substr( start,k-start ) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|