/*
Demonstration program showing use of DevIL/OpenIL to load and modify variety of image types
Written by Rich Schafermeyer 2005
Uses includes and DevIL library for Ibasic made by Todd Riggins [www.exodev.com]
Link to Todd's includes and library is at http://www.pyxia.com/community/viewtopic.php?t=9041
Information on DevIL can be found at http://openil.sourceforge.net/
'
-------Version 1.02
Modifications in 1.02: added copy/paste to/from Clipboard, added convert to edges effect, added crop action
Modifications in 1.01: added 1 level of undo, added restore, set rotate to 90 degrees instead of 45 degrees,
allow overwriting of existing file on save, resize window if image greater than 400 by 350,
change window caption to show file name
'
Instructions:
1.  Open Image
2.  Select modification(s)
3.  Modifications can be applied multiple times to add more of same effect, eg, pixelate
4.  Can save image in original file format or convert to new format
5.  To crop, choose from menu, then select region of image using the mouse
6.  Press "L" or "l" to load an image (removed from code)
7.  Press "S" or "s" to save an image
'
'Modified July 2019 by Brian Pugh
8.  Press "U" or "u" to undo a modification
9.  Press "R" or "r" to restore an image
10. Removed loadfile menuitem and relevant code
11. Added custom BrowseForFolder and FileListBox - from ebknoppert, now Freeware
12. Added Vertical and Horizontal Splitter Bars
13. Added Statusbar, showing filename and file's path
14. Adjusted picture dimensions to display correctly given width of Splitter and depth of Statusbar
15. Window adjusts to width and depth of loaded image; unless...
16. If image width or depth is less than 1024 x 768, windows size stays at 1024 x 768
17. Changed Save Image filter to reflect all file types that can be saved with DevIL
18. Pressing Cursor Up (enlarge) or Cursor Down (reduce) resizes a loaded image. Needs work!
19. Added filter when loading files to show most file types - only .tiff, .rgba, .bw, .jpeg missing from filter code
    I can live with that!
20. Now using DevIL 1.8.0 DLLs
21. Added an 'About' box, showing DevIL DLL versions
22. Added background colour to the BrowseForFolder and FileListBox controls
23. Added code to load and save last-used directory in ini file (DevIL.ini)
24. Added DevIl icon to statusbar and window caption
*/

autodefine "off"

$include "windowssdk.inc"
$include "il.inc" 'Include file for Devil.DLL
$include "ilu.inc"
$include "ilut.inc"
$include "ctl.inc"

WINDOW win,winV,winH
DIALOG d1
FILE ini
INT bitmap,bitmap2,bitmap3,x,y,w,h,pixelsize,i,drawrectangle,pos
INT selection,buttondn,xstart,ystart,xend,yend,w1,l,t,h1,w2,h2
INT xmax,ymax,temp,bf,fl,min,max,timeractive,currentsplitter
ISTRING filename$[260],filenamesave$[260],directory$[260],showfilename$[260],tempfilename$[260],a$[260]
ISTRING StartPath[260]
ISTRING Paths[260]
UINT hDC,hInst,BFFhWnd
POINTER image[5]
INT left,top,width,height,panes[2],splitWidth,sbarHeight,ww,hh
INT sh1,sw1,sy1,sx1,sw,sh,fError,ret
ISTRING filter[528]

TYPE OPENFILENAME
	DEF lStructSize:INT
	DEF hWndOwner:INT
	DEF hInstance:INT
	DEF lpstrFilter:POINTER
	DEF lpstrCustomFilter:POINTER
	DEF nMaxCustFilter:INT
	DEF nFilterIndex:INT
	DEF lpstrFile:POINTER
	DEF nMaxFile:INT
	DEF lpstrFileTitle:POINTER
	DEF nMaxFileTitle:INT
	DEF lpstrInitialDir:POINTER
	DEF lpstrTitle:POINTER
	DEF flags:INT
	DEF nFileOffset:WORD
	DEF nFileExtension:WORD
	DEF lpstrDefExt:POINTER
	DEF lCustData:INT
	DEF lpfnHook:INT
	DEF lpTemplateName:POINTER
ENDTYPE

TYPE OPENFILENAMEEX
	DEF ofn as OPENFILENAME
	DEF pvReserved as POINTER
	DEF dwReserved as UINT
	DEF FlagsEx as UINT
ENDTYPE
	OPENFILENAMEEX ofn

