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