root/trunk/minwin/app.d

Revision 78, 6.6 kB (checked in by lindquist, 7 years ago)

replaced trunk with branches/bughunt

Line 
1 // Written in the D programming language.
2 /* MinWin Application structure
3  *
4  * An Application encapsulates the global state provided by
5  * the OS when starting the application and it manages the event queue.
6  *
7  * Written by Ben Hinkle and released to the public domain, as
8  * explained at http://creativecommons.org/licenses/publicdomain
9  * Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
10  */
11
12 module minwin.app;
13
14 private {
15     import minwin.logging;
16     import minwin.multidg;
17     import minwin.event;
18     import std.string;
19 }
20
21 version(MinWin32) {
22     private import minwin.mswindows;
23 }
24
25 extern (C) void gc_init();
26 extern (C) void gc_term();
27 extern (C) void _minit();
28 extern (C) void _moduleCtor();
29 extern (C) void _moduleUnitTests();
30 extern (C) int MinWinMain(Application* app);
31
32 const int NO_ID = -1;
33 class MinWinException : Exception {
34     int id = NO_ID;
35     this(char[] msg) {
36         super(msg);
37     }
38     this(char[] msg, int id) {
39         this.id = id;
40         if (id == NO_ID)
41             super(msg);
42         else
43             super(format("%s (error code %x)",msg,id));
44     }
45 }
46
47 // Assert a condition is true and if not throw an exception.
48 void sysAssert(bool passed, char[] msg, int id = 0) {
49     if (!passed) {
50         version (MinWin32) {
51             if (GetVersion() < 0x80_00_00_00 || id != 0) {
52                 throw new MinWinException(msg,id);
53             } else {
54                 throw new MinWinException(msg,GetLastError());
55             }
56         } else {
57             throw new MinWinException(msg,id);
58         }
59     }
60 }
61
62 Application gApp;
63
64 version (MinWin32) {
65
66     extern (Windows)
67     void MinWinIdleProc(HWND hWnd, uint msg, uint id, DWORD time) {
68         gApp.idleDelegate();
69     }
70
71     struct Application {
72
73         char[] rsrc(char[] id, char[] group = "strings") {
74             wchar[] wres;
75             char[] cres;
76             if (useWfuncs)
77                 wres.length = 64;
78             else
79                 cres.length = 64;
80             int len;
81             for (;;) {
82                 if (useWfuncs) {
83                     len = cast(int)LoadStringW(gApp.hInstance,toUTF16z(id),wres.ptr,wres.length);
84                     if (len < wres.length) break;
85                     else wres.length = 2*wres.length;
86                 }
87                 else {
88                     len = cast(int)LoadStringA(gApp.hInstance,toMBSz(id),cres.ptr,cres.length);
89                     if (len < cres.length) break;
90                     else cres.length = 2*cres.length;
91                 }
92             }
93             if (useWfuncs)
94                 return toUTF8(wres[0..len]);
95             else {
96                 return fromMBSz(cres[0..len].ptr);
97             }
98         }
99
100         char[][] cmdLineArgs(){
101             // TODO: parse cmd line args
102             return parsedCmdLineArgs;
103         }
104
105         MultiDelegate!() idleDelegate;
106
107         private uint fTimerID;
108         private uint fIdleTime;
109         uint idleTime() {
110             return fIdleTime;
111         }
112         void idleTime(uint t) { // time 0 means stop
113             fIdleTime = t;
114             if (fTimerID) {
115                 BOOL ok = KillTimer(null,fTimerID);
116                 sysAssert(ok != false, "Failed to kill existing timer");
117             }
118             if (t) {
119                 fTimerID = SetTimer(null,0,t,&MinWinIdleProc);
120                 sysAssert(fTimerID != 0, "Failed to set timer");
121             }
122         }
123
124         int enterEventLoop() {
125             while (nextEvent(&event)) {
126                 // TODO: check IsDialogMessage
127                 dispatchEvent(&event);
128             }
129             return 1;
130         }
131
132         void exitEventLoop() {
133             PostQuitMessage(0);
134         }
135
136         HINSTANCE hInstance;
137         HINSTANCE hPrevInstance;
138         LPSTR lpCmdLine;
139         char[][] parsedCmdLineArgs;
140         int nCmdShow;
141         Event event;
142     }
143
144     extern (Windows)
145     int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
146         /*{
147             INITCOMMONCONTROLSEX icc;
148             icc.dwSize = INITCOMMONCONTROLSEX.sizeof;
149             icc.dwICC = ICC_WIN95_CLASSES;
150             InitCommonControlsEx(&icc);
151         }*/
152        
153         int result;
154         gc_init();          // initialize garbage collector
155         _minit();           // initialize module constructor table
156
157         try
158         {
159             _moduleCtor();      // call module constructors
160             _moduleUnitTests(); // run unit tests (optional)
161
162             gApp.hInstance = hInstance;
163             gApp.hPrevInstance = hPrevInstance;
164             gApp.nCmdShow = nCmdShow;
165             version (LOG) log.writefln("about to enter MinWinMain");
166             result = MinWinMain(&gApp);
167             version (LOG) log.writefln("done with MinWinMain");
168         }
169
170         catch (Object o)        // catch any uncaught exceptions
171         {
172             MessageBoxX(null, o.toString(), "Error",MB_OK | MB_ICONEXCLAMATION);
173             result = 0;     // failed
174         }
175         version(LOG) log.close();
176         if (gApp.fTimerID) {
177             BOOL ok = KillTimer(null,gApp.fTimerID);
178             sysAssert(ok != false, "Failed to kill existing timer at exit");
179         }
180         gc_term();          // run finalizers; terminate garbage collector
181         return result;
182     }
183
184 } else version (GTK) {
185
186     private {
187         import minwin.gtk;
188         import std.string;
189         import std.file;
190     }
191
192     extern (C)
193     gboolean MinWinIdleProc(gpointer data) {
194         gApp.idleDelegate();
195         return true;
196     }
197
198     struct Application {
199
200         char[][] cmdLineArgs;
201
202         char[] rsrc(char[] id, char[] group = "strings") {
203             // TODO
204             return "";
205         }
206
207         char[] resourcePath;
208
209         int enterEventLoop() {
210             gtk_main();
211             return 1;
212         }
213
214         void exitEventLoop() {
215             gtk_main_quit();
216         }
217
218         MultiDelegate!() idleDelegate;
219         uint fIdleTime;
220         uint idleTime() {
221             return fIdleTime;
222         }
223
224         guint fTimerID;
225
226         static
227         void idleTime(uint t) {
228             gApp.fIdleTime = t;
229             if (gApp.fTimerID)
230                 g_source_remove(gApp.fTimerID);
231             if (t)
232                 gApp.fTimerID = g_timeout_add(t,&MinWinIdleProc,null);
233         }
234     }
235
236     int main(char[][] args) {
237         gApp.cmdLineArgs = args;
238
239         char*[] argv;
240         argv.length = args.length;
241         foreach (int n, char[] str; args) {
242             argv[n] = toStringz(str);
243         }
244         int argc = args.length;
245         char**argvp = argv.ptr;
246         gtk_init(&argc,&argvp);
247
248         int res = MinWinMain(&gApp);
249         version(LOG) log.close();
250         return res;
251     }
252 }
Note: See TracBrowser for help on using the browser.