SETID "OFN_ALLOWMULTISELECT",0x200
SETID "OFN_ENABLEHOOK",0x20
SETID "OFN_EXPLORER",0x80000
SETID "OFN_HIDEREADONLY",0x4
SETID "OFN_NONETWORKBUTTON",0x20000
SETID "OFN_OVERWRITEPROMPT",0x2
'SETID "OFN_PATHMUSTEXIST" , 0x800
'SETID "OFN_READONLY" , 0x1
'SETID "OFN_SHAREAWARE" , 0x4000
'SETID "OFN_SHAREFALLTHROUGH" , 2
'SETID "OFN_SHARENOWARN" , 1
'SETID "OFN_SHAREWARN", 0
'SETID "OFN_SHOWHELP" , 0x10
'SETID "OFN_USEMONIKERS" , 0x1000000
'SETID "OFN_CREATEPROMPT" , 0x2000
'SETID "OFN_DONTADDTORECENT" , 0x2000000
'SETID "OFN_ENABLEINCLUDENOTIFY" , 0x400000
'SETID "OFN_ENABLESIZING" , 0x800000
'SETID "OFN_ENABLETEMPLATE" , 0x40
'SETID "OFN_ENABLETEMPLATEHANDLE" , 0x80
'SETID "OFN_EX_NOPLACESBAR" , 0x1
'SETID "OFN_EXTENSIONDIFFERENT" , 0x400
'SETID "OFN_FILEMUSTEXIST" , 0x1000
'SETID "OFN_FORCESHOWHIDDEN" , 0x10000000
'SETID "OFN_LONGNAMES" , 0x200000
'SETID "OFN_NOCHANGEDIR" , 0x8
'SETID "OFN_NODEREFERENCELINKS" , 0x100000
'SETID "OFN_NOLONGNAMES" , 0x40000
'SETID "OFN_NOREADONLYRETURN" , 0x8000
'SETID "OFN_NOTESTFILECREATE" , 0x10000
'SETID "OFN_NOVALIDATE" , 0x100

DECLARE zFileRequest(title:STRING,parent:POINTER,nOpen:INT,OPT filter:STRING,OPT ext:STRING,OPT flags:INT,OPT initdir:STRING),HEAP
DECLARE ofnIBHookProc2(hDlg:UINT,uiMsg:UINT,wParam:UINT,lParam:UINT),INT
DECLARE IMPORT,PathFindExtensionA(pszPath:POINTER),STRING
DECLARE IMPORT,PathIsDirectoryA(pszPath:POINTER),INT

'pbsctrl.dll
$use "pbsctrl.lib"
DECLARE IMPORT,InitPBSoftCtrls(),INT
	InitPBSoftCtrls()

'Constants
'CONST IDC_SIZENS=32645
'CONST IDC_SIZEWE=32644
'CONST WM_COMMAND=0x111
'CONST WS_HSCROLL=0x100000
'CONST LB_GETCURSEL=0x188
'CONST LB_SETCURSEL=0x186
'CONST LB_GETTEXT=0x189
'CONST LB_DELETESTRING=0x182
'CONST LB_GETCOUNT=0x18B

CONST WM_USER=0x400
'BrowseForFolder constants (BFF)
CONST BFF=300
'CONST BFF_CLEAR         =WM_USER+10000 'Remove all items from Treeview.
'CONST BFF_REFRESH       =WM_USER+10001 'Forces a repaint.
'CONST BFF_PATH          =WM_USER+10002 'New path, lParam is pszString
'CONST BFF_PATHBYPIDL    =WM_USER+10003 'New path, wParam = %CSIDL_..
CONST BFF_JUMPTOPATH     =WM_USER+10004 'Set to path. Selects the item with corresponding path, lParam is pszString
CONST BFF_GETPATH        =WM_USER+10005 'Returns path placed in provided buffer. wparam = size of empty buffer, lparam = pointer to buffer
CONST BFF_GETPATHLEN     =WM_USER+10006 'Use this to prepare a buffer.
'CONST BFF_EXPANDFIRSTITEM=WM_USER+10007 'Opens/closes the first treeview item, wParam is switch
'CONST BFF_READY=1
CONST BFF_SELCHANGE=2

'FileListBox constants (FLB)
CONST FLB=301
CONST FLB_BACKCOLOR   =WM_USER+1000 'wParam is new RGB()
'CONST FLB_GETBACKCOLOR=WM_USER+1001 'Get backcolor
'CONST FLB_FORECOLOR   =WM_USER+1002 'wParam is new RGB()
'CONST FLB_GETFORECOLOR=WM_USER+1003 'Get forecolor set
CONST FLB_PATH        =WM_USER+1004 'wParam is size of buffer set in lParam, 0 for szstring, lParam is buffer containing new path
'CONST FLB_GETPATH     =WM_USER+1005 'wParam is size of buffer to fill, 0 for returning len required, lParam is buffer to fill
CONST FLB_GETITEM     =WM_USER+1006 'wParam is size of buffer to fill, 0 for returning len required, lParam is buffer to fill
CONST FLB_SHOWICONS   =WM_USER+1007 'wParam is Boolean
'CONST FLB_CLEAR       =WM_USER+1008 'Empties control
CONST FLB_REFRESH     =WM_USER+1009 'Refills the control

CONST TV_FIRST=0x1100
CONST TVM_SETBKCOLOR=(TV_FIRST+29)
'CONST TVM_SELECTITEM=(TV_FIRST+11)
'CONST TVGN_FIRSTVISIBLE=0x5
'CONST TVGN_CARET=0x9
'CONST TVGN_DROPHILITE=0x8

'About box constants
CONST STATIC_1=501
CONST STATIC_2=502
CONST BUTTON_3=503

CONST CCM_FIRST=0x2000
CONST SB_SETBKCOLOR=(CCM_FIRST+1)
CONST SB_SETICON=(WM_USER+15)

