source: trunk/dll/notify.c@ 1036

Last change on this file since 1036 was 1009, checked in by Steven Levine, 17 years ago

Add xfree xstrdup Fortify support
Add MT capable Fortify scope logic

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