''
'' FbEdit Example, by KetilO
'' compile with:	fbc -s gui FbEdit.rc FbEdit.bas
''

option explicit
option escape

#include once "windows.bi"
#include once "win/commctrl.bi"
#include once "win/commdlg.bi"
#include once "win/richedit.bi"
#include once "win/shellapi.bi"

#include "..\..\Inc\RAEdit.bi"
#include "FbEdit.bi"

#include "Misc.bas"
#include "FileIO.bas"
#include "TabTool.bas"
#include "Find.bas"
#include "Goto.bas"
#include "Toolbar.bas"
#include "About.bas"

sub EnableMenu()
	dim bm as integer
	dim chrg as CHARRANGE

	bm=SendMessage(hREd,EM_CANUNDO,0,0)
	EnableDisable(bm,IDM_EDIT_UNDO)
	bm=SendMessage(hREd,EM_CANREDO,0,0)
	EnableDisable(bm,IDM_EDIT_REDO)
	SendMessage(hREd,EM_EXGETSEL,0,@chrg)
	bm=chrg.cpMax-chrg.cpMin
	EnableDisable(bm,IDM_EDIT_CUT)
	EnableDisable(bm,IDM_EDIT_COPY)
	EnableDisable(bm,IDM_EDIT_DELETE)
	bm=SendMessage(hREd,EM_CANPASTE,CF_TEXT,0)
	EnableDisable(bm,IDM_EDIT_PASTE)
	bm=SendMessage(hREd,REM_NXTBOOKMARK,nLastLine,3)+1
	EnableDisable(bm,IDM_EDIT_BOOKMARKNEXT)
	bm=SendMessage(hREd,REM_PRVBOOKMARK,nLastLine,3)+1
	EnableDisable(bm,IDM_EDIT_BOOKMARKPREVIOUS)
	bm=SendMessage(hREd,REM_NXTBOOKMARK,-1,3)+1
	EnableDisable(bm,IDM_EDIT_BOOKMARKDELETE)

end sub

sub IndentComment(byval char as string,byval fUn as bool)
	dim ochrg as CHARRANGE
	dim chrg as CHARRANGE
	dim LnSt as integer
	dim LnEn as integer
	dim LnCnt as integer
	dim buffer as string*32

	SendMessage(hREd,WM_SETREDRAW,FALSE,0)
	SendMessage(hREd,REM_LOCKUNDOID,TRUE,0)
	SendMessage(hREd,EM_EXGETSEL,0,@ochrg)
	SendMessage(hREd,EM_EXGETSEL,0,@chrg)
	SendMessage(hREd,EM_HIDESELECTION,TRUE,0)
	LnSt=SendMessage(hREd,EM_EXLINEFROMCHAR,0,chrg.cpMin)
	if chrg.cpMax>chrg.cpMin then
		chrg.cpMax=chrg.cpMax-1
	endif
	LnEn=SendMessage(hREd,EM_EXLINEFROMCHAR,0,chrg.cpMax)
	LnCnt=LnEn-LnSt
	if LnCnt then
		ochrg.cpMin=SendMessage(hREd,EM_LINEINDEX,LnSt,0)
		ochrg.cpMax=SendMessage(hREd,EM_LINEINDEX,LnEn+1,0)
	endif
	do while LnSt<=LnEn
		if fUn then
			' Uncomment or Outdent
			chrg.cpMin=SendMessage(hREd,EM_LINEINDEX,LnSt,0)
			chrg.cpMax=chrg.cpMin+1
			SendMessage(hREd,EM_EXSETSEL,0,@chrg)
			SendMessage(hREd,EM_GETSELTEXT,0,@buffer)
			if char=buffer then
				SendMessage(hREd,EM_REPLACESEL,TRUE,StrPtr(""))
				ochrg.cpMax=ochrg.cpMax-1
				if LnCnt=0 then
					ochrg.cpMin=ochrg.cpMin-1
				endif
			endif
		else
			' Comment or Indent
			chrg.cpMin=SendMessage(hREd,EM_LINEINDEX,LnSt,0)
			chrg.cpMax=chrg.cpMin
			SendMessage(hREd,EM_EXSETSEL,0,@chrg)
			SendMessage(hREd,EM_REPLACESEL,TRUE,@char)
			ochrg.cpMax=ochrg.cpMax+1
			if LnCnt=0 then
				ochrg.cpMin=ochrg.cpMin+1
			endif
		endif
		LnSt=LnSt+1
	loop
	SendMessage(hREd,EM_EXSETSEL,0,@ochrg)
	SendMessage(hREd,WM_SETREDRAW,TRUE,0)
	SendMessage(hREd,EM_HIDESELECTION,FALSE,0)
	SendMessage(hREd,EM_SCROLLCARET,0,0)
	SendMessage(hREd,REM_REPAINT,0,0)
	SendMessage(hREd,REM_LOCKUNDOID,FALSE,0)