'Check for ini file - if missing, write an ini file with GETSTARTPATH and use that path for initial viewing
	fError=OPENFILE(ini,GETSTARTPATH+"DevIL.ini","R")
IF fError<>0
	CLOSEFILE ini
	OPENFILE(ini,GETSTARTPATH+"DevIL.ini","W")
	WRITE ini,GETSTARTPATH
	CLOSEFILE ini
	StartPath=GETSTARTPATH
ELSE
	OPENFILE(ini,GETSTARTPATH+"DevIL.ini","R")
	READ ini,StartPath
	CLOSEFILE ini
ENDIF
	SetCurrentDirectoryA(StartPath)
	ret=PathIsDirectoryA(StartPath)
IF ret=0
	MESSAGEBOX win,"Your last accessed directory is not available:\nUsing "+UCASE$(GETSTARTPATH),"Path error",48
	SetCurrentDirectoryA(GETSTARTPATH)
ENDIF

OPENWINDOW win,0,0,1024,768,@MINBOX|@MAXBOX|@SIZE|@NOAUTODRAW,0,"DevIL Image Viewer",&mainwindow
	SETWINDOWCOLOR win,RGB(190,190,190)
	CONTROL win,@STATUS,"Status",0,0,0,0,0,200
	GETCLIENTSIZE win,left,top,width,height
	panes=width/2,-1
	CONTROLCMD win,200,@SWSETPANES,2,panes
	CONTROLCMD win,200,@SWSETPANETEXT,0,"DevIL 1.8.0"
	CONTROLCMD win,200,@SWSETPANETEXT,1,StartPath
	SENDMESSAGE win,SB_SETBKCOLOR,0,RGB(240,240,240),200 'Set Statusbar Colour
	UINT hIcon=LoadIconFromFile(GETSTARTPATH+"DevIL.ico") 'Load icon
	StatusBarPaneSetIcon(win,200,0,hIcon) 'Set Statusbar icon
	SETICON(win,hIcon) 'Set Window icon

BEGINMENU win
   MENUTITLE "&File"
   MENUITEM "&Save Image",0,2
	SEPARATOR
   MENUITEM "&Quit",0,3
ENDMENU
BEGININSERTMENU win,1
   MENUTITLE "&Edit"
   MENUITEM "&Undo",0,100
   MENUITEM "&Restore to Original",0,101
   SEPARATOR
   MENUITEM "C&ut",0,102
   MENUITEM "&Copy",0,103
   MENUITEM "&Paste",0,104
   SEPARATOR
   MENUITEM "Crop",0,105
ENDMENU
BEGININSERTMENU win,2
   MENUTITLE "&Modify"
   BEGINPOPUP "Flip"
      MENUITEM "&Vertically",0,14
      MENUITEM "&Horizontally",0,15
    ENDPOPUP
   BEGINPOPUP "Rotate 90 Degrees"
      MENUITEM "&Clockwise",0,19
      MENUITEM "&Counterclockwise",0,25
   ENDPOPUP
   BEGINPOPUP "Zoom"
      MENUITEM "&In",0,20
      MENUITEM "&Out",0,21
   ENDPOPUP
   SEPARATOR
   BEGINPOPUP "Blur"
      MENUITEM "&Average",0,11
      MENUITEM "&Gaussian",0,12
   ENDPOPUP
   MENUITEM "&Pixelate",0,18
   MENUITEM "&Sharpen",0,22
   MENUITEM "&Emboss",0,13
   MENUITEM "&Convert to Edges",0,26
   MENUITEM "&Add Noise",0,17
   SEPARATOR
   MENUITEM "&Invert Colors",0,16
   MENUITEM "&Alien Colors",0,10
   MENUITEM "&More Contrast",0,23
   MENUITEM "&Less Contrast",0,24

MENUTITLE "&Help"
   MENUITEM "&About...",0,110
ENDMENU

FOR i=100 TO 105
   ENABLEMENUITEM win,i,0 
NEXT i

CreateSplitter(win,winV,0,200,-1,6,-1,50)
	SetSplitterColors(winV,RGB(128,128,128),RGB(128,0,128))
	SetSplitterMin(winV,200)
CreateSplitter(win,winH,1,0,320,200,6,51)
	SetSplitterColors(winH,RGB(128,128,128),RGB(128,0,128))
	SetSplitterMin(winH,200)

hInst=GetModuleHandleA(win.hWnd)
	CreateWindowExA(0x200,"BrowseForFolder","",0x56810027|@TVSSHOWSELALWAYS,0,0,0,0,win.hWnd,BFF,hInst,0)
	CreateWindowExA(0x200,"FileListBox","",0x56A10103|@TVSSHOWSELALWAYS,0,0,0,0,win.hWnd,FLB,hInst,0)

Paths=StartPath
	BFFhWnd=GetDlgItem(win.hWnd,BFF)
	SENDMESSAGE BFFhWnd,TVM_SETBKCOLOR,0,RGB(240,240,240)
	SENDMESSAGE win,BFF_JUMPTOPATH,LEN(Paths),Paths,BFF
	bf=SENDMESSAGE win,BFF_GETPATHLEN,0,0,BFF
	SENDMESSAGE win,FLB_SHOWICONS,1,0,FLB
	SENDMESSAGE win,FLB_BACKCOLOR,RGB(240,240,240),0,FLB

