source: trunk/dll/notify.c@ 1163

Last change on this file since 1163 was 1163, checked in by John Small, 17 years ago

Ticket 187: Draft 1: Functions only

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