source: trunk/dll/notify.c@ 1225

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

Ticket 187: Moved typedef's and some #define's from fm3dll.h

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