end sub

function DlgProc(byval hWin as HWND,byval uMsg as UINT,byval wParam as WPARAM,byval lParam as LPARAM) as integer
	dim as long id,event,x,y,lret,bm,hgt,wdt
	dim rect as RECT
	dim rect1 as RECT
	dim chrg as CHARRANGE
	dim lpRASELCHANGE as RASELCHANGE PTR
	dim lpTOOLTIPTEXT as TOOLTIPTEXT PTR
	dim hCtl as HWND
	dim lfnt as LOGFONT
	dim tci as TCITEM
	dim lpTABMEM as TABMEM ptr
	dim nLine as integer

	select case uMsg
		case WM_INITDIALOG
			hWnd=hWin
			' Get handle of ToolBar control
			hCtl=GetDlgItem(hWin,IDC_TOOLBAR)
			DoToolBar(hInstance,hCtl)
			' Create font
			lfnt.lfHeight=-12
			lfnt.lfFaceName="Courier New"
			hFont=CreateFontIndirect(@lfnt)
			' Create edit control
			FileName="(Untitled)"
			hREd=CreateEdit(hWin)
			AddTab(hWin,hREd,FileName)
			' Turn off default comment char
			SendMessage(hREd,REM_SETCHARTAB,Asc(";"),CT_OPER)
			' Set comment char
			SendMessage(hREd,REM_SETCHARTAB,Asc("'"),CT_CMNTCHAR)
			' Set comment block init char
			SendMessage(hREd,REM_SETCHARTAB,Asc("/"),CT_CMNTINITCHAR)
			' Set comment block definition
			SendMessage(hREd,REM_SETCOMMENTBLOCKS,StrPtr("/'"),StrPtr("'/"))
			' Set colors and words to hilite
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(0,0,128),@C0)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(0,0,128),@C1)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(0,0,128),@C2)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(64,64,0),@C3)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(128,0,0),@C4)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(0,0,128),@C5)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(0,0,128),@C6)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(0,0,128),@C7)
			SendMessage(hREd,REM_SETHILITEWORDS,RGB(0,0,128),@C8)
			' Set code blocks
			SendMessage(hREd,REM_ADDBLOCKDEF,0,@BD1)
			SendMessage(hREd,REM_ADDBLOCKDEF,0,@BD2)
			return FALSE
			'
		case WM_CLOSE
			if CloseAllTabs(hWin)=FALSE then
				DestroyWindow(hWin)
			endif
			'
		case WM_DESTROY
			DeleteObject(hFont)
			PostQuitMessage(0)
			'
		case WM_COMMAND
			id=loword(wParam)
			event=hiword(wParam)
			select case id
				case IDM_FILE_NEW
					FileName="(Untitled)"
					hREd=CreateEdit(hWin)
					AddTab(hWin,hREd,FileName)
					'
				case IDM_FILE_OPEN
					OpenAFile(hWin)
					'
				case IDM_FILE_SAVE
					if FileName="(Untitled)" then
						SaveFileAs(hWin)
					else
						WriteTheFile(hWin)
					endif
					'
				case IDM_FILE_SAVEAS
					SaveFileAs(hWin)
					'
				case IDM_FILE_CLOSE
					if WantToSave(hWin)=FALSE then
						DelTab(hWin)
					endif
					'
				case IDM_FILE_CLOSEALL
					if CloseAllTabs(hWin)=FALSE then
						FileName="(Untitled)"
						hREd=CreateEdit(hWin)
						AddTab(hWin,hREd,FileName)
					endif
					'
				case IDM_FILE_EXIT
					SendMessage(hWin,WM_CLOSE,0,0)
					'
				case IDM_EDIT_UNDO
					SendMessage(hREd,EM_UNDO,0,0)
					'
				case IDM_EDIT_REDO
					SendMessage(hREd,EM_REDO,0,0)
					'
				case IDM_EDIT_CUT
					SendMessage(hREd,WM_CUT,0,0)
					'
				case IDM_EDIT_COPY
					SendMessage(hREd,WM_COPY,0,0)
					'
				case IDM_EDIT_PASTE
					SendMessage(hREd,WM_PASTE,0,0)
					'
				case IDM_EDIT_DELETE
					SendMessage(hREd,WM_CLEAR,0,0)
					'
				case IDM_EDIT_SELECTALL
					chrg.cpMin=0
					chrg.cpMax=-1
					SendMessage(hREd,EM_EXSETSEL,0,@chrg)
					'
				case IDM_EDIT_GOTO
					CreateDialogParam(hInstance,IDD_GOTODLG,hWin,@GotoDlgProc,0)
					'
				case IDM_EDIT_FIND
					CreateDialogParam(hInstance,IDD_FINDDLG,hWin,@FindDlgProc,FALSE)
					'
				case IDM_EDIT_FINDNEXT
					Find(hWin,fr or FR_DOWN)
					'
				case IDM_EDIT_FINDPREVIOUS
					Find(hWin,fr and (-1 xor FR_DOWN))
					'
				case IDM_EDIT_REPLACE
					CreateDialogParam(hInstance,IDD_FINDDLG,hWin,@FindDlgProc,TRUE)
					'
				case IDM_EDIT_BLOCKINDENT
					IndentComment(chr(9),FALSE)
					'
				case IDM_EDIT_BLOCKOUTDENT
					IndentComment(chr(9),TRUE)
					'
				case IDM_EDIT_BLOCKCOMMENT
					IndentComment("'",FALSE)
					'
				case IDM_EDIT_BLOCKUNCOMMENT
					IndentComment("'",TRUE)
					'
				case IDM_EDIT_BOOKMARKTOGGLE
					lret=SendMessage(hREd,REM_GETBOOKMARK,nLastLine,0)
					if lret=0 then
						SendMessage(hREd,REM_SETBOOKMARK,nLastLine,3)
					elseif lret=3 then
						SendMessage(hREd,REM_SETBOOKMARK,nLastLine,0)
					endif
					EnableMenu
					'
				case IDM_EDIT_BOOKMARKNEXT
					nLine=SendMessage(hREd,REM_NXTBOOKMARK,nLastLine,3)
					if nLine<>-1 then
						chrg.cpMin=SendMessage(hREd,EM_LINEINDEX,nLine,0)
						chrg.cpMax=chrg.cpMin
						SendMessage(hREd,EM_EXSETSEL,0,@chrg)
						SendMessage(hREd,EM_SCROLLCARET,0,0)
					endif
					'
				case IDM_EDIT_BOOKMARKPREVIOUS
					nLine=SendMessage(hREd,REM_PRVBOOKMARK,nLastLine,3)
					if nLine<>-1 then
						chrg.cpMin=SendMessage(hREd,EM_LINEINDEX,nLine,0)
						chrg.cpMax=chrg.cpMin
						SendMessage(hREd,EM_EXSETSEL,0,@chrg)
						SendMessage(hREd,EM_SCROLLCARET,0,0)
					endif
					'
				case IDM_EDIT_BOOKMARKDELETE
					SendMessage(hREd,REM_CLRBOOKMARKS,0,3)
					EnableMenu
					'
				case IDM_HELP_ABOUT
					DialogBoxParam(hInstance,IDD_DLGABOUT,hWin,@AboutDlgProc,0)
					SetFocus(hREd)
					'
				case &HFFFD
					' Expand button clicked
					SendMessage(hREd,REM_EXPANDALL,0,0)
					SendMessage(hREd,EM_SCROLLCARET,0,0)
					SendMessage(hREd,REM_REPAINT,0,0)
					'
				case &HFFFC
					' Collapse button clicked
					SendMessage(hREd,REM_COLLAPSEALL,0,0)
					SendMessage(hREd,EM_SCROLLCARET,0,0)
					SendMessage(hREd,REM_REPAINT,0,0)
					'
			end select
		case WM_NOTIFY
			lpRASELCHANGE=lParam
			if lpRASELCHANGE->nmhdr.hwndFrom=hREd then
				if lpRASELCHANGE->seltyp=SEL_OBJECT then
					bm=SendMessage(hREd,REM_GETBOOKMARK,lpRASELCHANGE->line,0)
					if bm=1 then
						' Collapse
						SendMessage(hREd,REM_COLLAPSE,lpRASELCHANGE->line,0)
					elseif bm=2 then
						' Expand
						SendMessage(hREd,REM_EXPAND,lpRASELCHANGE->line,0)
					endif
				else
					if lpRASELCHANGE->fchanged then
						' Set comment block definition
						SendMessage(hREd,REM_SETCOMMENTBLOCKS,StrPtr("/'"),StrPtr("'/"))
						do
							bm=SendMessage(hREd,REM_GETBOOKMARK,nLastLine,0)
							if bm=1 or bm=2 then
								lret=SendMessage(hREd,REM_ISLINE,nLastLine,@St1)
								if lret=-1 then
									lret=SendMessage(hREd,REM_ISLINE,nLastLine,@St2)
								endif
								if lret=-1 then
									' Remove collapse bookmark
									if bm=2 then
										SendMessage(hREd,REM_EXPAND,nLastLine,0)
									endif
									SendMessage(hREd,REM_SETBOOKMARK,nLastLine,0)
									SendMessage(hREd,REM_SETDIVIDERLINE,nLastLine,FALSE)
									SendMessage(hREd,REM_SETSEGMENTBLOCK,nLastLine,FALSE)
								endif
							elseif bm=0 then
								lret=SendMessage(hREd,REM_ISLINE,nLastLine,@St1)
								if lret=-1 then
									lret=SendMessage(hREd,REM_ISLINE,nLastLine,@St2)
								endif
								if lret<>-1 then
									' Set collapse bookmark
									SendMessage(hREd,REM_SETBOOKMARK,nLastLine,1)
								endif
							endif
							if lpRASELCHANGE->line>nLastLine then
								nLastLine=nLastLine+1
							elseif lpRASELCHANGE->line<nLastLine then
								nLastLine=nLastLine-1
							endif
						loop while lpRASELCHANGE->line<>nLastLine
					endif
				endif
				nLastLine=lpRASELCHANGE->line
				EnableMenu
				wsprintf(@buff,@fmt,nLastLine+1,lpRASELCHANGE->chrg.cpMin-lpRASELCHANGE->cpLine+1)
				SetDlgItemText(hWin,IDC_STATUSBAR,@buff)
			elseif lpRASELCHANGE->nmhdr.code=TTN_NEEDTEXTA then
				' ToolBar tooltip
				lpTOOLTIPTEXT=lParam
				LoadString(hInstance,lpTOOLTIPTEXT->hdr.idFrom,@buff,256)
				lpTOOLTIPTEXT->lpszText=@buff
			elseif lpRASELCHANGE->nmhdr.code=TCN_SELCHANGE then
				' Tab select
				hCtl=hREd
				tci.mask=TCIF_PARAM
				SendMessage(lpRASELCHANGE->nmhdr.hwndFrom,TCM_GETITEM,SendMessage(lpRASELCHANGE->nmhdr.hwndFrom,TCM_GETCURSEL,0,0),@tci)
				lpTABMEM=tci.lParam
				hREd=lpTABMEM->hedit
				FileName=lpTABMEM->filename
				SendMessage(hWin,WM_SIZE,0,0)
				ShowWindow(hREd,SW_SHOW)
				ShowWindow(hCtl,SW_HIDE)
				SetFocus(hREd)
				SetWinCaption(hWin)
			endif
			'
		case WM_SIZE
			' Size the FbEdit control to fill the dialogs client area
			' Get dialogs client rect
			GetClientRect(hWin,@rect)
			' Get height of toolbar
			hCtl=GetDlgItem(hWin,IDC_TOOLBAR)
			GetClientRect(hCtl,@rect1)
			hgt=rect1.bottom+3
			' Size the divider
			hCtl=GetDlgItem(hWin,IDC_DIVIDER)
			MoveWindow(hCtl,0,hgt,rect.right+1,2,TRUE)
			' Add height of divider
			hgt=hgt+4
			' Size the tab select
			hCtl=GetDlgItem(hWin,IDC_TABSELECT)
			GetClientRect(hCtl,@rect1)
			MoveWindow(hCtl,0,hgt,rect.right,rect1.bottom,TRUE)
			' Add height of tab select
			hgt=hgt+rect1.bottom+3
			' Autosize the statusbar
			hCtl=GetDlgItem(hWin,IDC_STATUSBAR)
			MoveWindow(hCtl,0,0,0,0,TRUE)
			' Get client rect of statusbar
			GetClientRect(hCtl,@rect1)
			' Size the edit control
			MoveWindow(hREd,rect.left,hgt,rect.right,rect.bottom-hgt-rect1.bottom,TRUE)
			'
		case else
			return FALSE
			'
	end select
	return TRUE

end function

'''
''' Program start
'''

	''
	'' Create the Dialog
	''
	hInstance=GetModuleHandle(NULL)
	hRAEditDll=LoadLibrary("RAEdit.dll")
	if hRAEditDll then
		hAccel=LoadAccelerators(hInstance,IDA_ACCEL)
		CreateDialogParam(hInstance,IDD_MAIN,NULL,@DlgProc,NULL)
		do while GetMessage(@msg,NULL,0,0)
			if TranslateAccelerator(hWnd,hAccel,@msg)=0 then
				if IsDialogMessage(hFind,@msg)=0 then
					TranslateMessage(@msg)
					DispatchMessage(@msg)
				endif
			endif
		loop
		FreeLibrary(hRAEditDll)
	else
		MessageBox(NULL,StrPtr("Could not find FbEdit.dll"),StrPtr("FreeBASIC editor"),MB_OK or MB_ICONERROR)
	endif
	''
	'' Program has ended
	''
	ExitProcess(0)
	end

'''
''' Program end
'''