IF bf>0
	Paths=STRING$(bf,0)
	bf=SENDMESSAGE win,BFF_GETPATH,bf,Paths,BFF
	Paths=LEFT$(Paths,bf)
	SENDMESSAGE win,FLB_PATH,bf,Paths,FLB
	SENDMESSAGE win,FLB_REFRESH,bf,Paths,FLB
ENDIF
	FilterFiles()

SETCURSOR winV,@CSCUSTOM,LoadCursorA(0,IDC_SIZEWE)
	SETCURSOR winH,@CSCUSTOM,LoadCursorA(0,IDC_SIZENS)
	SizeControls()

pixelsize=1
	x=0
	y=0

filter="Windows Bitmap (*.bmp)|*.bmp|C-style Header (*.h)|*.h|DirectDraw Surface (*.dds)|*.dds|JPEG (*.jpg)|*.jpg|"
filter+="JPEG (*.jpe)|*.jpe|JPEG (*.jpeg)|*.jpeg|Palette (*.pal)|*.pal|ZSoft PCX (*.pcx)|*.pcx|"
filter+="Portable Network Graphics (*.png)|*.png|PNM (*.pbm)|*.pbm|PNM (*.pgm)|*.pgm|PNM (*.ppm)|*.ppm|Adobe Photoshop (*.psd)|*.psd|Raw Data (*.raw)|*.raw|"
filter+="Silicon Graphics (*.sgi)|*.sgi|Silicon Graphics (*.bw)|*.bw|Silicon Graphics (*.rgb)|*.rgb|Silicon Graphics (*.rgba)|*.rgba|"
filter+="Targa (*.tga)|*.tga|TIF (*.tif)|*.tif|TIF (*.tiff)|*.tiff||"

'Initiate DevIL/OpenIL
xInitIL()
	ilEnable(il_file_overwrite) 'On save, allows overwriting of existing file
'	ilutRenderer(ILUT_WIN32)

CREATEDIALOG d1,0,0,300,110,0x80C00080,win,"About DevIL Image Viewer",&d1_handler
	CONTROL d1,@STATIC,"DevIL DLL 1.8.0",14,18,200,20,0x5000010B,STATIC_1
	CONTROL d1,@STATIC,"Ilu, Ilut DLLs 1.8.0",14,46,200,20,0x5000010B,STATIC_2
	CONTROL d1,@BUTTON,"OK",100,78,100,20,0x50000000,BUTTON_3
 
WAITUNTIL IsWindowClosed(win)
IF(bitmap) THEN DELETEIMAGE bitmap,@IMGBITMAP
IF(bitmap2) THEN DELETEIMAGE bitmap2,@IMGBITMAP
IF(bitmap3) THEN DELETEIMAGE bitmap3,@IMGBITMAP
	xShutdownIL()
	DeleteObject(hIcon)
IF StartPath="" THEN StartPath=GETSTARTPATH
	OPENFILE(ini,GETSTARTPATH+"DevIL.ini","W")
	WRITE ini,StartPath
	CLOSEFILE ini
END

SUB mainwindow(),INT
	SELECT @MESSAGE

CASE @IDCREATE
	CENTERWINDOW win

CASE @IDCLOSEWINDOW
      CLOSEWINDOW win

CASE @IDPAINT
IF(bitmap)
	SHOWIMAGE win,bitmap,@IMGBITMAP,splitWidth,0,w,h
ENDIF

CASE WM_SPLITTERRBUTTONDN
CASE& WM_SPLITTERLBUTTONDN
CASE& WM_SPLITTERSIZED
CASE& WM_SPLITTERSIZING
	currentsplitter=@WPARAM
CASE& @IDSIZE
	timeractive=0
	SizeControls()
IF currentsplitter<>2 AND timeractive=0
	timeractive=1
	STARTTIMER win,100
ENDIF
IF CONTROLEXISTS(win,200)
	CONTROLCMD win,200,@SWRESIZE
	GETCLIENTSIZE win,left,top,width,height
	panes=width/2,-1
	CONTROLCMD win,200,@SWSETPANES,2,panes
ENDIF

CASE WM_SPLITTERLBUTTONDBLCLK 'centre the splitter
	GETCLIENTSIZE win,l,t,w,h
IF @WPARAM=1
	GetSplitterPos(winV,sx1,sy1,sw1,sh1)
	SetSplitterPos(winV,sw/2,sy1,sw1,sh1)
ELSE
	GetSplitterPos(winH,sx1,sy1,sw1,sh1)
	SetSplitterPos(winH,sx1,sh/2,sw1,sh1)
ENDIF
	SizeControls()

CASE @IDCONTROL
	SELECT @CONTROLID

'Browse For Folder
CASE BFF
	SELECT @NOTIFYCODE
CASE BFF_SELCHANGE
	bf=SENDMESSAGE win,BFF_GETPATHLEN,0,0,BFF
