source: trunk/dll/notify.c@ 1038

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

More fortify cleanup

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