source: trunk/dll/notify.c@ 1211

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

Ticket 187: Move data declarations/definitions out of fm3dll.h

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