source: trunk/dll/notify.c@ 1188

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

Ticket 187: Draft 2: Move remaining function declarations

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