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