IF bf>0
	Paths=STRING$(bf,"0")
	bf=SENDMESSAGE win,BFF_GETPATH,bf,Paths,BFF
	Paths=LEFT$(Paths,bf)
	SENDMESSAGE win,FLB_PATH,bf,Paths,FLB
	SENDMESSAGE win,FLB_REFRESH,bf,Paths,FLB
	FilterFiles()
ENDIF
	StartPath=Paths
	CONTROLCMD win,200,@SWSETPANETEXT,1,StartPath
ENDSELECT

'File List Box
CASE FLB
	SELECT @NOTIFYCODE
CASE @LBNSELCHANGE
	fl=SENDMESSAGE win,FLB_GETITEM,0,0,FLB
IF fl>0
	filename$=STRING$(fl,"0")
	fl=SENDMESSAGE win,FLB_GETITEM,fl,filename$,FLB
	loadfile()
	SETWINDOWCOLOR win,RGB(190,190,190)
	SETFOCUS win
ELSE
	SETFOCUS win,FLB
ENDIF
ENDSELECT
ENDSELECT

CASE @IDMENUPICK
	SELECT @MENUNUM
		CASE 110 'About
			DOMODAL d1,win
         CASE 2
            savefile()
         CASE 3
            CLOSEWINDOW win
         CASE 10 'Alienify
            captureforundo()
            iluAlienify()
            updateimage()
         CASE 11 'Blur (average)
            captureforundo()
            iluBlurAvg(2) 'number of iterations, higher number is more blurred but slower
            updateimage()
         CASE 12 'Blur (gaussian)
            captureforundo()
            iluBlurGaussian(2) 'number of iterations, higher number is more blurred but slower
            updateimage()
         CASE 13 'Emboss
            captureforundo()
            iluEmboss()
            updateimage()
         CASE 14 'Flip
            captureforundo()
            iluFlipImage()
            updateimage()
         CASE 15 'Mirror
            captureforundo()
            iluMirror()
            updateimage()
         CASE 16 'Negative
            captureforundo()
            iluNegative()
            updateimage()
         CASE 17 'Noisify
            captureforundo()
            iluNoisify(0.2) '0.0=no noise, 1.0=extreme noise
            updateimage()
         CASE 18 'Pixelize
            captureforundo()
            pixelsize=pixelsize*4 'increase number to pixelate faster
            iluPixelize(pixelsize)
            updateimage()
         CASE 19 'Rotate Clockwise
            captureforundo()
            iluRotate(90) 'rotation degrees
            updateimage()
         CASE 20 'Zoom In
            captureforundo()
            iluEnlargeImage(1.5,1.5,1) 'multiplier of x,y,z dimension
            updateimage()
         CASE 21 'Zoom Out
            captureforundo()
            iluEnlargeImage(0.5,0.5,1) 'multiplier of x,y,z dimension
            updateimage()
         CASE 22 'Sharpen
            captureforundo()
            iluSharpen(1.5,2) '0.0-1.0 blurs while 1.0-2.5 increases sharpness/number of iterations increases effect
            updateimage()
         CASE 23 'More Contrast
            captureforundo()
            iluContrast(1.2) '1.0-1.7 increases contrast
            updateimage()
         CASE 24 'Less Contrast
            captureforundo()
            iluContrast(0.8) '0.0-1.0 decreases contrast
            updateimage()
         CASE 25 'Rotate CounterClockwise
            captureforundo()
            iluRotate(-90) 'rotation degrees
            updateimage()
         CASE 26 'Detect Edges
            captureforundo()
            iluEdgeDetectP()
            updateimage()
         CASE 100 'Undo
            ilutSetHBitMap(bitmap3)
            ENABLEMENUITEM win,100,0
            updateimage()
         CASE 101 'Restore
            ilutSetHBitMap(bitmap2)
            ENABLEMENUITEM win,100,0
            ENABLEMENUITEM win,101,0
            FOR i=102 to 105
               ENABLEMENUITEM win,i,1
            NEXT i
            updateimage()
         CASE 102 'Cut
            ilutSetWinClipboard()
            deleteILimage()
            ENABLEMENUITEM win,104,1
         CASE 103 'Copy
            ilutSetWinClipboard()
         CASE 104 'Paste
            ilutGetWinClipboard()
            FOR i=100 to 105
               ENABLEMENUITEM win,i,1
            NEXT i
            updateimage()
         CASE 105 'Crop
            captureforundo()
            cropdrawingmode()
            selection=1
         ENDSELECT

   CASE @IDCHAR
        IF (@CODE = ASC("S")) | (@CODE=ASC("s")) 'Save an image
			savefile()
      ENDIF
        IF (@CODE = ASC("U")) | (@CODE=ASC("u")) 'Undo a modification
			undo()
      ENDIF
        if (@CODE = ASC("R")) | (@CODE=ASC("r")) 'Restore an image
			restoreimage()
      ENDIF

	CASE @IDKEYDOWN
		SELECT 1
			CASE (@CODE = 0x26)	'Up arrow
				Enlarge()
			CASE (@CODE = 0x28)	'Down arrow
				Reduce()
		ENDSELECT

   CASE @IDMOUSEMOVE
      IF ((selection=1)&(buttondn=1)) THEN RECT win,xstart,ystart,xend-xstart,yend-ystart,0
		xend=@MOUSEX
		yend=@MOUSEY
      IF ((selection=1)&(buttondn=1)) THEN RECT win,xstart,ystart,xend-xstart,yend-ystart,0

   CASE @IDLBUTTONDN
		xstart=@MOUSEX
		ystart=@MOUSEY
		buttondn=1
		drawrectangle=1

   CASE @IDLBUTTONUP
      buttondn=0
      IF (selection=1)
         RECT win,xstart,ystart,xend-xstart,yend-ystart,0
         cropimage()
         selection=0
      ENDIF
