source: trunk/dll/notify.c@ 1047

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

Minor code cleanup

  • 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 1047 2008-07-06 23:43:17Z 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 16 Apr 08 SHL Comment and clean up logic
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 "fm3dlg.h"
32#include "fm3str.h"
33#include "errutil.h" // Dos_Error...
34#include "strutil.h" // GetPString
35#include "fm3dll.h"
36#include "fortify.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 free(p);
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 free((CHAR *)mp2);
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 free((CHAR *)mp2);
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# ifdef FORTIFY
435 Fortify_EnterScope();
436# endif
437 if (hab) {
438 HMQ hmq = WinCreateMsgQueue(hab, 0);
439 if (hmq) {
440 if (!hwndNotify)
441 WinDlgBox(HWND_DESKTOP,
442 HWND_DESKTOP,
443 NoteWndProc, FM3ModHandle, NOTE_FRAME, (CHAR *)args);
444 WinDestroyMsgQueue(hmq);
445 }
446 WinTerminate(hab);
447 }
448# ifdef FORTIFY
449 Fortify_LeaveScope();
450# endif
451}
452
453/**
454 * Start thread notes dialog window thread
455 */
456
457VOID StartNotes(CHAR * note)
458{
459 if (!hwndNotify) {
460 if (_beginthread(NoteThread, NULL, 65536, (PVOID) note) == -1)
461 Runtime_Error2(pszSrcFile, __LINE__, IDS_COULDNTSTARTTHREADTEXT);
462 else {
463 USHORT i;
464 for (i = 0; !hwndNotify && i < 10; i++)
465 DosSleep(10);
466 if (!hwndNotify)
467 Runtime_Error(pszSrcFile, __LINE__, "Can not create Notify window");
468 }
469 }
470}
471
472/**
473 * Add note to thread notes window or popup status window
474 */
475
476BOOL AddNote(CHAR * note)
477{
478 CHAR *s, *p;
479 BOOL once = FALSE, ret = FALSE;
480
481 if ((fThreadNotes || hwndNotify) && note && *note) {
482 p = note;
483 while (*p == ' ')
484 p++;
485 if (*p) {
486 if (!hwndNotify) {
487 fThreadNotes = FALSE;
488 StartNotes(NULL);
489 }
490 if (hwndNotify) {
491 s = xmalloc(strlen(p) + 14, pszSrcFile, __LINE__);
492 if (s) {
493 sprintf(s, "%08lx %s", _threadid, p);
494 while (!once) {
495 if ((SHORT) WinSendDlgItemMsg(hwndNotify,
496 NOTE_LISTBOX,
497 LM_INSERTITEM,
498 MPFROM2SHORT(LIT_END, 0),
499 MPFROMP(s)) >= 0) {
500 ret = TRUE;
501 PostMsg(hwndNotify, UM_NOTIFY, MPVOID, MPVOID);
502 break;
503 }
504 PostMsg(hwndNotify, UM_CONTAINER_FILLED, MPVOID, MPVOID);
505 once = TRUE;
506 }
507 free(s);
508 }
509 }
510 }
511 }
512 return ret;
513}
514
515/**
516 * Close thread notes window
517 */
518
519VOID EndNote(VOID)
520{
521 if (hwndNotify)
522 if (!PostMsg(hwndNotify, WM_CLOSE, MPVOID, MPVOID))
523 WinSendMsg(hwndNotify, WM_CLOSE, MPVOID, MPVOID);
524}
525
526/**
527 * Pop up thread notes window
528 */
529
530VOID ShowNote(VOID)
531{
532 if (!hwndNotify)
533 StartNotes(NULL);
534 if (hwndNotify)
535 PostMsg(hwndNotify, UM_SHOWME, MPVOID, MPVOID);
536}
537
538/**
539 * Hide thread notes window
540 */
541
542VOID HideNote(VOID)
543{
544 if (hwndNotify)
545 WinSetWindowPos(hwndNotify,
546 HWND_BOTTOM,
547 0,
548 0, 0, 0, SWP_MINIMIZE | SWP_ZORDER | SWP_FOCUSDEACTIVATE);
549}
550
551#pragma alloc_text(NOTIFY,Notify,NotifyWndProc,StartNotify,NotifyError)
552#pragma alloc_text(NOTIFY2,AddNote,NoteThread,NoteWndProc)
553#pragma alloc_text(NOTIFY3,StartNotes,EndNote,HideNote,ShowNote)
Note: See TracBrowser for help on using the repository browser.