source: trunk/dll/notify.c@ 1395

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

Allow user to turn off alert and/or error beeps in settings notebook. Ticket 341 Move repeated strings to PCSZs. Ticket 6 Add *DateFormat functions to format dates based on locale Ticket 28 Eliminate Win_Error2 by moving function names to PCSZs used in Win_Error Ticket 6

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