ENDSELECT
RETURN 0
ENDSUB

SUB loadfile()
IF(bitmap)
	DELETEIMAGE bitmap,@IMGBITMAP
	SETWINDOWCOLOR win,RGB(190,190,190)
ENDIF
	ilGenImages(1,image[1])
	ilBindImage(image[1])
	ilLoadImage(filename$)
	tempfilename$=filename$
	hDC = gethdc(win)
	bitmap=ilutConvertToHBitmap(hDC)
	releasehdc(win,hDC)
	hDC = gethdc(win)
	bitmap2=ilutConvertToHBitmap(hDC)
	releasehdc(win,hDC)
if(bitmap)
	getbitmapsize bitmap,w,h
	ww=w
	hh=h
	getclientsize win,l,t,w1,h1
	getsize win,l,t,w2,h2
if (w<450) then w=1024
if (h<384) then h=768
   setsize win,l,t,w+(w2-w1)+splitWidth,h+(h2-h1)+sbarHeight
   centerwindow win
   showimage win,bitmap,@IMGBITMAP,splitWidth,0,w,h
for i=102 to 105
	ENABLEMENUITEM win,i,1
next i
	parsefilename()
	SENDMESSAGE win,SB_SETBKCOLOR,0,RGB(89,198,133),200 'Set Statusbar Colour
	CONTROLCMD win,200,@SWSETPANETEXT,0,"Now viewing: "+UCASE$(a$)+"  - "+STR$(ww)+" x"+STR$(hh)
ENDIF
ENDSUB

SUB updateimage()
	getclientsize win,x,y,w,h
	rect win,0,0,w,h,rgb(255,255,255),rgb(255,255,255)
	hDC = gethdc(win)
	bitmap=ilutConvertToHBitmap(hDC)
	releasehdc(win,hDC)
if(bitmap)
	getbitmapsize bitmap,w,h
	SHOWIMAGE win,bitmap,@IMGBITMAP,splitWidth,0,w,h
ENDIF
ENDSUB

SUB deleteILimage()
	iluDeleteImage(image[1])
if(bitmap) THEN DELETEIMAGE bitmap,@IMGBITMAP
	getclientsize win,x,y,w,h
	rect win,0,0,w,h,rgb(255,255,255),rgb(255,255,255)
	deleteimage bitmap,@IMGBITMAP
	getclientsize win,x,y,w,h
	rect win,0,0,w,h,rgb(255,255,255),rgb(255,255,255)
for i=101 to 105
   ENABLEMENUITEM win,i,0
next i
ENDSUB

SUB captureforundo()
for i=100 to 101
   ENABLEMENUITEM win,i,1
next i
	hDC = gethdc(win)
	bitmap3=ilutConvertToHBitmap(hDC)
	releasehdc(win,hDC)
ENDSUB

SUB savefile()
	zFileRequest("Save Image",win,0,filter,"bmp",0,GETSTARTPATH) '0 for save - 1 for open
IF (LEN(filenamesave$)=0) THEN RETURN
	tempfilename$=filenamesave$
	parsefilename()
	CONTROLCMD win,200,@SWSETPANETEXT,0,"Saved as: "+a$
	ilSaveImage(filenamesave$)
	SENDMESSAGE win,FLB_REFRESH,bf,Paths,FLB
ENDSUB

SUB parsefilename()
	a$=tempfilename$
	i=0
DO
	pos=INSTR(a$,"\\")
	a$=RIGHT$(a$,LEN(a$)-pos)
	i=i+pos
UNTIL pos=0
	i=i
	directory$=LEFT$(tempfilename$,i)
	showfilename$=RIGHT$(tempfilename$,LEN(tempfilename$)-i)
ENDSUB

SUB cropdrawingmode()
	drawmode win,@transparent
	setlinestyle win,@lsdash,1
	rastermode win,@rmnot
ENDSUB

SUB cropimage()
'OpenIL has the origin in LOWER left corner
'This is the reverse of normal window coordinates, where the origin is in the UPPER left corner
	normaldrawingmode()
	xmax=ilGetInteger(il_image_width)
	ymax=ilGetInteger(il_image_height)
IF (xend<xstart)
	temp=xend
	xend=xstart
	xstart=temp
ENDIF
IF (yend<ystart)
	temp=yend
	yend=ystart
	ystart=temp
ENDIF
if (xend>xmax) then xend=xmax
if (yend>ymax) then yend=ymax
	iluCrop(xstart,ymax-yend,0,xend-xstart,yend-ystart,0)
	updateimage()
