www.digitalmars.com         C & C++   DMDScript  

D - Dig broken

reply J Anderson <REMOVEanderson badmama.com.au> writes:
I'm having trouble using dig in version 0.76.
Has anyone got it working in 0.76?

By downloading the dig libs that comes with Charles Sanders latest DIDE, 
I can at least get it to compile.  However, I get an "access violation" 
at run time.

Also how do I compile Dig?  I tried running the make but I get.
Error: Error reading file 'win32\windef.d'
MAKE : fatal error U1077: 'c:\dmd\bin\digc' : return code '0x1'

Thanks
Dec 06 2003
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
J Anderson wrote:

 I'm having trouble using dig in version 0.76.
 Has anyone got it working in 0.76?

 By downloading the dig libs that comes with Charles Sanders latest 
 DIDE, I can at least get it to compile.  However, I get an "access 
 violation" at run time.

 Also how do I compile Dig?  I tried running the make but I get.
 Error: Error reading file 'win32\windef.d'
 MAKE : fatal error U1077: 'c:\dmd\bin\digc' : return code '0x1'

 Thanks
Ok now I get: Error: Error reading file 'stream.d' I put in the std.(for import) and the op (for operators). I've attached my changes. Any ideas? -Anderson
Dec 06 2003
parent reply J C Calvarese <jcc7 cox.net> writes:
J Anderson wrote:
 J Anderson wrote:
 
 I'm having trouble using dig in version 0.76.
 Has anyone got it working in 0.76?

 By downloading the dig libs that comes with Charles Sanders latest 
 DIDE, I can at least get it to compile.  However, I get an "access 
 violation" at run time.

 Also how do I compile Dig?  I tried running the make but I get.
 Error: Error reading file 'win32\windef.d'
 MAKE : fatal error U1077: 'c:\dmd\bin\digc' : return code '0x1'

 Thanks
Ok now I get: Error: Error reading file 'stream.d' I put in the std.(for import) and the op (for operators). I've attached my changes.
I'm not sure how broken DIG is. A number of significant changes have occurred to DMD since Burton Radons last posted in this newsgroup. If you just want to use DIGC, I have a modified version that will compile (I don't really know if it run correctly, though). As far as the rest of DIG, well, I've had a lot of problems due to the new library names (std.stream, std.c.windows.windows, etc.). I'm afraid the rest of DIG my be very broken. At this point the compiler error messages have gotten very cryptic: net\BurtonRadons\dig\platform\base.d(8): import std conflicts with windows.std at net\BurtonRadons\dig\platform\windows.d(7) Going to the given lines and it doesn't shed any light on the problem for me, and I've given up trying to fix it. I'll probably post my work to my webpage sometime later today in case someone is interested. Justin http://jcc_7.tripod.com/d/
 
 Any ideas?
 
 -Anderson
Dec 06 2003
parent reply J C Calvarese <jcc7 cox.net> writes:
J C Calvarese wrote:
 ... I'll probably post my work 
 to my webpage sometime later today in case someone is interested.
My modified version is now up at: http://jcc_7.tripod.com/d/dig.html
 
 Justin
 http://jcc_7.tripod.com/d/
Dec 06 2003
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
J C Calvarese wrote:

 J C Calvarese wrote:

 ... I'll probably post my work to my webpage sometime later today in 
 case someone is interested.
My modified version is now up at: http://jcc_7.tripod.com/d/dig.html
 Justin
 http://jcc_7.tripod.com/d/
Thanks. I'm most interested in the opengl side of things. I'll try a bit longer. Pitty the compiler error messages are so vague. Anderson
Dec 06 2003
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
J Anderson wrote:

 J C Calvarese wrote:

 J C Calvarese wrote:

 ... I'll probably post my work to my webpage sometime later today in 
 case someone is interested.
My modified version is now up at: http://jcc_7.tripod.com/d/dig.html
 Justin
 http://jcc_7.tripod.com/d/
Thanks. I'm most interested in the opengl side of things. I'll try a bit longer. Pitty the compiler error messages are so vague. Anderson
Ok, I've done a bit more on that, but now I'm getting: net\BurtonRadons\dig\platform\canvasGL.d: identifier 'HANDLE' is not defined. If I try to define it with typedef void *HANDLE; or alias void *HANDLE; I get: net\BurtonRadons\dig\platform\canvasGL.d(350): function wglMakeCurrent (HANDLE hdc,HANDLE hglrc) does not match argument types (HANDLE ,HANDLE ) I don't know what type handle should be. I can't import std.c.windows.windows, as that brings a std conflict. PS - This time I've only included the source. It's based of J C Calvarese version. -Anderson
Dec 07 2003
next sibling parent albin.pucnik guest.arnes.si writes:
Hi!
Look at Charles Sanders DIDE site. He is working
on replacing DIG. Maybe you'll be interested.
BTW, I'm interested in openGL side of thing too.

