editor.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. #include "stdafx.h"
  2. #include "blitzide.h"
  3. #include "editor.h"
  4. static bool locked;
  5. #ifdef DEMO
  6. static const int TEXTLIMIT=16384;
  7. #else
  8. static const int TEXTLIMIT=1024*1024-1;
  9. #endif
  10. static const UINT wm_Find=RegisterWindowMessage( FINDMSGSTRING );
  11. IMPLEMENT_DYNAMIC( Editor,CWnd )
  12. BEGIN_MESSAGE_MAP( Editor,CWnd )
  13. ON_WM_CREATE()
  14. ON_WM_SIZE()
  15. ON_WM_SETFOCUS()
  16. ON_WM_KILLFOCUS()
  17. ON_WM_PAINT()
  18. ON_WM_MOUSEMOVE()
  19. ON_WM_LBUTTONDOWN()
  20. ON_WM_LBUTTONUP()
  21. ON_CONTROL( EN_CHANGE,1,en_change )
  22. ON_CONTROL( EN_UPDATE,1,en_update )
  23. ON_NOTIFY( EN_SELCHANGE,1,en_selchange )
  24. ON_NOTIFY( EN_PROTECTED,1,en_protected )
  25. ON_NOTIFY( EN_MSGFILTER,1,en_msgfilter )
  26. ON_REGISTERED_MESSAGE( wm_Find,onFind )
  27. END_MESSAGE_MAP()
  28. static int blink;
  29. static set<string> keyWordSet;
  30. static map<string,string> keyWordMap;
  31. static bool isid( int c ){
  32. return isalnum(c)||c=='_';
  33. }
  34. static bool isfmt( int ch,int nxt ){
  35. return ch==';' || ch=='\"' || isalpha(ch) || isdigit(ch) || (ch=='$' && isxdigit(nxt));
  36. }
  37. static string rtfbgr( int bgr ){
  38. return "\\red"+itoa(bgr&0xff)+"\\green"+itoa((bgr>>8)&0xff)+"\\blue"+itoa((bgr>>16)&0xff)+';';
  39. }
  40. DWORD Editor::streamIn( LPBYTE buff,LONG cnt,LONG *done ){
  41. int n=0;
  42. while( n<cnt ){
  43. if( is_curs==is_line.size() ){
  44. if( is_stream->peek()==EOF ) break;
  45. is_curs=0;is_line="";int c=0;
  46. for(;;){
  47. c=is_stream->get();
  48. if( c=='\r' || c=='\n' || c==EOF ) break;
  49. if( c=='\\' || c=='{' || c=='}' ) is_line+='\\';
  50. is_line+=(char)c;
  51. }
  52. formatStreamLine();++is_linenum;
  53. if( c=='\r' && is_stream->peek()=='\n' ) is_stream->get();
  54. if( is_stream->peek()==EOF ) is_line+='}';
  55. }
  56. int sz=is_line.size()-is_curs;
  57. if( n+sz>cnt ) sz=cnt-n;
  58. memcpy( buff+n,is_line.data()+is_curs,sz );
  59. is_curs+=sz;n+=sz;
  60. }
  61. *done=n;
  62. return 0;
  63. }
  64. DWORD CALLBACK Editor::streamIn( DWORD cookie,LPBYTE buff,LONG cnt,LONG *done ){
  65. Editor *e=(Editor*)cookie;
  66. return e->streamIn( buff,cnt,done );
  67. }
  68. DWORD CALLBACK Editor::streamOut( DWORD cookie,LPBYTE buff,LONG cnt,LONG *done ){
  69. ostream *out=(ostream*)cookie;
  70. out->write( (char*)buff,cnt );
  71. *done=cnt;return 0;
  72. }
  73. Editor::Editor( EditorListener *l ):
  74. listener(l),sizing(false),tabber_width(170),
  75. fmtBusy(false),findOnly(false),found(false),
  76. finder(0),selStart(0),selEnd(0),
  77. findFlags(0),lineToFmt(-1){
  78. findBuff[0]=replaceBuff[0]=0;
  79. if( !blink ) blink=GetCaretBlinkTime();
  80. funcList.setListener( this );
  81. typeList.setListener( this );
  82. labsList.setListener( this );
  83. }
  84. Editor::~Editor(){
  85. }
  86. void Editor::resized(){
  87. CRect r;
  88. GetClientRect( &r );
  89. int x=0,y=0,w=r.Width(),h=r.Height();
  90. if( w ){
  91. if( tabber_width<4 ) tabber_width=4;
  92. else if( w-64>0 && tabber_width>w-64 ) tabber_width=w-64;
  93. }
  94. editCtrl.MoveWindow( x,y,w-tabber_width-4,y+h );
  95. tabber.MoveWindow( w-tabber_width+4,y,tabber_width-4,y+h );
  96. }
  97. void Editor::OnPaint(){
  98. CPaintDC dc( this );
  99. CRect r;
  100. GetClientRect( &r );
  101. int x=0,y=0,w=r.Width(),h=r.Height();
  102. x=w-tabber_width-4;
  103. w=8;
  104. CBrush br( GetSysColor( COLOR_3DFACE ) );
  105. CRect tr( x,y,x+w,y+h );
  106. dc.FillRect( &tr,&br );
  107. // CRect ar( x,y,x+w,y+w );
  108. // dc.DrawFrameControl( &ar,DFC_SCROLL,DFCS_SCROLLRIGHT );
  109. // y+=w;h-=w;
  110. CRect dr( x+2,y+2,x+w-2,y+h-2 );
  111. dc.DrawEdge( &dr,EDGE_RAISED,BF_RECT );
  112. }
  113. void Editor::OnMouseMove( UINT flags,CPoint p ){
  114. CWnd::OnMouseMove( flags,p );
  115. CRect r;
  116. GetClientRect( &r );
  117. if( sizing ){
  118. int dx=p.x-point.x,dy=p.y-point.y;
  119. tabber_width-=dx;
  120. resized();Invalidate();
  121. point=p;
  122. }else if( abs(p.x-(r.Width()-tabber_width))<4 ){
  123. SetCursor( AfxGetApp()->LoadStandardCursor( IDC_SIZEWE ) );
  124. }else{
  125. SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) );
  126. }
  127. }
  128. void Editor::OnSize( UINT type,int sw,int sh ){
  129. CWnd::OnSize( type,sw,sh );
  130. resized();
  131. }
  132. void Editor::OnLButtonDown( UINT flags,CPoint p ){
  133. CRect r;
  134. GetClientRect( &r );
  135. if( abs(p.x-(r.Width()-tabber_width))<4 ){
  136. point=p;
  137. SetCapture();
  138. SetCursor( AfxGetApp()->LoadStandardCursor( IDC_SIZEWE ) );
  139. sizing=true;
  140. }
  141. }
  142. void Editor::OnLButtonUp( UINT flags,CPoint p ){
  143. if( sizing ){
  144. SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) );
  145. ReleaseCapture();
  146. sizing=false;
  147. }
  148. SetFocus();
  149. }
  150. int Editor::OnCreate( LPCREATESTRUCT cs ){
  151. CWnd::OnCreate( cs );
  152. CHARFORMAT fmt;fmt.cbSize=sizeof( fmt );
  153. fmt.dwMask=CFM_COLOR|CFM_PROTECTED;
  154. fmt.dwEffects=CFE_PROTECTED;
  155. fmt.crTextColor=prefs.rgb_default;
  156. PARAFORMAT pf;
  157. memset( &pf,0,sizeof( pf ) );
  158. pf.cbSize=sizeof( pf );
  159. pf.dwMask=PFM_TABSTOPS;
  160. pf.cTabCount=MAX_TAB_STOPS;
  161. int tabTwips=1440*8/GetDeviceCaps( ::GetDC(0),LOGPIXELSX ) * prefs.edit_tabs;
  162. for( int k=0;k<MAX_TAB_STOPS;++k ) pf.rgxTabs[k]=k*tabTwips;
  163. CRect r( 0,0,0,0 );
  164. editCtrl.Create(
  165. WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|WS_BORDER|
  166. ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_NOHIDESEL,
  167. r,this,1 );
  168. editCtrl.SetFont( &prefs.editFont );
  169. editCtrl.SetBackgroundColor( false,prefs.rgb_bkgrnd );
  170. editCtrl.SetDefaultCharFormat( fmt );
  171. editCtrl.SetEventMask( ENM_CHANGE|ENM_PROTECTED|ENM_KEYEVENTS|ENM_MOUSEEVENTS|ENM_SELCHANGE );
  172. editCtrl.SetParaFormat( pf );
  173. editCtrl.LimitText( TEXTLIMIT );
  174. if( editCtrl.GetLimitText()!=TEXTLIMIT ) AfxMessageBox( "Unable to set editor text Limit" );
  175. editCtrl.SetModify(false);
  176. tabber.Create( WS_CHILD|WS_VISIBLE|TCS_BUTTONS|TCS_HOTTRACK,r,this,2 );
  177. tabber.SetFont( &prefs.tabsFont );
  178. tabber.SetPadding( CSize(3,3) );
  179. tabber.setListener( this );
  180. int bk=prefs.rgb_bkgrnd;
  181. int fg=prefs.rgb_ident;
  182. int ws=WS_CHILD|WS_BORDER;
  183. funcList.Create( ws|LVS_LIST|LVS_SHOWSELALWAYS,r,&tabber,1 );
  184. funcList.SetFont( &prefs.debugFont );
  185. funcList.SetBkColor( bk );
  186. funcList.SetTextColor( fg );
  187. funcList.SetTextBkColor( bk );
  188. typeList.Create( ws|LVS_LIST|LVS_SHOWSELALWAYS,r,&tabber,2 );
  189. typeList.SetFont( &prefs.debugFont );
  190. typeList.SetBkColor( bk );
  191. typeList.SetTextColor( fg );
  192. typeList.SetTextBkColor( bk );
  193. labsList.Create( ws|LVS_LIST|LVS_SHOWSELALWAYS,r,&tabber,3 );
  194. labsList.SetFont( &prefs.debugFont );
  195. labsList.SetBkColor( bk );
  196. labsList.SetTextColor( fg );
  197. labsList.SetTextBkColor( bk );
  198. tabber.insert( 0,&funcList,"funcs" );
  199. tabber.insert( 1,&typeList,"types" );
  200. tabber.insert( 2,&labsList,"labels" );
  201. cursorMoved();
  202. return 0;
  203. }
  204. /************************************************* PUBLIC ***********************************************/
  205. void Editor::setName( const string &n ){
  206. name=n;
  207. }
  208. bool Editor::setText( istream &in ){
  209. // editCtrl.HideCaret();
  210. fmtBusy=true;
  211. EDITSTREAM es;
  212. es.dwCookie=(DWORD)this;
  213. es.dwError=0;
  214. es.pfnCallback=streamIn;
  215. is_line="{{\\colortbl;"+rtfbgr(prefs.rgb_string)+rtfbgr(prefs.rgb_ident)+
  216. rtfbgr(prefs.rgb_keyword)+rtfbgr(prefs.rgb_comment)+rtfbgr(prefs.rgb_digit)+
  217. rtfbgr(prefs.rgb_default)+"}";
  218. int tabTwips=1440*8/GetDeviceCaps( ::GetDC(0),LOGPIXELSX ) * prefs.edit_tabs;
  219. for( int k=0;k<MAX_TAB_STOPS;++k ) is_line+="\\tx"+itoa( k*tabTwips )+' ';
  220. is_stream=&in;
  221. is_curs=is_linenum=0;
  222. funcList.clear();
  223. typeList.clear();
  224. labsList.clear();
  225. editCtrl.StreamIn( SF_RTF,es );
  226. fmtBusy=false;
  227. // editCtrl.HideCaret();
  228. caret();
  229. return es.dwError==0;
  230. }
  231. void Editor::setModified( bool n ){
  232. editCtrl.SetModify( n );
  233. }
  234. void Editor::setCursor( int n ){
  235. int row=(n>>16)&0xffff,col=n&0xffff;
  236. int pos=editCtrl.LineIndex( row )+col;
  237. editCtrl.SetSel( pos,pos );
  238. }
  239. string Editor::getName()const{
  240. return name;
  241. }
  242. bool Editor::getText( ostream &out ){
  243. fixFmt(true);
  244. EDITSTREAM es;
  245. es.dwCookie=(DWORD)&out;
  246. es.dwError=0;
  247. es.pfnCallback=streamOut;
  248. editCtrl.StreamOut( SF_TEXT,es );
  249. return es.dwError==0;
  250. }
  251. void Editor::cut(){
  252. editCtrl.Cut();
  253. }
  254. void Editor::copy(){
  255. editCtrl.Copy();
  256. }
  257. void Editor::paste(){
  258. editCtrl.PasteSpecial( CF_TEXT,0 );
  259. }
  260. bool Editor::canCutCopy(){
  261. getSel();return selStart!=selEnd;
  262. }
  263. bool Editor::canPaste(){
  264. return editCtrl.CanPaste() ? true : false;
  265. }
  266. void Editor::print(){
  267. static const int MARG=720; //1440=1 inch
  268. CPrintDialog dlg(false);
  269. int e=dlg.DoModal();if( e==IDCANCEL ) return;
  270. HDC hdc=dlg.GetPrinterDC();
  271. if( !hdc ){
  272. MessageBox( "Error printing" );
  273. return;
  274. }
  275. int hr=GetDeviceCaps(hdc,HORZRES),vr=GetDeviceCaps(hdc,VERTRES);
  276. int px=GetDeviceCaps(hdc,LOGPIXELSX),py=GetDeviceCaps(hdc,LOGPIXELSY);
  277. SetMapMode(hdc,MM_TEXT);
  278. FORMATRANGE fr={0};
  279. fr.hdc=fr.hdcTarget=hdc;
  280. fr.rcPage.left=fr.rcPage.top=0;
  281. fr.rcPage.right=(hr/px)*1440;
  282. fr.rcPage.bottom=(vr/py)*1440;
  283. //margins
  284. fr.rc.left=fr.rcPage.left+MARG;
  285. fr.rc.top=fr.rcPage.top+MARG;
  286. fr.rc.right=fr.rcPage.right-MARG;
  287. fr.rc.bottom=fr.rcPage.bottom-MARG;
  288. char buff[MAX_PATH];
  289. strcpy( buff,name.c_str() );
  290. DOCINFO di={sizeof(di)};
  291. di.lpszDocName=buff;
  292. getSel();
  293. int start=selStart,end=selEnd;
  294. if( start==end ){ start=0;end=editCtrl.GetTextLength(); }
  295. StartDoc(hdc,&di);
  296. while( start<end ){
  297. StartPage(hdc);
  298. fr.chrg.cpMin=start;
  299. fr.chrg.cpMax=end;
  300. start=editCtrl.FormatRange(&fr,true);
  301. EndPage(hdc);
  302. }
  303. EndDoc(hdc);
  304. editCtrl.FormatRange(0,false);
  305. DeleteDC(hdc);
  306. }
  307. void Editor::find(){
  308. if( finder ) return;
  309. finder=new CFindReplaceDialog();
  310. finder->m_fr.lpstrFindWhat=findBuff;
  311. finder->m_fr.wFindWhatLen=256;
  312. finder->m_fr.lpstrReplaceWith=replaceBuff;
  313. finder->m_fr.wReplaceWithLen=256;
  314. finder->Create( findOnly=true,0,0,FR_HIDEUPDOWN,this );
  315. found=false;
  316. }
  317. void Editor::replace(){
  318. if( finder ) return;
  319. finder=new CFindReplaceDialog();
  320. finder->m_fr.lpstrFindWhat=findBuff;
  321. finder->m_fr.wFindWhatLen=256;
  322. finder->m_fr.lpstrReplaceWith=replaceBuff;
  323. finder->m_fr.wReplaceWithLen=256;
  324. finder->Create( findOnly=false,0,0,FR_HIDEUPDOWN,this );
  325. found=false;
  326. }
  327. bool Editor::canFind(){
  328. return finder==0;
  329. }
  330. bool Editor::findNext( bool wrap ){
  331. long start,end;
  332. editCtrl.GetSel( start,end );
  333. FINDTEXTEX t;
  334. memset( &t,0,sizeof( t ) );
  335. t.chrg.cpMin=end;
  336. t.chrg.cpMax=-1;
  337. t.lpstrText=findBuff;
  338. if( editCtrl.FindText( findFlags,&t )>=0 ){
  339. editCtrl.SetSel( t.chrgText.cpMin,t.chrgText.cpMax );
  340. return true;
  341. }
  342. if( !wrap ) return false;
  343. t.chrg.cpMin=0;
  344. t.chrg.cpMax=end;
  345. if( editCtrl.FindText( findFlags,&t )>=0 ){
  346. editCtrl.SetSel( t.chrgText.cpMin,t.chrgText.cpMax );
  347. return true;
  348. }
  349. string s( "Can't find \"" );s+=findBuff;s+='\"';
  350. MessageBox( s.c_str(),"Text not found" );
  351. if( finder ) finder->SetFocus();
  352. return false;
  353. }
  354. void Editor::hilight( int pos ){
  355. int row=(pos>>16)&0xffff,col=pos&0xffff;
  356. pos=editCtrl.LineIndex( row )+col;
  357. editCtrl.HideSelection( true,false );
  358. getSel();
  359. bool quote=false;
  360. int end=pos,len=editCtrl.GetTextLength();
  361. while( end<len ){
  362. char temp[8];
  363. editCtrl.SetSel( end,end+1 );
  364. editCtrl.GetSelText( temp );
  365. if( temp[0]=='\"' ) quote=!quote;
  366. if( !quote && (temp[0]==':' || !isprint( temp[0] )) ) break;
  367. ++end;
  368. }
  369. editCtrl.HideSelection( false,false );
  370. editCtrl.SetSel( pos,end );
  371. }
  372. void Editor::selectAll(){
  373. editCtrl.SetSel( 0,-1 );
  374. }
  375. void Editor::lock(){
  376. locked=true;
  377. }
  378. void Editor::unlock(){
  379. locked=false;
  380. }
  381. string Editor::getKeyword(){
  382. fixFmt(true);
  383. getSel();
  384. int ln=editCtrl.LineFromChar(selStart);
  385. int pos=selStart-editCtrl.LineIndex( ln );
  386. string line=getLine( ln );if( pos>line.size() ) return "";
  387. //ok, scan back until we have an isapha char preceded by a nonalnum/non '_' char
  388. for(;;){
  389. while( pos>0 && ( !isalpha(line[pos]) || isid(line[pos-1]) ) ) --pos;
  390. if( !isalpha(line[pos]) ) return "";
  391. int end=pos;while( end<line.size() && isid(line[end]) ) ++end;
  392. string t=line.substr( pos,end-pos );
  393. if( keyWordSet.find( t )!=keyWordSet.end() ) return t;
  394. if( !pos ) return "";
  395. --pos;
  396. }
  397. }
  398. bool Editor::getModified(){
  399. return editCtrl.GetModify() ? true : false;
  400. }
  401. int Editor::getCursor(){
  402. long start,end;
  403. editCtrl.GetSel( start,end );
  404. int row,col;
  405. row=editCtrl.LineFromChar( start );
  406. col=start-editCtrl.LineIndex( row );
  407. return ((row)<<16)|(col);
  408. }
  409. void Editor::getCursor( int *row,int *col ){
  410. long start,end;
  411. editCtrl.GetSel( start,end );
  412. *row=editCtrl.LineFromChar( end );
  413. *col=end-editCtrl.LineIndex( *row );
  414. }
  415. void Editor::addKeyword( const string &s ){
  416. keyWordSet.insert( s );
  417. string t=s;
  418. for( int k=0;k<t.size();++k ) t[k]=tolower(t[k]);
  419. keyWordMap[t]=s;
  420. }
  421. /************************************************* PRIVATE ***********************************************/
  422. void Editor::endFind(){
  423. if( !finder ) return;
  424. finder->DestroyWindow();
  425. finder=0;
  426. }
  427. LRESULT Editor::onFind( WPARAM w,LPARAM l ){
  428. if( !finder ) return 0;
  429. findFlags=0;
  430. if( finder->MatchCase() ) findFlags|=FR_MATCHCASE;
  431. if( finder->MatchWholeWord() ) findFlags|=FR_WHOLEWORD;
  432. strcpy( findBuff,finder->GetFindString() );
  433. strcpy( replaceBuff,finder->GetReplaceString() );
  434. if( finder->FindNext() ){
  435. found=findNext( true );
  436. if( found && findOnly ) endFind();
  437. }else if( finder->ReplaceCurrent() ){
  438. if( found ) editCtrl.ReplaceSel( replaceBuff,true );
  439. found=findNext( true );
  440. }else if( finder->ReplaceAll() ){
  441. int cnt=0;
  442. editCtrl.HideSelection( true,false );
  443. editCtrl.SetSel( 0,0 );
  444. while( findNext( false ) ){
  445. editCtrl.ReplaceSel( replaceBuff,true );
  446. ++cnt;
  447. }
  448. endFind();
  449. char buff[32];itoa( cnt,buff,10 );
  450. string s( buff );s+=" occurances replaced";
  451. MessageBox( s.c_str(),"Replace All Done" );
  452. editCtrl.HideSelection( false,false );
  453. }
  454. if( finder && finder->IsTerminating() ) endFind();
  455. return 0;
  456. }
  457. void Editor::caret(){
  458. if( !prefs.edit_blkcursor ) return;
  459. long start,end;
  460. editCtrl.GetSel( start,end );
  461. if( start==end ){
  462. editCtrl.CreateSolidCaret( 8,13 );
  463. editCtrl.ShowCaret();
  464. }else editCtrl.HideCaret();
  465. }
  466. void Editor::OnSetFocus( CWnd *wnd ){
  467. if( prefs.edit_blkcursor ) SetCaretBlinkTime( 200 );
  468. editCtrl.SetFocus();
  469. caret();
  470. }
  471. void Editor::OnKillFocus( CWnd *wnd ){
  472. CWnd::OnKillFocus( wnd );
  473. fixFmt(true);
  474. }
  475. string Editor::getLine( int line ){
  476. int idx1=editCtrl.LineIndex( line );
  477. int idx2=editCtrl.LineIndex( line+1 );if( idx2==-1 ) idx2=editCtrl.GetTextLength();
  478. int len=idx2-idx1;
  479. char *buff=new char[ len>3 ? len+1 : 4 ];
  480. *(int*)buff=len;
  481. int out=editCtrl.GetLine( line,buff );
  482. buff[len]=0;
  483. string t=string( buff );
  484. delete [] buff;
  485. return t;
  486. }
  487. void Editor::funcSelected( int line ){
  488. int pos=editCtrl.LineIndex( line );
  489. editCtrl.SetSel( editCtrl.GetTextLength()-1,editCtrl.GetTextLength()-1 );
  490. editCtrl.SetSel( pos,pos );
  491. SetFocus();
  492. }
  493. void Editor::currentSet( Tabber *tabber,int index ){
  494. SetFocus();
  495. }
  496. void Editor::cursorMoved(){
  497. listener->cursorMoved( this );
  498. }
  499. void Editor::en_update(){
  500. caret();
  501. }
  502. void Editor::en_msgfilter( NMHDR *nmhdr,LRESULT *result ){
  503. if( locked || fmtBusy ){ *result=1;return; }
  504. *result=0;
  505. getSel();
  506. MSGFILTER *msg=(MSGFILTER*)nmhdr;
  507. if( msg->msg==WM_RBUTTONDOWN ){
  508. CPoint p( LOWORD(msg->lParam),HIWORD(msg->lParam) );
  509. ClientToScreen( &p );
  510. CMenu *menu=blitzIDE.mainFrame->GetMenu();
  511. CMenu *edit=menu->GetSubMenu(1);
  512. edit->TrackPopupMenu( TPM_LEFTALIGN,p.x,p.y,blitzIDE.mainFrame );
  513. }else if( msg->msg==WM_CHAR ){
  514. if( msg->wParam=='\t' ){
  515. int lineStart=editCtrl.LineFromChar( selStart );
  516. int lineEnd=editCtrl.LineFromChar( selEnd );
  517. if( lineEnd<=lineStart ) return;
  518. editCtrl.HideSelection( true,false );
  519. if( GetAsyncKeyState( VK_SHIFT )&0x80000000 ){
  520. char buff[4];
  521. for( int line=lineStart;line<lineEnd;++line ){
  522. int n=editCtrl.LineIndex( line );
  523. editCtrl.SetSel( n,n+1 );editCtrl.GetSelText( buff );
  524. if( buff[0]=='\t' ) editCtrl.ReplaceSel( "",true );
  525. }
  526. }else{
  527. for( int line=lineStart;line<lineEnd;++line ){
  528. int n=editCtrl.LineIndex( line );
  529. editCtrl.SetSel( n,n );editCtrl.ReplaceSel( "\t",true );
  530. }
  531. }
  532. selStart=editCtrl.LineIndex( lineStart );
  533. selEnd=editCtrl.LineIndex( lineEnd );
  534. setSel();*result=1;
  535. editCtrl.HideSelection( false,false );
  536. }else if( msg->wParam==13 ){
  537. if( selStart!=selEnd ) return;
  538. int k;
  539. int ln=editCtrl.LineFromChar( selStart );
  540. int pos=selStart-editCtrl.LineIndex( ln );
  541. string line=getLine( ln );if( pos>line.size() ) return;
  542. for( k=0;k<pos && line[k]=='\t';++k ){}
  543. line="\r\n"+line.substr( 0,k )+'\0';
  544. editCtrl.ReplaceSel( line.data(),true );
  545. *result=1;
  546. }
  547. }
  548. caret();
  549. }
  550. void Editor::en_selchange( NMHDR *nmhdr,LRESULT *result ){
  551. if( !fmtBusy ) fixFmt(false);
  552. cursorMoved();
  553. caret();
  554. }
  555. void Editor::en_protected( NMHDR *nmhdr,LRESULT *result ){
  556. *result=0;if( fmtBusy ) return;
  557. fmtLineCount=editCtrl.GetLineCount();
  558. found=false;
  559. }
  560. void Editor::en_change(){
  561. if( fmtBusy ) return;
  562. fmtBusy=true;
  563. editCtrl.HideSelection( true,false );
  564. getSel();
  565. int begin=editCtrl.LineFromChar( selStart );
  566. int end=begin+1;
  567. int lineCount=editCtrl.GetLineCount();
  568. int delta=lineCount-fmtLineCount;
  569. if( delta>0 ){
  570. begin-=delta;
  571. funcList.relocate( begin,delta );
  572. typeList.relocate( begin,delta );
  573. labsList.relocate( begin,delta );
  574. funcList.remove( begin,end );
  575. typeList.remove( begin,end );
  576. labsList.remove( begin,end );
  577. }else if( delta<0 ){
  578. int t=end-delta;
  579. funcList.remove( begin,t );
  580. typeList.remove( begin,t );
  581. labsList.remove( begin,t );
  582. funcList.relocate( t,delta );
  583. typeList.relocate( t,delta );
  584. labsList.relocate( t,delta );
  585. }else{
  586. funcList.remove( begin,end );
  587. typeList.remove( begin,end );
  588. labsList.remove( begin,end );
  589. }
  590. for( int n=begin;n<end;++n ) formatLine( n );
  591. setSel();editCtrl.HideSelection( false,false );
  592. fmtBusy=false;
  593. cursorMoved();
  594. }
  595. void Editor::setFormat( int from,int to,int color,const string &s ){
  596. editCtrl.SetSel( from,to );
  597. if( s.size() ){
  598. char buff[256];
  599. editCtrl.GetSelText( buff );buff[to-from]=0;
  600. if( string(buff)!=s ){
  601. editCtrl.ReplaceSel( s.c_str() );
  602. editCtrl.SetSel( from,to );
  603. }
  604. }
  605. CHARFORMAT fmt;
  606. fmt.cbSize=sizeof( fmt );
  607. DWORD t=editCtrl.GetSelectionCharFormat( fmt );
  608. if( (t&CFM_COLOR) && fmt.crTextColor==color ) return;
  609. fmt.dwMask=CFM_COLOR|CFM_PROTECTED;
  610. fmt.dwEffects=CFE_PROTECTED;
  611. fmt.crTextColor=color;
  612. editCtrl.SetSelectionCharFormat( fmt );
  613. }
  614. void Editor::formatStreamLine(){
  615. string out;
  616. char cf='0';
  617. for( int k=0;k<is_line.size(); ){
  618. int from=k;
  619. char pf=cf;
  620. int c=is_line[k],is_sz=is_line.size();
  621. if( !isgraph( c ) ){
  622. for( ++k;k<is_sz && !isgraph(is_line[k]);++k ){}
  623. }else if( !isfmt( c,k+1<is_sz?is_line[k+1]:0 ) ){
  624. for( ++k;k<is_sz && !isfmt( is_line[k],k+1<is_sz?is_line[k+1]:0 );++k ){}
  625. cf='6';
  626. }else if( c==';' ){ //comment?
  627. k=is_sz;
  628. cf='4';
  629. }else if( c=='\"' ){ //string const?
  630. for( ++k;k<is_sz && is_line[k]!='\"';++k ){}
  631. if( k<is_sz ) ++k;
  632. cf='1';
  633. }else if( isalpha( c ) ){ //ident?
  634. for( ++k;k<is_sz && isid(is_line[k]);++k ){}
  635. if( keyWordSet.find( is_line.substr( from,k-from ) )==keyWordSet.end() ) cf='2';
  636. else cf='3';
  637. }else if( c=='$' ){
  638. for( ++k;k<is_sz && isxdigit(is_line[k]);++k ){}
  639. cf='5';
  640. }else if( isdigit( c ) ){ //numeric const?
  641. for( ++k;k<is_sz && isdigit(is_line[k]);++k ){}
  642. cf='5';
  643. }
  644. if( cf!=pf ){
  645. out+="\\cf";out+=cf;out+=' ';
  646. }
  647. out+=is_line.substr( from,k-from );
  648. }
  649. if( is_line[0]=='F' && is_line.find( "Function" )==0 ){
  650. for( int k=8;k<is_line.size();++k ){
  651. if( isalpha( is_line[k] ) ){
  652. int start=k;
  653. for( ++k;k<is_line.size() && isid(is_line[k]);++k ){}
  654. funcList.insert( is_linenum,is_line.substr( start,k-start ) );
  655. break;
  656. }
  657. }
  658. }else if( is_line[0]=='T' && is_line.find( "Type" )==0 ){
  659. for( int k=4;k<is_line.size();++k ){
  660. if( isalpha( is_line[k] ) ){
  661. int start=k;
  662. for( ++k;k<is_line.size() && isid(is_line[k]);++k ){}
  663. typeList.insert( is_linenum,is_line.substr( start,k-start ) );
  664. break;
  665. }
  666. }
  667. }else if( is_line[0]=='.' ){
  668. for( int k=1;k<is_line.size();++k ){
  669. if( isalpha( is_line[k] ) ){
  670. int start=k;
  671. for( ++k;k<is_line.size() && isid(is_line[k]);++k ){}
  672. labsList.insert( is_linenum,is_line.substr( start,k-start ) );
  673. break;
  674. }
  675. }
  676. }
  677. is_line=out+"\\line ";
  678. }
  679. void Editor::fixFmt( bool fmt ){
  680. if( lineToFmt<0 || fmtBusy ) return;
  681. fmtBusy=true;
  682. editCtrl.HideSelection( true,false );getSel();
  683. long start=selStart;if( fmt ) selStart=-1;
  684. formatLine( lineToFmt );
  685. selStart=start;setSel();editCtrl.HideSelection( false,false );
  686. fmtBusy=false;
  687. }
  688. void Editor::formatLine( int ln ){
  689. if( ln<0 || ln>=editCtrl.GetLineCount() ) return;
  690. lineToFmt=-1;
  691. int pos=editCtrl.LineIndex( ln );
  692. string tline=getLine( ln );
  693. string line=tolower( tline );
  694. int *cf=0;
  695. string rep;
  696. for( int k=0;k<line.size(); ){
  697. rep.resize(0);
  698. int *pf=cf;
  699. int from=k,c=line[k],sz=line.size();
  700. if( !isgraph( c ) ){
  701. for( ++k;k<sz && !isgraph(line[k]);++k ){}
  702. }else if( !isfmt( c,k+1<sz?line[k+1]:0 ) ){
  703. for( ++k;k<sz && !isfmt(line[k],k+1<sz?line[k+1]:0);++k ){}
  704. cf=&prefs.rgb_default;
  705. }else if( c==';' ){ //comment?
  706. k=sz;
  707. cf=&prefs.rgb_comment;
  708. }else if( c=='\"' ){ //string const?
  709. for( ++k;k<sz && line[k]!='\"';++k ){}
  710. if( k<sz ) ++k;
  711. cf=&prefs.rgb_string;
  712. }else if( isalpha( c ) ){ //ident?
  713. for( ++k;k<sz && isid(line[k]);++k ){}
  714. cf=&prefs.rgb_ident;pf=0;
  715. if( selStart<=pos+from || selStart>pos+k ){
  716. map<string,string>::iterator it=keyWordMap.find( line.substr( from,k-from ) );
  717. if( it!=keyWordMap.end() ){
  718. rep=it->second;cf=&prefs.rgb_keyword;
  719. }
  720. }else lineToFmt=ln;
  721. }else if( c=='$' && k+1<sz && isxdigit(line[k+1]) ){
  722. for( ++k;k<sz && isxdigit(line[k]);++k ){}
  723. cf=&prefs.rgb_digit;
  724. }else if( isdigit( c ) ){ //numeric const?
  725. for( ++k;k<sz && isdigit(line[k]);++k ){}
  726. cf=&prefs.rgb_digit;
  727. }
  728. if( cf!=pf ) setFormat( pos+from,pos+k,*cf,rep );
  729. }
  730. if( line[0]=='f' && line.find( "function" )==0 ){
  731. for( int k=8;k<line.size();++k ){
  732. if( isalpha( line[k] ) ){
  733. int start=k;
  734. for( ++k;k<line.size() && isid(line[k]);++k ){}
  735. funcList.insert( ln,tline.substr( start,k-start ) );
  736. break;
  737. }
  738. }
  739. }else if( line[0]=='t' && line.find( "type" )==0 ){
  740. for( int k=4;k<line.size();++k ){
  741. if( isalpha( line[k] ) ){
  742. int start=k;
  743. for( ++k;k<line.size() && isid(line[k]);++k ){}
  744. typeList.insert( ln,tline.substr( start,k-start ) );
  745. break;
  746. }
  747. }
  748. }else if( line[0]=='.' ){
  749. for( int k=1;k<line.size();++k ){
  750. if( isalpha( line[k] ) ){
  751. int start=k;
  752. for( ++k;k<line.size() && isid(line[k]);++k ){}
  753. labsList.insert( ln,tline.substr( start,k-start ) );
  754. break;
  755. }
  756. }
  757. }
  758. }