ENDSUB

SUB normaldrawingmode()
	drawmode win,@transparent
	setlinestyle win,@lssolid,1
	rastermode win,@rmcopypen
ENDSUB

SUB undo()
	ilutSetHBitMap(bitmap3)
	ENABLEMENUITEM win,100,0
	updateimage()
ENDSUB

SUB restoreimage()
	ilutSetHBitMap(bitmap2)
	ENABLEMENUITEM win,100,0
	ENABLEMENUITEM win,101,0
FOR i=102 TO 105
	ENABLEMENUITEM win,i,1
NEXT i
	updateimage()
ENDSUB

'GLOBAL xInitIL
SUB xInitIL()
	ilInit()
	iluInit()
	ilutInit()
ENDSUB

'GLOBAL xShutdownIL
SUB xShutdownIL()
	ilShutDown()
ENDSUB

SUB FilterFiles()
	INT count,x,y,flag,num
	ISTRING filename[260]
	ISTRING ext[8]
	ISTRING allowedextensions[128]=".BMP.CUT.DDS.GIF.ICO.CUR.JPG.JPE.LBM.LIF.LMP.MDL.MNG.PCD.PCX.PIC.PIX.PNG.PBM.PGM.PPM.PNM.PSD.PXR.SGI.RGB.TGA.TIF.WAL.XPM"
	count=SENDMESSAGE(win,LB_GETCOUNT,0,0,FLB)-1
	num=(LEN(allowedextensions)/4)-1
FOR x=count TO 0 STEP - 1
	flag=0
	SENDMESSAGE win,LB_GETTEXT,x,filename,FLB
	ext=PathFindExtensionA(filename)
FOR y=0 TO num
IF UCASE$(ext)=MID$(allowedextensions,(4*y+1),4)
	flag=1
	BREAKFOR
ENDIF
NEXT y
IF flag=0 THEN SENDMESSAGE win,LB_DELETESTRING,x,0,FLB
NEXT x
ENDSUB

SUB SizeControls()
	INT x1,y1,w1,h1,x2,y2,w2,h2
	INT sbsx,sbsy,sbsw,sbsh
	GETCLIENTSIZE win,l,t,w,h
	GetSplitterPos(winV,x1,y1,w1,h1)
	GetSplitterPos(winH,x2,y2,w2,h2)
IF x1>w-200 THEN x1=w-200
IF x1<200 THEN x1=200
	SetSplitterPos(winV,x1,y1,w1,h) 'set the height of winV to client height h, also any adjustment to x1
IF y2>h-200 THEN y2=h-200
IF y2<200 THEN y2=200
	SetSplitterPos(winH,x2,y2,x1,h2) 'set the width of winH to x1 of winV, also any adjustment to y2
	GetSplitterPos(winV,x1,y1,w1,h1)
	GetSplitterPos(winH,x2,y2,w2,h2)
	SETSIZE win,0,0,x1,y2,BFF
	SETSIZE win,0,y2+h2-2,x1,h-y2-h2-18,FLB
	SetSplitterMax(winV,w-200)
	SetSplitterMax(winH,h-200)
	min=GetSplitterMin(winV)
	max=GetSplitterMax(winV)
IF CONTROLEXISTS(win,200)
	CONTROLCMD win,200,@SWRESIZE
	GETCLIENTSIZE win,left,top,width,height
	panes=width/2,-1
	CONTROLCMD win,200,@SWSETPANES,2,panes
ENDIF
	splitWidth=w1+x1 'Set splitter true width
	GETSIZE win,sbsx,sbsy,sbsw,sbsh,200
	sbarHeight=sbsh+2
ENDSUB

SUB Reduce()
	captureforundo()
	iluImageParameter(ILU_FILTER,ILU_SCALE_MITCHELL)
	iluEnlargeImage(0.5,0.5,1) 'multiplier of x,y,z dimension
	updateimage()
ENDSUB

SUB Enlarge()
	captureforundo()
	iluImageParameter(ILU_FILTER,ILU_SCALE_MITCHELL)
	iluEnlargeImage(1.5,1.5,1) 'multiplier of x,y,z dimension
	updateimage()
ENDSUB

