source: trunk/dll/notify.c@ 1038

Last change on this file since 1038 was 1038, checked in by Gregg Young, 17 years ago

More fortify cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1
2/***********************************************************************
3
4 $Id: notify.c 1038 2008-07-04 20:33:59Z gyoung $
5
6 Thread notes window and popup notification status line
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2006, 2008 Steven H.Levine
10
11 17 Jul 06 SHL Use Win_Error
12 22 Jul 06 SHL Check more run time errors
13 30 Mar 07 GKY Remove GetPString for window class names
14 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
15 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
16 29 Feb 08 GKY Use xfree where appropriate
17 16 Apr 08 SHL Comment and clean up logic
18
19***********************************************************************/
20
21#include <stdlib.h>
22#include <string.h>
23#include <ctype.h>
24#include <stddef.h> // _threadid
25#include <process.h> // _beginthread
26
27#define INCL_DOS
28#define INCL_WIN
29#define INCL_GPI
30#define INCL_LONGLONG // dircnrs.h
31
32#include "fm3dlg.h"
33#include "fm3str.h"
34#include "errutil.h" // Dos_Error...
35#include "strutil.h" // GetPString
36#include "fm3dll.h"
37#include "fortify.h"
38
39#pragma data_seg(DATA1)
40
41static PSZ pszSrcFile = __FILE__;
42
43static volatile HWND hwndNotify; // 16 Apr 08 SHL
44
45/**
46 * Popup notification message window procedure
47 * Display timed message over status line
48 */
49
50MRESULT EXPENTRY NotifyWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
51{
52 static ULONG showing = 0;
53
54 switch (msg) {
55 case WM_CREATE:
56 showing++;
57 {
58 MRESULT rc = PFNWPStatic(hwnd, msg, mp1, mp2);
59
60 if (!WinStartTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_TIMER2, 5000)) {
61 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "WinStartTimer");
62 WinDestroyWindow(hwnd);
63 }
64 else {
65
66 RGB2 rgb2F, rgb2;
67
68 memset(&rgb2F, 0, sizeof(RGB2));
69 rgb2F.bRed = (BYTE)65;
70 rgb2.bRed = rgb2.bGreen = rgb2.bBlue = (BYTE)255;
71 rgb2.fcOptions = 0;
72 SetPresParams(hwnd, &rgb2, &rgb2F, &rgb2, GetPString(IDS_8HELVTEXT));
73 if (hwndMain) {
74 if (hwndStatus)
75 WinShowWindow(hwndStatus, FALSE);
76 if (hwndStatus2)
77 WinShowWindow(hwndStatus2, FALSE);
78 }
79 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
80 }
81 return rc;
82 }
83
84 case UM_SETUP:
85 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER | SWP_SHOW);
86 WinInvalidateRect(hwnd, NULL, FALSE);
87 return 0;
88
89 case WM_SETFOCUS:
90 if (mp2)
91 PostMsg(hwnd, UM_REPLACEFOCUS, mp1, MPVOID);
92 break;
93
94 case UM_REPLACEFOCUS:
95 if (mp1)
96 WinSetFocus(HWND_DESKTOP, (HWND) mp1);
97 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
98 return 0;
99
100 case WM_PAINT:
101 {
102 SWP swp;
103 POINTL ptl;
104
105 MRESULT mr = PFNWPStatic(hwnd, msg, mp1, mp2);
106 HPS hps = WinGetPS(hwnd);
107 if (hps) {
108 if (WinQueryWindowPos(hwnd, &swp)) {
109 ptl.x = 0;
110 ptl.y = 0;
111 GpiMove(hps, &ptl);
112 GpiSetColor(hps, CLR_RED);
113 ptl.x = swp.cx - 1;
114 ptl.y = swp.cy - 1;
115 GpiBox(hps, DRO_OUTLINE, &ptl, 2, 2);
116 }
117 WinReleasePS(hwnd);
118 }
119 return mr;
120 }
121
122 case WM_BUTTON1DOWN:
123 case WM_BUTTON2DOWN:
124 case WM_BUTTON3DOWN:
125 case WM_TIMER:
126 case WM_CLOSE:
127 WinStopTimer(WinQueryAnchorBlock(hwnd), hwnd, ID_TIMER2);
128 WinDestroyWindow(hwnd);
129 return 0;
130
131 case WM_DESTROY:
132 showing--;
133 if (!showing && hwndMain) {
134 if (hwndStatus)
135 WinShowWindow(hwndStatus, TRUE);
136 if (hwndStatus2)
137 WinShowWindow(hwndStatus2, TRUE);
138 }
139 break;
140 }
141 return PFNWPStatic(hwnd, msg, mp1, mp2);
142}
143
144/**
145 * Display timed notification window over status line
146 */
147
148HWND DoNotify(char *str)
149{
150 char *p;
151 HWND hwnd = (HWND) 0, hwndP;
152 LONG x, y, cx, cy;
153 SWP swp, swpS, swpS2;
154 static USHORT id = NOTE_FRAME;
155
156 if (str && *str) {
157 // figure out what size the window should be and where it should be
158 hwndP = hwndMain ? WinQueryWindow(hwndMain, QW_PARENT) : HWND_DESKTOP;
159 WinQueryWindowPos(hwndP, &swp);
160 if (hwndStatus)
161 WinQueryWindowPos(hwndStatus, &swpS);
162 if (hwndStatus2)
163 WinQueryWindowPos(hwndStatus2, &swpS2);
164 x = hwndMain ? (hwndStatus ? swpS.x - 1 :
165 WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER)) : 0;
166 y = hwndMain ? (hwndStatus ? swpS.y - 1 :
167 WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER)) : 0;
168 if (hwndMain && hwndStatus) {
169 if (hwndStatus2)
170 cx = swpS2.cx + swpS.cx + 8;
171 else
172 cx = swpS.cx + 6;
173 }
174 else
175 cx = (swp.cx - ((x * 2) + 4));
176 cy = hwndMain ? (hwndStatus ? swpS.cy + 2 : 28) : 28;
177
178 // pretty-up the note by putting on a leading space
179 if (*str != ' ') {
180 p = xmalloc(strlen(str) + 2, pszSrcFile, __LINE__);
181 if (!p)
182 p = str;
183 else {
184 strcpy(p + 1, str);
185 *p = ' ';
186 }
187 }
188 else
189 p = str;
190
191 hwnd = WinCreateWindow(hwndP,
192 WC_ERRORWND,
193 p,
194 SS_TEXT | DT_LEFT | DT_VCENTER | WS_VISIBLE,
195 x, y, cx, cy, hwndP, HWND_TOP, id++, NULL, NULL);
196 if (!hwndP)
197 Win_Error2(hwndP, hwndP, pszSrcFile, __LINE__, IDS_WINCREATEWINDOW);
198
199 if (p != str)
200 xfree(p, pszSrcFile, __LINE__);
201 if (id > NOTE_MAX)
202 id = NOTE_FRAME;
203 }
204
205 AddNote(str);
206
207 return hwnd;
208}
209
210/**
211 * Add message to thread notes window
212 */
213
214HWND Notify(char *str)
215{
216 return (HWND)WinSendMsg(MainObjectHwnd, UM_NOTIFY, MPFROMP(str), MPVOID);
217}
218
219/**
220 * Add error message to thread notes window
221 */
222
223VOID NotifyError(CHAR * filename, APIRET status)
224{
225 CHAR errortext[512];
226
227 if (!filename)
228 return;
229 sprintf(errortext, GetPString(IDS_ERRORACCESSTEXT), status, filename);
230 if (toupper(*filename) > 'B') {
231 if (status == 21)
232 strcat(errortext, GetPString(IDS_EMPTYREMOVETEXT));
233 else if (status == 27)
234 strcat(errortext, GetPString(IDS_CDMUSICTEXT));
235 else if (status == 19)
236 strcat(errortext, GetPString(IDS_WRITEPROTECTTEXT));
237 else if (status == 108)
238 strcat(errortext, GetPString(IDS_DRIVELOCKEDTEXT));
239 }
240 else {
241 if (status == 21)
242 strcat(errortext, GetPString(IDS_EMPTYFLOPPYTEXT));
243 else if (status == 27)
244 strcat(errortext, GetPString(IDS_UNFORMATEDTEXT));
245 else if (status == 107)
246 sprintf(&errortext[strlen(errortext)],
247 GetPString(IDS_PHANTOMTEXT), toupper(*filename));
248 else if (status == 19)
249 strcat(errortext, GetPString(IDS_DISKWRITEPROTEXTTEXT));
250 else if (status == 108)
251 strcat(errortext, GetPString(IDS_DISKLOCKEDTEXT));
252 }
253 DosBeep(250, 10);
254 DosBeep(500, 10);
255 DosBeep(250, 10);
256 DosBeep(500, 10);
257 Notify(errortext);
258}
259
260/**
261 * Thread notes dialog window dialog procedure
262 */
263
264MRESULT EXPENTRY NoteWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
265{
266 static HPOINTER hptrIcon = (HPOINTER) 0;
267
268 switch (msg) {
269 case WM_INITDLG:
270 if (hwndNotify != (HWND)0) {
271 // Already have notes dialog - pass message on
272 if (mp2) {
273 WinSendDlgItemMsg(hwndNotify,
274 NOTE_LISTBOX,
275 LM_INSERTITEM, MPFROM2SHORT(LIT_END, 0), mp2);
276 PostMsg(hwndNotify, UM_NOTIFY, MPVOID, MPVOID);
277 xfree((CHAR *)mp2, pszSrcFile, __LINE__);
278 }
279 WinDismissDlg(hwnd, 0);
280 break;
281 }
282 hwndNotify = hwnd;
283 fThreadNotes = FALSE;
284 // Remember showing
285 {
286 BOOL dummy = TRUE;
287 PrfWriteProfileData(fmprof,
288 FM3Str, "ThreadNotes", &dummy, sizeof(BOOL));
289 }
290 if (mp2) {
291 WinSendDlgItemMsg(hwnd,
292 NOTE_LISTBOX,
293 LM_INSERTITEM, MPFROM2SHORT(LIT_END, 0), mp2);
294 xfree((CHAR *)mp2, pszSrcFile, __LINE__);
295 }
296
297 {
298 // Return focus
299 HWND hwndActive = WinQueryActiveWindow(HWND_DESKTOP);
300 PostMsg(hwnd, UM_FOCUSME, MPFROMLONG(hwndActive), MPVOID);
301 }
302
303 hptrIcon = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, NOTE_FRAME);
304 if (hptrIcon)
305 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(hptrIcon), MPFROMLONG(0L));
306 break;
307
308 case UM_FOCUSME:
309 {
310 ULONG size = sizeof(SWP),
311 fl = SWP_ZORDER | SWP_FOCUSDEACTIVATE | SWP_SHOW;
312 SWP swp;
313
314 if (PrfQueryProfileData(fmprof,
315 FM3Str, "NoteWndSwp", (PVOID) & swp, &size)) {
316 if (swp.fl & (SWP_HIDE | SWP_MINIMIZE)) {
317 fl |= SWP_MINIMIZE;
318 fl &= (~SWP_SHOW);
319 }
320 else
321 fl |= (SWP_MOVE | SWP_SIZE);
322 }
323 WinSetWindowPos(hwnd, HWND_BOTTOM, swp.x, swp.y, swp.cx, swp.cy, fl);
324 if (fl & SWP_MINIMIZE) {
325 WinSetWindowUShort(hwnd, QWS_XRESTORE, (USHORT) swp.x);
326 WinSetWindowUShort(hwnd, QWS_CXRESTORE, (USHORT) swp.cx);
327 WinSetWindowUShort(hwnd, QWS_YRESTORE, (USHORT) swp.y);
328 WinSetWindowUShort(hwnd, QWS_CYRESTORE, (USHORT) swp.cy);
329 }
330 }
331 if (mp1)
332 WinSetActiveWindow(HWND_DESKTOP, (HWND) mp1);
333 return 0;
334
335 case UM_STRETCH:
336 {
337 SWP swp;
338 LONG titl, szbx, szby;
339
340 WinQueryWindowPos(hwnd, &swp);
341 if (!(swp.fl & (SWP_MINIMIZE | SWP_HIDE))) {
342 szbx = SysVal(SV_CXSIZEBORDER);
343 szby = SysVal(SV_CYSIZEBORDER);
344 titl = SysVal(SV_CYTITLEBAR);
345 WinSetWindowPos(WinWindowFromID(hwnd, NOTE_LISTBOX),
346 HWND_TOP,
347 szbx,
348 szby,
349 swp.cx - (szbx * 2L),
350 (swp.cy - titl) - (szby * 2L), SWP_MOVE | SWP_SIZE);
351 }
352 if (!(swp.fl & SWP_MAXIMIZE)) {
353 if (swp.fl & (SWP_MINIMIZE | SWP_HIDE)) {
354 swp.x = WinQueryWindowUShort(hwnd, QWS_XRESTORE);
355 swp.y = WinQueryWindowUShort(hwnd, QWS_YRESTORE);
356 swp.cx = WinQueryWindowUShort(hwnd, QWS_CXRESTORE);
357 swp.cy = WinQueryWindowUShort(hwnd, QWS_CYRESTORE);
358 }
359 PrfWriteProfileData(fmprof,
360 FM3Str, "NoteWndSwp", (PVOID) & swp, sizeof(SWP));
361 }
362 }
363 return 0;
364
365 case WM_ADJUSTWINDOWPOS:
366 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
367 break;
368
369 case UM_CONTAINER_FILLED:
370 {
371 SHORT y;
372 SHORT x = (SHORT)WinSendDlgItemMsg(hwnd,
373 NOTE_LISTBOX,
374 LM_QUERYITEMCOUNT, MPVOID, MPVOID);
375 if (x > 60) {
376 for (y = 0; y < x - 50; y++) {
377 WinSendDlgItemMsg(hwnd,
378 NOTE_LISTBOX,
379 LM_DELETEITEM, MPFROMSHORT(y), MPVOID);
380 }
381 }
382 }
383 return 0;
384
385 case UM_NOTIFY:
386 {
387 SHORT x = (SHORT) WinSendDlgItemMsg(hwnd,
388 NOTE_LISTBOX,
389 LM_QUERYITEMCOUNT, MPVOID, MPVOID);
390 if (x > 0)
391 WinSendDlgItemMsg(hwnd,
392 NOTE_LISTBOX,
393 LM_SETTOPINDEX, MPFROMSHORT(x), MPVOID);
394 }
395 return 0;
396
397 case UM_SHOWME:
398 WinSetWindowPos(hwnd,
399 HWND_TOP,
400 0,
401 0,
402 0, 0, SWP_SHOW | SWP_RESTORE | SWP_ZORDER | SWP_ACTIVATE);
403 return 0;
404
405 case WM_COMMAND:
406 return 0;
407
408 case WM_CLOSE:
409 WinDismissDlg(hwnd, 0);
410 return 0;
411
412 case WM_DESTROY:
413 if (hwndNotify == hwnd) {
414 fThreadNotes = FALSE;
415 PrfWriteProfileData(fmprof,
416 FM3Str, "ThreadNotes", &fThreadNotes, sizeof(BOOL));
417 hwndNotify = (HWND) 0;
418 }
419 if (hptrIcon)
420 WinDestroyPointer(hptrIcon);
421 if (!PostMsg((HWND) 0, WM_QUIT, MPVOID, MPVOID))
422 WinSendMsg((HWND) 0, WM_QUIT, MPVOID, MPVOID);
423 break;
424 }
425 return WinDefDlgProc(hwnd, msg, mp1, mp2);
426}
427
428/**
429 * Thread notes dialog window thread
430 */
431
432static VOID NoteThread(VOID * args)
433{
434 HAB hab = WinInitialize(0);
435# ifdef FORTIFY
436 Fortify_EnterScope();
437# endif
438 if (hab) {
439 HMQ hmq = WinCreateMsgQueue(hab, 0);
440 if (hmq) {
441 if (!hwndNotify)
442 WinDlgBox(HWND_DESKTOP,
443 HWND_DESKTOP,
444 NoteWndProc, FM3ModHandle, NOTE_FRAME, (CHAR *)args);
445 WinDestroyMsgQueue(hmq);
446 }
447 WinTerminate(hab);
448 }
449# ifdef FORTIFY
450 Fortify_LeaveScope();
451# endif
452}
453
454/**
455 * Start thread notes dialog window thread
456 */
457
458VOID StartNotes(CHAR * note)
459{
460 if (!hwndNotify) {
461 if (_beginthread(NoteThread, NULL, 65536, (PVOID) note) == -1)
462 Runtime_Error2(pszSrcFile, __LINE__, IDS_COULDNTSTARTTHREADTEXT);
463 else {
464 USHORT i;
465 for (i = 0; !hwndNotify && i < 10; i++)
466 DosSleep(10);
467 if (!hwndNotify)
468 Runtime_Error(pszSrcFile, __LINE__, "Can not create Notify window");
469 }
470 }
471}
472
473/**
474 * Add note to thread notes window or popup status window
475 */
476
477BOOL AddNote(CHAR * note)
478{
479 CHAR *s, *p;
480 BOOL once = FALSE, ret = FALSE;
481
482 if ((fThreadNotes || hwndNotify) && note && *note) {
483 p = note;
484 while (*p == ' ')
485 p++;
486 if (*p) {
487 if (!hwndNotify) {
488 fThreadNotes = FALSE;
489 StartNotes(NULL);
490 }
491 if (hwndNotify) {
492 s = xmalloc(strlen(p) + 14, pszSrcFile, __LINE__);
493 if (s) {
494 sprintf(s, "%08lx %s", _threadid, p);
495 while (!once) {
496 if ((SHORT) WinSendDlgItemMsg(hwndNotify,
497 NOTE_LISTBOX,
498 LM_INSERTITEM,
499 MPFROM2SHORT(LIT_END, 0),
500 MPFROMP(s)) >= 0) {
501 ret = TRUE;
502 PostMsg(hwndNotify, UM_NOTIFY, MPVOID, MPVOID);
503 break;
504 }
505 PostMsg(hwndNotify, UM_CONTAINER_FILLED, MPVOID, MPVOID);
506 once = TRUE;
507 }
508 }
509 xfree(s, pszSrcFile, __LINE__);
510 }
511 }
512 }
513 return ret;
514}
515
516/**
517 * Close thread notes window
518 */
519
520VOID EndNote(VOID)
521{
522 if (hwndNotify)
523 if (!PostMsg(hwndNotify, WM_CLOSE, MPVOID, MPVOID))
524 WinSendMsg(hwndNotify, WM_CLOSE, MPVOID, MPVOID);
525}
526
527/**
528 * Pop up thread notes window
529 */
530
531VOID ShowNote(VOID)
532{
533 if (!hwndNotify)
534 StartNotes(NULL);
535 if (hwndNotify)
536 PostMsg(hwndNotify, UM_SHOWME, MPVOID, MPVOID);
537}
538
539/**
540 * Hide thread notes window
541 */
542
543VOID HideNote(VOID)
544{
545 if (hwndNotify)
546 WinSetWindowPos(hwndNotify,
547 HWND_BOTTOM,
548 0,
549 0, 0, 0, SWP_MINIMIZE | SWP_ZORDER | SWP_FOCUSDEACTIVATE);
550}
551
552#pragma alloc_text(NOTIFY,Notify,NotifyWndProc,StartNotify,NotifyError)
553#pragma alloc_text(NOTIFY2,AddNote,NoteThread,NoteWndProc)
554#pragma alloc_text(NOTIFY3,StartNotes,EndNote,HideNote,ShowNote)
Note: See TracBrowser for help on using the repository browser.