1 /*   ncbimsg.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name:  ncbimsg.c
27 *
28 * Author:  Gish, Kans, Ostell, Schuler
29 *
30 * Version Creation Date:   2/13/91
31 *
32 * $Revision: 6.15 $
33 *
34 * File Description:
35 *   	user alert and error messages
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * Date     Name        Description of modification
40 * -------  ----------  -----------------------------------------------------
41 * 2/13/91  Kans        Now only used for non-Vibrant versions
42 * 09-19-91 Schuler     Added LIBCALL to Nlm_Beep()
43 * 09-20-91 Schuler     Include <conio.h> for getche() prototype
44 * 04-15-93 Schuler     Changed _cdecl to LIBCALL
45 * 05-28-93 Schuler     New function: SetMonitorHook()
46 * 06-06-93 Schuler     Added code to set/check magic_value for Monitors
47 * 01-13-94 Schuler     Converted ErrPost to ErrPostEx
48 * 01-13-94 Schuler     Added SetMsgHook and SetBeepHook
49 * 01-31-94 Schuler     Modified Message and _DefMessageHook (see below)
50 * 02-07-94 Schuler     Added element to _sev_code[] array for SEV_NONE
51 * 06-29-94 Schuler     Moved VSPRINTF macros to corepriv.h
52 * 06-07-95 Epstein     Change UNIX's GetOneChar() to burn fewer CPU cycles
53 * 07-19-95 Epstein     Bug fix to previous GetOneChar() so that user's
54 *                      input will be read properly.
55 *
56 * $Log: ncbimsg.c,v $
57 * Revision 6.15  2009/08/14 18:14:35  lavr
58 * Heed a warning
59 *
60 * Revision 6.14  2009/08/14 18:01:09  lavr
61 * Use {Get|Set}ProgramName()
62 *
63 * Revision 6.13  2008/04/04 20:36:46  kans
64 * cast MessageBox to (MsgAnswer) in Windows version to silence CodeWarrior warning
65 *
66 * Revision 6.12  2006/12/07 14:13:56  lavr
67 * #include <stdio.h> just in case for *_FILENO macros
68 *
69 * Revision 6.11  2006/12/07 14:13:02  lavr
70 * Add checks for whether the message device is a terminal (UNIX)
71 *
72 * Revision 6.10  2002/06/17 15:07:01  ivanov
73 * Added fix for BeOS platform in GetOneChar
74 *
75 * Revision 6.9  2000/08/28 18:46:24  vakatov
76 * Made internal hooks "static" and "C" -- to pass C++ compilation
77 *
78 * Revision 6.8  1999/10/01 14:41:40  kans
79 * added SEV_REJECT between SEV_ERROR and SEV_FATAL
80 *
81 * Revision 6.7  1999/08/31 21:36:25  vakatov
82 * Nlm_Message(), Nlm_MsgAlert() -- pre-save the temporary "scratch_str"
83 * buffer to avoid its overriding on calling the "ncbierr.c"-related code
84 *
85 * Revision 6.6  1999/08/23 19:16:08  vakatov
86 * Nlm_Message():  handle MSG_FATAL as SEV_MAX (was SEV_FATAL)
87 *
88 * Revision 6.5  1998/08/24 17:42:01  kans
89 * fixed old style function definition warnings
90 *
91 * Revision 6.4  1998/06/11 21:02:29  shavirin
92 * Fixed few warnings
93 *
94 * Revision 6.3  1997/11/26 21:26:23  vakatov
95 * Fixed errors and warnings issued by C and C++ (GNU and Sun) compilers
96 *
97 * Revision 6.2  1997/10/29 02:44:04  vakatov
98 * Type castings to pass through the C++ compiler
99 *
100 * Revision 6.1  1997/09/10 21:35:30  vakatov
101 * [OS_MSWIN] _DefMessageHook(): Removed extraneous AbnormalExit()
102 *
103 * Revision 6.0  1997/08/25 18:16:51  madden
104 * Revision changed to 6.0
105 *
106 * Revision 5.7  1997/07/22 19:11:39  vakatov
107 * Separated Main() from GetArg[svc]() functions;  [WIN_MSWIN] converged
108 * console and GUI libraries; [for WIN32-DLL] encapsulated global variables
109 *
110 * Revision 5.6  1997/07/15 16:57:08  vakatov
111 * Nlm_Message() -- assign "ans" to ANS_NONE if no message(0 or "\0") posted
112 *
113 * Revision 5.5  1997/01/27 18:10:24  shavirin
114 * Removed bug in function GetOneChar()
115 *
116  * Revision 5.4  1996/12/03  21:48:33  vakatov
117  * Adopted for 32-bit MS-Windows DLLs
118  *
119  * Revision 5.3  1996/11/25  19:04:58  vakatov
120  * Made 'sProgramName' WIN_MSWIN-only
121  *
122  * Revision 5.2  1996/07/16  19:57:02  vakatov
123  * VSPRINTF macros has been replaced by the TSPRINTF macros in the
124  * code responsible for the error message composing -- in order to
125  * avoid memory limits overrun when printing the messages (by
126  * the means of function "vsprintf()") to a memory-located string.
127  * The application name is added as the message caption.
128  * Added ReleaseAppMsgInfo() function to clean dynamically allocated
129  * memory used by the message posing routines;  +some casting
130  *
131  * Revision 5.1  1996/07/05  16:26:10  kans
132  * changed MonitorXXNew functions to MonitorXXXNewEx, with new hasCancelBtn
133  * parameter, defined old functions to call new ones with hasCancelBtn TRUE.
134  *
135  * Revision 5.0  1996/05/28  13:18:57  ostell
136  * Set to revision 5.0
137  *
138  * Revision 4.0  1995/07/26  13:46:50  ostell
139  * force revision to 4.0
140  *
141  * Revision 2.30  1995/07/19  17:48:06  epstein
142  * bug fix to GetOneChar() so that a non-null input string will be read correctly
143  *
144  * Revision 2.29  1995/07/05  14:22:37  kans
145  * move #include <sys/select.h> to ncbilcl.r6k
146  *
147  * Revision 2.28  1995/06/07  15:13:22  epstein
148  * re-add Kans's changes to permit cancelling of Monitors (changes were erroneously removed by Epstein)
149  *
150  * Revision 2.26  95/06/05  18:28:32  kans
151  * *** empty log message ***
152  *
153  * Revision 2.25  1995/05/31  20:34:06  ostell
154  * made the WIN_DUMB default MsgAlertStr case insensitive for responses
155  *
156  * Revision 2.24  1995/05/15  18:45:58  ostell
157  * added Log line
158  *
159 *
160 *
161 * ==========================================================================
162 */
163 
164 static char *_filename = __FILE__;
165 #define THIS_FILE _filename
166 
167 #include "corepriv.h"
168 #include <tsprintf.h>
169 #if defined(OS_UNIX)
170 #  include <stdio.h>
171 #  include <unistd.h>
172 #endif
173 
174 #ifdef __cplusplus
175 extern "C" {
176 #endif
177 
178     static MsgAnswer PASCAL _DefMessageHook
179     (MsgKey key, ErrSev sev, const char *caption, const char *message);
180 
181     static void PASCAL _DefBeepHook(void);
182 
183     static int PASCAL _DefMonitorHook(MonitorPtr pMon, MonCode code);
184 
185 #ifdef __cplusplus
186 } /* extern "C" */
187 #endif
188 
189 
190 
191 /*************************************************************************\
192 |                    INSTANCE-SPECIFIC INFO STRUCTURE                     |
193 \*************************************************************************/
194 
195 typedef struct AppMsgInfo
196 {
197 	MessageHook hookMessage;
198 	BeepHook hookBeep;
199 	MonitorHook hookMonitor;
200 }
201 AppMsgInfo;
202 
203 static char * _szPropKey = "_AppMsgInfo";
204 
205 
ReleaseAppMsgInfo(void)206 extern void ReleaseAppMsgInfo( void )
207 {
208   AppMsgInfo *info = (AppMsgInfo *)GetAppProperty( _szPropKey );
209 
210   if (info == NULL)
211     return;
212 
213   Nlm_MemFree( info );
214   RemoveAppProperty( _szPropKey );
215 }
216 
217 
GetAppMsgInfo(void)218 static AppMsgInfo * GetAppMsgInfo (void)
219 
220 {
221 	AppMsgInfo *info = (AppMsgInfo*) GetAppProperty(_szPropKey);
222 
223 	if (info == NULL)
224 	{
225 		info = (AppMsgInfo*) MemGet(sizeof(struct AppMsgInfo), TRUE);
226 		if (info == NULL)  AbnormalExit(1);
227 
228 		info->hookMessage = _DefMessageHook;
229 		info->hookBeep = _DefBeepHook;
230 		info->hookMonitor = _DefMonitorHook;
231 
232 		SetAppProperty(_szPropKey,(void*)info);
233 	}
234 	return info;
235 }
236 
237 
238 /*************************************************************************\
239 |                                ALERTS                                   |
240 \*************************************************************************/
241 #if defined(WIN_DUMB) || defined(OS_MAC)
242 static int GetOneChar PROTO((void));
243 #endif
244 
245 
246 /*-------------------------------------------------------------------------
247 * Message
248 *
249 *   Nlm_Message(key, format, ...)
250 *   	key = type of message
251 *   	MSG_ERROR 0 = non-fatal error
252 *   	MSG_FATAL 1 = fatal error
253 *   	MSG_OK    2 = OK
254 *   	MSG_RC    3 = Retry Cancel
255 *   	MSG_ARI   4 = Abort Retry Ignore
256 *   	MSG_YN    5 = Yes/No
257 *   	MSG_YNC   6 = Yes/No/Cancel
258 *       MSG_OKC   7 = OK/Cancel
259 *   	MSG_POST  8 = show message, no response required
260 *   	MSG_POSTERR 9 = beep, show message, no response required
261 *
262 *   reply is:
263 *   	0 = no
264 *   	1 = yes or ok or retry
265 *   	abort/cancel
266 *   	3 = ignore
267 *
268 *       #define ANS_NO 0
269 *       #define ANS_YES 1
270 *       #define ANS_OK 1
271 *       #define ANS_RETRY 1
272 *       #define ANS_ABORT 2
273 *       #define ANS_CANCEL 2
274 *       #define ANS_IGNORE 3
275 *
276 *
277 * MODIFICATIONS
278 * 01-31-94 Schuler   Added calls to Beep() and AbnormalExit() where
279 *                    appropriate instead of expecting the MessageHook
280 *                    to do this.
281 */
282 
283 
284 #ifdef VAR_ARGS
Nlm_Message(sevkey,fmt,va_alist)285 NLM_EXTERN MsgAnswer CDECL Nlm_Message (sevkey, fmt, va_alist)
286 Nlm_Int2 sevkey;
287 const char *fmt;
288 va_dcl
289 #else
290 NLM_EXTERN MsgAnswer CDECL Nlm_Message (Nlm_Int2 sevkey, const char *fmt, ...)
291 #endif
292 {
293   const char *caption = GetProgramName();
294   MsgKey key = KEY_OK;
295   ErrSev sev = SEV_INFO;
296   MsgAnswer ans;
297 
298   if (sevkey < KEY_other)
299     {
300       key = (MsgKey) sevkey;
301     }
302   else
303     {
304       switch (sevkey)
305         {
306         case MSG_ERROR :
307           Nlm_Beep();
308           sev = SEV_ERROR;
309           break;
310         case MSG_FATAL :
311           Nlm_Beep();
312           sev = SEV_MAX;
313           break;
314         case MSG_POSTERR :
315           Nlm_Beep();
316           sev = SEV_ERROR;
317           key = KEY_NONE;
318           break;
319         case MSG_POST :
320           key = KEY_NONE;
321           break;
322         }
323     }
324 
325   {{
326     const Nlm_Char PNTR scratch_str = NULL;
327     Nlm_Char PNTR message;
328     TSPRINTF(scratch_str, fmt);
329     message = Nlm_StringSave(scratch_str);
330     ans = message ? MsgAlertStr(key, sev, caption, message) : ANS_NONE;
331     Nlm_MemFree(message);
332   }}
333 
334   if (sevkey == MSG_FATAL)
335     AbnormalExit(1);
336 
337   return ans;
338 }
339 
340 
341 /*-------------------------------------------------------------------------
342 * MsgAlert  [Schuler, 01-13-94]
343 */
344 
345 #ifdef VAR_ARGS
Nlm_MsgAlert(key,sev,caption,fmt,va_alist)346 NLM_EXTERN MsgAnswer CDECL Nlm_MsgAlert (key, sev, caption, fmt, va_alist)
347 	MsgKey key;
348 	ErrSev sev;
349 	const char *caption;
350 	const char *fmt;
351 	va_dcl
352 #else
353 NLM_EXTERN MsgAnswer CDECL Nlm_MsgAlert (MsgKey key, ErrSev sev, const char *caption, const char *fmt, ...)
354 #endif
355 {
356   MsgAnswer ans;
357   const Nlm_Char PNTR scratch_str = NULL;
358   Nlm_Char PNTR message;
359   TSPRINTF(scratch_str, fmt);
360   message = Nlm_StringSave(scratch_str);
361   ans = message ? MsgAlertStr(key, sev, caption, message) : ANS_NONE;
362   Nlm_MemFree(message);
363   return ans;
364 }
365 
366 
367 /*-------------------------------------------------------------------------
368 * MsgAlertStr  [Schuler, 01-13-94]
369 */
Nlm_MsgAlertStr(MsgKey key,ErrSev sev,const char * caption,const char * message)370 NLM_EXTERN MsgAnswer LIBCALL Nlm_MsgAlertStr (MsgKey key, ErrSev sev,
371 			const char *caption, const char *message)
372 {
373 	MessageHook hook = GetAppMsgInfo()->hookMessage;
374 	return (*hook)(key,sev,caption,message);
375 }
376 
377 
378 /*-------------------------------------------------------------------------
379 * _DefMessageHook  [Schuler, 01-13-94, from the old Message]
380 *
381 * MODIFICATIONS:
382 * 01-24-94 Schuler   Check for NULL message string
383 * 01-31-94 Schuler   Removed Beep() and AbnormalExit() calls
384 */
385 
386 
_DefMessageHook(MsgKey key,ErrSev sev,const char * caption,const char * message)387 MsgAnswer PASCAL _DefMessageHook (MsgKey key, ErrSev sev,
388                                   const char *caption, const char *message)
389 {
390   MsgAnswer answer = ANS_NONE;
391 
392 #ifdef OS_MSWIN
393   if ( !Nlm_HasConsole )
394     {
395       static UINT _sev_code[SEV_MAX+1] = {
396         /* SEV_NONE */    MB_OK,
397         /* SEV_INFO */    MB_ICONINFORMATION,
398         /* SEV_WARNING */ MB_ICONASTERISK, /* same as MB_ICONINFORMATION */
399         /* SEV_ERROR */   MB_ICONEXCLAMATION,
400         /* SEV_REJECT */  MB_ICONEXCLAMATION,
401         /* SEV_FATAL */   MB_ICONHAND,
402         /* SEV_MAX */     MB_ICONHAND
403       };
404 
405       UINT flags = MB_TASKMODAL | _sev_code[(int)sev];
406       if (key > 0)
407         flags |= (key-1);
408       answer = (MsgAnswer) MessageBox(NULL,message,caption,flags);
409       return answer;
410     }
411 #endif
412 
413 #if defined(WIN_DUMB) || defined(OS_MAC)
414   {{
415     static char * _key_str [] = {
416       /* KEY_NONE */ "",
417       /* KEY_OK   */ "Hit Return  ",
418       /* KEY_OKC  */ "C = Cancel, Anything else = OK  ",
419       /* KEY_ARI  */ "A = abort, R = retry, I = ignore  ",
420       /* KEY_YNC  */ "Y = yes, N = no, C = cancel  ",
421       /* KEY_YN   */ "Y = yes, N = no  ",
422       /* KEY_RC   */ "R = retry, C = Cancel  "
423     };
424 
425     fflush(stdout);
426     fprintf(stderr,"[%s] %s\n",
427             caption ? caption : "NULL_Caption",
428             message ? message : "NULL_Message");
429 
430 #if defined(OS_UNIX)
431   if (isatty(STDIN_FILENO))
432 #endif
433     if (key>KEY_NONE && key<KEY_other)
434       {
435         int ch;
436 
437         /* show prompt */
438         fprintf(stderr,"%s  ",_key_str[(int)key]);
439 
440         /* set default value */
441         switch (key)
442           {
443           case KEY_OK:   case KEY_OKC:
444             answer = ANS_OK;     break;
445           case KEY_ARI:  case KEY_RC:
446             answer = ANS_RETRY;  break;
447           case KEY_YNC:  case KEY_YN:
448             answer = ANS_YES;    break;
449           case KEY_NONE: case KEY_other:
450             ASSERT_HARD ( FALSE );
451           }
452 
453         /* get response */
454         ch = GetOneChar();
455         ch = isalpha(ch) ? toupper(ch) : ch;
456         switch (ch)
457           {
458           case 'A' :
459             answer = ANS_ABORT;   break;
460           case 'C' :
461             answer = ANS_CANCEL;  break;
462           case 'I' :
463             answer = ANS_IGNORE;  break;
464           case 'N' :
465             answer = ANS_NO;      break;
466           }
467       }
468   }}
469 #endif /* WIN_DUMB || OS_MAC */
470 
471   return answer;
472 }
473 
474 /*-------------------------------------------------------------------------
475 * SetMessageHook  [Schuler, 01-13-94]
476 */
Nlm_SetMessageHook(MessageHook hook)477 NLM_EXTERN MessageHook LIBCALL Nlm_SetMessageHook (MessageHook hook)
478 {
479 	AppMsgInfo *info = GetAppMsgInfo();
480 	MessageHook hookPrev = info->hookMessage;
481 	if (hookPrev ==_DefMessageHook) hookPrev = NULL;
482 	info->hookMessage = (hook == NULL) ? _DefMessageHook : hook;
483 	return hookPrev;
484 }
485 
486 
487 #ifndef WIN16
488 /*-------------------------------------------------------------------------
489 * GetOneChar
490 *
491 * Gets a single character from the console
492 *
493 * MODIFICATIONS
494 * 01-13-94 Schuler   Simplified (old version preserved below)
495 */
496 #if defined(COMP_MSC) || defined(COMP_BOR)
497 #include <conio.h>		// for getche prototype
498 #endif
499 #ifdef OS_UNIX
500 #include <sys/time.h>
501 #include <sys/types.h>
502 #endif /* OS_UNIX */
503 
GetOneChar(void)504 static int GetOneChar (void)
505 {
506   int value = 0;
507 
508 #if defined(COMP_MSC) || defined(COMP_BOR)
509   value = getche();
510   putchar('\n');
511 
512 #else /* COMP_MSC || COMP_BOR */
513   int tvalue;
514   do
515     {
516 #ifdef OS_UNIX
517 #ifndef OS_UNIX_BEOS
518       if (value == 0)
519         {
520           fd_set rfds;
521 
522           FD_ZERO(&rfds);
523           FD_SET(0 /* standard input */, &rfds);
524           /* wait for some data so that we don't overwork the CPU */
525           while (select(1, &rfds, NULL, NULL, NULL) < 0)
526             {
527               sleep(1);
528             }
529         }
530 #endif
531 #endif /* OS_UNIX */
532       if((tvalue = getchar()) == EOF) {
533         return 0;
534       }
535 
536       if (! value)
537         value = tvalue;
538     } while (tvalue != '\n' && tvalue != '\r');
539 #endif /* else COMP_MSC || COMP_BOR */
540 
541   return value;
542 }
543 #endif /* !WIN16 */
544 
545 
546 /*************************************************************************\
547 |                                 BEEPS                                   |
548 \*************************************************************************/
549 
550 
551 /*-------------------------------------------------------------------------
552 * Beep
553 *
554 * MODIFICATIONS
555 * 01-13-94 Schuler   Modified to use BeepHook (old version preserved below)
556 */
557 
Nlm_Beep(void)558 NLM_EXTERN void LIBCALL  Nlm_Beep (void)
559 {
560 	BeepHook hook = GetAppMsgInfo()->hookBeep;
561 	(*hook)();
562 }
563 
564 
565 /*-------------------------------------------------------------------------
566 * _DefBeepHook  [Schuler, 01-13-94, from old Beep code]
567 *
568 * Default beep function
569 */
_DefBeepHook(void)570 void LIBCALLBACK _DefBeepHook (void)
571 {
572 #if   defined(OS_MAC)
573   SysBeep( 60 );
574 
575 #elif defined(OS_MSWIN)
576 #ifdef WIN32
577   Beep(60, 10);
578 #else
579   MessageBeep( 0 );
580 #endif
581 
582 #elif defined(OS_UNIX) || defined(OS_VMS)
583 #  if defined(OS_UNIX)
584   if (isatty(STDERR_FILENO))
585 #  endif
586     putc(7, stderr);
587 #endif
588 }
589 
590 /*-------------------------------------------------------------------------
591 * SetBeepHook  [Schuler, 01-13-94]
592 */
Nlm_SetBeepHook(BeepHook hook)593 NLM_EXTERN BeepHook LIBCALL Nlm_SetBeepHook (BeepHook hook)
594 {
595 	AppMsgInfo *info = GetAppMsgInfo();
596 	BeepHook hookPrev = info->hookBeep;
597 	if (hookPrev == (BeepHook)_DefBeepHook) hookPrev = NULL;
598 	info->hookBeep = (hook == NULL) ? _DefBeepHook : hook;
599 	return hookPrev;
600 }
601 
602 /*************************************************************************\
603 |                            PROGRESS MONITORS                            |
604 \*************************************************************************/
605 
606 #define MON_MAGIC_VALUE		1234
607 
608 
609 #define MON_SET_MAGIC(x)	(x)->magic_value = MON_MAGIC_VALUE
610 #define MON_IS_VALID(x)		((x)!=NULL  && (x)->magic_value==MON_MAGIC_VALUE)
611 
612 /**
613 #define MON_MAGIC(x)	   *((int*)((char*)(x) + sizeof(Monitor)))
614 #define MON_SET_MAGIC(x)   MON_MAGIC(x) = MON_MAGIC_VALUE
615 #define MON_IS_VALID(x)    (MON_MAGIC(x) == MON_MAGIC_VALUE)
616 ***/
617 
618 /*-------------------------------------------------------------------------
619 * MonitorIntNew
620 *
621 * Creates an integer range monitor
622 *
623 * MODIFICATIONS
624 * 05-27-93 Schuler   Support for applications hooking into monitors
625 * 06-03-93 Schuler   Use of magic number to detect invalid pointers
626 */
627 
Nlm_MonitorIntNewEx(Nlm_CharPtr title,Nlm_Int4 n1,Nlm_Int4 n2,Nlm_Boolean hasCancelBtn)628 NLM_EXTERN MonitorPtr LIBCALL Nlm_MonitorIntNewEx (Nlm_CharPtr title, Nlm_Int4 n1, Nlm_Int4 n2, Nlm_Boolean hasCancelBtn)
629 {
630 	AppMsgInfo *info = GetAppMsgInfo();
631 	Monitor *pMon = (Monitor*) MemNew(sizeof(Monitor));
632 
633 	if (pMon != NULL)
634 	{
635 		MON_SET_MAGIC(pMon);
636 		pMon->type = MonType_Int;
637 		pMon->strTitle = title ? StrSave(title) : 0;
638 		pMon->num1 = n1;
639 		pMon->num2 = n2;
640 		pMon->cancel = FALSE;
641 		pMon->hasCancelBtn = (int) hasCancelBtn;
642 		if (!(*info->hookMonitor)(pMon,MonCode_Create))
643 		{
644 		    MonitorFree(pMon);
645 		    /* only post an information message here; it is expected
646 		    	that the hook function would report the real reason
647 		    	that the monitor creation failed. */
648 			ErrPostEx(SEV_INFO,0,0,"Unable to create monitor");
649 			return NULL;
650 		}
651 	}
652 	return pMon;
653 }
654 
655 
656 /** TO DO:  define error codes for these conditions **/
657 static char * _invalid_mon = "invalid monitor pointer";
658 static char * _invalid_type = "invalid monitor type";
659 
660 /*-------------------------------------------------------------------------
661 * MonitorStrNew
662 *
663 * Creates a string monitor.  The len argument is the maximum string length.
664 *
665 * MODIFICATIONS
666 * 05-27-93 Schuler   Support for applications hooking into monitors
667 * 06-03-93 Schuler   Use of magic number to detect invalid pointers
668 */
669 
Nlm_MonitorStrNewEx(Nlm_CharPtr title,Nlm_Int2 len,Nlm_Boolean hasCancelBtn)670 NLM_EXTERN MonitorPtr LIBCALL Nlm_MonitorStrNewEx (Nlm_CharPtr title, Nlm_Int2 len, Nlm_Boolean hasCancelBtn)
671 {
672 	AppMsgInfo *info = GetAppMsgInfo();
673 	Monitor *pMon = (Monitor*) MemNew(sizeof(Monitor));
674 
675 	if (pMon != NULL)
676 	{
677 		MON_SET_MAGIC(pMon);
678 		pMon->type = MonType_Str;
679 		pMon->strTitle = title ? StrSave(title) : 0;
680 		pMon->num1 = MAX(0,MIN(len,72));
681 		pMon->cancel = FALSE;
682 		pMon->hasCancelBtn = (int) hasCancelBtn;
683 		(*info->hookMonitor)(pMon,MonCode_Create);
684 	}
685 	return pMon;
686 }
687 
688 
689 /*-------------------------------------------------------------------------
690 * MonitorStrValue
691 *
692 * Sets the string value for a string monitor.
693 *
694 * MODIFICATIONS
695 * 05-27-93 Schuler   Support for applications hooking into monitors
696 * 06-03-93 Schuler   Use of magic number to detect invalid pointers
697 * 06-03-93 Schuler   Check that monitor is correct type (MonType_Str)
698 */
699 
Nlm_MonitorStrValue(MonitorPtr pMon,Nlm_CharPtr sval)700 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_MonitorStrValue (MonitorPtr pMon, Nlm_CharPtr sval)
701 {
702 	AppMsgInfo *info = GetAppMsgInfo();
703 	if ( ! MON_IS_VALID(pMon) )
704 	{
705 		ErrPostEx(SEV_WARNING,0,0,"MonitorStrValue: %s",_invalid_mon);
706 		return FALSE;
707 	}
708 	if (pMon->type != MonType_Str)
709 	{
710 		ErrPostEx(SEV_WARNING,0,0,"MonitorStrValue: %s",_invalid_type);
711 		return (Nlm_Boolean)(!pMon->cancel);
712 	}
713 
714 	if (pMon->strValue) MemFree((void*)pMon->strValue);
715 	pMon->strValue = sval ? StrSave(sval) : 0;
716 	(*info->hookMonitor)(pMon,MonCode_StrValue);
717 	return (Nlm_Boolean)(!pMon->cancel);
718 }
719 
720 
721 /*-------------------------------------------------------------------------
722 * MonitorIntValue
723 *
724 * Sets the integer value for an integer range monitor
725 *
726 * MODIFICATIONS
727 * 05-27-93 Schuler   Support for applications hooking into monitors
728 * 06-03-93 Schuler   Use of magic number to detect invalid pointers
729 * 06-03-93 Schuler   Check that monitor is correct type (MonType_Int)
730 */
731 
Nlm_MonitorIntValue(MonitorPtr pMon,Nlm_Int4 ival)732 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_MonitorIntValue (MonitorPtr pMon, Nlm_Int4 ival)
733 {
734 	AppMsgInfo *info = GetAppMsgInfo();
735 	if ( !MON_IS_VALID(pMon) )
736 	{
737 		ErrPostEx(SEV_WARNING,0,0,"MonitorIntValue: %s",_invalid_mon);
738 		return FALSE;
739 	}
740 	if (pMon->type != MonType_Int)
741 	{
742 		ErrPostEx(SEV_WARNING,0,0,"MonitorStrValue: %s",_invalid_type);
743 		return (Nlm_Boolean)(!pMon->cancel);
744 	}
745 
746 	pMon->intValue = ival;
747 	(*info->hookMonitor)(pMon,MonCode_IntValue);
748 	return (Nlm_Boolean)(!pMon->cancel);
749 }
750 
751 
752 /*-------------------------------------------------------------------------
753 * MonitorFree
754 *
755 * MODIFICATIONS
756 * 05-27-93 Schuler   Support for applications hooking into monitors
757 * 06-03-93 Schuler   Use of magic number to detect invalid pointers
758 */
759 
Nlm_MonitorFree(MonitorPtr pMon)760 NLM_EXTERN MonitorPtr LIBCALL Nlm_MonitorFree (MonitorPtr pMon)
761 {
762 	AppMsgInfo *info = GetAppMsgInfo();
763 	if ( ! MON_IS_VALID(pMon) )
764 	{
765 		ErrPostEx(SEV_WARNING,0,0,"MonitorFree: %s",_invalid_mon);
766 	}
767 	else
768 	{
769 		(*info->hookMonitor)(pMon,MonCode_Destroy);
770 		MemFree((void*)pMon->strTitle);
771 		MemFree((void*)pMon->strValue);
772 		MemFree(pMon);
773 	}
774 	return NULL;
775 }
776 
777 
778 /*-------------------------------------------------------------------------
779 * SetMonitorHook	[Schuler, 05-27-93]
780 *
781 * Allows the application to set a hook procedure that will be called
782 * when a monitor is created, destroyed, or changes value.
783 *
784 * MODIFICATIONS
785 * 01-13-94 Schuler   No longer allows you to set the hook to NULL.
786 */
787 
Nlm_SetMonitorHook(MonitorHook hook)788 NLM_EXTERN MonitorHook LIBCALL Nlm_SetMonitorHook (MonitorHook hook)
789 {
790 	AppMsgInfo *info = GetAppMsgInfo();
791 	MonitorHook hookPrev = info->hookMonitor;
792 	if (hookPrev ==_DefMonitorHook) hookPrev = NULL;
793 	info->hookMonitor = (hook == NULL) ? _DefMonitorHook : hook;
794 	return hookPrev;
795 }
796 
797 
798 
799 /*-------------------------------------------------------------------------
800 *	_DefMonitorHook	[Schuler, 05-27-93]
801 *
802 *	IMPORTANT:  If your program is NOT a console-style (WIN_DUMB), you
803 *	should either (1) use Vibrant or (2) write a monitor hook function
804 *	and install it with SetMonitorHook.  Otherwise, the following
805 *	"do-nothing" function will be used and you will not see anything.
806 */
807 
808 #ifdef WIN16
809 
_DefMonitorHook(MonitorPtr pMon,MonCode code)810 int PASCAL _DefMonitorHook (MonitorPtr pMon, MonCode code)
811 {
812 	switch (code)
813 	{
814 		case MonCode_Create :
815 			TRACE("[%s]\n",pMon->strTitle);
816 			return TRUE;
817 		case MonCode_StrValue :
818 			TRACE("%s\n",pMon->strValue);
819 			break;
820 	}
821 	return 0;
822 }
823 
824 #else  /* WIN16 */
825 
826 static int  Dumb_MonCreate PROTO((MonitorPtr pMon));
827 static void Dumb_MonDestroy PROTO((MonitorPtr pMon));
828 static void Dumb_MonIntValue PROTO((MonitorPtr pMon));
829 static void Dumb_MonStrValue PROTO((MonitorPtr pMon));
830 
831 
832 
_DefMonitorHook(MonitorPtr pMon,MonCode code)833 int PASCAL _DefMonitorHook (MonitorPtr pMon, MonCode code)
834 {
835 	switch (code)
836 	{
837 		case MonCode_Create :
838 			return Dumb_MonCreate(pMon);
839 		case MonCode_Destroy :
840 			Dumb_MonDestroy(pMon);
841 			break;
842 		case MonCode_IntValue :
843 			Dumb_MonIntValue(pMon);
844 			break;
845 		case MonCode_StrValue :
846 			Dumb_MonStrValue(pMon);
847 			break;
848 	}
849 	return 0;
850 }
851 
Dumb_MonCreate(MonitorPtr pMon)852 static int Dumb_MonCreate (MonitorPtr pMon)
853 {
854 	char *buf;
855 
856 	if ((buf = (char *)Nlm_Calloc(81,1)) == NULL)
857             return FALSE;
858 	buf[80] = '\0';
859 	pMon->extra = buf;
860 
861 	fprintf(stderr, "\n\n<<< %s >>>\n", pMon->strTitle);
862 
863 	if (pMon->type == MonType_Int)
864 	{
865 		fprintf(stderr, "<-%-8ld--------------------%8ld->\n",pMon->num1,pMon->num2);
866 	}
867 	else
868 	{
869 		size_t len = (size_t) pMon->num1;
870 
871 		MemSet(buf, '<', 3);
872 		MemSet(&buf[3], ' ', len+2);
873 		MemSet(&buf[len+5], '>', 3);
874 		buf[80] = '\0';
875 		fprintf(stderr, "%s", buf);
876 	}
877 
878 	fflush(stderr);
879 	return TRUE;
880 }
881 
Dumb_MonDestroy(MonitorPtr pMon)882 static void Dumb_MonDestroy (MonitorPtr pMon)
883 {
884 	MemFree(pMon->extra);
885 	fprintf(stderr, "\n\n");
886 	fflush(stderr);
887 }
888 
Dumb_MonIntValue(MonitorPtr pMon)889 static void Dumb_MonIntValue (MonitorPtr pMon)
890 {
891 	char *buf  = (char*) pMon->extra;
892 	long value = pMon->intValue;
893 	long range = ABS(pMon->num2 - pMon->num1);
894 	size_t diff = 0;
895 	int bRefresh = FALSE;
896 
897 	if (range ==0)  return;  /* watch out for divide-by-zero! */
898 
899 	if (pMon->num2 >= pMon->num1)
900 	{
901 		if (value > pMon->num1)
902 		{
903 			if (value >= pMon->num2)
904 				diff = 40;
905 			else
906 				diff = (size_t) (((value - pMon->num1) * 40) / range);
907 
908 			if (diff==0 || diff==40 || buf[diff-1] != '#' || buf[diff] != ' ')
909 			{
910 				MemSet(&buf[0], '#', diff);
911 				MemSet(&buf[diff], ' ', 40-diff);
912 				bRefresh = TRUE;
913 			}
914 		}
915 	}
916 	else
917 	{
918 		if (value < pMon->num1)
919 		{
920 			if (value <= pMon->num2)
921 				diff = 40;
922 			else
923 				diff = (size_t) (((value - pMon->num2) * 40) / range);
924 
925 			if (diff==0 || diff==40 || buf[40-diff] != '#' || buf[40-diff-1] != ' ')
926 			{
927 				MemSet(&buf[40 - diff],'#',diff);
928 				MemSet(&buf[0], ' ', 40-diff);
929 				bRefresh = TRUE;
930 			}
931 		}
932 	}
933 	if (bRefresh)
934 	{
935 		fprintf(stderr, "\r%s", buf);
936 		fflush(stderr);
937 	}
938 }
939 
Dumb_MonStrValue(MonitorPtr pMon)940 static void Dumb_MonStrValue (MonitorPtr pMon)
941 {
942 	char *buf = (char *) pMon->extra;
943 	size_t len0 = (int)pMon->num1;
944 	size_t len1 = MIN(StringLen(pMon->strValue),len0);
945 	size_t diff = (len0-len1)/2;
946 	Nlm_MemFill(&buf[3],' ',len0+2);
947 	Nlm_MemCopy(&buf[4+diff],pMon->strValue,len1);
948 	fprintf(stderr,"\r%s",buf);
949 	fflush(stderr);
950 }
951 
952 #endif  /* else WIN16 */
953 
954 
955 /*****************************************************************************
956 *
957 *   Default Monitor
958 *      This will be moved to ncbimsg soon !!!!
959 *
960 *****************************************************************************/
961 
962 
963 static Nlm_VoidPtr stdmondata = NULL;
964 static Nlm_ProgMonFunc stdmonfunc = NULL;
965 
966 /*****************************************************************************
967 *
968 *   ProgMon(str)
969 *   	Default progress monitor
970 *
971 *****************************************************************************/
Nlm_ProgMon(Nlm_CharPtr str)972 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_ProgMon(Nlm_CharPtr str)
973 {
974 	Nlm_Boolean retval;
975 
976 	if (stdmonfunc == NULL)
977 		return TRUE;
978 
979 	retval = (* stdmonfunc)(stdmondata, str);
980 
981 	return retval;
982 }
983 
984 
985 /*****************************************************************************
986 *
987 *   SetProgMon(func, data)
988 *
989 *****************************************************************************/
Nlm_SetProgMon(ProgMonFunc func,Nlm_VoidPtr data)990 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_SetProgMon (ProgMonFunc func, Nlm_VoidPtr data)
991 {
992 	stdmonfunc = func;
993 	stdmondata = data;
994 	return TRUE;
995 }
996 
997 
998 /*****************************************************************************
999 *
1000 *   StdProgMon(data, str)
1001 *
1002 *****************************************************************************/
Nlm_StdProgMon(Nlm_VoidPtr data,Nlm_CharPtr str)1003 NLM_EXTERN Nlm_Boolean LIBCALLBACK Nlm_StdProgMon(Nlm_VoidPtr data, Nlm_CharPtr str)
1004 {
1005 	return Nlm_MonitorStrValue((Nlm_MonitorPtr) data, str);
1006 }
1007 
1008