source: trunk/dll/notify.c@ 1335

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

Ticket 26: Add exception handlers to all threads using xbeginthread

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