Albin
Dec 07 2003
prev sibling parent reply "Carlos Santander B." <carlos8294 msn.com> writes:
I had gone as far as JC, but I decided to spend a couple of hours trying and
these are the results.
I removed the private import std.c.windows.windows; from
net.BurtonRadons.dig.platform.windows, and instead included the whole file
(kinda desperate, isn't it?). Then I had to comment out some duplicated
names, add all the 'std.' where needed, change the names of the operator
overloadings, and then voila!, the dig library compiled (yes, with dmd
0.76). However, there seems to be a problem with that solution, or with the
dig stripper because when trying to compile diggl, the expanded dig (under
digc_temp) doesn't work properly.
Anyway, in http://earth.prohosting.com/carlos3/ you can find the zip
file containing my advance.

-------------------------
Carlos Santander



---

Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27
Dec 07 2003
parent reply J C Calvarese <jcc7 cox.net> writes:
Carlos Santander B. wrote:
 I had gone as far as JC, but I decided to spend a couple of hours trying and
 these are the results.
 I removed the private import std.c.windows.windows; from
 net.BurtonRadons.dig.platform.windows, and instead included the whole file
 (kinda desperate, isn't it?). 
My motto is: If it works, it's right.
 Then I had to comment out some duplicated
 names, add all the 'std.' where needed, change the names of the operator
 overloadings, and then voila!, the dig library compiled (yes, with dmd
 0.76). However, there seems to be a problem with that solution, or with the
 dig stripper because when trying to compile diggl, the expanded dig (under
 digc_temp) doesn't work properly.
 Anyway, in http://earth.prohosting.com/carlos3/ you can find the zip
 file containing my advance.
Thank you for uploading it. I've looked at it some. DIG appearently has an (undocumented?) feature that suppresses deleting the temporary stripped directories: -dontdeletetempdir. I think I got the same error as you did with diggl: Library diggl Searching source for imports. Expanding import libraries... opengl32.lib, dig.lib, comdlg32.lib, shell32.lib, 40 files and 166.17 kb expanded d:\dmd\bin\dmd.exe -unittest -release -O -c net\BurtonRadons\dig\gl.d net\BurtonRadons\dig\common\glEnums.d net\BurtonRadons\dig\windows\canvasGL.d opengl32.lib dig.lib advapi32.lib comdlg32.lib gdi32.lib comctl32.lib shell32.lib -I\dmd\src -Idigc_temp digc_temp\net\BurtonRadons\dig\platform\windows.d(191): declaration expected following attribute, not ';' ... --- errorlevel 1 So I took a look at the DIG-produced header file (I think stripping headers is overrated). The problem seems start at the double export ("export;export;") at line 191: 190 cFileName[260];WCHAR 191 cAlternateFileName[14];}export;export;HMODULE 192 LoadLibraryA(LPCSTR 193 lpLibFileName);FARPROC 194 GetProcAddress(HMODULE 195 hModule,LPCSTR 196 lpProcName);enum{KEY_QUERY_VALUE=0x0001,KEY_SET_VALUE=0x0002, KEY_CREATE_SUB_KEY=0x0004,KEY_ENUMERATE_SUB_KEYS=0x0008, KEY_NOTIFY=0x0010,KEY_CREATE_LINK=0x0020,KEY_READ= ((STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS| KEY_NOTIFY)&~SYNCHRONIZE),KEY_WRITE=((STANDARD_RIGHTS_WRITE| KEY_SET_VALUE|KEY_CREATE_SUB_KEY)&~SYNCHRONIZE),KEY_EXECUTE= (KEY_READ&~SYNCHRONIZE),KEY_ALL_ACCESS=((STANDARD_RIGHTS_ALL| KEY_QUERY_VALUE|KEY_SET_VALUE|KEY_CREATE_SUB_KEY| KEY_ENUMERATE_SUB_KEYS|KEY_NOTIFY|KEY_CREATE_LINK) &~SYNCHRONIZE),}const 197 int 198 REG_CREATED_NEW_KEY=0x00000001;const This is what the code looks like in the original windows.d: 273 struct WIN32_FIND_DATAW { 274 DWORD dwFileAttributes; 275 FILETIME ftCreationTime; 276 FILETIME ftLastAccessTime; 277 FILETIME ftLastWriteTime; 278 DWORD nFileSizeHigh; 279 DWORD nFileSizeLow; 280 DWORD dwReserved0; 281 DWORD dwReserved1; 282 WCHAR cFileName[ 260 ]; 283 WCHAR cAlternateFileName[ 14 ]; 284 } 285 286 export 287 { 288 BOOL SetCurrentDirectoryA(LPCSTR lpPathName); 289 BOOL SetCurrentDirectoryW(LPCWSTR lpPathName); 290 DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer); 291 DWORD GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer); 292 BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 293 BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 294 BOOL CreateDirectoryExA(LPCSTR lpTemplateDirectory, LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 295 BOOL CreateDirectoryExW(LPCWSTR lpTemplateDirectory, LPCWSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes); I don't see a problem with that so I think the stripping function is confused by "export { ..." It sounds like you've figured this out already, so I guess I'm just thinking out loud. Justin
 
 -------------------------
 Carlos Santander
 
 
 
 ---
 
 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27 
Dec 07 2003
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
J C Calvarese wrote:

 Carlos Santander B. wrote:

 I had gone as far as JC, but I decided to spend a couple of hours 
 trying and
 these are the results.
 I removed the private import std.c.windows.windows; from
 net.BurtonRadons.dig.platform.windows, and instead included the whole 
 file
 (kinda desperate, isn't it?). 
My motto is: If it works, it's right.
 Then I had to comment out some duplicated
 names, add all the 'std.' where needed, change the names of the operator
 overloadings, and then voila!, the dig library compiled (yes, with dmd
 0.76). However, there seems to be a problem with that solution, or 
 with the
 dig stripper because when trying to compile diggl, the expanded dig 
 (under
 digc_temp) doesn't work properly.
 Anyway, in http://earth.prohosting.com/carlos3/ you can find the zip
 file containing my advance.
Thank you for uploading it. I've looked at it some. DIG appearently has an (undocumented?) feature that suppresses deleting the temporary stripped directories: -dontdeletetempdir. I think I got the same error as you did with diggl: Library diggl Searching source for imports. Expanding import libraries... opengl32.lib, dig.lib, comdlg32.lib, shell32.lib, 40 files and 166.17 kb expanded d:\dmd\bin\dmd.exe -unittest -release -O -c net\BurtonRadons\dig\gl.d net\BurtonRadons\dig\common\glEnums.d net\BurtonRadons\dig\windows\canvasGL.d opengl32.lib dig.lib advapi32.lib comdlg32.lib gdi32.lib comctl32.lib shell32.lib -I\dmd\src -Idigc_temp digc_temp\net\BurtonRadons\dig\platform\windows.d(191): declaration expected following attribute, not ';' .... --- errorlevel 1 So I took a look at the DIG-produced header file (I think stripping headers is overrated). The problem seems start at the double export ("export;export;") at line 191: 190 cFileName[260];WCHAR 191 cAlternateFileName[14];}export;export;HMODULE 192 LoadLibraryA(LPCSTR 193 lpLibFileName);FARPROC 194 GetProcAddress(HMODULE 195 hModule,LPCSTR 196 lpProcName);enum{KEY_QUERY_VALUE=0x0001,KEY_SET_VALUE=0x0002, KEY_CREATE_SUB_KEY=0x0004,KEY_ENUMERATE_SUB_KEYS=0x0008, KEY_NOTIFY=0x0010,KEY_CREATE_LINK=0x0020,KEY_READ= ((STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS| KEY_NOTIFY)&~SYNCHRONIZE),KEY_WRITE=((STANDARD_RIGHTS_WRITE| KEY_SET_VALUE|KEY_CREATE_SUB_KEY)&~SYNCHRONIZE),KEY_EXECUTE= (KEY_READ&~SYNCHRONIZE),KEY_ALL_ACCESS=((STANDARD_RIGHTS_ALL| KEY_QUERY_VALUE|KEY_SET_VALUE|KEY_CREATE_SUB_KEY| KEY_ENUMERATE_SUB_KEYS|KEY_NOTIFY|KEY_CREATE_LINK) &~SYNCHRONIZE),}const 197 int 198 REG_CREATED_NEW_KEY=0x00000001;const This is what the code looks like in the original windows.d: 273 struct WIN32_FIND_DATAW { 274 DWORD dwFileAttributes; 275 FILETIME ftCreationTime; 276 FILETIME ftLastAccessTime; 277 FILETIME ftLastWriteTime; 278 DWORD nFileSizeHigh; 279 DWORD nFileSizeLow; 280 DWORD dwReserved0; 281 DWORD dwReserved1; 282 WCHAR cFileName[ 260 ]; 283 WCHAR cAlternateFileName[ 14 ]; 284 } 285 286 export 287 { 288 BOOL SetCurrentDirectoryA(LPCSTR lpPathName); 289 BOOL SetCurrentDirectoryW(LPCWSTR lpPathName); 290 DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer); 291 DWORD GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer); 292 BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 293 BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 294 BOOL CreateDirectoryExA(LPCSTR lpTemplateDirectory, LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 295 BOOL CreateDirectoryExW(LPCWSTR lpTemplateDirectory, LPCWSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes); I don't see a problem with that so I think the stripping function is confused by "export { ..." It sounds like you've figured this out already, so I guess I'm just thinking out loud. Justin
 -------------------------
 Carlos Santander



 ---

 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27 
Thanks guys. I got mine to compile before I saw those emails. Since I don't have a webspace, I can't upload it to a webserver (although I'll email it). However, I get a warning message when linking. It seems I don't have advapi32.lib. I don't know how much help it will be, but I've included it. C:\dmd\bin\digc -unittest -release -O -lib=dig net/BurtonRadons/dig/main.d net/B urtonRadons/dig/platform/*.d net/BurtonRadons/dig/common/*.d -not=net/BurtonRado ns/dig/platform/canvasGL.d -not=net/BurtonRadons/dig/common/glEnums.d advapi32.l ib comdlg32.lib gdi32.lib comctl32.lib shell32.lib -install ------------------------------------------------------------ Library dig Searching source for imports. Files are not modified, skipping compilation. C:\dmd\bin\digc -unittest -release -O -then="copy *.dll &(SystemDirectory)" ------------------------------------------------------------ Program copy *.dll C:\WINXP\System32 libjpeg.dll libpng.dll libz.dll 3 file(s) copied. C:\dmd\bin\digc -unittest -release -O -lib=diggl net/BurtonRadons/dig/gl.d net/B urtonRadons/dig/common/glEnums.d net/BurtonRadons/dig/platform/canvasGL.d opengl 32.lib -install ------------------------------------------------------------ Library diggl Searching source for imports. Files are not modified, skipping compilation. rmdir /S /Q C:\dmd\src\dig The system cannot find the file specified. copy opengl32.lib C:\dm\lib 1 file(s) copied. copy shell32.lib C:\dm\lib 1 file(s) copied. copy glu32.lib C:\dm\lib 1 file(s) copied. C:\dmd\bin\digc -unittest -release -O net/BurtonRadons/dig/examples/cartoon.d -e xe=cartoon ------------------------------------------------------------ Program cartoon Searching source for imports. Files are not modified, skipping compilation. C:\dmd\bin\digc -unittest -release -O net/BurtonRadons/dig/examples/halhello.d - exe=halhello ------------------------------------------------------------ Program halhello Searching source for imports. Files are not modified, skipping compilation. make dedit BASEDIR=C: ------------------------------------------------------------ Program deditexec Searching source for imports. Files are not modified, skipping compilation. ------------------------------------------------------------ Program dedit Searching source for imports. Expanding import libraries... dig.lib, 40 files and 144.40 kb expanded C:\dmd\bin\dmd.exe -unittest -release -O dedit.exe net\BurtonRadons\dedit\docum ent.d net\BurtonRadons\dedit\fileCommands.d net\BurtonRadons\dedit\findCommands. d net\BurtonRadons\dedit\main.d net\BurtonRadons\dedit\mainCommands.d net\Burton Radons\dedit\options.d net\BurtonRadons\dedit\projectCommands.d net\BurtonRadons \dedit\projectView.d net\BurtonRadons\dedit\syntaxHighlighter.d net\BurtonRadons \dedit\view.d net\BurtonRadons\dedit\highlight\bat.d net\BurtonRadons\dedit\high light\cecil.d net\BurtonRadons\dedit\highlight\cpp.d net\BurtonRadons\dedit\high light\d.d net\BurtonRadons\dedit\highlight\html.d net\BurtonRadons\dedit\highlig ht\java.d net\BurtonRadons\dedit\highlight\makefile.d net\BurtonRadons\dedit\hig hlight\mango.d net\BurtonRadons\dedit\highlight\msasm.d net\BurtonRadons\dedit\h ighlight\python.d dig.lib advapi32.lib comdlg32.lib gdi32.lib comctl32.lib shell 32.lib -I\dmd\src digc_manifest.res -Idigc_temp C:\dmd\bin\..\..\dm\bin\link.exe document+fileCommands+findCommands+main+mainCom mands+options+projectCommands+projectView+syntaxHighlighter+view+bat+cecil+cpp+d +html+java+makefile+mango+msasm+python,dedit.exe,,dig.lib+advapi32.lib+comdlg32. lib+gdi32.lib+comctl32.lib+shell32.lib+user32+kernel32/RC:digc_manifest.res/noi; OPTLINK (R) for Win32 Release 7.50B1 Copyright (C) Digital Mars 1989 - 2001 All Rights Reserved advapi32.lib Warning 2: File Not Found advapi32.lib C:\dmd\bin\..\lib\dig.lib(registry) Error 42: Symbol Undefined _RegCreateKeyA 12 C:\dmd\bin\..\lib\dig.lib(registry) Error 42: Symbol Undefined _RegSetValueExA 24 C:\dmd\bin\..\lib\dig.lib(registry) Error 42: Symbol Undefined _RegCloseKey 4 C:\dmd\bin\..\lib\dig.lib(registry) Error 42: Symbol Undefined _RegQueryValueExA 24 --- errorlevel 4 --- errorlevel 4 --- errorlevel 4 Press any key to continue . . .
Dec 07 2003
parent reply J C Calvarese <jcc7 cox.net> writes:
J Anderson wrote:
 Thanks guys.
 I got mine to compile before I saw those emails.  Since I don't have a 
 webspace, I can't upload it to a webserver (although I'll email it). 
 However, I get a warning message when linking.  It seems I don't have 
 advapi32.lib.
Obviously, you're making progress. You and Carlos both have make much more progress than I have. Even though you didn't include a build file, I managed to get halhello.exe to compile and run. I uploaded my results from compiling your version to my free Tripod website at http://jcc_7.tripod.com/d/dig.html. (Please e-mail me your build file so I can look at simplifing up my build routine.) The example cartoon.exe and dedit.exe definitely don't work yet. I didn't seem to share your problem with advapi32.lib, but it may be that I missed that step. I don't know. This stuff is so hard to track down... Thanks for the console output. It helped me build some files. Justin
Dec 07 2003
next sibling parent reply "Charles Sanders" <sanders-consulting comcast.net> writes:
Thought I would shamelessly promote my new GUI lib here, its at

http://www.atari-soldiers.com/windy.html

Though there is no native support from GL, it is in active development so
any help in bringing DIG's or Mikes OpenGL to it would be awesome!

Thanks ,

C
"J C Calvarese" <jcc7 cox.net> wrote in message
news:br0flf$2859$1 digitaldaemon.com...
 J Anderson wrote:
 Thanks guys.
 I got mine to compile before I saw those emails.  Since I don't have a
 webspace, I can't upload it to a webserver (although I'll email it).
 However, I get a warning message when linking.  It seems I don't have
 advapi32.lib.
Obviously, you're making progress. You and Carlos both have make much more progress than I have. Even though you didn't include a build file, I managed to get halhello.exe to compile and run. I uploaded my results from compiling your version to my free Tripod website at http://jcc_7.tripod.com/d/dig.html. (Please e-mail me your build file so I can look at simplifing up my build routine.) The example cartoon.exe and dedit.exe definitely don't work yet. I didn't seem to share your problem with advapi32.lib, but it may be that I missed that step. I don't know. This stuff is so hard to track down... Thanks for the console output. It helped me build some files. Justin
Dec 07 2003
next sibling parent Georg Wrede <Georg_member pathlink.com> writes:
In article <br0j1n$2d5c$1 digitaldaemon.com>, Charles Sanders says...
Thought I would shamelessly promote my new GUI lib here, 
Just downloaded it. But before I try it, I gotta hand it to you, "Positive Software Corporation" is a killer name!!!
Dec 07 2003
prev sibling parent reply "Charles Sanders" <sanders-consulting comcast.net> writes:
Hmm ok, is treeview.d present ? let me re-package it.

C

"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2dfn$26vv$1 digitaldaemon.com...
 Charles Sanders wrote:

Thought I would shamelessly promote my new GUI lib here, its at

http://www.atari-soldiers.com/windy.html

Though there is no native support from GL, it is in active development so
any help in bringing DIG's or Mikes OpenGL to it would be awesome!

Thanks ,

C
"J C Calvarese" <jcc7 cox.net> wrote in message
news:br0flf$2859$1 digitaldaemon.com...


J Anderson wrote:


Thanks guys.
I got mine to compile before I saw those emails.  Since I don't have a
webspace, I can't upload it to a webserver (although I'll email it).
However, I get a warning message when linking.  It seems I don't have
advapi32.lib.
Obviously, you're making progress. You and Carlos both have make much more progress than I have. Even though you didn't include a build file, I managed to get halhello.exe to compile and run. I uploaded my results from compiling your version to my free Tripod website at http://jcc_7.tripod.com/d/dig.html. (Please e-mail me your build file so I can look at simplifing up my build routine.) The example cartoon.exe and dedit.exe definitely don't work yet. I didn't seem to share your problem with advapi32.lib, but it may be that I missed that step. I don't know. This stuff is so hard to track
down...
Thanks for the console output.  It helped me build some files.


Justin
When running the make I get: C:\windy\windy package_12_3_2003>path C:\WINXP\system32;C:\WINXP;C:\WINXP\system 32\WBEM;C:\Program Files\doxygen\bin;c:\dmd\bin;c:\dm\bin; C:\windy\windy package_12_3_2003>make dmd -g -gt -debug -Iinclude\ -IprojectLibs -I.. -I. -c api.d listbox.d men u.d static_.d dialog.d msg.d window.d app.d edit.d listctrl.d butto n.d listview.d os.d combobox.d font.d rect.d Error: Error reading file 'windy\treeview.d' --- errorlevel 1
Dec 08 2003
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Charles Sanders wrote:

Hmm ok, is treeview.d present ? let me re-package it.

C

"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2dfn$26vv$1 digitaldaemon.com...
  

Charles Sanders wrote:

    

Thought I would shamelessly promote my new GUI lib here, its at

http://www.atari-soldiers.com/windy.html

Though there is no native support from GL, it is in active development so
any help in bringing DIG's or Mikes OpenGL to it would be awesome!

Thanks ,

C
"J C Calvarese" <jcc7 cox.net> wrote in message
news:br0flf$2859$1 digitaldaemon.com...


      

J Anderson wrote:


        

Thanks guys.
I got mine to compile before I saw those emails.  Since I don't have a
webspace, I can't upload it to a webserver (although I'll email it).
However, I get a warning message when linking.  It seems I don't have
advapi32.lib.


          
Obviously, you're making progress. You and Carlos both have make much more progress than I have. Even though you didn't include a build file, I managed to get halhello.exe to compile and run. I uploaded my results from compiling your version to my free Tripod website at http://jcc_7.tripod.com/d/dig.html. (Please e-mail me your build file so I can look at simplifing up my build routine.) The example cartoon.exe and dedit.exe definitely don't work yet. I didn't seem to share your problem with advapi32.lib, but it may be that I missed that step. I don't know. This stuff is so hard to track
down...
Thanks for the console output.  It helped me build some files.


Justin



        
When running the make I get: C:\windy\windy package_12_3_2003>path C:\WINXP\system32;C:\WINXP;C:\WINXP\system 32\WBEM;C:\Program Files\doxygen\bin;c:\dmd\bin;c:\dm\bin; C:\windy\windy package_12_3_2003>make dmd -g -gt -debug -Iinclude\ -IprojectLibs -I.. -I. -c api.d listbox.d men u.d static_.d dialog.d msg.d window.d app.d edit.d listctrl.d butto n.d listview.d os.d combobox.d font.d rect.d Error: Error reading file 'windy\treeview.d' --- errorlevel 1
Are you able to include a project file for DIDE with it?
Dec 08 2003
parent reply "Charles Sanders" <sanders-consulting comcast.net> writes:
Yes, but since the paths are absolute it wont compile, im writing in an
'export project' option that will allow this.

C

"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2kqb$2i0q$2 digitaldaemon.com...
 Charles Sanders wrote:

Hmm ok, is treeview.d present ? let me re-package it.

C

"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2dfn$26vv$1 digitaldaemon.com...


Charles Sanders wrote:



Thought I would shamelessly promote my new GUI lib here, its at

http://www.atari-soldiers.com/windy.html

Though there is no native support from GL, it is in active development
so
any help in bringing DIG's or Mikes OpenGL to it would be awesome!

Thanks ,

C
"J C Calvarese" <jcc7 cox.net> wrote in message
news:br0flf$2859$1 digitaldaemon.com...




J Anderson wrote:




Thanks guys.
I got mine to compile before I saw those emails.  Since I don't have
a
webspace, I can't upload it to a webserver (although I'll email it).
However, I get a warning message when linking.  It seems I don't have
advapi32.lib.
Obviously, you're making progress. You and Carlos both have make much more progress than I have. Even though you didn't include a build file, I managed to get halhello.exe to compile and run. I uploaded my results from compiling your version to my free Tripod website at http://jcc_7.tripod.com/d/dig.html. (Please e-mail me your build file so I can look at simplifing up my build routine.) The example cartoon.exe and dedit.exe definitely don't work yet. I didn't seem to share your problem with advapi32.lib, but it may be
that
I missed that step.  I don't know.  This stuff is so hard to track
down...
Thanks for the console output.  It helped me build some files.


Justin
When running the make I get: C:\windy\windy package_12_3_2003>path C:\WINXP\system32;C:\WINXP;C:\WINXP\system 32\WBEM;C:\Program Files\doxygen\bin;c:\dmd\bin;c:\dm\bin; C:\windy\windy package_12_3_2003>make dmd -g -gt -debug -Iinclude\ -IprojectLibs -I.. -I. -c api.d listbox.d men u.d static_.d dialog.d msg.d window.d app.d edit.d listctrl.d butto n.d listview.d os.d combobox.d font.d rect.d Error: Error reading file 'windy\treeview.d' --- errorlevel 1
Are you able to include a project file for DIDE with it?
Dec 08 2003
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Charles Sanders wrote:

Yes, but since the paths are absolute it wont compile, im writing in an
'export project' option that will allow this.

C
  

Are you able to include a project file for DIDE with it?

    
Cool. Parhaps it could generate a bat + make file as well (although relativity may be a problem here).
Dec 08 2003
parent "Charles Sanders" <sanders-consulting comcast.net> writes:
Good point ive been meaning to add a 'generate makefile' option too, since
all I really use it for now is a build manager ( like most IDE's, if only we
could embed emacs.... )

Ill write those in then bundle Windy with it thanks,
C
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2nla$2m18$2 digitaldaemon.com...
 Charles Sanders wrote:

Yes, but since the paths are absolute it wont compile, im writing in an
'export project' option that will allow this.

C


Are you able to include a project file for DIDE with it?
Cool. Parhaps it could generate a bat + make file as well (although relativity may be a problem here).
Dec 08 2003
prev sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
J C Calvarese wrote:

 J Anderson wrote:

 Thanks guys.
 I got mine to compile before I saw those emails.  Since I don't have 
 a webspace, I can't upload it to a webserver (although I'll email 
 it). However, I get a warning message when linking.  It seems I don't 
 have advapi32.lib.
Obviously, you're making progress. You and Carlos both have make much more progress than I have. Even though you didn't include a build file, I managed to get halhello.exe to compile and run. I uploaded my results from compiling your version to my free Tripod website at http://jcc_7.tripod.com/d/dig.html. (Please e-mail me your build file so I can look at simplifing up my build routine.) The example cartoon.exe and dedit.exe definitely don't work yet. I didn't seem to share your problem with advapi32.lib, but it may be that I missed that step. I don't know. This stuff is so hard to track down... Thanks for the console output. It helped me build some files. Justin
It seems I forgot to install dmc when I reinstalled dmd. Caused those dig link errors. I had another small look today at dig and fixed scintilla.d. so halhello -> works themeExplorer -> works scintilla -> works dedit -> partly works (show the dialog and then exits -> access violation) catroon -> partly works (show the dialog and then exits -> access violation) deditexec -> doesn't work My own test code has an access volation (digtest). But it's simular to halhello, so I must be compiling it wrong. import c.stdio; import net.BurtonRadons.dig.main; class Program : Frame { this () { //Never gets here, crashes in parent construction caption ("Caption"); with (new Label (this)) { grid (0, 0); caption ("This is a label"); } } } int main( char [] [] args ) //So I can get messages { (new Program ()).showModal (); return 1; } Using prinf I tracked it down to this line: frame(89) digPlatformHWNDCreate (0, toWStringz (digPlatformWindowClass.lpszClassName), null, digPlatformStyle, menu.digPlatformHandle); I put printf in both the toWStringz and the digPlatformHWNDCreate functions. digPlatformHWNDCreate is never called in my code (but it is in halhello). What could I be doing wrong? I wish access violation would give a line number or even better a stack trace. How can I trace the code to find out exactly what's happening.
Dec 08 2003
parent reply "Carlos Santander B." <carlos8294 msn.com> writes:
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2koa$2i0q$1 digitaldaemon.com...
| ...
|
| import c.stdio;
| import net.BurtonRadons.dig.main;
|
| class Program : Frame
| {
|   this ()
|   {
|     //Never gets here, crashes in parent construction
|     caption ("Caption");
|
|       with (new Label (this))
|       {
|           grid (0, 0);
|           caption ("This is a label");
|       }
|
|   }
| }
|
| int main( char [] [] args ) //So I can get messages
| {
|     (new Program ()).showModal ();
|     return 1;
| }
|
| ...

IIRC, you need to call super() in the first line of your constructor (that'd
be right where you have the comment).

-------------------------
Carlos Santander


---

Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27
Dec 08 2003
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Carlos Santander B. wrote:

"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2koa$2i0q$1 digitaldaemon.com...
| ...
|
| import c.stdio;
| import net.BurtonRadons.dig.main;
|
| class Program : Frame
| {
|   this ()
|   {
|     //Never gets here, crashes in parent construction
|     caption ("Caption");
|
|       with (new Label (this))
|       {
|           grid (0, 0);
|           caption ("This is a label");
|       }
|
|   }
| }
|
| int main( char [] [] args ) //So I can get messages
| {
|     (new Program ()).showModal ();
|     return 1;
| }
|
| ...

IIRC, you need to call super() in the first line of your constructor (that'd
be right where you have the comment).

-------------------------
Carlos Santander


---

Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27


  
Thanks, but that didn't help, the assertions still on the same line.
Dec 08 2003
parent J Anderson <REMOVEanderson badmama.com.au> writes:
J Anderson wrote:

 Carlos Santander B. wrote:

 "J Anderson" <REMOVEanderson badmama.com.au> wrote in message
 news:br2koa$2i0q$1 digitaldaemon.com...
 | ...
 |
 | import c.stdio;
 | import net.BurtonRadons.dig.main;
 |
 | class Program : Frame
 | {
 |   this ()
 |   {
 |     //Never gets here, crashes in parent construction
 |     caption ("Caption");
 |
 |       with (new Label (this))
 |       {
 |           grid (0, 0);
 |           caption ("This is a label");
 |       }
 |
 |   }
 | }
 |
 | int main( char [] [] args ) //So I can get messages
 | {
 |     (new Program ()).showModal ();
 |     return 1;
 | }
 |
 | ...

 IIRC, you need to call super() in the first line of your constructor 
 (that'd
 be right where you have the comment).

 -------------------------
 Carlos Santander


 ---

 Checked by AVG anti-virus system (http://www.grisoft.com).
 Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27


  
Thanks, but that didn't help, the assertions still on the same line.
I mean, assertion -> access violation.
Dec 08 2003
prev sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Carlos Santander B. wrote:

"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:br2koa$2i0q$1 digitaldaemon.com...
| ...
|
| import c.stdio;
| import net.BurtonRadons.dig.main;
|
| class Program : Frame
| {
|   this ()
|   {
|     //Never gets here, crashes in parent construction
|     caption ("Caption");
|
|       with (new Label (this))
|       {
|           grid (0, 0);
|           caption ("This is a label");
|       }
|
|   }
| }
|
| int main( char [] [] args ) //So I can get messages
| {
|     (new Program ()).showModal ();
|     return 1;
| }
|
| ...

IIRC, you need to call super() in the first line of your constructor (that'd
be right where you have the comment).

-------------------------
Carlos Santander


---

Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.545 / Virus Database: 339 - Release Date: 2003-11-27


  
Ok, I solved the problem. (forgot the -I\dig\ switch).
Dec 10 2003
prev sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
I got cartoon and dedit  working. deditexec.exe still doesn't work (but 
I don't really care about that)

The problem was:

    /** Get the number of milliseconds the program has been running. */
    static ulong elapsedTime ()
    {
        ulong value;
        LARGE_INTEGER freq;

        return GetTickCount (); //Added by Joel Anderson
        /+if 
(!net.BurtonRadons.dig.platform.base.QueryPerformanceFrequency (&freq) 
|| freq == 0 || !std.random.QueryPerformanceCounter (&value))
            return GetTickCount ();
        if (!digPlatformElapsedTimeCounter)
            digPlatformElapsedTimeCounter = value;
        return (value - digPlatformElapsedTimeCounter) * 1000 / freq;+/ 
//Causes access violation -> fix yourself if you really want such accuracy
    }

It's still not quite correct. I'm simply using the low resolution timer 
(which burton old code defaulted to if the higher one isn't avaliable).

I still haven't gotten my own example to work, I guess I'm mucking up 
the make file. I did have it working before .75.
Dec 08 2003
next sibling parent reply J C Calvarese <jcc7 cox.net> writes:
J Anderson wrote:
 I got cartoon and dedit  working. deditexec.exe still doesn't work (but 
 I don't really care about that)
 
I applied your fixes to my set of the source and voila! Thanks for your help. Everything seems to work now except cartoon.exe and deditexec.exe. I'm not even sure that deditexec.exe is even supposed to do anything, so I'm not concerned about that. I uploaded the newest version to my website: http://jcc_7.tripod.com/d/dig.html Justin
Dec 08 2003
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
J C Calvarese wrote:

 J Anderson wrote:

 I got cartoon and dedit  working. deditexec.exe still doesn't work 
 (but I don't really care about that)
I applied your fixes to my set of the source and voila! Thanks for your help. Everything seems to work now except cartoon.exe and deditexec.exe. I'm not even sure that deditexec.exe is even supposed to do anything, so I'm not concerned about that. I uploaded the newest version to my website: http://jcc_7.tripod.com/d/dig.html Justin
I'll send you my complete dig, because cartoon works for me. + I also added my proper-fullscreen mod. Also, if someone wants to take the time to tidy up my very messy version (I won't have very much time to work on it ATM). There's also the matter if the two code statements I commented out. One being the elapsedTime () function in control I just mentioned and other other being the missing DragQueryPoint in frame.
Dec 08 2003
parent J C Calvarese <jcc7 cox.net> writes:
J Anderson wrote:
 I'll send you my complete dig, because cartoon works for me. + I also 
 added my proper-fullscreen mod.  Also, if someone wants to take the time 
 to tidy up my very messy version (I won't have very much time to work on 
 it ATM).  There's also the matter if the two code statements I commented 
 out.  One being the elapsedTime () function in control I just mentioned 
 and other other being the missing DragQueryPoint in frame.
 
Thanks. Now cartoon works for me too, now. I uploaded it again: http://jcc_7.tripod.com/d/dig.html This one's a keeper. Justin
Dec 08 2003
prev sibling parent "Sean L. Palmer" <palmer.sean verizon.net> writes:
I'm sorry, but I must speak up.

I think Dig is a great thing.  But I don't have a whole lot of time, and I
don't even use Dig, and there's always lots of messages in the "Dig
broken"/"Dig fixed" thread.

Would that be a good thing to put in it's own newsgroup?

(I suppose I can filter).  But I want to see stuff like major Dig release
announcements cross-posted.  It's just better if the dig traffic is kept
separate since it's its own fairly big library and warrants a lot of
conversation that has little to do with D as a whole..

Sean

"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:3FD4F0B7.6070608 badmama.com.au...
 I got cartoon and dedit  working. deditexec.exe still doesn't work (but
 I don't really care about that)

 The problem was:

     /** Get the number of milliseconds the program has been running. */
     static ulong elapsedTime ()
     {
         ulong value;
         LARGE_INTEGER freq;

         return GetTickCount (); //Added by Joel Anderson
         /+if
 (!net.BurtonRadons.dig.platform.base.QueryPerformanceFrequency (&freq)
 || freq == 0 || !std.random.QueryPerformanceCounter (&value))
             return GetTickCount ();
         if (!digPlatformElapsedTimeCounter)
             digPlatformElapsedTimeCounter = value;
         return (value - digPlatformElapsedTimeCounter) * 1000 / freq;+/
 //Causes access violation -> fix yourself if you really want such accuracy
     }

 It's still not quite correct. I'm simply using the low resolution timer
 (which burton old code defaulted to if the higher one isn't avaliable).

 I still haven't gotten my own example to work, I guess I'm mucking up
 the make file. I did have it working before .75.
---------------------------------------------------------------------------- ----
 module net.BurtonRadons.dig.platform.control;

 private import net.BurtonRadons.dig.platform.base;
 private import net.BurtonRadons.dig.platform.windows;
 private import net.BurtonRadons.dig.platform.font;
 private import net.BurtonRadons.dig.platform.clipboard;
 private import net.BurtonRadons.dig.platform.registry;



 //private import std.c.windows.windows;

 //private import std.string;
 //private import std.random;
 //private import std.ctype;

 /+
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 +/

 std.c.windows.windows.HINSTANCE hinst;
 Font digPlatformMainFont;
 std.c.windows.windows.HFONT digPlatformMainFontHandle;

 static this ()
 {
     hinst = std.c.windows.windows.GetModuleHandleA (null);
     InitCommonControls ();

     LOGFONT log;

     log.lfHeight = -12; // height
     log.lfWidth = 0; // width
     log.lfEscapement = 0; // escapement
     log.lfOrientation = 0; // orientation
     log.lfWeight = 400; // weight
     log.lfItalic = 0; // italic
     log.lfUnderline = 0; // underline
     log.lfStrikeOut = 0; // strikeOut
     log.lfCharSet = 1; // charSet
     log.lfOutPrecision = 3; // outPrecision
     log.lfClipPrecision = 2; // clipPrecision
     log.lfQuality = 1; // quality
     log.lfPitchAndFamily = 34; // pitchAndFamily
     std.string.strcpy (log.lfFaceName, "Arial"); // faceName

     digPlatformMainFont = new Font (log);
     digPlatformMainFontHandle = digPlatformMainFont.digPlatformGetHFONT
();
 }

 /+
 #endif
 +/

 /** The base GUI widget class.

   <h2>Grid Fitting</h2>

   By default, you are under control of the location of your widgets,
although
   their dimensions are specified by the class itself.  Gridfitting is also
   provided that locates the controls based on their position in a table.
   You can turn on gridfitting using the #grid method and control it with
   the #sticky method.  These methods will automatically gridfit the
parent.
   Gridfitting can't modify any client-assigned parameters (assigning to
#left,
   #top, #width, #height).

   #grid takes two or four arguments.   a col and  a colspan are
   the horizontal first cell and number of cells across for the control;
    a row and  a rowspan are the same vertically.  Gridfitting will find
the
   minimum occupiable area for these cells and put the controls within
them.
   #sticky controls the placement of the control within its grid area.
   For example, the following pseudoimage is built using this code:

    code

 with (a = new MyBox (this))
     grid (0, 0);

 with (b = new MyBox (this))
     grid (1, 0);

 with (c = new MyBox (this))
 {
     grid (0, 1, 2, 1);
     sticky ("<");
 }

    endcode

   This creates this image:

    image html gridfit_left.gif

   If you don't supply the stickiness for c, then it will be left-aligned
as
   above.  If you provide a stickiness of "|", meaning horizontal center,
we get:
    image html gridfit_center.gif

   If you provide a stickiness of ">", meaning right-aligned, we get:

    image html gridfit_right.gif

   Finally, if we provide a stickiness of "<>", meaning to cover the full
area,
   we get:

    image html gridfit_full.gif

   Vertical stickiness works the same, but using "^" for top-aligned, "v"
for
   bottom-aligned, "-" for vertically centered, and "^v" to cover the full
area
   vertically.

   */

 class Control
 {
     static Registry registry; /**< The registry std.math.singleton. */
     static Clipboard clipboard; /**< The clipboard std.math.singleton. */

     /** Setup the registry. */
     static this ()
     {
         registry = new Registry ();
         clipboard = new Clipboard ();
     }

     BindingList bindings; /**< The list of bindings attached to this
control. */
     Dispatcher onChar; /**< Character has been pressed or is repeating.
The a keyCode, a keyRepeat, and a keyPrevious fields are filled in. */
     Dispatcher onHelp; /**< Help has been requested for this control; if
empty, sends it to its parent. */
     Dispatcher onHScroll;
         /**< A horizontal scrollbar action has been requested.
            *  a scrollType contains the variety of action;
            *  a scrollPoint contains the current point of the scrollbar.
            */

     Dispatcher onKeyDown; /**< Key has been pressed or is repeating.  The
a keyCode, a keyRepeat, and a keyPrevious fields are filled in. */
     Dispatcher onKeyUp; /**< Key has been released.  The  a keyCode,  a
keyRepeat, and a keyPrevious fields are filled in. */
     Dispatcher onLButtonDown; /**< Left mouse button has been pressed. */
     Dispatcher onLButtonUp; /**< Left mouse button has been released. */
     Dispatcher onLostFocus; /**< No longer has keyboard focus. */

     Dispatcher onMButtonDown; /**< Middle mouse button has been pressed.
x, y, and the flag fields are all filled in. */
     Dispatcher onMButtonUp; /**< Middle mouse button has been released.
x, y, and the flag fields are all filled in. */
     Dispatcher onMouseMove; /**< Posted when the mouse moves. */

     Dispatcher onMouseWheel;
         /**< The mouse wheel has been spun.  x, y, and the flag fields are
all
            * filled in, and the wheel field is filled in with the amount
the
            * wheel has been spun in number of units; positive for spun
away
            * from the user (pushing it forward), negative for spun towards
the
            * user (pulling it backward).  Note that this is sent to the
Frame
            * that is currently the mouse focus, not any of its controls.
            */

     Dispatcher onMouseOver; /**< The mouse has entered the control's
region. x and y are filled in with the relative coordinates of the mouse. */
     Dispatcher onMouseLeave; /**< The mouse has left the control's region.
This is currently supported under Windows 98 and up only. */
     Dispatcher onPaint; /**< Paint the control. */

     Dispatcher onRButtonDown; /**< Right mouse button has been pressed.
x, y, and the flag fields are all filled in. */
     Dispatcher onRButtonUp; /**< Right mouse button has been released.  x,
y, and the flag fields are all filled in. */
     Dispatcher onVScroll;
         /**< A vertical scrollbar action has been requested.  The default
is to scroll the control and repaint it.
            *  a scrollType contains the variety of action.
            *  a scrollPoint contains the current point of the scrollbar.
            *  a scrollDest contains one place you could set the scrollbar
to in response.
            */

     Dispatcher onSizeChanged; /**< The control size has been altered by
gridfitting. The event's e.x and e.y hold the previous size. */
     /** A dispatcher for the drag and drop message.  The method forms for
add are:
          code
         void delegate (char [] [] files);
         void delegate (int x, int y, char [] [] files);
          endcode

         "files" is the list of filenames with full path dropped on the
control.
         "x" and "y" are the coordinates of the mouse in this control when
dropped.
       */

     struct DropDispatcher
     {
         typedef void delegate (char [] [] files) cMethodA; /**< The form
of a registered method. */
         typedef void delegate (int x, int y, char [] [] files) cMethodB;
/**< Explicit form. */
         cMethodA [] methoda; /**< The list of methods called by notify. */
         cMethodB [] methodb; /**< Second list of methods called by notify.
*/
         private Control control;

         /** Add a method to the list and enable dropping. */
         void add (cMethodA method)
         {
             methoda ~= method;
             enable ();
         }

         /** Add a second-form method to the list and enable dropping. */
         void add (cMethodB method)
         {
             methodb ~= method;
             enable ();
         }

         /** Notify the methods that an event has occured. */
         void notify (int x, int y, char [] [] files)
         {
             for (cMethodA *m = methoda, n = m + methoda.length; m < n; m
++)
                 (*m) (files);
             for (cMethodB *m = methodb, n = m + methodb.length; m < n; m
++)
                 (*m) (x, y, files);
         }

         /** Remove all methods and stop allowing drop. */
         void empty ()
         {
             methoda = null;
             methodb = null;
             disable ();
         }

         /** Enable acceptance of drop.  This is automatically called when
           * a method is added.
           */

         void enable ()
         {
             DragAcceptFiles (control.digPlatformHWND, true);
         }

         /** Disable acceptance of drop. */

         void disable ()
         {
             DragAcceptFiles (control.digPlatformHWND, false);
         }
     }

     DropDispatcher onDrop;
        /**< A set of files have been dropped upon the control.  So long
             as this dispatcher is empty, the control will not accept
             drops.

             The following example creates a file list control that will
load files
             dropped upon it.

              code
             class FileList : Canvas
             {
                 void doDrop (char [] [] files)
                 {
                     for (int c; c < files.length; c ++)
                         load (files [c]);
                 }

                 this (Control parent)
                 {
                     super (parent);
                     onDrop.add (&doDrop);
                 }
             }
              endcode

            */

     /** Set the parent and append this to the parent's children list if it
is not null. */
     this (Control parent)
     {
         digPlatformCursor = (_HANDLE) 0;//LoadCursorA (0, IDC_ARROW);
         digPlatformParent = parent;
         if (parent)
             parent.digPlatformChildren ~= this;

         onDrop.control = this;
     }

     /** Free data and children. */
     ~this ()
     {
         /* Release the mouse. */
         if (digPlatformHWND && GetCapture () === digPlatformHWND)
             ReleaseCapture ();

         /* Delete the entry. */
         //if (hwnd)
             //delete hwndToControl [hwnd]; /* Investigate! */

         /* Remove this from the parent's list of children. */
         if (parent ())
         {
             Control [] pc = parent ().digPlatformChildren;

             for (int c; c < pc.length; c ++)
                 if (pc [c] === this)
                 {
                     for ( ; c < pc.length - 1; c ++)
                         pc [c] = pc [c + 1];
                     parent ().digPlatformChildren = pc [0 .. pc.length -
1];
                     break;
                 }
         }

         deleteChildren ();

         if (digPlatformHWND)
             DestroyWindow (digPlatformHWND);
         digPlatformHWND = (_HANDLE) 0;

         if (digPlatformFontSet)
             DeleteObject (digPlatformFontSet);
         digPlatformClosed = true;
     }

     /** Close the control. */
     void close ()
     {
         delete this;
     }

 /**  name Hierarchy Methods
   * These methods deal with the hierarchy tree of controls.
   */

 /** {*/

     /** Return the parent of this control, or null if it's at the top
level. */
     Control parent ()
     {
         return digPlatformParent;
     }

     /** Return the number of children of this control. */
     uint childCount ()
     {
         return digPlatformChildren.length;
     }

     /** Iterate over the children from back-to-front, calling func on
each. */
     void childIterate (void delegate (Control child) func)
     {
         Control *c = digPlatformChildren;
         Control *e = c + digPlatformChildren.length;

         while (c < e)
             func (*(c ++));
     }

     /** Return a child indexed in the control.  Out-of-range values are
bounds checked.
       * The order of children is from back-to-front.
       */

     Control child (uint index)
     {
         return digPlatformChildren [index];
     }

     /** Delete all the children of the control. */
     void deleteChildren ()
     {
         for (int c = digPlatformChildren.length - 1; c >= 0; c --)
             delete digPlatformChildren [c];
         delete digPlatformChildren;
         digPlatformChildren = null;
     }

     /** Find the frame object that this control exists within or null. */
     Control findFrame ()
     {
         if (!parent ())
             return null;
         return parent ().findFrame ();
     }

 /** }*/

 /**  name Grid-Fitting
   * You can optionally locate controls within a grid, similar to HTML
   * tables.
   */

 /** {*/

     /** Set grid parameters.   colspan and rowspan are set to 1. */
     void grid (int col, int row)
     {
         grid (col, row, 1, 1);
     }

     /** Set grid parameters.  col and row are the horizontal and
       * vertical location of the control in the table; colspan and
       * rowspan are the number of cells each covers.
       */

     void grid (int col, int row, int colspan, int rowspan)
     {
         this.digPlatformCol = col;
         this.digPlatformRow = row;
         this.digPlatformColSpan = colspan;
         this.digPlatformRowSpan = rowspan;
         digPlatformMoved ();
     }

     /** Set grid and add one to the inout row parameter. */
     void gridAddRow (int col, inout int row)
     {
         gridAddRow (col, row, 1, 1);
     }

     /** Set grid and add rowspan to the inout row parameter. */
     void gridAddRow (int col, inout int row, int colspan, int rowspan)
     {
         grid (col, row, colspan, rowspan);
         row += rowspan;
     }

     /** Get the grid row. */
     int gridRow () { return digPlatformRow; }

     /** Set the control's stickiness.  This determines where it is places
in
       * its region during gridfitting, and is a combination of:
       *
       * "<" - Stick to left, default, and used if none is given.
       * \n ">" - Stick to right.
       * \n "|" - Center horizontally.
       * \n "<" and ">" - Resize width to cover the full region.
       *
       * \n "^" - Stick to top, default, and used if none is given.
       * \n "v" - Stick to bottom.
       * \n "-" - Center vertically.
       * \n "^" and "v" - Resize height to cover the full region.
       *
       * So "<>^v" means to cover the entire region provided.
       */

     void sticky (char [] value)
     {
         bit w = digPlatformStickyW, e = digPlatformStickyE, hc =
digPlatformStickyHC;
         bit n = digPlatformStickyN, s = digPlatformStickyS, vc =
digPlatformStickyVC;
         digPlatformStickyW = digPlatformStickyE = digPlatformStickyHC =
false;
         digPlatformStickyN = digPlatformStickyS = digPlatformStickyVC =
false;
         if (std.string.find (value, '<') >= 0) digPlatformStickyW = true;
         if (std.string.find (value, '>') >= 0) digPlatformStickyE = true;
         if (std.string.find (value, '|') >= 0) digPlatformStickyHC = true;
         if (std.string.find (value, '^') >= 0) digPlatformStickyN = true;
         if (std.string.find (value, 'v') >= 0) digPlatformStickyS = true;
         if (std.string.find (value, '-') >= 0) digPlatformStickyVC = true;
         if (!digPlatformStickyW && !digPlatformStickyE &&
!digPlatformStickyHC) digPlatformStickyW = true;
         if (!digPlatformStickyN && !digPlatformStickyS &&
!digPlatformStickyVC) digPlatformStickyN = true;
         if (digPlatformStickyW != w || digPlatformStickyE != e ||
digPlatformStickyHC != hc
          || digPlatformStickyN != n || digPlatformStickyS != s ||
digPlatformStickyVC != vc)
             digPlatformMoved ();
     }

     /** Set padding used to separate this control from its neighbours. */
     void pad (int x, int y)
     {
         digPlatformPadX = x;
         digPlatformPadY = y;
         digPlatformMoved ();
     }

     /** Set border used on each side of the control's children to
       * separate the contents from the border.
       */

     void border (int x, int y)
     {
         digPlatformBorderX = x;
         digPlatformBorderY = y;
         digPlatformMoved ();
     }

     /** Get the grid extents for the children. */
     void gridExtents (out int colmax, out int rowmax)
     {
         int cw = 0, ch = 0;

         for (Control *c = digPlatformChildren, e = c +
digPlatformChildren.length; c < e; c ++)
         {
             if (c.digPlatformCol == -1)
                 continue;
             if (c.digPlatformCol + c.digPlatformColSpan > cw)
                 cw = c.digPlatformCol + c.digPlatformColSpan;
             if (c.digPlatformRow + c.digPlatformRowSpan > ch)
                 ch = c.digPlatformRow + c.digPlatformRowSpan;
         }

         colmax = cw;
         rowmax = ch;
     }

     /** Do any necessary gridfitting. */
     void display ()
     {
         if (digPlatformDirty)
             digPlatformGridfit ();
     }

 /** }*/

 /**  name Advanced Placement
   * These methods poll and place the exact positioning of a control within
   * its parent.  Normally these coordinates are unlocked and can be
assigned
   * by grid-fitting; assigning them locks them so that this value is
always
   * used.
   */

 /** {*/

     /** Assignment to this property results in the control being
       * moved and the control being resized; until it is assigned,
       * it is in flux and can be modified by grid-fitting.
       */

     final void left (int value)
     {
         digPlatformClientLeft = value;
         digPlatformMoved ();
     }

     /** The left margin of the control in its parent's client area. */
     final int left ()
     {
         if (digPlatformClientLeft >= 0)
             return digPlatformClientLeft;
         return digPlatformSuggestLeft;
     }

     /** Assignment to this property results in the control being
       * moved and the control being resized; until it is assigned,
       * it is in flux and can be modified by grid-fitting.
       */

     final void top (int value)
     {
         digPlatformClientTop = value;
         digPlatformMoved ();
     }

     /** The top margin of the control in its parent's client area. */
     final int top ()
     {
         if (digPlatformClientTop >= 0)
             return digPlatformClientTop;
         return digPlatformSuggestTop;
     }

     /** Assignment to this property results in the control being
       * moved and the control being resized; until it is assigned,
       * it is in flux and can be modified by grid-fitting.
       */

     final void width (int value)
     {
         int owidth = width ();

         digPlatformClientWidth = value;
         if (digPlatformClientWidth != owidth)
             digPlatformMoved ();
     }

     /** The width of the control in pixels. */
     final int width ()
     {
         if (digPlatformClientWidth >= 0)
             return digPlatformClientWidth;
         return digPlatformSuggestWidth;
     }

     /** Return the width of the content of the control, before
grid-fitting. */
     final int actualWidth ()
     {
         if (digPlatformClientWidth >= 0)
             return digPlatformClientWidth;
         return digPlatformSuggestWidth;
     }

     /** Make the width flexible. */
     final void widthFlex ()
     {
         int old = width ();

         digPlatformClientWidth = -1;
         if (width () != old)
             digPlatformMoved ();
     }

     /** Change width and height. */
     final void widthAndHeight (int width, int height)
     {
         int owidth = this.width ();
         int oheight = this.height ();

         digPlatformClientWidth = width;
         digPlatformClientHeight = height;
         if (digPlatformClientWidth != owidth || digPlatformClientHeight !=
oheight)
             digPlatformMoved ();
     }

     /** Assignment to this property results in the control being
       * moved and the control being resized; until it is assigned,
       * it is in flux and can be modified by grid-fitting.
       */

     final void right (int value) { width (value - left ()); }

     /** The right margin of the control in its parent's client area. */
     final int right () { return left () + width (); }

     /** Assignment to this property results in the control being
       * moved and the control being resized; until it is assigned,
       * it is in flux and can be modified by grid-fitting.
       */

     final void height (int value)
     {
         int oheight = height ();

         digPlatformClientHeight = value;
         if (digPlatformClientHeight != oheight)
             digPlatformMoved ();
     }

     /** The height of the control in pixels. */
     final int height ()
     {
         if (digPlatformClientHeight >= 0)
             return digPlatformClientHeight;
         return digPlatformSuggestHeight;
     }

     /** Make the height flexible. */
     final void heightFlex ()
     {
         int old = height ();

         digPlatformClientHeight = -1;
         if (height () != old)
             digPlatformMoved ();
     }

     /** Return the width of the content of the control, before
grid-fitting. */
     final int actualHeight ()
     {
         if (digPlatformClientHeight >= 0)
             return digPlatformClientHeight;
         return digPlatformSuggestHeight;
     }

     /** Assignment to this property results in the control being
       * moved and the control being resized; until it is assigned,
       * it is in flux and can be modified by grid-fitting.
       */

     final void bottom (int value)
     {
         height (value - top ());
     }

     /** The bottom margin of the control in its parent's client area. */
     final int bottom ()
     {
         return top () + height ();
     }

     /** Set suggested dimensions. */
     final void suggestWidthAndHeight (int twidth, int theight)
     {
         int owidth = width (), oheight = height ();

         digPlatformSuggestWidth = twidth;
         digPlatformSuggestHeight = theight;
         if (width () != owidth || height () != oheight)
             digPlatformMoved ();
     }

     /** Set suggested width. */
     final void suggestWidth (int twidth)
     {
         int owidth = width ();

         digPlatformSuggestWidth = twidth;
         if (width () != owidth)
             digPlatformMoved ();
     }

     /** Set suggested height. */
     final void suggestHeight (int theight)
     {
         int oheight = height ();

         digPlatformSuggestHeight = theight;
         if (height () != oheight)
             digPlatformMoved ();
     }

     /** Return the width minus the scrollbar if visible. */
     final int visualWidth ()
     {
         if (/*vscroll () && */vscrollPage () < vscrollRangeMax () -
vscrollRangeMin ())
             return width () - GetSystemMetrics (SM_CXVSCROLL) + 1;
         return width ();
     }

     /** Return the height minus the scrollbar if visible. */
     final int visualHeight ()
     {
         if (hscrollRangeMax () != hscrollRangeMin () && /*hscroll () &&
*/hscrollPage () < hscrollRangeMax () - hscrollRangeMin ())
             return height () - GetSystemMetrics (SM_CXHSCROLL) + 1;
         return height ();
     }

 /** }*/

     /** Spawn a message box with an Okay button. */
     void messageBox (char [] title, char [] message)
     {
         MessageBoxW (digPlatformHWND, toWStringz (message), toWStringz
(title), 0);
     }

     /** Message box flags, a combination of the sets of fields following.
*/
     enum MB
     {
         /* The buttons to display. */
         OK = 1 << 0, /**< OK. */
         AbortRetryIgnore = 1 << 1, /**< Abort, Retry, Ignore. */
         OKCancel = 1 << 3, /**< OK, Cancel. */
         RetryCancel = 1 << 4, /**< Retry, Cancel. */
         YesNo = 1 << 5, /**< Yes, No. */
         YesNoCancel = 1 << 6, /**< Yes, No, Cancel. */

         /* An icon to display, no icon is the default. */
         IconExclamation = 1 << 7, /**< An exclamation-point icon. */
         IconWarning = 1 << 8, /**< A warning icon (may be
IconExclamation). */
         IconInformation = 1 << 9, /**< Information icon. */
         IconAsterisk = 1 << 10, /**< Asterisk icon (may be
IconInformation). */
         IconQuestion = 1 << 11, /**< Question-mark icon. */
         IconStop = 1 << 12, /**< Stop-sign icon. */
         IconError = 1 << 13, /**< Error icon (may be IconStop). */
         IconHand = 1 << 14, /**< Hand icon (may be IconStop). */

         /* The button that is default.  The default is the first button.
*/
         Default1 = 1 << 15, /**< The first button is the default. */
         Default2 = 1 << 16, /**< The second button is the default. */
         Default3 = 1 << 17, /**< The third button is the default. */
         Default4 = 1 << 18, /**< The fourth button is the default. */
     }

     /** Spawn a message box with a set of flags.
       * Returns the name of the button that the user pressed.
       */

     char [] messageBox (char [] title, char [] message, MB flags)
     {
         int type;

         if (flags & MB.OK) type |= MB_OK;
         if (flags & MB.AbortRetryIgnore) type |= MB_ABORTRETRYIGNORE;
         if (flags & MB.OKCancel) type |= MB_OKCANCEL;
         if (flags & MB.RetryCancel) type |= MB_RETRYCANCEL;
         if (flags & MB.YesNo) type |= MB_YESNO;
         if (flags & MB.YesNoCancel) type |= MB_YESNOCANCEL;
         if (flags & MB.IconExclamation) type |= MB_ICONEXCLAMATION;
         if (flags & MB.IconWarning) type |= MB_ICONWARNING;
         if (flags & MB.IconInformation) type |= MB_ICONINFORMATION;
         if (flags & MB.IconAsterisk) type |= MB_ICONASTERISK;
         if (flags & MB.IconQuestion) type |= MB_ICONQUESTION;
         if (flags & MB.IconStop) type |= MB_ICONSTOP;
         if (flags & MB.IconError) type |= MB_ICONERROR;
         if (flags & MB.IconHand) type |= MB_ICONHAND;
         if (flags & MB.Default1) type |= MB_DEFBUTTON1;
         if (flags & MB.Default2) type |= MB_DEFBUTTON2;
         if (flags & MB.Default3) type |= MB_DEFBUTTON3;
         if (flags & MB.Default4) type |= MB_DEFBUTTON4;

         int r = MessageBoxW (digPlatformHWND, toWStringz (message),
toWStringz (title), type);
         switch (r)
         {
             case IDABORT: return "Abort";
             case IDCANCEL: return "Cancel";
             case IDCLOSE: return "Close";
             case IDHELP: return "Help";
             case IDIGNORE: return "Ignore";
             case IDNO: return "No";
             case IDOK: return "OK";
             case IDRETRY: return "Retry";
             case IDYES: return "Yes";
         }
     }

     /** Force a painting on this control. */
     void paint ()
     {
         std.c.windows.windows.InvalidateRect (digPlatformHWND, null,
false);
     }

     /** Paint an inclusive region of the control. */
     void paintRegion (int left, int top, int right, int bottom)
     {
         _RECT rect;

         rect.left = left;
         rect.top = top;
         rect.right = right;
         rect.bottom = bottom;
         std.c.windows.windows.InvalidateRect (digPlatformHWND, &rect,
false);
     }

     /** The background color of this control. */
     Color backgroundColor ()
     {
         if (parent ())
             return parent ().backgroundColor ();
         return Color.Black;
     }

     /** Create a timer; the dispatcher will be notified in delay
milliseconds. */
     static Dispatcher *timer (ulong delay)
     {
         digPlatformTimerFunc *func;
         digPlatformTimerFunc add;
         Dispatcher dispatcher;
         int result, c;

         for (c = 0; ; c ++)
         {
             if (c >= digPlatformTimers.length)
             {
                 digPlatformTimers ~= add;
                 func = &digPlatformTimers [c];
                 break;
             }

             if (!digPlatformTimers [c].mark)
             {
                 func = &digPlatformTimers [c];
                 *func = add;
                 break;
             }
         }

         func.mark = SetTimer ((_HANDLE) 0, 0, delay, null);
         return &func.dispatcher;
     }

     /** Create a timer and add a dispatch to it, then return the
dispatcher */
     static Dispatcher *timer (ulong delay, Dispatcher.Method method)
     {
         Dispatcher *dispatcher = timer (delay);

         dispatcher.add (method);
         return dispatcher;
     }

     /** Create a timer and add a dispatch to it, then return the
dispatcher */
     static Dispatcher *timer (ulong delay, Dispatcher.MethodB method)
     {
         Dispatcher *dispatcher = timer (delay);

         dispatcher.add (method);
         return dispatcher;
     }

     /** Get the number of milliseconds the program has been running. */
     static ulong elapsedTime ()
     {
         ulong value;
 LARGE_INTEGER freq;

 return GetTickCount (); //Added by Joel Anderson
         /+if
(!net.BurtonRadons.dig.platform.base.QueryPerformanceFrequency (&freq) || freq == 0 || !std.random.QueryPerformanceCounter (&value))
             return GetTickCount ();
         if (!digPlatformElapsedTimeCounter)
             digPlatformElapsedTimeCounter = value;
         return (value - digPlatformElapsedTimeCounter) * 1000 / freq;+/
//Causes access voliation -> fix yourself if you really want such accuracy
     }

     /** Get the number of microseconds the program has been running. */
     static ulong elapsedMicroTime ()
     {
         ulong value;
 LARGE_INTEGER freq;

         if (!net.BurtonRadons.dig.platform.base.QueryPerformanceFrequency
(&freq) || freq == 0 || !std.random.QueryPerformanceCounter (&value))
             return GetTickCount () * 1000;
         if (!digPlatformElapsedTimeCounter)
             digPlatformElapsedTimeCounter = value;
         return (value - digPlatformElapsedTimeCounter) * 1000000 / freq;
     }

     /** Return whether this control is visible. */
     bit visible ()
     {
         Control control = this;

         while (control !== null)
         {
             if (!control.digPlatformVisible)
                 return false;
             control = control.parent ();
         }

         return true;
     }

     /** Get the control with keyboard focus, or null if it's not on this
application. */
     Control focus ()
     {
         _HWND f;

         f = GetFocus ();
         if (f == (_HANDLE) 0 || !(f in digPlatformHWNDToControl))
             return null;
         return digPlatformHWNDToControl [f];
     }

     /** Set the control with keyboard focus; pass null to set to none;
returns previous focus or null. */
     Control makeFocus ()
     {
         _HWND result;

         result = SetFocus (digPlatformHWND);
         if (result == (_HANDLE) 0 || !(result in
digPlatformHWNDToControl))
             return null;
         return digPlatformHWNDToControl [result];
     }

     /** Set the keyboard focus to none. */
     void clearFocus ()
     {
         SetFocus (null);
     }

     /** Get whether this control has the keyboard focus. */
     bit isFocus ()
     {
         return GetFocus () == digPlatformHWND;
     }

     /** Change the text font; passing null results in no effect. */
     void font (Font font)
     {
         if (font === null)
             return;
         if (digPlatformFont === null)
         {
             digPlatformFont = new Font (digPlatformMainFont);
             digPlatformFont.digPlatformOnChange.add
(&digPlatformOnFontChange);
         }

         digPlatformFont.digPlatformLog = font.digPlatformLog;
         digPlatformOnFontChange ();
         recalculate ();
     }

     /** Get the text font. */
     Font font ()
     {
         if (digPlatformFont === null)
         {
             digPlatformFont = new Font (digPlatformMainFont);
             digPlatformFont.digPlatformOnChange.add
(&digPlatformOnFontChange);
         }

         return digPlatformFont;
     }

     /** Perform size esimate recalculation. */
     void recalculate ()
     {
     }

     /** Set whether this is active (true) or grayed and inactive (false).
*/
     void enabled (bit value)
     {
         EnableWindow (digPlatformHWND, value);
     }

     /** Return whether this is enabled. */
     bit enabled ()
     {
         return (bit) IsWindowEnabled (digPlatformHWND);
     }

 /**  name Mouse Methods
   * These methods relate to the mouse.
   */

     /** Capture the mouse; when captured,
       * #onMouseMove, #onLButtonDown, #onLButtonUp, #onMButtonDown,
       * #onMButtonUp,
       * #onRButtonDown, #onRButtonUp are sent to this control
       * regardless of the position of the mouse
       */

     void captureMouse ()
     {
         SetCapture (digPlatformHWND);
     }

     /** Release the mouse from #captureMouse. */
     void releaseMouse ()
     {
         ReleaseCapture ();
     }

     /** Return whether this control is holding the mouse captive. */
     bit isCaptor ()
     {
         return GetCapture () == digPlatformHWND;
     }

     /** Return whether this point is within the client region. */
     bit inClientRegion (int x, int y)
     {
         return x >= 0 && y >= 0 && x < width () && y < height ();
     }

     /** Cursors that can be passed to the cursor method.
       * Here is an image showing good cursors for each value:
       *  image html cursors.gif
       */

     enum Cursor
     {
         Arrow, /**< The standard arrow cursor. */
         Help, /**< Arrow with a question mark beside it or the normal
arrow cursor if unavailable. */
         Working, /**< Arrow with an hourglass beside it or the hourglass
cursor if unavailable. */
         Invalid, /**< A crossed-out circle or other insignia indicating
invalidity. */
         Text, /**< The "I" beam text editing cursor. */
         Crosshair, /**< Vertical and horizontal crossed lines, or the
normal arrow cursor if unavailable. */
         Wait, /**< An hourglass. */
         SizeAll, /**< An arrow pointing in all four cardinal directions
(north, south, east, west). */
         SizeNESW, /**< A double-pointed arrow pointing north-east and
south-west. */
         SizeNWSE, /**< A double-pointed arrow pointing north-west and
south-east. */
         SizeEW, /**< A double-pointed arrow pointing west and east. */
         SizeNS, /**< A double-pointed arrow pointing north and south. */
     }

     /** Set a standard cursor to use when the mouse is over this control.
By default it uses the arrow cursor. */
     void cursor (Cursor value)
     {
         _LPCTSTR set;

         switch (value)
         {
             case Cursor.Arrow: set = IDC_ARROW; break;
             case Cursor.Help: set = IDC_HELP; break;
             case Cursor.Text: set = IDC_IBEAM; break;
             case Cursor.Working: set = IDC_APPSTARTING; break;
             case Cursor.Crosshair: set = IDC_CROSS; break;
             case Cursor.Invalid: set = IDC_NO; break;
             case Cursor.SizeAll: set = IDC_SIZEALL; break;
             case Cursor.SizeNESW: set = IDC_SIZENESW; break;
             case Cursor.Wait: set = IDC_WAIT; break;
             case Cursor.SizeNWSE: set = IDC_SIZENWSE; break;
             case Cursor.SizeEW: set = IDC_SIZEWE; break;
             case Cursor.SizeNS: set = IDC_SIZENS; break;
         }

         digPlatformCursor = (_HANDLE) LoadCursorA ((_HANDLE) 0, set);
     }

 /**  name Horizontal Scrollbar
   * These methods, along with the #onHScroll event, control the horizontal
scrollbar.
   */

 /** {*/

     /** Set whether to display a horizontal scrollbar. */
     void hscroll (bit value)
     {
         digPlatformHScrollVisible = value;
         ShowScrollBar (digPlatformHWND, SB_HORZ, value);
         //setRecreateStyle (WS_HSCROLL, value);
     }

     /** Set the horizontal scrollbar range. */
     void hscrollRange (int min, int max)
     {
         if (hscrollRangeMin () == min && hscrollRangeMax () == max)
             return;
         SetScrollRange (digPlatformHWND, SB_HORZ, min, max, true);
     }

     /** Get the horizontal scrollbar minimum point. */
     int hscrollRangeMin ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_ALL;
         GetScrollInfo (digPlatformHWND, SB_HORZ, &info);
         return info.nMin;
     }

     /** Get the horizontal scrollbar maximum point. */
     int hscrollRangeMax ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_ALL;
         GetScrollInfo (digPlatformHWND, SB_HORZ, &info);
         return info.nMax;
     }

     /** Set the horizontal scrollbar point. */
     void hscrollPoint (int position)
     {
         if (hscrollPoint () == position)
             return;
         SetScrollPos (digPlatformHWND, SB_HORZ, position, true);
     }

     /** Get the horizontal scrollbar point. */
     int hscrollPoint ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_ALL;
         GetScrollInfo (digPlatformHWND, SB_HORZ, &info);
         return info.nPos;
     }

     /** Get the units count in a std.math.single horizontal scrollbar
page. */
     int hscrollPage ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_ALL;
         GetScrollInfo (digPlatformHWND, SB_HORZ, &info);
         return info.nPage;
     }

     /** Set the units count in a std.math.single horizontal scrollbar
page. */
     void hscrollPage (int size)
     {
         SCROLLINFO info;

         if (hscrollPage () == size)
             return;
         info.cbSize = info.size;
         info.fMask = SIF_PAGE;
         info.nPage = size;
         SetScrollInfo (digPlatformHWND, SB_HORZ, &info, true);
     }

 /** }*/

 /**  name Vertical Scrollbar
   * These methods, along with the #onVScroll event, control the vertical
scrollbar.
   */

 /** {*/

     /** Set whether to display a vertical scrollbar. */
     void vscroll (bit value)
     {
         digPlatformVScrollVisible = value;
         ShowScrollBar (digPlatformHWND, SB_VERT, value);
         //setRecreateStyle (WS_VSCROLL, value);
     }

     /** Return whether the vertical scrollbar can be displayed. */
     bit vscroll ()
     {
         return digPlatformVScrollVisible;
     }

     /** Set both the vertical scrollbar range and page. */
     void vscrollRangeAndPage (int min, int max, int page)
     {
         if (vscrollRangeMin () == min && vscrollRangeMax () == max &&
vscrollPage () == page)
             return;

         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_ALL;
         GetScrollInfo (digPlatformHWND, SB_VERT, &info);
         info.nMin = min;
         info.nMax = max;
         info.nPage = page;
         SetScrollInfo (digPlatformHWND, SB_VERT, &info, true);
     }

     /** Set the vertical scrollbar range. */
     void vscrollRange (int min, int max)
     {
         if (vscrollRangeMin () == min && vscrollRangeMax () == max)
             return;
         ShowScrollBar (digPlatformHWND, SB_VERT, max - min > vscrollPage
());
         SetScrollRange (digPlatformHWND, SB_VERT, min, max, true);
     }

     /** Get the vertical scrollbar minimum point. */
     int vscrollRangeMin ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_RANGE;
         GetScrollInfo (digPlatformHWND, SB_VERT, &info);
         return info.nMin;
     }

     /** Get the vertical scrollbar maximum point. */
     int vscrollRangeMax ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_RANGE;
         GetScrollInfo (digPlatformHWND, SB_VERT, &info);
         return info.nMax;
     }

     /** Set the vertical scrollbar point. */
     void vscrollPoint (int position)
     {
         if (vscrollPoint () == position)
             return;
         SetScrollPos (digPlatformHWND, SB_VERT, position, true);
     }

     /** Get the vertical scrollbar point. */
     int vscrollPoint ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_POS;
         GetScrollInfo (digPlatformHWND, SB_VERT, &info);
         return info.nPos;
     }

     /** Set the units count in a std.math.single vertical scrollbar page.
*/
     void vscrollPage (int size)
     {
         SCROLLINFO info;

         if (vscrollPage () == size)
             return;
         ShowScrollBar (digPlatformHWND, SB_VERT, vscrollRangeMax () -
vscrollRangeMin () > size);
         info.cbSize = info.size;
         info.fMask = SIF_PAGE;
         info.nPage = size;
         SetScrollInfo (digPlatformHWND, SB_VERT, &info, true);
     }

     /** Get the units count in a std.math.single vertical scrollbar page.
*/
     int vscrollPage ()
     {
         SCROLLINFO info;

         info.cbSize = info.size;
         info.fMask = SIF_PAGE;
         GetScrollInfo (digPlatformHWND, SB_VERT, &info);
         return info.nPage;
     }

 /** }*/

     /** Bind a keypress to a dispatcher for this control.  code describes
       * the keypress and ends with a key name (such as "Return") and
starts
       * with a combination of shift, control, and ctrl, in any case with
       * any separator.  For example, "Shift-X", "Shift CONTROL y", and
       * "CtrlZ".  Another modifier is "Focus", which prevents the binding
       * from being called if the control isn't the keyboard focus.  See
       * #Event for the key names.
       *
       * The dispatcher pointer returned is valid until the next bind
method
       * call only.  Unless if frames have their own binding for the key,
they
       * will pass it to the first sub-control which has a binding, so you
       * don't need to bind to the frame.
       */

     Dispatcher *bind (char [] code)
     {
         return bindings.bind (code);
     }

     /** Bind a method to the dispatcher and return it. */
     Dispatcher *bind (char [] code, Dispatcher.Method method)
     {
         return bindings.bind (code, method);
     }

     /** Bind a method to the dispatcher and return it. */
     Dispatcher *bind (char [] code, Dispatcher.MethodB method)
     {
         return bindings.bind (code, method);
     }

     /** Bind a dispatcher pointer to the dispatcher and return it. */
     Dispatcher *bind (char [] code, Dispatcher *dispatcher)
     {
         return bindings.bind (code, dispatcher);
     }

 /**  name Processor Capabilities
   * When writing assembly code, it's useful to know not just the processor
you're using but also
   * its variant.  These functions return such values.
   */

 /** {*/

     /** Return whether this is an Intel x86 processor with MMX capability
(Pentium Pro/6 and up). */
     static bit x86_has_mmx ()
     {
         version (X86)
         {
             asm
             {
                 // Check feature flag 23 in cpuid for MMX support
                 mov EAX, 1;
                 cpuid; // Note that I don't check that this instruction is
available first
                 mov EAX, EDX;
                 shr EAX, 23;
                 and EAX, 1;
             }
         }
         else
             return false;
     }

 /** }*/

 /**  name File Listing
   * This creates a list of search files from a directory; each file has
information such as its
   * name, whether it's a directory, and size.
   */

 /** {*/

     /** File found from searching. */
     class SearchFile
     {
         char [] name; /**< Filename. */
         char [] full; /**< Filename with path. */
         char [] ext; /**< Extension only, no dot. */
         char [] alternate; /**< Alternate filename, the 8.3 name in DOS,
or name. */
         bit directory; /**< File is a directory. */

         ulong size; /**< File size in bytes. */

         override int opCmp (Object b) /* operator overloading for
comparison */
         {
             if ((SearchFile) b === null)
                 return 0;
             return std.string.cmp (name, ((SearchFile) b).name);
         }
     }

     /** List files in a directory ("." and ".." are not included). */
     class Search
     {
         /** Assign the path. */
         this (char [] path)
         {
             if (path.length && (path [path.length - 1] == '/' || path
[path.length - 1] == '\\'))
                 path = path [0 .. path.length - 1];
             digPlatformPath = path;
         }

         /** Delete anything attached to the search. */
         ~this ()
         {
             if (digPlatformHandle)
                 std.file.FindClose (digPlatformHandle);
         }

         /** Read in the next file or null if this is done. */
         SearchFile next ()
         {
             if (digPlatformDone)
                 return null;
             if (digPlatformStarting)
             {
                 digPlatformHandle = std.file.FindFirstFileA
(std.string.toStringz (digPlatformPath ~ "/*"), &digPlatformData);
                 if (digPlatformHandle == (_HANDLE) 0)
                     throw new Error ("couldn't find path '" ~
digPlatformPath ~ "'");
                 digPlatformStarting = false;
             }
             else if (!std.file.FindNextFileA (digPlatformHandle,
&digPlatformData))
             {
                 digPlatformDone = true;
                 std.file.FindClose (digPlatformHandle);
                 digPlatformHandle = (_HANDLE) 0;
                 return null;
             }

             if (digPlatformData.cFileName [0 .. 2] == ".\0" ||
digPlatformData.cFileName [0 .. 3] == "..\0")
                 return next ();

             SearchFile file;

             if (std.string.strlen (digPlatformData.cFileName) == 0)
             {
                 digPlatformDone = true;
                 std.file.FindClose (digPlatformHandle);
                 return null;
             }

             file = new SearchFile ();
             file.name = digPlatformData.cFileName [0 .. std.file.strlen
(digPlatformData.cFileName)].dup;
             file.full = digPlatformPath ~ "/" ~ file.name;
             for (int c = file.name.length; c > 0; c --)
                 if (file.name [c - 1] == '.')
                 {
                     file.ext = file.name [c .. file.name.length];
                     break;
                 }

             if (digPlatformData.cAlternateFileName [0])
                 file.alternate = digPlatformData.cAlternateFileName [0 ..
std.string.strlen (digPlatformData.cAlternateFileName)].dup;
             else
                 file.alternate = file.name;

             if (digPlatformData.dwFileAttributes &
FILE_ATTRIBUTE_DIRECTORY)
                 file.directory = true;

             file.size = ((ulong) digPlatformData.nFileSizeHigh << 32UL)
                       + (ulong) digPlatformData.nFileSizeLow;

             return file;
         }

     /+
     #ifdef DoxygenMustSkipThis
     +/

         char [] digPlatformPath; /**< Path to list. */
         bit digPlatformStarting = true;
         bit digPlatformDone = false;

         std.c.windows.windows.WIN32_FIND_DATA digPlatformData;
         std.c.windows.windows.HANDLE digPlatformHandle;

     /+
     #endif
     +/
     }

     /** Get the full list of files in a directory. */
     static SearchFile [] listPath (char [] path)
     {
         Search search = new Search (path);
         SearchFile [] list;
         SearchFile add;

         while ((add = search.next ()) !== null)
             list ~= add;

         return list;
     }

     /** A static class for operating system calls. */
     class OS
     {
         /** Return the command name that allegedly created this process.
*/
         static char [] commandName ()
         {
             char [] line = std.string.toString (GetCommandLineA ());

             if (line [0] == '\"')
                 return line [1 .. std.string.find (line [1 ..
line.length], '\"') + 1].dup;
             for (int c; ; c ++)
                 if (c >= line.length || std.ctype.isspace (line [c]))
                     return line [0 .. c];
         }

         /** Assign the current working directory. */
         static void currentWorkingDirectory (char [] path)
         {
 //std.file.chdir (path);
             if (chdir (std.string.toStringz (path)) < 0)
                 throw new Error ("Couldn't change current working
directory to '" ~ path ~ "' because the path does not exist.");
         }

         /** Return the current working directory. */
         static char [] currentWorkingDirectory ()
         {
             char [] buffer;

 //buffer = std.file.getcwd ();
 if (getcwd (buffer, buffer.length) === null)
                 throw new Error ("Couldn't get the current working
directory.");
             return std.string.toString (buffer).dup;
         }

         /** Return an environment variable or null if this is not
assigned. */
         static char [] environmentVariable (char [] name)
         {
             return std.string.toString (getenv (std.string.toStringz
(name))).dup;
         }

         /** Assign an environment variable. */
         static void environmentVariable (char [] name, char [] value)
         {
             putenv (std.string.toStringz (name ~ "=" ~ value));
         }

         /** A system process.  This is here to allow parallel controlled
execution of
           * subsidiary processes as well as debugging.
           */

         class Process
         {
             private PROCESS_INFORMATION info;
             private _DWORD returnValue;
             private bit finished = false;
             private bit isPaused = true;

             /** Create a process.  The process will be paused; use "paused
(false)" to start it.
               *  param command The path and filename of the executable.
               * This is either an absolute path or searched using whatever
path settings are made for this operating system.
               * You can control other parameters by prefixing characters
to the command. Prefixing
               * "%" shows a command window.  "$" debugs the process.
               *  param args A list of arguments passed to the command.
               */

             this (char [] command, char [] [] args)
             {
                 bit shouldDebug, window;
                 int mode;
                 int *result;
                 char *[] argv;

                 while (1)
                 {
                     if (command [0] == '$')
                         shouldDebug = true;
                     else if (command [0] == '%')
                         window = true;
                     else
                         break;
                     command = command [1 .. command.length];
                 }

                 char [] commandline;
                 STARTUPINFOA startup;
                 int flags;

                 commandline ~= "\"" ~ command ~ "\"";

                 for (int c; c < args.length; c ++)
                     commandline ~= " \"" ~ args [c] ~ "\"";

                 startup.cb = startup.size;
                 startup.dwFlags = 0;
                 flags = NORMAL_PRIORITY_CLASS;

                 if (window)
                     flags |= CREATE_NEW_CONSOLE;
                 if (shouldDebug)
                     flags |= DEBUG_PROCESS;

                 flags |= CREATE_SUSPENDED;

                 if (!CreateProcessA (null, commandline, null, null, false,
                     flags, null, null, &startup, &info))
                     digPlatformGetLastError ("Control.OS.system");
             }

             /** Unpause the process if it is paused, and then wait until
the process is finished and return its exit code. */
             int finish ()
             {
                 if (finished)
                     return returnValue;
                 paused (false);
                 std.c.windows.windows.WaitForSingleObject (info.hProcess,
~0);
                 if (!GetExitCodeProcess (info.hProcess, &returnValue))
                     digPlatformGetLastError ("Control.OS.Process.finish:
GetExitCodeProcess");
                 std.thread.CloseHandle (info.hProcess);
                 std.thread.CloseHandle (info.hThread);
                 finished = true;
                 return returnValue;
             }

             /** Unpause the process and then wait for it for a number of
milliseconds. Returns whether the process is not finished. */
             bit wait (int milliseconds)
             {
                 if (finished)
                     return false;
                 paused (false);
                 std.thread.WaitForSingleObject (info.hProcess, ~0);
                 GetExitCodeProcess (info.hProcess, &returnValue);
                 if (returnValue != 0x103) // STILL_ACTIVE
                 {
                     finished = true;
                     std.thread.CloseHandle (info.hProcess);
                     std.thread.CloseHandle (info.hThread);
                 }
                 return !finished;
             }

             /** A debug event created by waitForDebugEvent. */
             class DebugEvent
             {
                 Process process; /**< The process this event is for. */
             }

             /** Wait for a debug event for a number of milliseconds.  Note
that if
               * you are debugging a process you just created, you have to
unpause
               * it first using paused (false).
               *  param milliseconds The number of milliseconds to wait, or
zero to check if there is a waiting event and return that.
               *  return Returns a new debug event or null if none occured
before the timeout.
               */
             static DebugEvent waitForDebugEvent (int milliseconds)
             {
                 DEBUG_EVENT input;

                 if (!WaitForDebugEvent (&input, milliseconds))
                     return null;
                 printf ("Got a debug event, woot!\n");
                 return null;
             }

             /** Return whether this process is paused.  Initially the
process is paused. */
             bit paused ()
             {
                 return isPaused;
             }

             /** Assign whether to pause execution of the process or
continue it. */
             void paused (bit value)
             {
                 if (finished)
                     return;
                 if (value)
                     std.thread.SuspendThread (info.hThread);
                 else
                     std.thread.ResumeThread (info.hThread);
                 isPaused = value;
             }
         }

         /** Run a command in system and return the result.
           *  param command The path and filename of the executable.
           * This is either an absolute path or searched using whatever
path settings are made for this operating system.
           * You can control other parameters by prefixing characters to
the command. Prefixing
           * "&" makes the execution asynchronous, so that it creates an
entirely different process
           * and returns zero rather than waiting for it to finish.  "%"
shows a command window.
           *  param args A list of arguments passed to the command.
           *  return The return value from the executable or zero if it is
asynchronous.
           */
         static int system (char [] command, char [] [] args)
         {
             bit asynchronous, window;
             int mode;
             int *result;
             char *[] argv;

             while (1)
             {
                 if (command [0] == '&')
                     asynchronous = true;
                 else if (command [0] == '%')
                     window = true;
                 else
                     break;
                 command = command [1 .. command.length];
             }

             char [] commandline;
             STARTUPINFOA startup;
             PROCESS_INFORMATION process;
             int flags;

             commandline ~= "\"" ~ command ~ "\"";

             for (int c; c < args.length; c ++)
                 commandline ~= " \"" ~ args [c] ~ "\"";

             startup.cb = startup.size;
             startup.dwFlags = 0;
             flags = NORMAL_PRIORITY_CLASS;

             if (window)
                 flags |= CREATE_NEW_CONSOLE;

             if (!CreateProcessA (null, commandline, null, null, false,
                 flags, null, null, &startup, &process))
                 digPlatformGetLastError ("Control.OS.system");

             if (!asynchronous)
             {
                 _DWORD code;

                 std.thread.WaitForSingleObject (process.hProcess, ~0);
                 if (!GetExitCodeProcess (process.hProcess, &code))
                     digPlatformGetLastError ("Control.OS.system:
GetExitCodeProcess");
                 std.thread.CloseHandle (process.hProcess);
                 std.thread.CloseHandle (process.hThread);
                 return code;
             }

             return 0;

             /+mode |= asynchronous ? _P_NOWAIT : _P_WAIT;

             if (window)
             {
                 char [] [] prefix;

                 prefix ~= "/c";
                 prefix ~= command;
                 args = prefix ~ args;

                 command = environmentVariable ("COMSPEC");
                 if (command === null)
                     command = (osver & 0x8000) ? "command.com" :
"cmd.exe";
                 /*printf ("added command %.*s", command);
                 for (int c; c < args.length; c ++)
                     printf (" %.*s", args [c]);
                 printf ("\n");*/
             }

             argv = new char *[args.length + 2];
             argv [0] = std.string.toStringz (command);
             for (int c; c < args.length; c ++)
                 argv [c + 1] = std.string.toStringz (args [c]);

             result = spawnvp (mode, argv [0], argv);
             if (asynchronous)
                 return 0;
             return (int) result;+/
         }

         /** Split the directory from a string; for example, 'src/foo.c'
becomes 'src/'. If there is no directory, null is returned. */
         static char [] pathDir (char [] path)
         {
             for (int c = path.length - 1; ; c --)
                 if (c < 0 || path [c] == '/' || path [c] == '\\')
                     return path [0 .. c + 1];
         }

         /** Split everything but the directory from a string; for example,
'src/foo.c' becomes 'foo.c'. */
         static char [] pathNotDir (char [] path)
         {
             for (int c = path.length - 1; ; c --)
                 if (c < 0 || path [c] == '/' || path [c] == '\\')
                     return path [c + 1 .. path.length];
         }

         /** Split the suffix from a string; for example, 'src/foo.c'
becomes '.c'. */
         static char [] pathSuffix (char [] path)
         {
             for (int c = path.length - 1; ; c --)
                 if (c < 0 || path [c] == '/' || path [c] == '\\')
                     return null;
                 else if (path [c] == '.')
                     return path [c .. path.length];
         }

         /** Extract all but the suffix from a string; for example,
'src/foo.c' becomes 'src/foo'. */
         static char [] pathBaseName (char [] path)
         {
             for (int c = path.length - 1; ; c --)
                 if (c < 0 || path [c] == '/' || path [c] == '\\')
                     return path;
                 else if (path [c] == '.')
                     return path [0 .. c];
         }
     }

 /** }*/

 /+
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 +/

 //protected:
     Control [] digPlatformChildren; /**< The children of the control. */
     Control digPlatformParent; /**< The parent of the control, null if
there is none. */
     static Control [std.c.windows.windows.HWND] digPlatformHWNDToControl;
     std.c.windows.windows.HFONT digPlatformFontSet =
(std.c.windows.windows.HFONT) 0;
     Font digPlatformFont;

     struct digPlatformTimerFunc
     {
         int mark;
         Dispatcher dispatcher;
     }

     static digPlatformTimerFunc [] digPlatformTimers;

     std.c.windows.windows.HWND digPlatformHWND =
(std.c.windows.windows.HWND) 0;
     int digPlatformSuggestLeft;
     int digPlatformSuggestTop;
     int digPlatformSuggestWidth;
     int digPlatformSuggestHeight;

     int digPlatformClientLeft = -1;
     int digPlatformClientTop = -1;
     int digPlatformClientWidth = -1;
     int digPlatformClientHeight = -1;
     std.c.windows.windows.HDC digPlatformHDC;
     bit digPlatformClosed;
     bit digPlatformVisible = true;

     int digPlatformCol = -1;
     int digPlatformRow = -1;
     int digPlatformColSpan = -1;
     int digPlatformRowSpan = -1;

     int digPlatformPadX = 4; /* Padding on the outside. */
     int digPlatformPadY = 1; /* Padding on the outside. */

     int digPlatformBorderX = 5; /* Padding on the inside. */
     int digPlatformBorderY = 5; /* Padding on the inside. */
     int digPlatformBorderSY = 0;
     int digPlatformBorderSX = 0;
     int digPlatformBorderEY = 0;
     int digPlatformBorderEX = 0;

     bit digPlatformStickyW = true, digPlatformStickyE = false,
digPlatformStickyHC = false;
     bit digPlatformStickyN = true, digPlatformStickyS = false,
digPlatformStickyVC = false;
     _WPARAM digPlatformStyle =  std.c.windows.windows.WS_HSCROLL |
std.c.windows.windows.WS_VSCROLL;
     _WPARAM digPlatformCurrentStyle = 0;
     wchar [] digPlatformClassName;
     wchar [] digPlatformCaption;

     bit digPlatformFitting; /* The parent is being asked to gridfit. */

     static ulong digPlatformElapsedTimeCounter;

     void digPlatformOnFontChange ()
     {
         _HFONT handle = digPlatformFont.digPlatformGetHFONT ();

         SendMessageA (digPlatformHWND, WM_SETFONT, (uint) handle, 1);
         if (digPlatformFontSet)
             DeleteObject (digPlatformFontSet);
         digPlatformFontSet = handle;
     }

     /** Change the caption. */
     void digPlatformSetCaption (char [] value)
     {
         digPlatformCaption = toWStringz (value);
         SendMessageW (digPlatformHWND, WM_SETTEXT, 0, (_LPARAM) (wchar *)
digPlatformCaption);
     }

     /* Perform gridfitting on the contents. */
     void digPlatformGridfit ()
     {
         Control *cStart = digPlatformChildren, cEnd = cStart +
digPlatformChildren.length, c;
         int [] coldims, coloffs;
         int [] rowdims, rowoffs;
         int rowmax, colmax;
         int row, col;

         digPlatformGridfitted = true;

         /* Prevent parent-child recursion. */
         if (digPlatformFitting)
             return;

         if (!digPlatformChildren.length)
             return;

         /* Get extents and allocate temporaries. */
         gridExtents (colmax, rowmax);
         if (colmax < 0 || rowmax < 0)
             return;

         digPlatformFitting = true; /* Prevent recursion. */

         rowdims = new int [rowmax + 1];
         coldims = new int [colmax + 1];
         rowoffs = new int [rowmax + 1];
         coloffs = new int [colmax + 1];

         for (c = cStart; c < cEnd; c ++)
             if (c.digPlatformDirty)
             {
                 c.digPlatformDirty = false;
                 c.digPlatformGridfit ();
             }

         /* Determine the row heights. */
         {
             int bottom = 0;

             for (row = 0; row < rowmax; row ++)
             {
                 int height = 0;

                 for (c = cStart; c < cEnd; c ++)
                 {
                     if (c.digPlatformCol == -1)
                         continue;
                     if (c.digPlatformRow + c.digPlatformRowSpan - 1 ==
row)
                     {
                         int child_height;

                         child_height = c.actualHeight () +
c.digPlatformPadY * 2;
                         if (c.digPlatformRowSpan != 1)
                             child_height -= bottom;
                         if (child_height > height)
                             height = child_height;
                     }
                 }

                 rowoffs [row] = bottom;
                 rowdims [row] = height;
                 bottom += height;
             }

             rowoffs [row] = bottom;
             rowdims [row] = 0;
         }

         /* Determine the col widths */
         {
             int right = 0;

             for (col = 0; col < colmax; col ++)
             {
                 int width;

                 width = 0;
                 for (c = cStart; c < cEnd; c ++)
                 {
                     if (c.digPlatformCol == -1)
                         continue;
                     if (c.digPlatformCol + c.digPlatformColSpan - 1 ==
col)
                     {
                         int child_width;

                         child_width = c.actualWidth () + c.digPlatformPadX
* 2;
                         if (c.digPlatformColSpan != 1)
                             child_width -= right;
                         if (child_width > width)
                             width = child_width;
                     }
                 }

                 coloffs [col] = right;
                 coldims [col] = width;
                 right += width;
             }

             coloffs [col] = right;
             coldims [col] = 0;
         }

 /*
         if (force_coldim)
         {
             int right = coloffs [colmax];

             for (col = 0; col <= colmax; col ++)
             {
                 if (right == 0)
                     coloffs [col] = coldims [col] = 0;
                 else
                 {
                     int dim = coldims [col], off = coloffs [col];

                     coloffs [col] = off * force_coldim / right;
                     coldims [col] = dim * force_coldim / right;
                 }
             }
         }

         if (force_rowdim)
         {
             int bottom = rowoffs [rowmax];

             for (row = 0; row <= rowmax; row ++)
             {
                 if (bottom == 0)
                     rowoffs [row] = rowdims [row] = 0;
                 else
                 {
                     int dim = rowdims [row], off = rowoffs [row];

                     rowoffs [row] = off * force_rowdim / bottom;
                     rowdims [row] = dim * force_rowdim / bottom;
                 }
             }
         }
 */

         /* Determine our client offset. */
         int startx = digPlatformBorderX + digPlatformBorderSX;
         int starty = digPlatformBorderY + digPlatformBorderSY;

         /* Get jiggy with it */
         for (c = cStart; c < cEnd; c ++)
         {
             int rowch, rowdim, rowoff, rowcell, basey;
             int colch, coldim, coloff, colcell, basex;
             int regridfit = 0;

             if (c.digPlatformRow == -1)
                 continue;

             colch = c.width ();
             rowch = c.height ();

             rowdim = rowdims [c.digPlatformRow];
             rowoff = rowoffs [c.digPlatformRow];
             rowcell = rowoffs [c.digPlatformRow + c.digPlatformRowSpan] -
rowoff - c.digPlatformPadY * 2;
             basey = (rowcell - rowch) / 2;

             if (c.digPlatformStickyN)
                 basey = 0;
             if (c.digPlatformStickyS)
             {
                 if (c.digPlatformStickyN)
                 {
                     rowch = rowcell;
                     regridfit = 1;
                 }
                 else
                     basey = rowcell - rowch;
             }
             if (c.digPlatformStickyVC)
                 basey = (rowcell - rowch) / 2;

             coldim = coldims [c.digPlatformCol];
             coloff = coloffs [c.digPlatformCol];
             colcell = coloffs [c.digPlatformCol + c.digPlatformColSpan] -
coloff - c.digPlatformPadX * 2;
             basex = (colcell - colch) / 2;

             if (c.digPlatformStickyW)
                 basex = 0;
             if (c.digPlatformStickyE)
             {
                 if (c.digPlatformStickyW)
                 {
                     colch = colcell;
                     regridfit = 1;
                 }
                 else
                     basex = colcell - colch;
             }
             if (c.digPlatformStickyHC)
                 basex = (colcell - colch) / 2;

             /*if (regridfit)
             {
                 gui_widget_rect rect;

                 if (gui_widget_frame_indent (child, &rect) < 0)
                     goto failure;
                 child->need_gridfit = 1;
                 if (gui_widget_gridfit (child, colch - rect.sx - rect.ex,
rowch - rect.sy - rect.ey) < 0)
                     goto failure;
             }*/

             basex += coloff + c.digPlatformPadX;
             basey += rowoff + c.digPlatformPadY;
             int oldx = c.width ();
             int oldy = c.height ();
             c.digPlatformSuggestLeft = basex + startx;//_borderx +
_bordersx;
             c.digPlatformSuggestTop = basey + starty;//_bordery +
_bordersy;
             c.digPlatformSuggestWidth = colch;
             c.digPlatformSuggestHeight = rowch;
             c.digPlatformSetDimensions (oldx, oldy);
             //c.digPlatformMoved ();
         }

         digPlatformSuggestWidth = coloffs [colmax] + digPlatformBorderX *
2 + digPlatformBorderSX + digPlatformBorderEX;
         digPlatformSuggestHeight = rowoffs [rowmax] + digPlatformBorderY *
2 + digPlatformBorderSY + digPlatformBorderEY;
         digPlatformMoved ();

         /*for (c = 0; c < 2; c ++)
         {
             gui_widget_rect frame;

             if (gui_widget_frame (self, &frame) < 0)
                 goto failure;
             swidth  = (frame.sx - sleft) + (self->ex - frame.ex) + coloffs
[colmax];
             sheight = (frame.sy - stop) + (self->ey - frame.ey) + rowoffs
[rowmax];
         }

         self->need_gridfit = 0;
         self->width = width;
         self->height = height;

         self->ex = self->sx + width;
         self->ey = self->sy + height;
         }*/

         /* Now ask the parent to gridfit. */
         if (parent () !== null)
             parent ().digPlatformGridfit ();

         /* All done. */
         digPlatformFitting = false;
         delete rowdims;
         delete coldims;
         delete rowoffs;
         delete coloffs;
     }

     void digPlatformSetDimensions (int oldx, int oldy)
     {
         if (oldx != width () || oldy != height ())
         {
             Event e;

             e.x = oldx;
             e.y = oldy;
             e.deltax = width () - oldx;
             e.deltay = height () - oldy;
             onSizeChanged.notify (e);
         }
         MoveWindow (digPlatformHWND, left (), top (), width (), height (),
false);
     }

     static void digPlatformEventKeySet (inout Event e,
std.c.windows.windows.WPARAM wParam)
     {
         e.control = (bit) (wParam & MK_CONTROL);
         e.lbutton = (bit) (wParam & MK_LBUTTON);
         e.mbutton = (bit) (wParam & MK_MBUTTON);
         e.rbutton = (bit) (wParam & MK_RBUTTON);
         e.shift = (bit) (wParam & MK_SHIFT);
     }

     bit digPlatformDirty = false;

     void digPlatformMoved ()
     {
         digPlatformDirty = true;
     }

     void digPlatformChildMoved (Control control)
     {
     }

     void digPlatformChangeStyle ()
     {
         if (digPlatformStyle == digPlatformCurrentStyle)
             return;
         //SendMessageA (hwnd, BM_SETSTYLE, style, 1);
         SetWindowLongA (digPlatformHWND, GWL_STYLE, digPlatformStyle);
         digPlatformCurrentStyle = digPlatformStyle;
     }

     void digPlatformSetStyle (int mask, bit value)
     {
         digPlatformStyle = value ? (digPlatformStyle | mask) :
(digPlatformStyle & ~mask);
         digPlatformChangeStyle ();
     }

     void digPlatformSetResetStyle (int setmask, int resetmask, bit value)
     {
         if (value)
         {
             digPlatformStyle |= setmask;
             digPlatformStyle &= ~resetmask;
         }
         else
             digPlatformStyle &= ~setmask;
         digPlatformChangeStyle ();
     }

     void digPlatformSetRecreateStyle (int mask, bit value)
     {
         int ostyle = digPlatformCurrentStyle;

         digPlatformSetStyle (mask, value);
         if (ostyle == digPlatformCurrentStyle)
             return;

         digPlatformRecreate ();
     }

     void digPlatformHWNDCreate (_DWORD dwExStyle,
                      wchar [] lpClassName,
                      wchar [] lpWindowName,
                      _DWORD dwStyle,
                      int x,
                      int y,
                      int nWidth,
                      int nHeight,
                      _HWND hWndParent,
                      _HMENU hMenu,
                      _HINSTANCE hInstance,
                      _LPVOID lpParam)
     {
         digPlatformClassName = lpClassName;
         digPlatformHWND = CreateWindowExW (dwExStyle, lpClassName,
lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
         digPlatformHDC = std.c.windows.windows.GetDC (digPlatformHWND);
         digPlatformHWNDToControl [digPlatformHWND] = this;
         digPlatformStyle = digPlatformCurrentStyle = dwStyle;
         vscroll (digPlatformVScrollVisible);
         hscroll (digPlatformHScrollVisible);
         this.font (this.font ());
         /*if (digPlatformFontSet)
             SendMessageA (digPlatformHWND, WM_SETFONT, (_DWORD)
digPlatformFontSet, 1);
         else
             SendMessageA (digPlatformHWND, WM_SETFONT, (_DWORD)
digPlatformMainFontHandle, 1);*/
     }

     void digPlatformHWNDCreate (_DWORD dwExStyle,
                      wchar [] lpClassName,
                      wchar [] lpWindowName,
                      _DWORD dwStyle,
                      _HMENU hMenu)
     {
         digPlatformHWNDCreate (dwExStyle, lpClassName, lpWindowName,
dwStyle,
                     std.c.windows.windows.CW_USEDEFAULT,
 std.c.windows.windows.CW_USEDEFAULT,
 std.c.windows.windows.CW_USEDEFAULT,
 std.c.windows.windows.CW_USEDEFAULT,
                     parent () ? parent ().digPlatformHWND : (_HANDLE) 0,
hMenu, hinst, null);
     }

     void digPlatformCommand (int code, int id)
     {
     }

     bit digPlatformHScrollVisible = false;
     bit digPlatformVScrollVisible = false;
     _HCURSOR digPlatformCursor = (_HCURSOR) 0;
     bit digPlatformGridfitted = false;

     void digPlatformRecreate ()
     {
         SCROLLINFO vscroll, hscroll;
         bit vokay, hokay;
         bit hscrollVisibleOld = digPlatformHScrollVisible;
         bit vscrollVisibleOld = digPlatformVScrollVisible;

         vscroll.cbSize = vscroll.size;
         vscroll.fMask = SIF_ALL;
         vokay = (bit) GetScrollInfo (digPlatformHWND, SB_VERT, &vscroll);

         hscroll.cbSize = hscroll.size;
         hscroll.fMask = SIF_ALL;
         hokay = (bit) GetScrollInfo (digPlatformHWND, SB_HORZ, &hscroll);

         DestroyWindow (digPlatformHWND);
         delete digPlatformHWNDToControl [digPlatformHWND];
         digPlatformHWNDCreate (0, digPlatformClassName,
digPlatformCaption, digPlatformStyle, (_HANDLE) 0);
         digPlatformMoved ();
         childIterate (delegate void (Control child) {
child.digPlatformRecreate (); });
         if (vokay) SetScrollInfo (digPlatformHWND, SB_VERT, &vscroll,
true);
         if (hokay) SetScrollInfo (digPlatformHWND, SB_HORZ, &hscroll,
true);
         this.vscroll (vscrollVisibleOld);
         this.hscroll (hscrollVisibleOld);
     }

     static char [] digPlatformMessageNameBase (_UINT message)
     {
         switch (message)
         {
             case WM_ACTIVATE: return "WM_ACTIVATE";
             case WM_ACTIVATEAPP: return "WM_ACTIVATEAPP";
             case WM_CONTEXTMENU: return "WM_CONTEXTMENU";
             case WM_CREATE: return "WM_CREATE";
             case WM_CTLCOLORBTN: return "WM_CTLCOLORBTN";
             case WM_DESTROY: return "WM_DESTROY";
             case WM_ERASEBKGND: return "WM_ERASEBKGND";
             case WM_GETICON: return "WM_GETICON";
             case WM_GETMINMAXINFO: return "WM_GETMINMAXINFO";
             case WM_KEYDOWN: return "WM_KEYDOWN";
             case WM_KEYUP: return "WM_KEYUP";
             case WM_KILLFOCUS: return "WM_KILLFOCUS";
             case WM_LBUTTONDOWN: return "WM_LBUTTONDOWN";
             case WM_LBUTTONUP: return "WM_LBUTTONUP";
             case WM_MBUTTONDOWN: return "WM_MBUTTONDOWN";
             case WM_MBUTTONUP: return "WM_MBUTTONUP";
             case WM_MOUSEACTIVATE: return "WM_MOUSEACTIVATE";
             case WM_MOUSEMOVE: return "WM_MOUSEMOVE";
             case WM_MOUSEWHEEL: return "WM_MOUSEWHEEL";
             case WM_MOVE: return "WM_MOVE";
             case WM_NCACTIVATE: return "WM_NCACTIVATE";
             case WM_NCCALCSIZE: return "WM_NCCALCSIZE";
             case WM_NCCREATE: return "WM_NCCREATE";
             case WM_NCDESTROY: return "WM_NCDESTROY";
             case WM_NCHITTEST: return "WM_NCHITTEST";
             case WM_NCLBUTTONDOWN: return "WM_NCLBUTTONDOWN";
             case WM_NCMOUSEMOVE: return "WM_NCMOUSEMOVE";
             case WM_NCPAINT: return "WM_NCPAINT";
             case WM_PAINT: return "WM_PAINT";
             case WM_PARENTNOTIFY: return "WM_PARENTNOTIFY";
             case WM_RBUTTONDOWN: return "WM_RBUTTONDOWN";
             case WM_RBUTTONUP: return "WM_RBUTTONUP";
             case WM_SETCURSOR: return "WM_SETCURSOR";
             case WM_SETFOCUS: return "WM_SETFOCUS";
             case WM_SETTEXT: return "WM_SETTEXT";
             case WM_SHOWWINDOW: return "WM_SHOWWINDOW";
             case WM_SIZE: return "WM_SIZE";
             case WM_SYSCOMMAND: return "WM_SYSCOMMAND";
             case WM_WINDOWPOSCHANGED: return "WM_WINDOWPOSCHANGED";
             case WM_WINDOWPOSCHANGING: return "WM_WINDOWPOSCHANGING";
             default: return null;
         }
     }

     static char [] digPlatformMessageName (_UINT message)
     {
         char [] result;

         result = digPlatformMessageNameBase (message);
         if (result === null)
         {
             static char [16] buffer;

             std.c.stdio.sprintf (buffer, "(%d)", message);
             return buffer [0 .. std.string.strlen (buffer)];
         }
     }

     static _COLORREF digPlatformColorToCOLORREF (Color c)
     {
         return c.r | (c.g << 8) | (c.b << 16);
     }

     static Color digPlatformColorFromCOLORREF (_COLORREF r)
     {
         return AColor (r & 0xFF, (r >> 8) & 0xFF, (r >> 16) & 0xFF);
     }

     /* Get the window text, allocated. */
     char [] digPlatformGetText ()
     {
         int length = digPlatformGetTextLength ();
         char [] data = new char [length + 1];

         length = SendMessageA (digPlatformHWND, WM_GETTEXT, data.length,
(_LPARAM) (char *) data);
         return data [0 .. length];
     }

     /* Get the length of the text in the window in characters. */
     int digPlatformGetTextLength ()
     {
         return SendMessageA (digPlatformHWND, WM_GETTEXTLENGTH, 0, 0);
     }

     /* Set the text of the window. */
     void digPlatformSetText (char [] text)
     {
         char *ztext = std.string.toStringz (text);
         char [1] empty;

         if (ztext == null)
             ztext = empty;
         SendMessageA (digPlatformHWND, WM_SETTEXT, 0, (_LPARAM) ztext);
     }

 /+
 #endif
 +/
 };
Dec 09 2003