SUB zFileRequest(title:STRING,parent:POINTER,nOpen:INT,OPT filter:STRING,OPT ext:STRING,OPT flags:INT,OPT initdir:STRING)
	POINTER pTest,p1,p2,mem,copymem
	INT bMulti,nReturn,x
	CHAR filtercopy[528]
	ISTRING strPath[260]
	ZeroMemory(ofn,LEN(OPENFILENAMEEX))
	filtercopy[0]=0
	mem=0
	copymem=0
	IF (GetVersion() & 0x000000FF) >= 5
		ofn.ofn.lStructSize=LEN(OPENFILENAMEEX)
	ELSE
		ofn.ofn.lStructSize=LEN(OPENFILENAME)
	ENDIF
	ofn.ofn.lpstrTitle=title
	IF parent <> 0 THEN ofn.ofn.hWndOwner=#<WINDOW>parent.hWnd
	pTest=filter
	IF pTest <> 0
		x=0
		DO
			IF filter[x]=ASC("|") THEN filtercopy[x]=0 ELSE filtercopy[x]=filter[x]
			x++
			IF x > 527 THEN filter[x]=0
		UNTIL filter[x]=0
		filtercopy[x]=0
		filtercopy[x+1]=0
	ENDIF
	ofn.ofn.lpstrFilter=filtercopy
	ofn.ofn.lpstrDefExt=ext
	ofn.ofn.lpstrInitialDir=initdir
	ofn.ofn.lpfnHook=&ofnIBHookProc2
	ofn.ofn.flags=@OFN_HIDEREADONLY | @OFN_EXPLORER | @OFN_ENABLEHOOK | @OFN_NONETWORKBUTTON
	ofn.ofn.flags=ofn.ofn.flags | flags
	IF (flags & @OFN_ALLOWMULTISELECT)=@OFN_ALLOWMULTISELECT
		bMulti=1
		mem=ALLOCHEAP(30000)
		copymem=ALLOCHEAP(30000)
		ofn.ofn.lpstrFile=mem
		ofn.ofn.nMaxFile=32767
	ELSE
		bMulti=0
		copymem=ALLOCHEAP(528)
		ofn.ofn.lpstrFile=copymem
		ofn.ofn.nMaxFile=528
	ENDIF
	IF nOpen=0 THEN ofn.ofn.flags=ofn.ofn.flags | @OFN_OVERWRITEPROMPT
	IF nOpen
		nReturn=GetOpenFileNameA(ofn)
	ELSE
		nReturn=GetSaveFileNameA(ofn)
	ENDIF
	IF(bMulti <> 0)
		IF nReturn <> 0
			p1=mem
			p2=mem
			WHILE #<CHAR>p1 <> 0:p1=p1 + 1:ENDWHILE
			p1++
			IF (p1 - p2) > ofn.ofn.nFileOffset
				lstrcpynA(copymem,mem,528)
				lstrcatA(copymem,"|")
			ELSE
				strPath=#<STRING>p2
				IF LEN(strPath) AND ( strPath[len(strPath)-1] <> ASC("\\") )
					strPath=strPath + "\\"
				ENDIF
				#<STRING>copymem=strPath
				p2=copymem
				p2=p2 + lstrlenA(strPath)
				#<STRING>p2=#<STRING>p1
				p2=p2 + lstrlenA(p1)
				#<CHAR>p2="|"
				p2++
				#<CHAR>p2=0
				p1=p1+lstrlenA(p1)+1
				DO
					#<STRING>p2=strPath
					p2=p2 + lstrlenA(strPath)
					#<STRING>p2=#<STRING>p1
					p2=p2 + lstrlenA(p1)
					#<CHAR>p2="|"
					p2++
					#<CHAR>p2=0
					p1=p1+lstrlenA(p1)+1
				UNTIL #<CHAR>p1=0
			ENDIF
		ENDIF
		FREEHEAP(mem)
	ENDIF
IF nReturn=0 THEN #<STRING>copymem=""
	filenamesave$=#<STRING>copymem
RETURN #<STRING>copymem
ENDSUB

SUB ofnIBHookProc2(hDlg:UINT,uiMsg:UINT,wParam:UINT,lParam:UINT)
	WINDOW wTemp
	INT thWnd
IF uiMsg=0x110
	wTemp.hWnd=GetParent(hDlg)
	CENTERWINDOW wTemp
	thWnd=FindWindowExA(wTemp.hWnd,0,"SHELLDLL_DefView","")
IF thWnd
	SENDMESSAGE thWnd,WM_COMMAND,0x702E,0
ENDIF
ENDIF
RETURN 0
ENDSUB

SUB d1_handler(),INT 'About
	SELECT @MESSAGE
CASE @IDINITDIALOG
	CENTERWINDOW d1
	SETFONT d1,"Segoe UI",10,700,0x00FF0000,STATIC_1
	SETFONT d1,"Segoe UI",10,700,0x00FF0000,STATIC_2
	SETCONTROLCOLOR d1,STATIC_1,RGB(0,0,0),RGB(121,150,222)
	SETCONTROLCOLOR d1,STATIC_2,RGB(0,0,0),RGB(121,150,222)
'Colour the dialog window
CASE WM_CTLCOLORDLG
   RETURN CreateSolidBrush(RGB(121,150,222))
CASE @IDCONTROL
	SELECT @CONTROLID
CASE BUTTON_3
IF @NOTIFYCODE=0
	CLOSEDIALOG d1,@IDOK
ENDIF
ENDSELECT
ENDSELECT
RETURN 0
ENDSUB

'Load an Icon from a file
SUB LoadIconFromFile(STRING path),UINT
	RETURN _LoadImage(GetModuleHandle(0),path,IMAGE_ICON,16,16,LR_LOADFROMFILE)
ENDSUB
'Set an icon to a pane
SUB StatusBarPaneSetIcon(w:WINDOW,statusid:UINT,panenumber:INT,hIcon:UINT),INT
	RETURN SENDMESSAGE(w,SB_SETICON,panenumber,hIcon,statusid)
ENDSUB
